-
Notifications
You must be signed in to change notification settings - Fork 94
fix(awssecrets): support ARN-style secret identifiers in URIs (#909) #910
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
base: main
Are you sure you want to change the base?
Changes from 1 commit
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 |
|---|---|---|
|
|
@@ -339,10 +339,52 @@ func (r *Runtime) prepare() (*expansion.ExpandRegexMatch, error) { | |
| return valStr, nil | ||
| } | ||
|
|
||
| uri, err := url.Parse(key) | ||
| // Handle ARN-based URIs which contain colons that would be misinterpreted as port separators | ||
| // ARN format: arn:aws:service:region:account:resource | ||
| // We need to detect and transform the ARN to avoid URL parsing issues with colons | ||
| processedKey := key | ||
| arnValue := "" | ||
|
|
||
| // Check if this looks like an ARN-based URI (contains "://arn:aws:" or "://arn:aws-") | ||
| if strings.Contains(key, "://arn:aws:") || strings.Contains(key, "://arn:aws-") { | ||
| // Find the scheme end and extract the ARN | ||
| schemeEnd := strings.Index(key, "://") | ||
| if schemeEnd != -1 { | ||
| prefix := key[:schemeEnd+3] // includes "://" | ||
| remainder := key[schemeEnd+3:] | ||
|
|
||
| // Find where the ARN ends (at ? for query params, # for fragment, or end of string) | ||
| arnEnd := len(remainder) | ||
| if idx := strings.IndexAny(remainder, "?#"); idx != -1 { | ||
| arnEnd = idx | ||
| } | ||
|
|
||
| arnValue = remainder[:arnEnd] | ||
| suffix := remainder[arnEnd:] | ||
|
|
||
| // Transform to use triple-slash format (empty host, ARN in path) | ||
| // This prevents the colon in ARN from being interpreted as a port separator | ||
| processedKey = prefix + "/" + arnValue + suffix | ||
| } | ||
| } | ||
|
|
||
| uri, err := url.Parse(processedKey) | ||
| if err != nil { | ||
| return "", err | ||
| } | ||
|
|
||
borgius marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // If we processed an ARN, extract it from the path and restore to host | ||
| if arnValue != "" { | ||
| // Remove the leading slash we added | ||
| uri.Host = strings.TrimPrefix(uri.Path, "/") | ||
| // Find the actual path after the ARN | ||
| arnLen := len(arnValue) | ||
| if len(uri.Path) > arnLen+1 { | ||
| uri.Path = uri.Path[arnLen+1:] | ||
| } else { | ||
| uri.Path = "" | ||
| } | ||
|
Comment on lines
+379
to
+385
|
||
| } | ||
|
|
||
| hash := uriToProviderHash(uri) | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,8 @@ import ( | |
| "sort" | ||
| "strings" | ||
| "testing" | ||
| "crypto/md5" | ||
| "fmt" | ||
|
Comment on lines
+10
to
+11
|
||
|
|
||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
@@ -187,3 +189,97 @@ datetime_offset: "2025-01-01T12:34:56+01:00" | |
|
|
||
| require.Equal(t, expected, buf.String()) | ||
| } | ||
|
|
||
| // mockProvider is a simple test double implementing api.Provider | ||
| type mockProvider struct { | ||
| getStringFunc func(string) (string, error) | ||
| getStringMapFunc func(string) (map[string]interface{}, error) | ||
| } | ||
|
|
||
| func (m *mockProvider) GetString(key string) (string, error) { | ||
| if m.getStringFunc != nil { | ||
| return m.getStringFunc(key) | ||
| } | ||
| return "", nil | ||
| } | ||
|
|
||
| func (m *mockProvider) GetStringMap(key string) (map[string]interface{}, error) { | ||
| if m.getStringMapFunc != nil { | ||
| return m.getStringMapFunc(key) | ||
| } | ||
| return nil, nil | ||
| } | ||
|
|
||
| func TestARNFragmentExtractionWithMockProvider(t *testing.T) { | ||
| r, err := New(Options{}) | ||
| require.NoError(t, err) | ||
|
|
||
| // compute provider hash used by Runtime (scheme + query.Encode()) | ||
| hash := fmt.Sprintf("%x", md5.Sum([]byte("echo"))) | ||
|
Comment on lines
+217
to
+218
|
||
|
|
||
| arn := "arn:aws:secretsmanager:us-east-1:123456789012:secret:/myteam/mydoc" | ||
|
|
||
| // mock provider returns a nested map for the ARN key | ||
| mock := &mockProvider{ | ||
| getStringMapFunc: func(key string) (map[string]interface{}, error) { | ||
| if key != arn { | ||
| t.Fatalf("unexpected key passed to provider.GetStringMap: %q", key) | ||
| } | ||
| return map[string]interface{}{ | ||
| "myteam": map[string]interface{}{ | ||
| "mydoc": "mydoc", | ||
| }, | ||
| }, nil | ||
| }, | ||
| } | ||
|
|
||
| r.providers[hash] = mock | ||
|
|
||
| res, err := r.Get("ref+echo://" + arn + "#/myteam/mydoc") | ||
| require.NoError(t, err) | ||
| require.Equal(t, "mydoc", res) | ||
| } | ||
|
|
||
| func TestARNBasedURIParsing(t *testing.T) { | ||
| // Test that ARN-based URIs with colons are parsed correctly | ||
| // This tests the fix for issue #909 | ||
| testCases := []struct { | ||
| name string | ||
| input string | ||
| expected string | ||
| checkResult bool | ||
| }{ | ||
| { | ||
| name: "Simple echo ARN format", | ||
| input: "ref+echo://arn:aws:secretsmanager:us-east-1:123456789012:secret:/demo/app/database", | ||
| expected: "arn:aws:secretsmanager:us-east-1:123456789012:secret:/demo/app/database", | ||
| checkResult: true, | ||
| }, | ||
| { | ||
| name: "ARN with query params", | ||
| input: "ref+echo://arn:aws:secretsmanager:us-east-1:123456789012:secret:/demo/app/database?region=us-east-1", | ||
| expected: "arn:aws:secretsmanager:us-east-1:123456789012:secret:/demo/app/database", | ||
| checkResult: true, | ||
| }, | ||
| { | ||
| name: "ARN with fragment - parse only", | ||
| input: "ref+echo://arn:aws:secretsmanager:us-east-1:123456789012:secret:/myteam/mydoc#/myteam/mydoc", | ||
| checkResult: false, | ||
| }, | ||
| { | ||
| name: "ARN with both query and fragment - parse only", | ||
| input: "ref+echo://arn:aws:secretsmanager:us-east-1:123456789012:secret:/demo/app/database?region=us-east-1#/demo/app/database", | ||
| checkResult: false, | ||
| }, | ||
| } | ||
|
|
||
| for _, tc := range testCases { | ||
| t.Run(tc.name, func(t *testing.T) { | ||
| result, err := Get(tc.input, Options{}) | ||
| require.NoError(t, err, "Failed to parse ARN-based URI: %s", tc.input) | ||
| if tc.checkResult { | ||
| require.Equal(t, tc.expected, result) | ||
| } | ||
| }) | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.