Skip to content

Commit ed0f2f4

Browse files
committed
Anonymous auth for openfaasltd images
Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
1 parent bb14dab commit ed0f2f4

File tree

2 files changed

+124
-11
lines changed

2 files changed

+124
-11
lines changed

cmd/oci/install.go

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/alexellis/arkade/pkg/archive"
1313
"github.com/alexellis/arkade/pkg/env"
14+
"github.com/google/go-containerregistry/pkg/authn"
1415
"github.com/google/go-containerregistry/pkg/crane"
1516
v1 "github.com/google/go-containerregistry/pkg/v1"
1617
"github.com/spf13/cobra"
@@ -79,16 +80,7 @@ OCI image.`,
7980
installPath, _ = cmd.Flags().GetString("path")
8081
}
8182

82-
switch imageName {
83-
case "vmmeter":
84-
imageName = "ghcr.io/openfaasltd/vmmeter"
85-
case "slicer":
86-
imageName = "ghcr.io/openfaasltd/slicer"
87-
case "superterm":
88-
imageName = "ghcr.io/openfaasltd/superterm"
89-
case "k3sup-pro":
90-
imageName = "ghcr.io/openfaasltd/k3sup-pro"
91-
}
83+
imageName, forceAnonymousAuth := resolveShortcutImage(imageName)
9284

9385
if !strings.Contains(imageName, ":") {
9486
imageName = imageName + ":" + version
@@ -133,7 +125,7 @@ OCI image.`,
133125

134126
downloadArch, downloadOS := getDownloadArch(clientArch, clientOS)
135127

136-
img, err = crane.Pull(imageName, crane.WithPlatform(&v1.Platform{Architecture: downloadArch, OS: downloadOS}))
128+
img, err = crane.Pull(imageName, buildPullOptions(&v1.Platform{Architecture: downloadArch, OS: downloadOS}, forceAnonymousAuth)...)
137129
if err != nil {
138130
return fmt.Errorf("pulling %s: %w", imageName, err)
139131
}
@@ -160,6 +152,33 @@ OCI image.`,
160152
return command
161153
}
162154

155+
func resolveShortcutImage(imageName string) (string, bool) {
156+
switch imageName {
157+
case "vmmeter":
158+
return "ghcr.io/openfaasltd/vmmeter", true
159+
case "slicer":
160+
return "ghcr.io/openfaasltd/slicer", true
161+
case "superterm":
162+
return "ghcr.io/openfaasltd/superterm", true
163+
case "k3sup-pro":
164+
return "ghcr.io/openfaasltd/k3sup-pro", true
165+
default:
166+
return imageName, false
167+
}
168+
}
169+
170+
func buildPullOptions(platform *v1.Platform, forceAnonymousAuth bool) []crane.Option {
171+
options := []crane.Option{
172+
crane.WithPlatform(platform),
173+
}
174+
175+
if forceAnonymousAuth {
176+
options = append(options, crane.WithAuth(authn.Anonymous))
177+
}
178+
179+
return options
180+
}
181+
163182
func getDownloadArch(clientArch, clientOS string) (arch string, os string) {
164183
downloadArch := strings.ToLower(clientArch)
165184
downloadOS := strings.ToLower(clientOS)

cmd/oci/install_test.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// Copyright (c) arkade author(s) 2022. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
package oci
5+
6+
import (
7+
"reflect"
8+
"runtime"
9+
"strings"
10+
"testing"
11+
12+
"github.com/google/go-containerregistry/pkg/crane"
13+
v1 "github.com/google/go-containerregistry/pkg/v1"
14+
)
15+
16+
func TestResolveShortcutImage(t *testing.T) {
17+
tests := []struct {
18+
name string
19+
input string
20+
wantImage string
21+
wantAnonymousAuth bool
22+
}{
23+
{
24+
name: "vmmeter shortcut uses anonymous auth",
25+
input: "vmmeter",
26+
wantImage: "ghcr.io/openfaasltd/vmmeter",
27+
wantAnonymousAuth: true,
28+
},
29+
{
30+
name: "slicer shortcut uses anonymous auth",
31+
input: "slicer",
32+
wantImage: "ghcr.io/openfaasltd/slicer",
33+
wantAnonymousAuth: true,
34+
},
35+
{
36+
name: "superterm shortcut uses anonymous auth",
37+
input: "superterm",
38+
wantImage: "ghcr.io/openfaasltd/superterm",
39+
wantAnonymousAuth: true,
40+
},
41+
{
42+
name: "k3sup-pro shortcut uses anonymous auth",
43+
input: "k3sup-pro",
44+
wantImage: "ghcr.io/openfaasltd/k3sup-pro",
45+
wantAnonymousAuth: true,
46+
},
47+
{
48+
name: "fully qualified image is unchanged",
49+
input: "ghcr.io/openfaasltd/custom-tool",
50+
wantImage: "ghcr.io/openfaasltd/custom-tool",
51+
wantAnonymousAuth: false,
52+
},
53+
}
54+
55+
for _, tc := range tests {
56+
t.Run(tc.name, func(t *testing.T) {
57+
gotImage, gotAnonymousAuth := resolveShortcutImage(tc.input)
58+
if gotImage != tc.wantImage {
59+
t.Fatalf("want image %q, got %q", tc.wantImage, gotImage)
60+
}
61+
if gotAnonymousAuth != tc.wantAnonymousAuth {
62+
t.Fatalf("want anonymous auth %v, got %v", tc.wantAnonymousAuth, gotAnonymousAuth)
63+
}
64+
})
65+
}
66+
}
67+
68+
func TestBuildPullOptions(t *testing.T) {
69+
platform := &v1.Platform{Architecture: "amd64", OS: "linux"}
70+
71+
t.Run("default uses keychain auth", func(t *testing.T) {
72+
opts := crane.GetOptions(buildPullOptions(platform, false)...)
73+
if opts.Platform != platform {
74+
t.Fatalf("want platform %p, got %p", platform, opts.Platform)
75+
}
76+
77+
authOptionName := runtime.FuncForPC(reflect.ValueOf(opts.Remote[0]).Pointer()).Name()
78+
if !strings.Contains(authOptionName, "WithAuthFromKeychain") {
79+
t.Fatalf("want keychain auth option, got %q", authOptionName)
80+
}
81+
})
82+
83+
t.Run("anonymous auth overrides keychain", func(t *testing.T) {
84+
opts := crane.GetOptions(buildPullOptions(platform, true)...)
85+
if opts.Platform != platform {
86+
t.Fatalf("want platform %p, got %p", platform, opts.Platform)
87+
}
88+
89+
authOptionName := runtime.FuncForPC(reflect.ValueOf(opts.Remote[0]).Pointer()).Name()
90+
if !strings.Contains(authOptionName, "WithAuth") || strings.Contains(authOptionName, "WithAuthFromKeychain") {
91+
t.Fatalf("want anonymous auth option, got %q", authOptionName)
92+
}
93+
})
94+
}

0 commit comments

Comments
 (0)