bake: allow overriding declared secret sources

Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax
2026-07-21 12:20:36 +02:00
parent 9618d82eff
commit febb45afe2
5 changed files with 152 additions and 7 deletions
+52 -7
View File
@@ -606,9 +606,12 @@ func (c Config) newOverrides(v []string) (map[string]map[string]Override, error)
override.Append = appendTo
override.ArrValue = append(override.ArrValue, parts[1])
}
case "resources":
case "resources", "secret":
if len(keys) != 3 {
return nil, errors.Errorf("invalid key %s, resources requires name", parts[0])
return nil, errors.Errorf("invalid key %s, %s requires name", parts[0], keys[1])
}
if appendTo {
return nil, errors.Errorf("invalid key %s, %s does not support append", parts[0], keys[1])
}
override.Value = parts[1]
case "args":
@@ -974,6 +977,8 @@ func (t *Target) Merge(t2 *Target) {
func (t *Target) AddOverrides(overrides map[string]Override, ent *EntitlementConf) error {
// IMPORTANT: if you add more fields here, do not forget to update
// docs/bake-reference.md and https://docs.docker.com/build/bake/overrides/
secretOverrides := map[string]Override{}
secretEntitlements := map[string]struct{}{}
for key, o := range overrides {
value := o.Value
keys := strings.SplitN(key, ".", 2)
@@ -1061,21 +1066,24 @@ func (t *Target) AddOverrides(overrides map[string]Override, ent *EntitlementCon
t.Target = &value
case "call":
t.Call = &value
case "secret":
if len(keys) != 2 {
return errors.Errorf("invalid format for secret, expecting secret.<id>=<value>")
}
secretOverrides[keys[1]] = o
case "secrets":
secrets, err := parseArrValue[buildflags.Secret](o.ArrValue)
if err != nil {
return errors.Wrap(err, "invalid value for outputs")
}
for _, s := range secrets {
secretEntitlements[s.ID] = struct{}{}
}
if o.Append {
t.Secrets = t.Secrets.Merge(secrets)
} else {
t.Secrets = secrets
}
for _, s := range t.Secrets {
if s.FilePath != "" {
ent.FSRead = append(ent.FSRead, s.FilePath)
}
}
case "ssh":
ssh, err := parseArrValue[buildflags.SSH](o.ArrValue)
if err != nil {
@@ -1189,9 +1197,46 @@ func (t *Target) AddOverrides(overrides map[string]Override, ent *EntitlementCon
return errors.Errorf("unknown key: %s", keys[0])
}
}
for id, o := range secretOverrides {
if err := t.updateSecret(id, o.Value); err != nil {
return err
}
secretEntitlements[id] = struct{}{}
}
for _, s := range t.Secrets {
if _, ok := secretEntitlements[s.ID]; ok && s.FilePath != "" {
ent.FSRead = append(ent.FSRead, s.FilePath)
}
}
return nil
}
func (t *Target) updateSecret(id, value string) error {
if id == "" {
return errors.Errorf("invalid format for secret, expecting secret.<id>=<value>")
}
for _, s := range t.Secrets {
if s.ID != id {
continue
}
var next buildflags.Secret
if err := next.UnmarshalText([]byte(value)); err != nil {
return err
}
if next.ID != "" && next.ID != id {
return errors.Errorf("secret override id %q does not match declared secret %q", next.ID, id)
}
s.Env = next.Env
s.FilePath = next.FilePath
return nil
}
return errors.Errorf("secret %q must be declared before it can be overridden", id)
}
func (g *Group) GetEvalContexts(ectx *hcl.EvalContext, block *hcl.Block, loadDeps func(hcl.Expression) hcl.Diagnostics) ([]*hcl.EvalContext, error) {
content, _, err := block.Body.PartialContent(&hcl.BodySchema{
Attributes: []hcl.AttributeSchema{{Name: "matrix"}},
+43
View File
@@ -237,6 +237,49 @@ target "webapp" {
require.Equal(t, "BAR", m["webapp"].Secrets[1].ID)
})
t.Run("SecretSourceOverrideEnv", func(t *testing.T) {
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.secret.FOO=env=BAR"}, nil, nil, &EntitlementConf{})
require.NoError(t, err)
require.Len(t, m["webapp"].Secrets, 1)
require.Equal(t, "FOO", m["webapp"].Secrets[0].ID)
require.Equal(t, "BAR", m["webapp"].Secrets[0].Env)
require.Empty(t, m["webapp"].Secrets[0].FilePath)
})
t.Run("SecretSourceOverrideFile", func(t *testing.T) {
ent := &EntitlementConf{}
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.secret.FOO=src=/tmp/foo"}, nil, nil, ent)
require.NoError(t, err)
require.Len(t, m["webapp"].Secrets, 1)
require.Equal(t, "FOO", m["webapp"].Secrets[0].ID)
require.Equal(t, "/tmp/foo", m["webapp"].Secrets[0].FilePath)
require.Empty(t, m["webapp"].Secrets[0].Env)
require.Equal(t, []string{"/tmp/foo"}, ent.FSRead)
})
t.Run("SecretSourceOverrideUsesFinalSourceForEntitlements", func(t *testing.T) {
ent := &EntitlementConf{}
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.secrets=id=FOO,src=/tmp/foo", "webapp.secret.FOO=env=BAR"}, nil, nil, ent)
require.NoError(t, err)
require.Len(t, m["webapp"].Secrets, 1)
require.Equal(t, "FOO", m["webapp"].Secrets[0].ID)
require.Equal(t, "BAR", m["webapp"].Secrets[0].Env)
require.Empty(t, m["webapp"].Secrets[0].FilePath)
require.Empty(t, ent.FSRead)
})
t.Run("SecretSourceOverrideUndeclared", func(t *testing.T) {
_, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.secret.BAR=env=BAR"}, nil, nil, &EntitlementConf{})
require.Error(t, err)
require.Equal(t, `secret "BAR" must be declared before it can be overridden`, err.Error())
})
t.Run("SecretSourceOverrideMismatchedID", func(t *testing.T) {
_, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.secret.FOO=id=BAR,env=BAR"}, nil, nil, &EntitlementConf{})
require.Error(t, err)
require.Equal(t, `secret override id "BAR" does not match declared secret "FOO"`, err.Error())
})
t.Run("ShmSizeOverride", func(t *testing.T) {
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.shm-size=256m"}, nil, nil, &EntitlementConf{})
require.NoError(t, err)