Skip to content

Commit 22f1793

Browse files
author
Miguel Martínez Triviño
authored
feat: container keychains exclusion (#138)
Signed-off-by: Miguel Martinez Trivino <[email protected]>
1 parent 2f83928 commit 22f1793

File tree

4 files changed

+43
-18
lines changed

4 files changed

+43
-18
lines changed

cmd/chart.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,16 @@ func moveChart(cmd *cobra.Command, args []string) error {
112112
Source: mover.Source{
113113
Chart: mover.ChartSpec{},
114114
ImageHintsFile: imagePatternsFile,
115+
// Use local keychain for authentication
116+
Containers: mover.Containers{UseDefaultLocalKeychain: true},
115117
},
116118
Target: mover.Target{
117-
Chart: mover.ChartSpec{},
118-
Rules: *targetRewriteRules,
119+
Chart: mover.ChartSpec{},
120+
Rules: *targetRewriteRules,
121+
Containers: mover.Containers{UseDefaultLocalKeychain: true},
119122
},
120123
}
124+
121125
inputChartPath := args[0]
122126
if mover.IsIntermediateBundle(inputChartPath) {
123127
cmd.Println("Intermediate bundle provided")

pkg/mover/auth.go

+14-3
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ import "github.com/google/go-containerregistry/pkg/authn"
1010
// See https://pkg.go.dev/github.com/google/go-containerregistry/pkg/authn#Keychain
1111
//
1212
// Returns a custom credentials authn.Authenticator if the given resource
13-
// RegistryStr() matches the Repository, otherwise it falls back to the default
14-
// KeyChain which may include local docker credentials.
13+
// RegistryStr() matches the Repository, otherwise it returns annonymous access
1514
func (repo ContainerRepository) Resolve(resource authn.Resource) (authn.Authenticator, error) {
1615
if repo.Server == resource.RegistryStr() {
1716
return repo, nil
1817
}
19-
return authn.DefaultKeychain.Resolve(resource)
18+
19+
// if no credentials are provided we return annon authentication
20+
return authn.Anonymous, nil
2021
}
2122

2223
// Authorization implements an authn.Authenticator
@@ -27,3 +28,13 @@ func (repo ContainerRepository) Resolve(resource authn.Resource) (authn.Authenti
2728
func (repo ContainerRepository) Authorization() (*authn.AuthConfig, error) {
2829
return &authn.AuthConfig{Username: repo.Username, Password: repo.Password}, nil
2930
}
31+
32+
// Define a container images keychain based on the settings provided via the containers struct
33+
// If useDefaultKeychain is set, use config/docker.json otherwise load the provided creds (if any)
34+
func getContainersKeychain(c Containers) authn.Keychain {
35+
if c.UseDefaultLocalKeychain {
36+
return authn.DefaultKeychain
37+
}
38+
39+
return c.ContainerRepository
40+
}

pkg/mover/chart.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func (nl noLogger) Println(i ...interface{}) {}
7676
// DefaultLogger to stdout
7777
var DefaultLogger Logger = defaultLogger{}
7878

79-
// DefaultNoLogger swallows all logs
79+
// NoLogger swallows all logs
8080
var NoLogger Logger = noLogger{}
8181

8282
// ChartMetadata exposes metadata about the Helm Chart to be relocated
@@ -103,6 +103,9 @@ type ContainerRepository struct {
103103
// Containers is the section for private repository definition
104104
type Containers struct {
105105
ContainerRepository
106+
// Use local keychain in the system (config/docker.json)
107+
// This is useful to offer a CLI experience similar to docker
108+
UseDefaultLocalKeychain bool
106109
}
107110

108111
// ChartSpec of possible chart inputs or outputs
@@ -151,13 +154,11 @@ type ChartMover struct {
151154
// NewChartMover creates a ChartMover to relocate a chart following the given
152155
// imagePatters and rules.
153156
func NewChartMover(req *ChartMoveRequest, opts ...Option) (*ChartMover, error) {
154-
sourceAuth := req.Source.Containers.ContainerRepository
155-
targetAuth := req.Target.Containers.ContainerRepository
156157
cm := &ChartMover{
157158
logger: defaultLogger{},
158159
retries: DefaultRetries,
159-
sourceContainerRegistry: internal.NewContainerRegistryClient(sourceAuth),
160-
targetContainerRegistry: internal.NewContainerRegistryClient(targetAuth),
160+
sourceContainerRegistry: internal.NewContainerRegistryClient(getContainersKeychain(req.Source.Containers)),
161+
targetContainerRegistry: internal.NewContainerRegistryClient(getContainersKeychain(req.Target.Containers)),
161162
}
162163

163164
if err := validateTarget(&req.Target); err != nil {

pkg/mover/registry_test.go

+17-8
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ func dockerLogout(t *testing.T, domain string) {
5858
dockerLogin(t, domain, "", "")
5959
}
6060

61-
func NewMoveRequest(chartPath, hints, target, targetRegistry, targetPrefix string) *mover.ChartMoveRequest {
62-
return &mover.ChartMoveRequest{
61+
func NewMoveRequest(chartPath, hints, target, targetRegistry, targetPrefix string, useLocalKeychain bool) *mover.ChartMoveRequest {
62+
req := &mover.ChartMoveRequest{
6363
Source: mover.Source{
6464
// The Helm Chart can be provided in either tarball or directory form
6565
Chart: mover.ChartSpec{Local: &mover.LocalChart{Path: chartPath}},
@@ -76,6 +76,13 @@ func NewMoveRequest(chartPath, hints, target, targetRegistry, targetPrefix strin
7676
},
7777
},
7878
}
79+
80+
if useLocalKeychain {
81+
req.Source.Containers = mover.Containers{UseDefaultLocalKeychain: true}
82+
req.Target.Containers = mover.Containers{UseDefaultLocalKeychain: true}
83+
}
84+
85+
return req
7986
}
8087

8188
func NewSaveRequest(chartPath, hints, bundle string) *mover.ChartMoveRequest {
@@ -85,6 +92,7 @@ func NewSaveRequest(chartPath, hints, bundle string) *mover.ChartMoveRequest {
8592
Chart: mover.ChartSpec{Local: &mover.LocalChart{Path: chartPath}},
8693
// path to file containing rules such as // {{.image.registry}}:{{.image.tag}}
8794
ImageHintsFile: hints,
95+
Containers: mover.Containers{UseDefaultLocalKeychain: true},
8896
},
8997
Target: mover.Target{
9098
Chart: mover.ChartSpec{IntermediateBundle: &mover.IntermediateBundle{Path: bundle}},
@@ -99,7 +107,8 @@ func NewLoadRequest(bundle, target, targetRegistry, targetPrefix string) *mover.
99107
Chart: mover.ChartSpec{IntermediateBundle: &mover.IntermediateBundle{Path: bundle}},
100108
},
101109
Target: mover.Target{
102-
Chart: mover.ChartSpec{Local: &mover.LocalChart{Path: target}},
110+
Chart: mover.ChartSpec{Local: &mover.LocalChart{Path: target}},
111+
Containers: mover.Containers{UseDefaultLocalKeychain: true},
103112
// Where to push and how to rewrite the found images
104113
// i.e docker.io/bitnami/mariadb => myregistry.com/myteam/mariadb
105114
Rules: mover.RewriteRules{
@@ -144,7 +153,7 @@ func TestRegistryDockerCredentials(t *testing.T) {
144153
params := loadParamsFromEnv()
145154
prepareDockerCA(t, params.certFile)
146155
dockerLogin(t, params.domain, params.user, params.passwd)
147-
got := relok8s(t, NewMoveRequest(TestChart, Hints, Target, params.domain, Prefix))
156+
got := relok8s(t, NewMoveRequest(TestChart, Hints, Target, params.domain, Prefix, true))
148157
var want error
149158
if got != want {
150159
t.Fatalf("want error %v got %v", want, got)
@@ -156,7 +165,7 @@ func TestRegistryCustomCredentials(t *testing.T) {
156165
params := loadParamsFromEnv()
157166
prepareDockerCA(t, params.certFile)
158167
dockerLogout(t, params.domain)
159-
req := NewMoveRequest(TestChart, Hints, Target, params.domain, Prefix)
168+
req := NewMoveRequest(TestChart, Hints, Target, params.domain, Prefix, false)
160169
req.Target.Containers.ContainerRepository = repo(params.domain, params.user, params.passwd)
161170
got := relok8s(t, req)
162171
var want error
@@ -170,7 +179,7 @@ func TestRegistryBadDockerCredentials(t *testing.T) {
170179
params := loadParamsFromEnv()
171180
prepareDockerCA(t, params.certFile)
172181
dockerLogin(t, params.domain, BadUser, BadPasswd)
173-
got := relok8s(t, NewMoveRequest(TestChart, Hints, Target, params.domain, Prefix))
182+
got := relok8s(t, NewMoveRequest(TestChart, Hints, Target, params.domain, Prefix, true))
174183
// retry.Error is incompatible with errors package, it cannot be unwrapped
175184
_, ok := got.(retry.Error)
176185
if !ok {
@@ -183,7 +192,7 @@ func TestRegistryBadCustomCredentials(t *testing.T) {
183192
params := loadParamsFromEnv()
184193
prepareDockerCA(t, params.certFile)
185194
dockerLogout(t, params.domain)
186-
req := NewMoveRequest(TestChart, Hints, Target, params.domain, Prefix)
195+
req := NewMoveRequest(TestChart, Hints, Target, params.domain, Prefix, false)
187196
req.Target.Containers.ContainerRepository = repo(params.domain, BadUser, BadPasswd)
188197
got := relok8s(t, req)
189198
// retry.Error is incompatible with errors package, it cannot be unwrapped
@@ -198,7 +207,7 @@ func TestMovePerformance(t *testing.T) {
198207
params := loadParamsFromEnv()
199208
prepareDockerCA(t, params.certFile)
200209
dockerLogin(t, params.domain, params.user, params.passwd)
201-
got := relok8s(t, NewMoveRequest(ComplexChart, ComplexHints, Target, params.domain, Prefix))
210+
got := relok8s(t, NewMoveRequest(ComplexChart, ComplexHints, Target, params.domain, Prefix, true))
202211
var want error
203212
if got != want {
204213
t.Fatalf("want error %v got %v", want, got)

0 commit comments

Comments
 (0)