Skip to content

Commit

Permalink
feat: add debug logs to k8s secret and docker config auth providers (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
akashsinghal authored Mar 7, 2024
1 parent a29d629 commit 71df5dd
Show file tree
Hide file tree
Showing 4 changed files with 332 additions and 16 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ require (
github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
github.com/go-ini/ini v1.67.0 // indirect
Expand Down
16 changes: 14 additions & 2 deletions pkg/common/oras/authprovider/authprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"time"

re "github.com/deislabs/ratify/errors"
"github.com/deislabs/ratify/internal/logger"
"github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/cli/config/types"
Expand Down Expand Up @@ -63,6 +64,8 @@ type defaultAuthProviderConf struct {
const DefaultAuthProviderName string = "dockerConfig"
const DefaultDockerAuthTTL = 1 * time.Hour

var logOpt = logger.Option{ComponentType: logger.AuthProvider}

// init calls Register for our default provider, which simply reads the .dockercfg file.
func init() {
Register(DefaultAuthProviderName, &defaultProviderFactory{})
Expand Down Expand Up @@ -96,7 +99,7 @@ func (d *defaultAuthProvider) Enabled(_ context.Context) bool {
}

// Provide reads docker config file and returns corresponding credentials from file if exists
func (d *defaultAuthProvider) Provide(_ context.Context, artifact string) (AuthConfig, error) {
func (d *defaultAuthProvider) Provide(ctx context.Context, artifact string) (AuthConfig, error) {
// load docker config file at default path if config file path not specified
var cfg *configfile.ConfigFile
if d.configPath == "" {
Expand Down Expand Up @@ -124,7 +127,16 @@ func (d *defaultAuthProvider) Provide(_ context.Context, artifact string) (AuthC
return AuthConfig{}, re.ErrorCodeHostNameInvalid.WithError(err).WithComponentType(re.AuthProvider)
}

dockerAuthConfig := cfg.AuthConfigs[artifactHostName]
dockerAuthConfig, exists := cfg.AuthConfigs[artifactHostName]
if !exists {
logger.GetLogger(ctx, logOpt).Debugf("no credentials found for registry hostname: %s", artifactHostName)
hostnames := []string{}
for k := range cfg.AuthConfigs {
hostnames = append(hostnames, k)
}
logger.GetLogger(ctx, logOpt).Debugf("list of registry host names in config : %v", hostnames)
return AuthConfig{}, nil
}
if dockerAuthConfig == (types.AuthConfig{}) {
return AuthConfig{}, nil
}
Expand Down
29 changes: 23 additions & 6 deletions pkg/common/oras/authprovider/k8secret_authprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ import (
"time"

re "github.com/deislabs/ratify/errors"
"github.com/deislabs/ratify/internal/logger"
"github.com/deislabs/ratify/pkg/utils"

"github.com/docker/cli/cli/config"
core "k8s.io/api/core/v1"
e "k8s.io/apimachinery/pkg/api/errors"
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
Expand All @@ -38,7 +40,7 @@ type k8SecretProviderFactory struct{}
type k8SecretAuthProvider struct {
ratifyNamespace string
config k8SecretAuthProviderConf
clusterClientSet *kubernetes.Clientset
clusterClientSet kubernetes.Interface
}

type secretConfig struct {
Expand Down Expand Up @@ -121,6 +123,7 @@ func (d *k8SecretAuthProvider) Provide(ctx context.Context, artifact string) (Au
return AuthConfig{}, re.ErrorCodeHostNameInvalid.WithError(err).WithComponentType(re.AuthProvider)
}

logger.GetLogger(ctx, logOpt).Debugf("attempting to resolve credentials for registry hostname: %s", hostName)
// iterate through config secrets, resolve each secret, and store in map
for _, k8secret := range d.config.Secrets {
// default value of secret is assumed to be ratify namespace
Expand All @@ -129,13 +132,16 @@ func (d *k8SecretAuthProvider) Provide(ctx context.Context, artifact string) (Au
}

secret, err := d.clusterClientSet.CoreV1().Secrets(k8secret.Namespace).Get(ctx, k8secret.SecretName, meta.GetOptions{})
if err != nil {
if e.IsNotFound(err) {
logger.GetLogger(ctx, logOpt).Debugf("secret %s not found in namespace %s", k8secret.SecretName, k8secret.Namespace)
continue
} else if err != nil {
return AuthConfig{}, re.ErrorCodeGetClusterResourceFailure.NewError(re.AuthProvider, "", re.EmptyLink, err, fmt.Sprintf("failed to pull secret %s from cluster.", k8secret.SecretName), re.HideStackTrace)
}

// only docker config json secret type allowed
if secret.Type == core.SecretTypeDockerConfigJson {
authConfig, err := d.resolveCredentialFromSecret(hostName, secret)
authConfig, err := d.resolveCredentialFromSecret(ctx, hostName, secret)
if err != nil && !errors.Is(err, re.ErrorCodeNoMatchingCredential) {
return AuthConfig{}, err
}
Expand All @@ -157,27 +163,32 @@ func (d *k8SecretAuthProvider) Provide(ctx context.Context, artifact string) (Au
// extract the imagePullSecrets linked to service account
for _, imagePullSecret := range serviceAccount.ImagePullSecrets {
secret, err := d.clusterClientSet.CoreV1().Secrets(d.ratifyNamespace).Get(ctx, imagePullSecret.Name, meta.GetOptions{})
if err != nil {
if e.IsNotFound(err) {
logger.GetLogger(ctx, logOpt).Debugf("image pull secret %s not found in namespace %s", imagePullSecret.Name, d.ratifyNamespace)
continue
} else if err != nil {
return AuthConfig{}, re.ErrorCodeGetClusterResourceFailure.WithError(err).WithComponentType(re.AuthProvider)
}

// only dockercfg or docker config json secret type allowed
if secret.Type == core.SecretTypeDockercfg || secret.Type == core.SecretTypeDockerConfigJson {
authConfig, err := d.resolveCredentialFromSecret(hostName, secret)
authConfig, err := d.resolveCredentialFromSecret(ctx, hostName, secret)
if err != nil && !errors.Is(err, re.ErrorCodeNoMatchingCredential) {
return AuthConfig{}, err
}
// if a resolved AuthConfig is returned
if err == nil {
return authConfig, nil
}
} else {
logger.GetLogger(ctx, logOpt).Debugf("image pull secret %s of type %s not supported", imagePullSecret.Name, secret.Type)
}
}

return AuthConfig{}, fmt.Errorf("could not find credentials for %s", artifact)
}

func (d *k8SecretAuthProvider) resolveCredentialFromSecret(hostName string, secret *core.Secret) (AuthConfig, error) {
func (d *k8SecretAuthProvider) resolveCredentialFromSecret(ctx context.Context, hostName string, secret *core.Secret) (AuthConfig, error) {
dockercfg, exists := secret.Data[core.DockerConfigJsonKey]
if !exists {
return AuthConfig{}, re.ErrorCodeConfigInvalid.WithDetail("could not extract auth configs from docker config")
Expand All @@ -190,6 +201,12 @@ func (d *k8SecretAuthProvider) resolveCredentialFromSecret(hostName string, secr

authConfig, exist := configFile.AuthConfigs[hostName]
if !exist {
logger.GetLogger(ctx, logOpt).Debugf("host name %s not found in image pull secret %s", hostName, secret.Name)
hostnames := []string{}
for k := range configFile.AuthConfigs {
hostnames = append(hostnames, k)
}
logger.GetLogger(ctx, logOpt).Debugf("list of host names in image pull secret %s: %v", secret.Name, hostnames)
return AuthConfig{}, re.ErrorCodeNoMatchingCredential
}

Expand Down
Loading

0 comments on commit 71df5dd

Please sign in to comment.