diff --git a/pkg/dagger.io/dagger/engine/image.cue b/pkg/dagger.io/dagger/engine/image.cue index ae346903..990269d5 100644 --- a/pkg/dagger.io/dagger/engine/image.cue +++ b/pkg/dagger.io/dagger/engine/image.cue @@ -14,11 +14,10 @@ package engine config: #ImageConfig // Authentication - auth: [...{ - target: string + auth?: { username: string - secret: string | #Secret - }] + secret: #Secret + } // Complete ref of the pushed image, including digest result: #Ref @@ -68,11 +67,10 @@ package engine source: #Ref // Authentication - auth: [...{ - target: string + auth?: { username: string - secret: string | #Secret - }] + secret: #Secret + } // Root filesystem of downloaded image output: #FS @@ -98,11 +96,10 @@ package engine } // Authentication - auth: [...{ - target: string + auth: [registry=string]: { username: string - secret: string | #Secret - }] + secret: #Secret + } platforms?: [...string] target?: string diff --git a/pkg/universe.dagger.io/docker/pull.cue b/pkg/universe.dagger.io/docker/pull.cue index b670f414..5a0b4d64 100644 --- a/pkg/universe.dagger.io/docker/pull.cue +++ b/pkg/universe.dagger.io/docker/pull.cue @@ -12,18 +12,16 @@ import ( source: #Ref // Registry authentication - // Key must be registry address, for example "index.docker.io" - auth: [registry=string]: { + auth?: { username: string secret: dagger.#Secret } _op: engine.#Pull & { "source": source - "auth": [ for target, creds in auth { - "target": target - creds - }] + if auth != _|_ { + "auth": auth + } } // Downloaded image diff --git a/pkg/universe.dagger.io/docker/push.cue b/pkg/universe.dagger.io/docker/push.cue index 391a3da7..9d29cf9f 100644 --- a/pkg/universe.dagger.io/docker/push.cue +++ b/pkg/universe.dagger.io/docker/push.cue @@ -14,8 +14,7 @@ import ( result: #Ref & _push.result // Registry authentication - // Key must be registry address - auth: [registry=string]: { + auth?: { username: string secret: dagger.#Secret } @@ -25,10 +24,9 @@ import ( _push: engine.#Push & { "dest": dest - "auth": [ for target, creds in auth { - "target": target - creds - }] + if auth != _|_ { + "auth": auth + } input: image.rootfs config: image.config } diff --git a/plan/task/auth.go b/plan/task/auth.go index 8fc7e44c..1d8983e5 100644 --- a/plan/task/auth.go +++ b/plan/task/auth.go @@ -6,7 +6,6 @@ import ( ) type authValue struct { - Target string Username string Secret *plancontext.Secret } @@ -14,41 +13,23 @@ type authValue struct { // Decodes an auth field value // // Cue format: -// auth: [...{ -// target: string +// auth: { // username: string // secret: string | #Secret -// }] -func decodeAuthValue(pctx *plancontext.Context, v *compiler.Value) ([]*authValue, error) { - vals, err := v.List() +// } +func decodeAuthValue(pctx *plancontext.Context, v *compiler.Value) (*authValue, error) { + authVal := authValue{} + username, err := v.Lookup("username").String() if err != nil { return nil, err } + authVal.Username = username - authVals := []*authValue{} - for _, val := range vals { - authVal := authValue{} - - target, err := val.Lookup("target").String() - if err != nil { - return nil, err - } - authVal.Target = target - - username, err := val.Lookup("username").String() - if err != nil { - return nil, err - } - authVal.Username = username - - secret, err := pctx.Secrets.FromValue(val.Lookup("secret")) - if err != nil { - return nil, err - } - authVal.Secret = secret - - authVals = append(authVals, &authVal) + secret, err := pctx.Secrets.FromValue(v.Lookup("secret")) + if err != nil { + return nil, err } + authVal.Secret = secret - return authVals, nil + return &authVal, nil } diff --git a/plan/task/dockerfile.go b/plan/task/dockerfile.go index 397da66e..1254114f 100644 --- a/plan/task/dockerfile.go +++ b/plan/task/dockerfile.go @@ -30,15 +30,24 @@ type dockerfileTask struct { func (t *dockerfileTask) Run(ctx context.Context, pctx *plancontext.Context, s solver.Solver, v *compiler.Value) (*compiler.Value, error) { lg := log.Ctx(ctx) - - // Read auth info - auth, err := decodeAuthValue(pctx, v.Lookup("auth")) + auths, err := v.Lookup("auth").Fields() if err != nil { return nil, err } - for _, a := range auth { - s.AddCredentials(a.Target, a.Username, a.Secret.PlainText()) - lg.Debug().Str("target", a.Target).Msg("add target credentials") + + for _, auth := range auths { + // Read auth info + a, err := decodeAuthValue(pctx, auth.Value) + if err != nil { + return nil, err + } + // Extract registry target from dest + target, err := solver.ParseAuthHost(auth.Label()) + if err != nil { + return nil, err + } + s.AddCredentials(target, a.Username, a.Secret.PlainText()) + lg.Debug().Str("target", target).Msg("add target credentials") } source, err := pctx.FS.FromValue(v.Lookup("source")) diff --git a/plan/task/pull.go b/plan/task/pull.go index d4dede0f..d374ff5c 100644 --- a/plan/task/pull.go +++ b/plan/task/pull.go @@ -28,13 +28,18 @@ func (c *pullTask) Run(ctx context.Context, pctx *plancontext.Context, s solver. } // Read auth info - auth, err := decodeAuthValue(pctx, v.Lookup("auth")) - if err != nil { - return nil, err - } - for _, a := range auth { - s.AddCredentials(a.Target, a.Username, a.Secret.PlainText()) - lg.Debug().Str("target", a.Target).Msg("add target credentials") + if auth := v.Lookup("auth"); auth.Exists() { + a, err := decodeAuthValue(pctx, auth) + if err != nil { + return nil, err + } + // Extract registry target from source + target, err := solver.ParseAuthHost(rawRef) + if err != nil { + return nil, err + } + s.AddCredentials(target, a.Username, a.Secret.PlainText()) + lg.Debug().Str("target", target).Msg("add target credentials") } ref, err := reference.ParseNormalizedNamed(rawRef) diff --git a/plan/task/push.go b/plan/task/push.go index 300b21a8..5e34fcfc 100644 --- a/plan/task/push.go +++ b/plan/task/push.go @@ -36,13 +36,19 @@ func (c *pushTask) Run(ctx context.Context, pctx *plancontext.Context, s solver. dest = reference.TagNameOnly(dest) // Read auth info - auth, err := decodeAuthValue(pctx, v.Lookup("auth")) - if err != nil { - return nil, err - } - for _, a := range auth { - s.AddCredentials(a.Target, a.Username, a.Secret.PlainText()) - lg.Debug().Str("target", a.Target).Msg("add target credentials") + if auth := v.Lookup("auth"); auth.Exists() { + // Read auth info + a, err := decodeAuthValue(pctx, auth) + if err != nil { + return nil, err + } + // Extract registry target from dest + target, err := solver.ParseAuthHost(rawDest) + if err != nil { + return nil, err + } + s.AddCredentials(target, a.Username, a.Secret.PlainText()) + lg.Debug().Str("target", target).Msg("add target credentials") } // Get input state diff --git a/solver/registryauth.go b/solver/registryauth.go index 04607758..e3337254 100644 --- a/solver/registryauth.go +++ b/solver/registryauth.go @@ -51,7 +51,7 @@ func (a *RegistryAuthProvider) Credentials(ctx context.Context, req *bkauth.Cred defer a.m.RUnlock() for authHost, auth := range a.credentials { - u, err := parseAuthHost(authHost) + u, err := ParseAuthHost(authHost) if err != nil { return nil, err } @@ -65,7 +65,7 @@ func (a *RegistryAuthProvider) Credentials(ctx context.Context, req *bkauth.Cred // Parsing function based on splitReposSearchTerm // "github.com/docker/docker/registry" -func parseAuthHost(host string) (string, error) { +func ParseAuthHost(host string) (string, error) { host = strings.TrimPrefix(host, "http://") host = strings.TrimPrefix(host, "https://") host = strings.TrimSuffix(host, "/") diff --git a/solver/registryauth_test.go b/solver/registryauth_test.go index 33e30a37..f2071372 100644 --- a/solver/registryauth_test.go +++ b/solver/registryauth_test.go @@ -257,7 +257,7 @@ func TestParseAuthHost(t *testing.T) { successRefs := []output{} for _, scase := range scases { - named, err := parseAuthHost(scase.Host) + named, err := ParseAuthHost(scase.Host) if err != nil { t.Fatalf("Invalid normalized reference for [%q]. Got %q", scase, err) } @@ -273,7 +273,7 @@ func TestParseAuthHost(t *testing.T) { } for _, fcase := range fcases { - named, err := parseAuthHost(fcase.Host) + named, err := ParseAuthHost(fcase.Host) if err == nil { t.Fatalf("Invalid normalized reference for [%q]. Expected failure for %q", fcase, named) } diff --git a/tests/tasks/dockerfile/build_auth.cue b/tests/tasks/dockerfile/build_auth.cue index 6f150143..897deebc 100644 --- a/tests/tasks/dockerfile/build_auth.cue +++ b/tests/tasks/dockerfile/build_auth.cue @@ -22,12 +22,10 @@ engine.#Plan & { build: engine.#Dockerfile & { source: inputs.directories.testdata.contents - auth: [{ - target: "daggerio/ci-test:private-pull" + auth: "daggerio/ci-test:private-pull": { username: "daggertest" - - secret: sopsSecrets.output.DOCKERHUB_TOKEN.contents - }] + secret: sopsSecrets.output.DOCKERHUB_TOKEN.contents + } dockerfile: contents: """ FROM daggerio/ci-test:private-pull@sha256:c74f1b1166784193ea6c8f9440263b9be6cae07dfe35e32a5df7a31358ac2060 """ diff --git a/tests/tasks/pull/pull_auth.cue b/tests/tasks/pull/pull_auth.cue index f6f3670b..5b9c44fa 100644 --- a/tests/tasks/pull/pull_auth.cue +++ b/tests/tasks/pull/pull_auth.cue @@ -19,11 +19,10 @@ engine.#Plan & { pull: engine.#Pull & { source: "daggerio/ci-test:private-pull@sha256:c74f1b1166784193ea6c8f9440263b9be6cae07dfe35e32a5df7a31358ac2060" - auth: [{ - target: "daggerio/ci-test:private-pull" + auth: { username: "daggertest" secret: sopsSecrets.output.DOCKERHUB_TOKEN.contents - }] + } } & { // assert result digest: "sha256:c74f1b1166784193ea6c8f9440263b9be6cae07dfe35e32a5df7a31358ac2060" diff --git a/tests/tasks/push/push.cue b/tests/tasks/push/push.cue index f7d2efd1..27641a18 100644 --- a/tests/tasks/push/push.cue +++ b/tests/tasks/push/push.cue @@ -12,11 +12,10 @@ engine.#Plan & { args: ["-d", "../../secrets_sops.yaml"] } - #auth: [{ - target: "daggerio/ci-test:private-pull" + #auth: { username: "daggertest" secret: actions.sopsSecrets.output.DOCKERHUB_TOKEN.contents - }] + } actions: {