From 5edcf7f32041816b1d7363e068cc8ebd4acda4da Mon Sep 17 00:00:00 2001 From: Jason Hall Date: Sun, 2 Jun 2024 15:02:55 -0400 Subject: [PATCH] enable per-host auth (#281) * enable per-host auth Signed-off-by: Jason Hall * no log Signed-off-by: Jason Hall --------- Signed-off-by: Jason Hall --- pkg/apk/implementation.go | 9 ++++----- pkg/apk/implementation_test.go | 11 +++++++---- pkg/apk/index.go | 14 ++++++++------ pkg/apk/options.go | 12 ++++++++---- pkg/apk/repo.go | 10 ++++++---- pkg/apk/repo_test.go | 6 ++++-- 6 files changed, 37 insertions(+), 25 deletions(-) diff --git a/pkg/apk/implementation.go b/pkg/apk/implementation.go index 1c31098..c105a25 100644 --- a/pkg/apk/implementation.go +++ b/pkg/apk/implementation.go @@ -65,7 +65,7 @@ type APK struct { cache *cache ignoreSignatures bool noSignatureIndexes []string - user, pass string + auth map[string]auth // filename to owning package, last write wins installedFiles map[string]*Package @@ -94,8 +94,7 @@ func New(options ...Option) (*APK, error) { cache: opt.cache, noSignatureIndexes: opt.noSignatureIndexes, installedFiles: map[string]*Package{}, - user: opt.user, - pass: opt.pass, + auth: opt.auth, }, nil } @@ -414,7 +413,7 @@ func (a *APK) InitKeyring(ctx context.Context, keyFiles, extraKeyFiles []string) pass, _ := asURL.User.Password() req.SetBasicAuth(user, pass) req.URL.User = nil - } else if a.user != "" && a.pass != "" { + } else if a, ok := a.auth[asURL.Host]; ok && a.user != "" && a.pass != "" { req.SetBasicAuth(a.user, a.pass) } @@ -1053,7 +1052,7 @@ func (a *APK) FetchPackage(ctx context.Context, pkg InstallablePackage) (io.Read if err != nil { return nil, err } - if a.user != "" && a.pass != "" { + if a, ok := a.auth[asURL.Host]; ok && a.user != "" && a.pass != "" { req.SetBasicAuth(a.user, a.pass) } diff --git a/pkg/apk/implementation_test.go b/pkg/apk/implementation_test.go index 4c7b742..c6768f1 100644 --- a/pkg/apk/implementation_test.go +++ b/pkg/apk/implementation_test.go @@ -238,6 +238,7 @@ func TestInitKeyring(t *testing.T) { http.FileServer(http.Dir(testPrimaryPkgDir)).ServeHTTP(w, r) })) defer s.Close() + host := strings.TrimPrefix(s.URL, "http://") ctx := context.Background() @@ -246,7 +247,7 @@ func TestInitKeyring(t *testing.T) { err := src.MkdirAll("lib/apk/db", 0o755) require.NoError(t, err, "unable to mkdir /lib/apk/db") - a, err := New(WithFS(src), WithAuth(testUser, testPass)) + a, err := New(WithFS(src), WithAuth(host, testUser, testPass)) require.NoError(t, err, "unable to create APK") err = a.InitDB(ctx) require.NoError(t, err) @@ -261,7 +262,7 @@ func TestInitKeyring(t *testing.T) { err := src.MkdirAll("lib/apk/db", 0o755) require.NoError(t, err, "unable to mkdir /lib/apk/db") - a, err := New(WithFS(src), WithAuth("baduser", "badpass")) + a, err := New(WithFS(src), WithAuth(host, "baduser", "badpass")) require.NoError(t, err, "unable to create APK") err = a.InitDB(ctx) require.NoError(t, err) @@ -544,6 +545,7 @@ func TestAuth_good(t *testing.T) { http.FileServer(http.Dir(testPrimaryPkgDir)).ServeHTTP(w, r) })) defer s.Close() + host := strings.TrimPrefix(s.URL, "http://") repo := Repository{URI: s.URL} repoWithIndex := repo.WithIndex(&APKIndex{Packages: []*Package{&testPkg}}) @@ -554,7 +556,7 @@ func TestAuth_good(t *testing.T) { err := src.MkdirAll("lib/apk/db", 0o755) require.NoError(t, err, "unable to mkdir /lib/apk/db") - a, err := New(WithFS(src), WithAuth(testUser, testPass)) + a, err := New(WithFS(src), WithAuth(host, testUser, testPass)) require.NoError(t, err, "unable to create APK") err = a.InitDB(ctx) require.NoError(t, err) @@ -575,6 +577,7 @@ func TestAuth_bad(t *testing.T) { http.FileServer(http.Dir(testPrimaryPkgDir)).ServeHTTP(w, r) })) defer s.Close() + host := strings.TrimPrefix(s.URL, "http://") repo := Repository{URI: s.URL} repoWithIndex := repo.WithIndex(&APKIndex{Packages: []*Package{&testPkg}}) @@ -585,7 +588,7 @@ func TestAuth_bad(t *testing.T) { err := src.MkdirAll("lib/apk/db", 0o755) require.NoError(t, err, "unable to mkdir /lib/apk/db") - a, err := New(WithFS(src), WithAuth("baduser", "badpass")) + a, err := New(WithFS(src), WithAuth(host, "baduser", "badpass")) require.NoError(t, err, "unable to create APK") err = a.InitDB(ctx) require.NoError(t, err) diff --git a/pkg/apk/index.go b/pkg/apk/index.go index be18a2d..9417726 100644 --- a/pkg/apk/index.go +++ b/pkg/apk/index.go @@ -213,8 +213,8 @@ func getRepositoryIndex(ctx context.Context, u string, keys map[string][]byte, a user := asURL.User.Username() pass, _ := asURL.User.Password() req.SetBasicAuth(user, pass) - } else if opts.user != "" || opts.pass != "" { - req.SetBasicAuth(opts.user, opts.pass) + } else if a, ok := opts.auth[asURL.Host]; ok && a.user != "" || a.pass != "" { + req.SetBasicAuth(a.user, a.pass) } // This will return a body that retries requests using Range requests if Read() hits an error. @@ -320,7 +320,7 @@ type indexOpts struct { ignoreSignatures bool noSignatureIndexes []string httpClient *http.Client - user, pass string + auth map[string]auth } type IndexOption func(*indexOpts) @@ -342,9 +342,11 @@ func WithHTTPClient(c *http.Client) IndexOption { } } -func WithIndexAuth(user, pass string) IndexOption { +func WithIndexAuth(domain, user, pass string) IndexOption { return func(o *indexOpts) { - o.user = user - o.pass = pass + if o.auth == nil { + o.auth = make(map[string]auth) + } + o.auth[domain] = auth{user, pass} } } diff --git a/pkg/apk/options.go b/pkg/apk/options.go index 6fad7bf..7c07fb1 100644 --- a/pkg/apk/options.go +++ b/pkg/apk/options.go @@ -30,7 +30,7 @@ type opts struct { version string cache *cache noSignatureIndexes []string - user, pass string + auth map[string]auth } type Option func(*opts) error @@ -106,10 +106,14 @@ func WithNoSignatureIndexes(noSignatureIndex ...string) Option { } } -func WithAuth(user, pass string) Option { +type auth struct{ user, pass string } + +func WithAuth(domain, user, pass string) Option { return func(o *opts) error { - o.user = user - o.pass = pass + if o.auth == nil { + o.auth = make(map[string]auth) + } + o.auth[domain] = auth{user, pass} return nil } } diff --git a/pkg/apk/repo.go b/pkg/apk/repo.go index c276211..b70f1af 100644 --- a/pkg/apk/repo.go +++ b/pkg/apk/repo.go @@ -176,11 +176,13 @@ func (a *APK) GetRepositoryIndexes(ctx context.Context, ignoreSignatures bool) ( if a.cache != nil { httpClient = a.cache.client(httpClient, true) } - return GetRepositoryIndexes(ctx, repos, keys, arch, - WithIgnoreSignatures(ignoreSignatures), + opts := []IndexOption{WithIgnoreSignatures(ignoreSignatures), WithIgnoreSignatureForIndexes(a.noSignatureIndexes...), - WithHTTPClient(httpClient), - WithIndexAuth(a.user, a.pass)) + WithHTTPClient(httpClient)} + for domain, auth := range a.auth { + opts = append(opts, WithIndexAuth(domain, auth.user, auth.pass)) + } + return GetRepositoryIndexes(ctx, repos, keys, arch, opts...) } // PkgResolver resolves packages from a list of indexes. diff --git a/pkg/apk/repo_test.go b/pkg/apk/repo_test.go index 262f34d..bfca967 100644 --- a/pkg/apk/repo_test.go +++ b/pkg/apk/repo_test.go @@ -315,11 +315,12 @@ func TestIndexAuth_good(t *testing.T) { http.FileServer(http.Dir(testPrimaryPkgDir)).ServeHTTP(w, r) })) defer s.Close() + host := strings.TrimPrefix(s.URL, "http://") ctx := context.Background() a, err := New(WithFS(apkfs.NewMemFS()), - WithAuth(testUser, testPass), + WithAuth(host, testUser, testPass), WithArch("x86_64")) require.NoErrorf(t, err, "unable to create APK") err = a.InitDB(ctx) @@ -343,11 +344,12 @@ func TestIndexAuth_bad(t *testing.T) { http.FileServer(http.Dir(testPrimaryPkgDir)).ServeHTTP(w, r) })) defer s.Close() + host := strings.TrimPrefix(s.URL, "http://") ctx := context.Background() a, err := New(WithFS(apkfs.NewMemFS()), - WithAuth("baduser", "badpass"), + WithAuth(host, "baduser", "badpass"), WithArch("x86_64")) require.NoErrorf(t, err, "unable to create APK") err = a.InitDB(ctx)