-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Vault CA bugfixes #19285
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Vault CA bugfixes #19285
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| ```release-note:bug | ||
| ca: Fix bug with Vault CA provider where token renewal goroutines could leak if CA failed to initialize. | ||
| ``` | ||
|
|
||
| ```release-note:bug | ||
| ca: Fix bug with Vault CA provider where renewing a retracted token would cause retries in a tight loop, degrading performance. | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ import ( | |
| "encoding/json" | ||
| "fmt" | ||
| "io" | ||
| "runtime/pprof" | ||
| "strconv" | ||
| "strings" | ||
| "sync/atomic" | ||
|
|
@@ -237,8 +238,69 @@ func TestVaultCAProvider_Configure(t *testing.T) { | |
| testcase.expectedValue(t, provider) | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| // This test must not run in parallel | ||
| func TestVaultCAProvider_ConfigureFailureGoroutineLeakCheck(t *testing.T) { | ||
| if testing.Short() { | ||
| t.Skip("too slow for testing.Short") | ||
| } | ||
| SkipIfVaultNotPresent(t) | ||
|
|
||
| testVault := NewTestVaultServer(t) | ||
|
|
||
| attr := &VaultTokenAttributes{ | ||
| RootPath: "pki-root", | ||
| IntermediatePath: "pki-intermediate", | ||
| ConsulManaged: true, | ||
| } | ||
| token := CreateVaultTokenWithAttrs(t, testVault.client, attr) | ||
|
|
||
| provider := NewVaultProvider(hclog.New(&hclog.LoggerOptions{Name: "ca.vault"})) | ||
|
|
||
| t.Run("error on Configure does not leak renewal routine", func(t *testing.T) { | ||
| config := map[string]any{ | ||
| "RootPKIPath": "pki-root/", | ||
| "IntermediatePKIPath": "badbadbad/", | ||
| } | ||
| cfg := vaultProviderConfig(t, testVault.Addr, token, config) | ||
|
|
||
| err := provider.Configure(cfg) | ||
| require.Error(t, err) | ||
|
|
||
| retry.RunWith(retry.TwoSeconds(), t, func(r *retry.R) { | ||
| profile := pprof.Lookup("goroutine") | ||
| sb := strings.Builder{} | ||
| require.NoError(r, profile.WriteTo(&sb, 2)) | ||
|
Comment on lines
+272
to
+274
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. pprof is a runtime profile which can dump goroutines. The 2 here means "format it like golang stacktraces". We are looking for this trace in particular:
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great job thinking through and implementing a testing solution to this! Not a straightforward, run-of-the-mill unit testing problem 👍 |
||
| require.NotContains(r, sb.String(), | ||
| "created by github.com/hashicorp/consul/agent/connect/ca.(*VaultProvider).Configure", | ||
| "found renewal goroutine leak") | ||
| // If this test is failing because you added a new goroutine to | ||
| // (*VaultProvider).Configure AND that goroutine should persist | ||
| // even if Configure errored, then you should change the checked | ||
| // string to (*VaultProvider).renewToken. | ||
| }) | ||
| }) | ||
|
|
||
| return | ||
| t.Run("successful Configure starts renewal routine", func(t *testing.T) { | ||
| config := map[string]any{ | ||
| "RootPKIPath": "pki-root/", | ||
| "IntermediatePKIPath": "pki-intermediate/", | ||
| } | ||
| cfg := vaultProviderConfig(t, testVault.Addr, token, config) | ||
|
|
||
| require.NoError(t, provider.Configure(cfg)) | ||
|
|
||
| retry.RunWith(retry.TwoSeconds(), t, func(r *retry.R) { | ||
| profile := pprof.Lookup("goroutine") | ||
| sb := strings.Builder{} | ||
| require.NoError(r, profile.WriteTo(&sb, 2)) | ||
| t.Log(sb.String()) | ||
| require.Contains(r, sb.String(), | ||
| "created by github.com/hashicorp/consul/agent/connect/ca.(*VaultProvider).Configure", | ||
| "expected renewal goroutine, got none") | ||
| }) | ||
| }) | ||
| } | ||
|
|
||
| func TestVaultCAProvider_SecondaryActiveIntermediate(t *testing.T) { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.