Skip to content

Commit b215074

Browse files
authored
Clean up auth for host builder (knative#3298)
Signed-off-by: Matej Vašek <[email protected]>
1 parent 4ef5654 commit b215074

File tree

9 files changed

+43
-151
lines changed

9 files changed

+43
-151
lines changed

cmd/build.go

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package cmd
22

33
import (
4-
"context"
54
"errors"
65
"fmt"
76
"strings"
@@ -214,8 +213,6 @@ For more options, run 'func build --help'`, err)
214213
}
215214
f = cfg.Configure(f) // Returns an f updated with values from the config (flags, envs, etc)
216215

217-
cmd.SetContext(cfg.WithValues(cmd.Context())) // Some optional settings are passed via context
218-
219216
// Client
220217
clientOptions, err := cfg.clientOptions()
221218
if err != nil {
@@ -245,16 +242,6 @@ For more options, run 'func build --help'`, err)
245242
return f.Stamp()
246243
}
247244

248-
// WithValues returns a context populated with values from the build config
249-
// which are provided to the system via the context.
250-
func (c buildConfig) WithValues(ctx context.Context) context.Context {
251-
// Push
252-
ctx = context.WithValue(ctx, fn.PushUsernameKey{}, c.Username)
253-
ctx = context.WithValue(ctx, fn.PushPasswordKey{}, c.Password)
254-
ctx = context.WithValue(ctx, fn.PushTokenKey{}, c.Token)
255-
return ctx
256-
}
257-
258245
type buildConfig struct {
259246
// Globals (builder, confirm, registry, verbose)
260247
config.Global

cmd/build_test.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,6 @@ func TestBuild_RegistryOrImageRequired(t *testing.T) {
8989
testRegistryOrImageRequired(NewBuildCmd, t)
9090
}
9191

92-
// TestBuild_Authentication ensures that Token and Username/Password auth
93-
// propagate to pushers which support them.
94-
func TestBuild_Authentication(t *testing.T) {
95-
testAuthentication(NewBuildCmd, t)
96-
}
97-
9892
// TestBuild_BaseImage ensures that base image is used only with the right
9993
// builders and propagates into f.Build.BaseImage
10094
func TestBuild_BaseImage(t *testing.T) {

cmd/client.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"net/http"
66
"os"
77

8+
"github.com/ory/viper"
9+
810
"knative.dev/func/cmd/prompt"
911
"knative.dev/func/pkg/buildpacks"
1012
"knative.dev/func/pkg/config"
@@ -106,6 +108,23 @@ func newCredentialsProvider(configPath string, t http.RoundTripper, authFilePath
106108
additionalLoaders := append(k8s.GetOpenShiftDockerCredentialLoaders(), k8s.GetGoogleCredentialLoader()...)
107109
additionalLoaders = append(additionalLoaders, k8s.GetECRCredentialLoader()...)
108110
additionalLoaders = append(additionalLoaders, k8s.GetACRCredentialLoader()...)
111+
112+
additionalLoaders = append(additionalLoaders,
113+
func(registry string) (oci.Credentials, error) {
114+
uname := viper.GetString("username")
115+
passw := viper.GetString("password")
116+
token := viper.GetString("token")
117+
if (uname != "" && passw != "") || token != "" {
118+
return oci.Credentials{
119+
Username: uname,
120+
Password: passw,
121+
Token: token,
122+
}, nil
123+
}
124+
return oci.Credentials{}, creds.ErrCredentialsNotFound
125+
},
126+
)
127+
109128
options := []creds.Opt{
110129
creds.WithPromptForCredentials(prompt.NewPromptForCredentials(os.Stdin, os.Stdout, os.Stderr)),
111130
creds.WithPromptForCredentialStore(prompt.NewPromptForCredentialStore()),

cmd/deploy.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,6 @@ For more options, run 'func deploy --help'`, err)
404404
if f, err = cfg.Configure(f); err != nil { // Updates f with deploy cfg
405405
return
406406
}
407-
cmd.SetContext(cfg.WithValues(cmd.Context())) // Some optional settings are passed via context
408407

409408
changingNamespace := func(f fn.Function) bool {
410409
// We're changing namespace if:

cmd/deploy_test.go

Lines changed: 0 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,74 +1501,6 @@ func testRegistryOrImageRequired(cmdFn commandConstructor, t *testing.T) {
15011501
}
15021502
}
15031503

1504-
// TestDeploy_Authentication ensures that Token and Username/Password auth
1505-
// propagate their values to pushers which support them.
1506-
func TestDeploy_Authentication(t *testing.T) {
1507-
testAuthentication(NewDeployCmd, t)
1508-
}
1509-
1510-
func testAuthentication(cmdFn commandConstructor, t *testing.T) {
1511-
// This test is currently focused on ensuring the flags for
1512-
// explicit credentials (bearer token and username/password) are respected
1513-
// and propagated to pushers which support this authentication method.
1514-
// Integration tests must be used to ensure correct integration between
1515-
// the system and credential helpers (Docker, ecs, acs)
1516-
t.Helper()
1517-
1518-
root := FromTempDirectory(t)
1519-
_, err := fn.New().Init(fn.Function{Runtime: "go", Root: root, Registry: TestRegistry})
1520-
if err != nil {
1521-
t.Fatal(err)
1522-
}
1523-
1524-
var (
1525-
testUser = "alice"
1526-
testPass = "123"
1527-
testToken = "example.jwt.token"
1528-
)
1529-
1530-
// Basic Auth: username/password
1531-
// -----------------------------
1532-
pusher := mock.NewPusher()
1533-
pusher.PushFn = func(ctx context.Context, _ fn.Function) (string, error) {
1534-
username, _ := ctx.Value(fn.PushUsernameKey{}).(string)
1535-
password, _ := ctx.Value(fn.PushPasswordKey{}).(string)
1536-
1537-
if username != testUser || password != testPass {
1538-
t.Fatalf("expected username %q, password %q. Got %q, %q", testUser, testPass, username, password)
1539-
}
1540-
1541-
return "", nil
1542-
}
1543-
1544-
cmd := cmdFn(NewTestClient(fn.WithPusher(pusher)))
1545-
cmd.SetArgs([]string{"--builder", "host", "--username", testUser, "--password", testPass})
1546-
if err := cmd.Execute(); err != nil {
1547-
t.Fatal(err)
1548-
}
1549-
1550-
// Basic Auth: token
1551-
// -----------------------------
1552-
pusher = mock.NewPusher()
1553-
pusher.PushFn = func(ctx context.Context, _ fn.Function) (string, error) {
1554-
token, _ := ctx.Value(fn.PushTokenKey{}).(string)
1555-
1556-
if token != testToken {
1557-
t.Fatalf("expected token %q, got %q", testToken, token)
1558-
}
1559-
1560-
return "", nil
1561-
}
1562-
1563-
cmd = cmdFn(NewTestClient(fn.WithPusher(pusher)))
1564-
1565-
cmd.SetArgs([]string{"--builder", "host", "--token", testToken})
1566-
if err := cmd.Execute(); err != nil {
1567-
t.Fatal(err)
1568-
}
1569-
1570-
}
1571-
15721504
// TestDeploy_RemoteBuildURLPermutations ensures that the remote, build and git-url flags
15731505
// are properly respected for all permutations, including empty.
15741506
func TestDeploy_RemoteBuildURLPermutations(t *testing.T) {

pkg/creds/credentials.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ func NewCredentialsProvider(configPath string, opts ...Opt) oci.CredentialsProvi
231231
return oci.Credentials{
232232
Username: creds.Username,
233233
Password: creds.Password,
234+
Token: creds.IdentityToken,
234235
}, nil
235236
})
236237
defaultCredentialLoaders = append(defaultCredentialLoaders,
@@ -247,6 +248,7 @@ func NewCredentialsProvider(configPath string, opts ...Opt) oci.CredentialsProvi
247248
return oci.Credentials{
248249
Username: creds.Username,
249250
Password: creds.Password,
251+
Token: creds.IdentityToken,
250252
}, nil
251253
})
252254
defaultCredentialLoaders = append(defaultCredentialLoaders,

pkg/functions/client.go

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -96,18 +96,6 @@ type Pusher interface {
9696
Push(ctx context.Context, f Function) (string, error)
9797
}
9898

99-
// PushUsernameKey is a type available for use to communicate a basic
100-
// authentication username to pushers which support this method.
101-
type PushUsernameKey struct{}
102-
103-
// PushPasswordKey is a type available for use as a context key for
104-
// providing a basic auth password to pushers which support this method.
105-
type PushPasswordKey struct{}
106-
107-
// PushTokenKey is a type available for use as a context key for providing a
108-
// token (for example a jwt bearer token) to pushers which support this method.
109-
type PushTokenKey struct{}
110-
11199
// Deployer of function source to running status.
112100
type Deployer interface {
113101
// Deploy a function of given name, using given backing image.

pkg/oci/pusher.go

Lines changed: 10 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414
v1 "github.com/google/go-containerregistry/pkg/v1"
1515
"github.com/google/go-containerregistry/pkg/v1/layout"
1616
"github.com/google/go-containerregistry/pkg/v1/remote"
17-
"github.com/pkg/errors"
1817
progress "github.com/schollz/progressbar/v3"
1918

2019
fn "knative.dev/func/pkg/functions"
@@ -23,6 +22,15 @@ import (
2322
type Credentials struct {
2423
Username string
2524
Password string
25+
Token string
26+
}
27+
28+
func (c Credentials) Authorization() (*authn.AuthConfig, error) {
29+
return &authn.AuthConfig{
30+
Username: c.Username,
31+
Password: c.Password,
32+
IdentityToken: c.Token,
33+
}, nil
2634
}
2735

2836
type CredentialsProvider func(ctx context.Context, image string) (Credentials, error)
@@ -35,8 +43,6 @@ type Pusher struct {
3543
credentialsProvider CredentialsProvider
3644

3745
Insecure bool
38-
Token string
39-
Username string
4046
Verbose bool
4147

4248
updates chan v1.Update
@@ -169,45 +175,8 @@ func (p *Pusher) writeIndex(ctx context.Context, ref name.Reference, ii v1.Image
169175
}
170176

171177
if !p.Anonymous {
172-
a, err := p.authOption(ctx, creds)
173-
if err != nil {
174-
return err
175-
}
176-
oo = append(oo, a)
178+
oo = append(oo, remote.WithAuth(creds))
177179
}
178180

179181
return remote.WriteIndex(ref, ii, oo...)
180182
}
181-
182-
// authOption selects an appropriate authentication option.
183-
// If user provided = basic auth (secret is password)
184-
// If only secret provided = bearer token auth
185-
// If neither are provided = creds from credentials provider
186-
// which performs the following in order:
187-
// - Default Keychain (docker and podman config files)
188-
// - Google Keychain
189-
// - TODO: ECR Amazon
190-
// - TODO: ACR Azure
191-
// - interactive prompt for username and password
192-
func (p *Pusher) authOption(ctx context.Context, creds Credentials) (remote.Option, error) {
193-
194-
// Basic Auth if provided
195-
username, _ := ctx.Value(fn.PushUsernameKey{}).(string)
196-
password, _ := ctx.Value(fn.PushPasswordKey{}).(string)
197-
token, _ := ctx.Value(fn.PushTokenKey{}).(string)
198-
if username != "" && token != "" {
199-
return nil, errors.New("only one of username/password or token authentication allowed. Received both a token and username")
200-
} else if token != "" {
201-
return remote.WithAuth(&authn.Bearer{Token: token}), nil
202-
} else if username != "" {
203-
return remote.WithAuth(&authn.Basic{Username: username, Password: password}), nil
204-
}
205-
206-
// Use provided credentials if available or prompt for them
207-
if creds.Username != "" && creds.Password != "" {
208-
return remote.WithAuth(&authn.Basic{Username: creds.Username, Password: creds.Password}), nil
209-
}
210-
211-
// Return anonymous auth when no credentials are provided (e.g., for localhost registries)
212-
return remote.WithAuth(authn.Anonymous), nil
213-
}

pkg/oci/pusher_test.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,21 @@ func TestPusher_BasicAuth(t *testing.T) {
123123
}
124124
defer server.Close()
125125

126+
pusher := NewPusher(false, false, verbose,
127+
WithCredentialsProvider(func(ctx context.Context, image string) (Credentials, error) {
128+
return Credentials{
129+
Username: username,
130+
Password: password,
131+
}, nil
132+
}),
133+
)
134+
126135
// Client
127136
// initialized with an OCI builder and pusher.
128137
client := fn.New(
129138
fn.WithBuilder(NewBuilder("", verbose)),
130-
fn.WithPusher(NewPusher(false, false, verbose)))
139+
fn.WithPusher(pusher),
140+
)
131141

132142
// Function
133143
// Built and tagged to push to the mock registry
@@ -144,15 +154,7 @@ func TestPusher_BasicAuth(t *testing.T) {
144154
t.Fatal(err)
145155
}
146156

147-
// Push
148-
// Enables optional basic authentication via the push context to use instead
149-
// of the default behavior of using the multi-auth chain of config files
150-
// and various known credentials managers.
151-
ctx := context.Background()
152-
ctx = context.WithValue(ctx, fn.PushUsernameKey{}, username)
153-
ctx = context.WithValue(ctx, fn.PushPasswordKey{}, password)
154-
155-
if _, _, err = client.Push(ctx, f); err != nil {
157+
if _, _, err = client.Push(context.Background(), f); err != nil {
156158
t.Fatal(err)
157159
}
158160

0 commit comments

Comments
 (0)