Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit db3d126

Browse files
Merge pull request #488 from ijc/APP-28-registry-auth-for-private-images
Share registry auth with invocation image
2 parents 4f41507 + 1a1db15 commit db3d126

File tree

24 files changed

+441
-148
lines changed

24 files changed

+441
-148
lines changed

Gopkg.lock

Lines changed: 5 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gopkg.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ required = ["github.com/wadey/gocovmerge"]
4040
name = "github.com/docker/cli"
4141
branch = "master"
4242

43-
# Waiting for https://github.com/deislabs/duffle/pull/664 to be merged
43+
# Waiting for https://github.com/deislabs/duffle/pull/682 to be merged
4444
[[override]]
4545
name = "github.com/deislabs/duffle"
46-
source = "github.com/silvin-lubecki/duffle"
47-
branch = "docker-app"
46+
source = "github.com/ijc/duffle"
47+
branch = "set-merge"
4848

4949
[[constraint]]
5050
name = "github.com/sirupsen/logrus"

cmd/cnab-run/env.go

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package main
22

33
import (
4+
"encoding/json"
5+
"io/ioutil"
46
"os"
57

8+
"github.com/docker/app/internal"
69
"github.com/docker/cli/cli/command"
710
cliconfig "github.com/docker/cli/cli/config"
811
"github.com/docker/cli/cli/context/docker"
@@ -11,10 +14,6 @@ import (
1114
cliflags "github.com/docker/cli/cli/flags"
1215
)
1316

14-
const (
15-
fileDockerContext = "/cnab/app/context.dockercontext"
16-
)
17-
1817
var storeConfig = contextstore.NewConfig(
1918
func() interface{} { return &command.DockerContext{} },
2019
contextstore.EndpointTypeGetter(docker.DockerEndpoint, func() interface{} { return &docker.EndpointMeta{} }),
@@ -23,7 +22,7 @@ var storeConfig = contextstore.NewConfig(
2322

2423
func setupDockerContext() (command.Cli, error) {
2524
s := contextstore.New(cliconfig.ContextStoreDir(), storeConfig)
26-
f, err := os.Open(fileDockerContext)
25+
f, err := os.Open(internal.CredentialDockerContextPath)
2726
if err != nil {
2827
return nil, err
2928
}
@@ -35,9 +34,23 @@ func setupDockerContext() (command.Cli, error) {
3534
if err != nil {
3635
return nil, err
3736
}
38-
return cli, cli.Initialize(&cliflags.ClientOptions{
37+
if err := cli.Initialize(&cliflags.ClientOptions{
3938
Common: &cliflags.CommonOptions{
4039
Context: "cnab",
4140
},
42-
})
41+
}); err != nil {
42+
return nil, err
43+
}
44+
authConfigsJSON, err := ioutil.ReadFile(internal.CredentialRegistryPath)
45+
if err != nil {
46+
return nil, err
47+
}
48+
49+
configFile := cli.ConfigFile()
50+
51+
if err := json.Unmarshal(authConfigsJSON, &configFile.AuthConfigs); err != nil {
52+
return nil, err
53+
}
54+
55+
return cli, nil
4356
}

cmd/cnab-run/install.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/json"
55
"io/ioutil"
66
"os"
7+
"strconv"
78

89
"github.com/deislabs/duffle/pkg/bundle"
910
"github.com/docker/app/internal"
@@ -52,11 +53,15 @@ func installAction(instanceName string) error {
5253
if err := os.Chdir(app.Path); err != nil {
5354
return err
5455
}
56+
sendRegistryAuth, err := strconv.ParseBool(os.Getenv("DOCKER_SHARE_REGISTRY_CREDS"))
57+
if err != nil {
58+
return err
59+
}
5560
// todo: pass registry auth to invocation image
5661
return stack.RunDeploy(cli, getFlagset(orchestrator), rendered, orchestrator, options.Deploy{
5762
Namespace: instanceName,
5863
ResolveImage: swarm.ResolveImageAlways,
59-
SendRegistryAuth: false,
64+
SendRegistryAuth: sendRegistryAuth,
6065
})
6166
}
6267

cmd/cnab-run/main.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ type cnabAction func(string) error
1212

1313
var (
1414
cnabActions = map[string]cnabAction{
15-
"install": installAction,
16-
"upgrade": installAction,
17-
"uninstall": uninstallAction,
18-
internal.Namespace + "status": statusAction,
19-
internal.Namespace + "inspect": inspectAction,
20-
internal.Namespace + "render": renderAction,
15+
"install": installAction,
16+
"upgrade": installAction, // upgrade is implemented as reinstall.
17+
"uninstall": uninstallAction,
18+
internal.ActionStatusName: statusAction,
19+
internal.ActionInspectName: inspectAction,
20+
internal.ActionRenderName: renderAction,
2121
}
2222
)
2323

e2e/testdata/simple-bundle.json.golden

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,16 @@
106106
"com.docker.app.render"
107107
]
108108
},
109+
"com.docker.app.share-registry-creds": {
110+
"type": "bool",
111+
"defaultValue": false,
112+
"metadata": {
113+
"description": "Share registry credentials with the invocation image"
114+
},
115+
"destination": {
116+
"env": "DOCKER_SHARE_REGISTRY_CREDS"
117+
}
118+
},
109119
"static_subdir": {
110120
"type": "string",
111121
"defaultValue": "data/static",
@@ -122,6 +132,9 @@
122132
}
123133
},
124134
"credentials": {
135+
"com.docker.app.registry-creds": {
136+
"path": "/cnab/app/registry-creds.json"
137+
},
125138
"docker.context": {
126139
"path": "/cnab/app/context.dockercontext"
127140
}

examples/cnab-simple/bundle.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
}
2323
},
2424
"parameters": {
25-
"docker.kubernetes-namespace": {
25+
"com.docker.app.kubernetes-namespace": {
2626
"type": "string",
2727
"defaultValue": "",
2828
"required": false,
@@ -34,7 +34,7 @@
3434
"env": "DOCKER_KUBERNETES_NAMESPACE"
3535
}
3636
},
37-
"docker.orchestrator": {
37+
"com.docker.app.orchestrator": {
3838
"type": "string",
3939
"defaultValue": "",
4040
"allowedValues": [
@@ -88,4 +88,4 @@
8888
"env": ""
8989
}
9090
}
91-
}
91+
}

