Skip to content

Commit 0d94259

Browse files
committed
fix(config): resolve secrets only from selected context
Signed-off-by: Sergio <c@rct.ai>
1 parent 460de1d commit 0d94259

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

pkg/config/loader.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/osteele/liquid/render"
1616
"github.com/spf13/viper"
1717
"go.opentelemetry.io/otel/attribute"
18+
"gopkg.in/yaml.v3"
1819
)
1920

2021
var _ DataStoreLoaderFunc = NoopDataLoader
@@ -175,6 +176,10 @@ func LoadFromViper(viperCfg func(v *viper.Viper), cobraCfg func(v *viper.Viper))
175176
return log.Error(err)
176177
}
177178

179+
// Scope template variables to the selected context only so that
180+
// `${secret.*}` from other contexts are not resolved.
181+
cfg.templateVariables = listTemplateVariablesForContext(contextConfigMap)
182+
178183
ctxViper := viper.New()
179184
ctxViper.SetFs(cfg.FileSystem)
180185
if err := setDefaultsFrom(ctxViper, cfg.Data); err != nil {
@@ -275,6 +280,26 @@ func listTemplateVariables(tmpl *liquid.Template) []string {
275280
return results
276281
}
277282

283+
func listTemplateVariablesForContext(contextConfigMap map[string]interface{}) []string {
284+
if len(contextConfigMap) == 0 {
285+
return nil
286+
}
287+
288+
cfgContents, err := yaml.Marshal(contextConfigMap)
289+
if err != nil {
290+
return nil
291+
}
292+
293+
engine := liquid.NewEngine()
294+
engine.Delims("${", "}", "${%", "%}")
295+
tmpl, err := engine.ParseTemplate(cfgContents)
296+
if err != nil {
297+
return nil
298+
}
299+
300+
return listTemplateVariables(tmpl)
301+
}
302+
278303
// findTemplateVariables looks at the template's abstract syntax tree (AST)
279304
// and identifies which variables were used
280305
func findTemplateVariables(curNode render.Node, vars map[string]struct{}) {

pkg/config/loader_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,39 @@ current-context: default
165165
require.ErrorContains(t, err, "missing required 'contexts' key")
166166
}
167167

168+
func TestLoadMultiContext_OnlyResolvesSelectedContextSecrets(t *testing.T) {
169+
t.Parallel()
170+
171+
c := NewTestConfig(t)
172+
c.SetHomeDir("/home/myuser/.porter")
173+
174+
cfg := `schemaVersion: "` + ConfigSchemaVersion + `"
175+
current-context: local
176+
contexts:
177+
- name: local
178+
config:
179+
default-secrets-plugin: filesystem
180+
- name: prod
181+
config:
182+
default-storage: proddb
183+
storage:
184+
- name: proddb
185+
plugin: mongodb
186+
config:
187+
url: "${secret.prodMongoConnectionString}"
188+
`
189+
require.NoError(t, c.TestContext.FileSystem.WriteFile(
190+
"/home/myuser/.porter/config.yaml", []byte(cfg), 0600))
191+
192+
c.DataLoader = LoadFromFilesystem()
193+
_, err := c.Load(context.Background(), func(ctx context.Context, secretKey string) (string, error) {
194+
t.Fatalf("unexpected secret resolution: %s", secretKey)
195+
return "", nil
196+
})
197+
require.NoError(t, err)
198+
assert.Equal(t, "filesystem", c.Data.DefaultSecretsPlugin)
199+
}
200+
168201
func TestListTemplateVariables(t *testing.T) {
169202
eng := liquid.NewEngine()
170203
tmpl, err := eng.ParseString(`not a variable {{secrets.foo}} more non variable junk{{env.var}}{{env.var}}`)

0 commit comments

Comments
 (0)