@@ -14,69 +14,41 @@ func redisProvisioner() sdk.Provisioner {
1414 return redisArgsProvisioner {}
1515}
1616
17- func (p redisArgsProvisioner ) Provision (ctx context.Context , in sdk.ProvisionInput , out * sdk.ProvisionOutput ) {
18- listOfPossibleUserInputArguments := []string {
19- "--user" ,
20- "-h" ,
21- "-p" ,
22- "--pass" ,
23- "-a" ,
24- }
25-
26- var (
27- commandLineContainsUserArgument bool = false
28- commandLineContainsHostArgument bool = false
29- commandLineContainsPortArgument bool = false
30- commandLineContainsPasswordArgument bool = false
31- )
17+ // Redis CLI flags that, when already supplied by the user, signal that we
18+ // should not provision the corresponding field from the 1Password item.
19+ var (
20+ hostFlags = []string {"-h" }
21+ portFlags = []string {"-p" }
22+ userFlags = []string {"--user" }
23+ passwordFlags = []string {"-a" , "--pass" }
24+ )
3225
33- for i , arg := range out .CommandLine {
34- for _ , userArg := range listOfPossibleUserInputArguments {
35- if arg == userArg {
36- // Get the executable "redis-cli", the matched argument we are looking for and its value
37- commandLine := []string {out .CommandLine [0 ], out .CommandLine [i ], out .CommandLine [i + 1 ]}
38- // Remove the matched argument and its value as they will be added to the beginning of the command line
39- out .CommandLine = append (out .CommandLine [:i ], out .CommandLine [i + 2 :]... )
40- // Add the executable "redis-cli", the matched argument and its value to the beginning of the command line
41- commandLine = append (commandLine , out .CommandLine [1 :]... )
42- out .CommandLine = commandLine
43- // Controller to check if the user has already provided the argument
44- switch userArg {
45- case "--user" :
46- commandLineContainsUserArgument = true
47- case "-h" :
48- commandLineContainsHostArgument = true
49- case "-p" :
50- commandLineContainsPortArgument = true
51- case "--pass" , "-a" :
52- commandLineContainsPasswordArgument = true
53- default :
54- break
55- }
56- }
57- }
58- }
26+ func (p redisArgsProvisioner ) Provision (ctx context.Context , in sdk.ProvisionInput , out * sdk.ProvisionOutput ) {
27+ suppliedFlags := flagSet (out .CommandLine )
5928
60- if value , ok := in .ItemFields [fieldname .Password ]; ok && ! commandLineContainsPasswordArgument {
29+ // The password is passed via an environment variable so it never appears in
30+ // the process's argument list. Skip it if the user already authenticated on
31+ // the command line.
32+ if value , ok := in .ItemFields [fieldname .Password ]; ok && ! containsAny (suppliedFlags , passwordFlags ) {
6133 out .AddEnvVar ("REDISCLI_AUTH" , value )
6234 }
6335
64- if value , ok := in .ItemFields [fieldname .Host ]; ok && ! commandLineContainsHostArgument {
65- commandLine := []string {out .CommandLine [0 ], "-h" , value }
66- commandLine = append (commandLine , out .CommandLine [1 :]... )
67- out .CommandLine = commandLine
36+ // Collect the flags to inject first, then prepend them in a single pass.
37+ // Mutating out.CommandLine while ranging over it risks index-out-of-range
38+ // panics and stale reads, so we never modify it during inspection.
39+ var injected []string
40+ if value , ok := in .ItemFields [fieldname .Host ]; ok && ! containsAny (suppliedFlags , hostFlags ) {
41+ injected = append (injected , "-h" , value )
6842 }
69-
70- if value , ok := in . ItemFields [ fieldname . Username ]; ok && ! commandLineContainsUserArgument {
71- commandLine := [] string { out . CommandLine [ 0 ], "--user" , value }
72- commandLine = append ( commandLine , out . CommandLine [ 1 :] ... )
73- out . CommandLine = commandLine
43+ if value , ok := in . ItemFields [ fieldname . Port ]; ok && ! containsAny ( suppliedFlags , portFlags ) {
44+ injected = append ( injected , "-p" , value )
45+ }
46+ if value , ok := in . ItemFields [ fieldname . Username ]; ok && ! containsAny ( suppliedFlags , userFlags ) {
47+ injected = append ( injected , "--user" , value )
7448 }
7549
76- if value , ok := in .ItemFields [fieldname .Port ]; ok && ! commandLineContainsPortArgument {
77- commandLine := []string {out .CommandLine [0 ], "-p" , value }
78- commandLine = append (commandLine , out .CommandLine [1 :]... )
79- out .CommandLine = commandLine
50+ if len (injected ) > 0 {
51+ out .CommandLine = prependArgs (out .CommandLine , injected )
8052 }
8153}
8254
@@ -85,5 +57,40 @@ func (p redisArgsProvisioner) Deprovision(ctx context.Context, in sdk.Deprovisio
8557}
8658
8759func (p redisArgsProvisioner ) Description () string {
88- return "Provision redis secrets as command-line arguments."
60+ return "Provision redis secrets as command-line arguments and the password as an environment variable."
61+ }
62+
63+ // flagSet returns the set of arguments present on the command line, excluding
64+ // the executable name at index 0.
65+ func flagSet (commandLine []string ) map [string ]bool {
66+ set := make (map [string ]bool , len (commandLine ))
67+ for i , arg := range commandLine {
68+ if i == 0 {
69+ continue
70+ }
71+ set [arg ] = true
72+ }
73+ return set
74+ }
75+
76+ func containsAny (set map [string ]bool , flags []string ) bool {
77+ for _ , f := range flags {
78+ if set [f ] {
79+ return true
80+ }
81+ }
82+ return false
83+ }
84+
85+ // prependArgs inserts args immediately after the executable name (index 0),
86+ // leaving the rest of the user-supplied command line intact.
87+ func prependArgs (commandLine []string , args []string ) []string {
88+ if len (commandLine ) == 0 {
89+ return append ([]string {}, args ... )
90+ }
91+ result := make ([]string , 0 , len (commandLine )+ len (args ))
92+ result = append (result , commandLine [0 ])
93+ result = append (result , args ... )
94+ result = append (result , commandLine [1 :]... )
95+ return result
8996}
0 commit comments