@@ -3,6 +3,7 @@ package awsenv
33import (
44 "context"
55 "errors"
6+ "fmt"
67 "io/ioutil"
78 "log"
89 "os"
@@ -66,6 +67,24 @@ mysql_users:
6667 admin_password = "awsenv:/path/to/the/password",
6768 }
6869 )
70+ `
71+ sampleCnfFile5 = `
72+ mysql_users:
73+ (
74+ {
75+ username = "awsenv:arn:aws:ssm:us-east-1:123456789012:parameter/remote/username",
76+ password = "awsenv:arn:aws:ssm:us-east-1:123456789012:parameter/remote/password",
77+ }
78+ )
79+ `
80+ sampleCnfFile6 = `
81+ mysql_users:
82+ (
83+ {
84+ username = "awsenv:/path/to/the/username",
85+ password = "awsenv:arn:aws:ssm:us-east-1:123456789012:parameter/remote/password",
86+ }
87+ )
6988`
7089)
7190
@@ -214,6 +233,101 @@ mysql_users:
214233 require .Equal (t , expectedContent , string (f ))
215234}
216235
236+ func TestFileReplacer_ReplaceAll_CrossAccountARN (t * testing.T ) {
237+
238+ fileName , cleanup := writeTempFile (sampleCnfFile5 )
239+ defer cleanup ()
240+
241+ oldContent , err := ioutil .ReadFile (fileName ) //nolint: gosec
242+ require .NoError (t , err )
243+ require .Equal (t , sampleCnfFile5 , string (oldContent ))
244+
245+ // Use mockParamsGetter to simulate SSM's behavior of stripping ARN prefixes from result keys
246+ getter := mockParamsGetter (func (_ context.Context , paths []string ) (map [string ]string , error ) {
247+ store := map [string ]string {
248+ "/remote/username" : "remote_user" ,
249+ "/remote/password" : "remote_pass" ,
250+ }
251+ result := make (map [string ]string , len (paths ))
252+ for _ , p := range paths {
253+ plain := stripARNPrefix (p )
254+ val , ok := store [plain ]
255+ if ! ok {
256+ return nil , fmt .Errorf ("not found: %s" , p )
257+ }
258+ result [plain ] = val
259+ }
260+ return result , nil
261+ })
262+
263+ r := NewFileReplacer (DefaultPrefix , fileName , getter )
264+
265+ ctx := context .Background ()
266+ err = r .ReplaceAll (ctx )
267+ require .NoError (t , err , "expected no error" )
268+
269+ expectedContent := `
270+ mysql_users:
271+ (
272+ {
273+ username = "remote_user",
274+ password = "remote_pass",
275+ }
276+ )
277+ `
278+ f , err := ioutil .ReadFile (fileName ) //nolint: gosec
279+ require .NoError (t , err )
280+
281+ require .Equal (t , expectedContent , string (f ))
282+ }
283+
284+ func TestFileReplacer_ReplaceAll_MixedLocalAndCrossAccount (t * testing.T ) {
285+
286+ fileName , cleanup := writeTempFile (sampleCnfFile6 )
287+ defer cleanup ()
288+
289+ oldContent , err := ioutil .ReadFile (fileName ) //nolint: gosec
290+ require .NoError (t , err )
291+ require .Equal (t , sampleCnfFile6 , string (oldContent ))
292+
293+ getter := mockParamsGetter (func (_ context.Context , paths []string ) (map [string ]string , error ) {
294+ store := map [string ]string {
295+ "/path/to/the/username" : "local_user" ,
296+ "/remote/password" : "remote_pass" ,
297+ }
298+ result := make (map [string ]string , len (paths ))
299+ for _ , p := range paths {
300+ plain := stripARNPrefix (p )
301+ val , ok := store [plain ]
302+ if ! ok {
303+ return nil , fmt .Errorf ("not found: %s" , p )
304+ }
305+ result [plain ] = val
306+ }
307+ return result , nil
308+ })
309+
310+ r := NewFileReplacer (DefaultPrefix , fileName , getter )
311+
312+ ctx := context .Background ()
313+ err = r .ReplaceAll (ctx )
314+ require .NoError (t , err , "expected no error" )
315+
316+ expectedContent := `
317+ mysql_users:
318+ (
319+ {
320+ username = "local_user",
321+ password = "remote_pass",
322+ }
323+ )
324+ `
325+ f , err := ioutil .ReadFile (fileName ) //nolint: gosec
326+ require .NoError (t , err )
327+
328+ require .Equal (t , expectedContent , string (f ))
329+ }
330+
217331func writeTempFile (contents string ) (string , func ()) {
218332
219333 uid , err := uuid .NewV4 ()
@@ -234,5 +348,5 @@ func writeTempFile(contents string) (string, func()) {
234348 log .Fatal (err )
235349 }
236350
237- return tmpfile .Name (), func () { os .Remove (fName ) } //nolint: errcheck,gosec
351+ return tmpfile .Name (), func () { os .Remove (tmpfile . Name () ) } //nolint: errcheck,gosec
238352}
0 commit comments