Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adding support for using multiple keychain for sending sbom results to a different repository #821

Merged
merged 1 commit into from
Sep 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ e.g.:
- `KO_DOCKER_REPO=gcr.io/my-project`, or
- `KO_DOCKER_REPO=my-dockerhub-user`

`ko` will default to storing sboms in the same repo as the image it is building. But there is an environment variable
named `COSIGN_REPOSITORY` that enables you to specify a different repository for storing sboms.

`KO_DOCKER_REPO=my-dockerhub-user COSIGN_REPOSITORY=gcr.io/my-project/sboms`

# Build an Image

`ko build ./cmd/app` builds and pushes a container image, and prints the
Expand Down
16 changes: 9 additions & 7 deletions pkg/publish/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ type defalt struct {
base string
t http.RoundTripper
userAgent string
auth authn.Authenticator
namer Namer
keychain authn.Keychain
tags []string
tagOnly bool
insecure bool
Expand All @@ -54,7 +54,7 @@ type defaultOpener struct {
base string
t http.RoundTripper
userAgent string
auth authn.Authenticator
keychain authn.Keychain
namer Namer
tags []string
tagOnly bool
Expand All @@ -67,8 +67,9 @@ type Namer func(string, string) string

// identity is the default namer, so import paths are affixed as-is under the repository
// name for maximum clarity, e.g.
// gcr.io/foo/github.com/bar/baz/cmd/blah
// ^--base--^ ^-------import path-------^
//
// gcr.io/foo/github.com/bar/baz/cmd/blah
// ^--base--^ ^-------import path-------^
func identity(base, in string) string { return path.Join(base, in) }

// As some registries do not support pushing an image by digest, the default tag for pushing
Expand All @@ -89,7 +90,7 @@ func (do *defaultOpener) Open() (Interface, error) {
base: do.base,
t: do.t,
userAgent: do.userAgent,
auth: do.auth,
keychain: do.keychain,
namer: do.namer,
tags: do.tags,
tagOnly: do.tagOnly,
Expand All @@ -104,7 +105,7 @@ func NewDefault(base string, options ...Option) (Interface, error) {
base: base,
t: http.DefaultTransport,
userAgent: "ko",
auth: authn.Anonymous,
keychain: authn.DefaultKeychain,
namer: identity,
tags: defaultTags,
}
Expand Down Expand Up @@ -203,7 +204,8 @@ func (d *defalt) Publish(ctx context.Context, br build.Result, s string) (name.R
// https://github.com/google/go-containerregistry/issues/212
s = strings.ToLower(s)

ro := []remote.Option{remote.WithAuth(d.auth), remote.WithTransport(d.t), remote.WithContext(ctx), remote.WithUserAgent(d.userAgent)}
ro := []remote.Option{remote.WithAuthFromKeychain(d.keychain), remote.WithTransport(d.t), remote.WithContext(ctx), remote.WithUserAgent(d.userAgent)}
developer-guy marked this conversation as resolved.
Show resolved Hide resolved

no := []name.Option{}
if d.insecure {
no = append(no, name.Insecure)
Expand Down
35 changes: 11 additions & 24 deletions pkg/publish/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,19 @@ package publish

import (
"crypto/tls"
"log"
"net/http"
"path"

"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
)

type staticKeychain struct {
auth authn.Authenticator
}

func (s staticKeychain) Resolve(resource authn.Resource) (authn.Authenticator, error) {
return s.auth, nil
}

// WithTransport is a functional option for overriding the default transport
// on a default publisher.
func WithTransport(t http.RoundTripper) Option {
Expand All @@ -44,9 +49,9 @@ func WithUserAgent(ua string) Option {

// WithAuth is a functional option for overriding the default authenticator
// on a default publisher.
func WithAuth(auth authn.Authenticator) Option {
func WithAuth(a authn.Authenticator) Option {
return func(i *defaultOpener) error {
i.auth = auth
i.keychain = staticKeychain{a}
return nil
}
}
Expand All @@ -55,25 +60,7 @@ func WithAuth(auth authn.Authenticator) Option {
// authenticator on a default publisher using an authn.Keychain
func WithAuthFromKeychain(keys authn.Keychain) Option {
developer-guy marked this conversation as resolved.
Show resolved Hide resolved
return func(i *defaultOpener) error {
// We parse this lazily because it is a repository prefix, which
// means that docker.io/mattmoor actually gets interpreted as
// docker.io/library/mattmoor, which gets tricky when we start
// appending things to it in the publisher.
//
// We append a fake path "ko" to KO_DOCKER_REPO in order to
// make parsing out the registry easier.
repo, err := name.NewRepository(path.Join(i.base, "ko"))
if err != nil {
return err
}
auth, err := keys.Resolve(repo.Registry)
if err != nil {
return err
}
if auth == authn.Anonymous {
log.Println("No matching credentials were found, falling back on anonymous")
}
i.auth = auth
imjasonh marked this conversation as resolved.
Show resolved Hide resolved
i.keychain = keys
return nil
}
}
Expand Down