Skip to content
Merged
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
69 changes: 5 additions & 64 deletions pkg/container/images/keychain.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,73 +4,14 @@
package images

import (
"os"
"strings"

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

// envKeychain implements a keychain that reads credentials from environment variables
type envKeychain struct{}

// Resolve implements the authn.Keychain interface
func (*envKeychain) Resolve(target authn.Resource) (authn.Authenticator, error) {
registry := target.RegistryStr()

// Try registry-specific environment variables first
// Format: REGISTRY_<NORMALIZED_REGISTRY_NAME>_USERNAME/PASSWORD, i.e., REGISTRY_DOCKER_IO_USERNAME
normalizedRegistry := strings.ToUpper(strings.ReplaceAll(registry, ".", "_"))
normalizedRegistry = strings.ReplaceAll(normalizedRegistry, "-", "_")

username := os.Getenv("REGISTRY_" + normalizedRegistry + "_USERNAME")
password := os.Getenv("REGISTRY_" + normalizedRegistry + "_PASSWORD")

// If registry-specific vars not found, try generic one REGISTRY_USERNAME/PASSWORD
if username == "" || password == "" {
username = os.Getenv("REGISTRY_USERNAME")
password = os.Getenv("REGISTRY_PASSWORD")
}

if username != "" && password != "" {
return &authn.Basic{
Username: username,
Password: password,
}, nil
}

return authn.Anonymous, nil
}

// compositeKeychain combines multiple keychains and tries them in order
type compositeKeychain struct {
keychains []authn.Keychain
}

// Resolve implements the authn.Keychain interface
func (c *compositeKeychain) Resolve(target authn.Resource) (authn.Authenticator, error) {
for _, keychain := range c.keychains {
auth, err := keychain.Resolve(target)
if err != nil {
continue
}

// Check if we got actual credentials (not anonymous)
if auth != authn.Anonymous {
return auth, nil
}
}

// If no keychain provided credentials, return anonymous
return authn.Anonymous, nil
}
coreimages "github.com/stacklok/toolhive-core/container/images"
)

// NewCompositeKeychain creates a keychain that tries environment variables first,
// then falls back to the default keychain
// then falls back to the default keychain.
// Deprecated: use github.com/stacklok/toolhive-core/container/images.NewCompositeKeychain.
func NewCompositeKeychain() authn.Keychain {
return &compositeKeychain{
keychains: []authn.Keychain{
&envKeychain{}, // Try environment variables first
authn.DefaultKeychain, // Then try default keychain (Docker config, etc.)
},
}
return coreimages.NewCompositeKeychain()
}
Loading