99	"strings" 
1010	"text/template" 
1111
12+ 	"github.com/grafana/synthetic-monitoring-agent/internal/prober/interpolation" 
1213	sm "github.com/grafana/synthetic-monitoring-agent/pkg/pb/synthetic_monitoring" 
1314)
1415
@@ -20,52 +21,7 @@ var templateFS embed.FS
2021var  userVariables  =  regexp .MustCompile (`\$\{([a-zA-Z_][a-zA-Z0-9_]*)\}` )
2122
2223func  performVariableExpansion (in  string ) string  {
23- 	if  len (in ) ==  0  {
24- 		return  `''` 
25- 	}
26- 
27- 	var  s  strings.Builder 
28- 	buf  :=  []byte (in )
29- 	locs  :=  userVariables .FindAllSubmatchIndex (buf , - 1 )
30- 
31- 	p  :=  0 
32- 	for  _ , loc  :=  range  locs  {
33- 		if  len (loc ) <  4  { // put the bounds checker at ease 
34- 			panic ("unexpected result while building URL" )
35- 		}
36- 
37- 		if  s .Len () >  0  {
38- 			s .WriteRune ('+' )
39- 		}
40- 
41- 		if  pre  :=  buf [p :loc [0 ]]; len (pre ) >  0  {
42- 			s .WriteRune ('\'' )
43- 			template .JSEscape (& s , pre )
44- 			s .WriteRune ('\'' )
45- 			s .WriteRune ('+' )
46- 		}
47- 
48- 		s .WriteString (`vars['` )
49- 		// Because of the capture in the regular expression, the result 
50- 		// has two indices that represent the matched substring, and 
51- 		// two more indices that represent the capture group. 
52- 		s .Write (buf [loc [2 ]:loc [3 ]])
53- 		s .WriteString (`']` )
54- 
55- 		p  =  loc [1 ]
56- 	}
57- 
58- 	if  len (buf [p :]) >  0  {
59- 		if  s .Len () >  0  {
60- 			s .WriteRune ('+' )
61- 		}
62- 
63- 		s .WriteRune ('\'' )
64- 		template .JSEscape (& s , buf [p :])
65- 		s .WriteRune ('\'' )
66- 	}
67- 
68- 	return  s .String ()
24+ 	return  interpolation .ToJavaScriptWithSecrets (in )
6925}
7026
7127// Query params must be appended to a URL that has already been created. 
@@ -113,13 +69,19 @@ func interpolateBodyVariables(bodyVarName string, body *sm.HttpRequestBody) []st
11369	default :
11470		var  buf  strings.Builder 
11571
116- 		matches  :=  userVariables .FindAllString (string (body .Payload ), - 1 )
72+ 		// Find both regular and secret variables using submatch indices 
73+ 		regularMatches  :=  userVariables .FindAllSubmatchIndex (body .Payload , - 1 )
74+ 		secretMatches  :=  interpolation .SecretRegex .FindAllSubmatchIndex (body .Payload , - 1 )
75+ 
11776		parsedMatches  :=  make (map [string ]struct {})
118- 		out  :=  make ([]string , 0 , len (matches ))
77+ 		out  :=  make ([]string , 0 , len (regularMatches ) + len ( secretMatches ))
11978
120- 		// For every instance of ${variable} in the body, 
121- 		// this block returns {bodyVarName} = {bodyVarName}.replaceAll('${variable}', vars['variable']) 
122- 		for  _ , m  :=  range  matches  {
79+ 		// Handle regular variables 
80+ 		for  _ , match  :=  range  regularMatches  {
81+ 			if  len (match ) <  4  {
82+ 				continue 
83+ 			}
84+ 			m  :=  string (body .Payload [match [0 ]:match [1 ]])
12385			if  _ , found  :=  parsedMatches [m ]; found  {
12486				continue 
12587			}
@@ -132,15 +94,38 @@ func interpolateBodyVariables(bodyVarName string, body *sm.HttpRequestBody) []st
13294			buf .WriteString (m )
13395			buf .WriteString ("', vars['" )
13496			// writing the variable name from between ${ and } 
135- 			for  i  :=  2 ; i  <  len (m )- 1 ; i ++  {
136- 				buf .WriteByte (m [i ])
137- 			}
97+ 			buf .Write (body .Payload [match [2 ]:match [3 ]])
13898			buf .WriteString ("'])" )
13999			out  =  append (out , buf .String ())
140100
141101			parsedMatches [m ] =  struct {}{}
142102		}
143103
104+ 		// Handle secret variables 
105+ 		for  _ , match  :=  range  secretMatches  {
106+ 			if  len (match ) <  4  {
107+ 				continue 
108+ 			}
109+ 			m  :=  string (body .Payload [match [0 ]:match [1 ]])
110+ 			if  _ , found  :=  parsedMatches [m ]; found  {
111+ 				continue 
112+ 			}
113+ 
114+ 			buf .Reset ()
115+ 			buf .WriteString (bodyVarName )
116+ 			buf .WriteString ("=" )
117+ 			buf .WriteString (bodyVarName )
118+ 			buf .WriteString (".replaceAll('" )
119+ 			buf .WriteString (m )
120+ 			buf .WriteString ("', await secrets.get('" )
121+ 			// writing the secret name from the capture group 
122+ 			buf .Write (body .Payload [match [2 ]:match [3 ]])
123+ 			buf .WriteString ("'))" )
124+ 			out  =  append (out , buf .String ())
125+ 
126+ 			parsedMatches [m ] =  struct {}{}
127+ 		}
128+ 
144129		return  out 
145130	}
146131}
@@ -422,6 +407,35 @@ func buildVars(variable *sm.MultiHttpEntryVariable) string {
422407	return  b .String ()
423408}
424409
410+ func  hasSecretVariables (settings  * sm.MultiHttpSettings ) bool  {
411+ 	for  _ , entry  :=  range  settings .Entries  {
412+ 		// Check URL 
413+ 		if  interpolation .SecretRegex .MatchString (entry .Request .Url ) {
414+ 			return  true 
415+ 		}
416+ 
417+ 		// Check headers 
418+ 		for  _ , header  :=  range  entry .Request .Headers  {
419+ 			if  interpolation .SecretRegex .MatchString (header .Value ) {
420+ 				return  true 
421+ 			}
422+ 		}
423+ 
424+ 		// Check query fields 
425+ 		for  _ , field  :=  range  entry .Request .QueryFields  {
426+ 			if  interpolation .SecretRegex .MatchString (field .Name ) ||  interpolation .SecretRegex .MatchString (field .Value ) {
427+ 				return  true 
428+ 			}
429+ 		}
430+ 
431+ 		// Check body 
432+ 		if  entry .Request .Body  !=  nil  &&  interpolation .SecretRegex .MatchString (string (entry .Request .Body .Payload )) {
433+ 			return  true 
434+ 		}
435+ 	}
436+ 	return  false 
437+ }
438+ 
425439func  settingsToScript (settings  * sm.MultiHttpSettings ) ([]byte , error ) {
426440	// Convert settings to script using a Go template 
427441	tmpl , err  :=  template .
@@ -442,9 +456,18 @@ func settingsToScript(settings *sm.MultiHttpSettings) ([]byte, error) {
442456
443457	var  buf  bytes.Buffer 
444458
459+ 	// Create template data with secret variable detection 
460+ 	templateData  :=  struct  {
461+ 		* sm.MultiHttpSettings 
462+ 		HasSecretVariables  bool 
463+ 	}{
464+ 		MultiHttpSettings :  settings ,
465+ 		HasSecretVariables : hasSecretVariables (settings ),
466+ 	}
467+ 
445468	// TODO(mem): figure out if we need to transform the data in some way 
446469	// before executing the template 
447- 	if  err  :=  tmpl .ExecuteTemplate (& buf , "script.tmpl" , settings ); err  !=  nil  {
470+ 	if  err  :=  tmpl .ExecuteTemplate (& buf , "script.tmpl" , templateData ); err  !=  nil  {
448471		return  nil , fmt .Errorf ("executing script template: %w" , err )
449472	}
450473
0 commit comments