internal/commands/cnab.go

Lines changed: 81 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package commands
22

33
import (
44
"bytes"
5+
"context"
6+
"encoding/json"
57
"fmt"
68
"io"
79
"io/ioutil"
@@ -23,8 +25,10 @@ import (
2325
"github.com/docker/cli/cli/context/docker"
2426
"github.com/docker/cli/cli/context/store"
2527
"github.com/docker/distribution/reference"
28+
"github.com/docker/docker/api/types"
2629
"github.com/docker/docker/api/types/container"
2730
"github.com/docker/docker/api/types/mount"
31+
"github.com/docker/docker/registry"
2832
"github.com/pkg/errors"
2933
)
3034

@@ -35,41 +39,91 @@ type bindMount struct {
3539

3640
const defaultSocketPath string = "/var/run/docker.sock"
3741

38-
func prepareCredentialSet(contextName string, contextStore store.Store, b *bundle.Bundle, namedCredentialsets []string) (map[string]string, error) {
42+
type credentialSetOpt func(b *bundle.Bundle, creds credentials.Set) error
43+
44+
func addNamedCredentialSets(namedCredentialsets []string) credentialSetOpt {
45+
return func(_ *bundle.Bundle, creds credentials.Set) error {
46+
for _, file := range namedCredentialsets {
47+
if _, err := os.Stat(file); err != nil {
48+
file = filepath.Join(duffleHome().Credentials(), file+".yaml")
49+
}
50+
c, err := credentials.Load(file)
51+
if err != nil {
52+
return err
53+
}
54+
values, err := c.Resolve()
55+
if err != nil {
56+
return err
57+
}
58+
if err := creds.Merge(values); err != nil {
59+
return err
60+
}
61+
}
62+
return nil
63+
}
64+
}
65+
66+
func addDockerCredentials(contextName string, contextStore store.Store) credentialSetOpt {
3967
// docker desktop contexts require some rewriting for being used within a container
4068
contextStore = dockerDesktopAwareStore{Store: contextStore}
41-
creds := map[string]string{}
42-
for _, file := range namedCredentialsets {
43-
if _, err := os.Stat(file); err != nil {
44-
file = filepath.Join(duffleHome().Credentials(), file+".yaml")
45-
}
46-
c, err := credentials.Load(file)
47-
if err != nil {
48-
return nil, err
69+
return func(_ *bundle.Bundle, creds credentials.Set) error {
70+
if contextName != "" {
71+
data, err := ioutil.ReadAll(store.Export(contextName, contextStore))
72+
if err != nil {
73+
return err
74+
}
75+
creds[internal.CredentialDockerContextName] = string(data)
4976
}
50-
values, err := c.Resolve()
51-
if err != nil {
52-
return nil, err
77+
return nil
78+
}
79+
}
80+
81+
func addRegistryCredentials(shouldPopulate bool, dockerCli command.Cli) credentialSetOpt {
82+
return func(b *bundle.Bundle, creds credentials.Set) error {
83+
if _, ok := b.Credentials[internal.CredentialRegistryName]; !ok {
84+
return nil
5385
}
54-
for k, v := range values {
55-
if _, ok := creds[k]; ok {
56-
return nil, fmt.Errorf("ambiguous credential resolution: %q is present in multiple credential sets", k)
86+
87+
registryCreds := map[string]types.AuthConfig{}
88+
if shouldPopulate {
89+
for _, img := range b.Images {
90+
named, err := reference.ParseNormalizedNamed(img.Image)
91+
if err != nil {
92+
return err
93+
}
94+
info, err := registry.ParseRepositoryInfo(named)
95+
if err != nil {
96+
return err
97+
}
98+
key := registry.GetAuthConfigKey(info.Index)
99+
if _, ok := registryCreds[key]; !ok {
100+
registryCreds[key] = command.ResolveAuthConfig(context.Background(), dockerCli, info.Index)
101+
}
57102
}
58-
creds[k] = v
59103
}
60-
}
61-
if contextName != "" {
62-
data, err := ioutil.ReadAll(store.Export(contextName, contextStore))
104+
registryCredsJSON, err := json.Marshal(registryCreds)
63105
if err != nil {
106+
return err
107+
}
108+
creds[internal.CredentialRegistryName] = string(registryCredsJSON)
109+
return nil
110+
}
111+
}
112+
113+
func prepareCredentialSet(b *bundle.Bundle, opts ...credentialSetOpt) (map[string]string, error) {
114+
creds := map[string]string{}
115+
for _, op := range opts {
116+
if err := op(b, creds); err != nil {
64117
return nil, err
65118
}
66-
creds["docker.context"] = string(data)
67119
}
68-
_, requiresDockerContext := b.Credentials["docker.context"]
69-
_, hasDockerContext := creds["docker.context"]
120+
121+
_, requiresDockerContext := b.Credentials[internal.CredentialDockerContextName]
122+
_, hasDockerContext := creds[internal.CredentialDockerContextName]
70123
if requiresDockerContext && !hasDockerContext {
71124
return nil, errors.New("no target context specified. Use --target-context= or DOCKER_TARGET_CONTEXT= to define it")
72125
}
126+
73127
return creds, nil
74128
}
75129

@@ -199,7 +253,7 @@ func resolveBundle(dockerCli command.Cli, name string, pullRef bool, insecureReg
199253

200254
func requiredClaimBindMount(c claim.Claim, targetContextName string, dockerCli command.Cli) (bindMount, error) {
201255
var specifiedOrchestrator string
202-
if rawOrchestrator, ok := c.Parameters["docker.orchestrator"]; ok {
256+
if rawOrchestrator, ok := c.Parameters[internal.ParameterOrchestratorName]; ok {
203257
specifiedOrchestrator = rawOrchestrator.(string)
204258
}
205259

@@ -253,7 +307,7 @@ func isDockerHostLocal(host string) bool {
253307
func prepareCustomAction(actionName string, dockerCli command.Cli, appname string, stdout io.Writer,
254308
registryOpts registryOptions, pullOpts pullOptions, paramsOpts parametersOptions) (*action.RunCustom, *claim.Claim, *bytes.Buffer, error) {
255309

256-
c, err := claim.New(actionName)
310+
c, err := claim.New("custom-action")
257311
if err != nil {
258312
return nil, nil, nil, err
259313
}
@@ -267,17 +321,15 @@ func prepareCustomAction(actionName string, dockerCli command.Cli, appname strin
267321
}
268322
c.Bundle = bundle
269323

270-
parameters, err := mergeBundleParameters(c.Bundle,
324+
if err := mergeBundleParameters(c,
271325
withFileParameters(paramsOpts.parametersFiles),
272326
withCommandLineParameters(paramsOpts.overrides),
273-
)
274-
if err != nil {
327+
); err != nil {
275328
return nil, nil, nil, err
276329
}
277-
c.Parameters = parameters
278330

279331
a := &action.RunCustom{
280-
Action: internal.Namespace + actionName,
332+
Action: actionName,
281333
Driver: driverImpl,
282334
}
283335
return a, c, errBuf, nil

0 commit comments

Comments
 (0)