github.com/anchore/syft@v1.38.2/cmd/syft/internal/options/registry.go (about)

     1  package options
     2  
     3  import (
     4  	"os"
     5  
     6  	"github.com/anchore/clio"
     7  	"github.com/anchore/stereoscope/pkg/image"
     8  )
     9  
    10  type RegistryCredentials struct {
    11  	Authority string `yaml:"authority" json:"authority" mapstructure:"authority"`
    12  	// IMPORTANT: do not show any credential information, use secret type to automatically redact the values
    13  	Username secret `yaml:"username" json:"username" mapstructure:"username"`
    14  	Password secret `yaml:"password" json:"password" mapstructure:"password"`
    15  	Token    secret `yaml:"token" json:"token" mapstructure:"token"`
    16  
    17  	TLSCert string `yaml:"tls-cert,omitempty" json:"tls-cert,omitempty" mapstructure:"tls-cert"`
    18  	TLSKey  string `yaml:"tls-key,omitempty" json:"tls-key,omitempty" mapstructure:"tls-key"`
    19  }
    20  
    21  type registryConfig struct {
    22  	InsecureSkipTLSVerify bool                  `yaml:"insecure-skip-tls-verify" json:"insecure-skip-tls-verify" mapstructure:"insecure-skip-tls-verify"`
    23  	InsecureUseHTTP       bool                  `yaml:"insecure-use-http" json:"insecure-use-http" mapstructure:"insecure-use-http"`
    24  	Auth                  []RegistryCredentials `yaml:"auth" json:"auth" mapstructure:"auth"`
    25  	CACert                string                `yaml:"ca-cert" json:"ca-cert" mapstructure:"ca-cert"`
    26  }
    27  
    28  var _ interface {
    29  	clio.PostLoader
    30  	clio.FieldDescriber
    31  } = (*registryConfig)(nil)
    32  
    33  func (cfg *registryConfig) PostLoad() error {
    34  	// there may be additional credentials provided by env var that should be appended to the set of credentials
    35  	authority, username, password, token, tlsCert, tlsKey :=
    36  		os.Getenv("SYFT_REGISTRY_AUTH_AUTHORITY"),
    37  		os.Getenv("SYFT_REGISTRY_AUTH_USERNAME"),
    38  		os.Getenv("SYFT_REGISTRY_AUTH_PASSWORD"),
    39  		os.Getenv("SYFT_REGISTRY_AUTH_TOKEN"),
    40  		os.Getenv("SYFT_REGISTRY_AUTH_TLS_CERT"),
    41  		os.Getenv("SYFT_REGISTRY_AUTH_TLS_KEY")
    42  
    43  	if hasNonEmptyCredentials(username, password, token, tlsCert, tlsKey) {
    44  		// note: we prepend the credentials such that the environment variables take precedence over on-disk configuration.
    45  		// since this PostLoad is called before the PostLoad on the Auth credentials list,
    46  		// all appropriate redactions will be added
    47  		cfg.Auth = append([]RegistryCredentials{
    48  			{
    49  				Authority: authority,
    50  				Username:  secret(username),
    51  				Password:  secret(password),
    52  				Token:     secret(token),
    53  				TLSCert:   tlsCert,
    54  				TLSKey:    tlsKey,
    55  			},
    56  		}, cfg.Auth...)
    57  	}
    58  	return nil
    59  }
    60  
    61  func (cfg *registryConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
    62  	descriptions.Add(&cfg.InsecureSkipTLSVerify, "skip TLS verification when communicating with the registry")
    63  	descriptions.Add(&cfg.InsecureUseHTTP, "use http instead of https when connecting to the registry")
    64  	descriptions.Add(&cfg.CACert, "filepath to a CA certificate (or directory containing *.crt, *.cert, *.pem) used to generate the client certificate")
    65  	descriptions.Add(&cfg.Auth, `Authentication credentials for specific registries. Each entry describes authentication for a specific authority:
    66  -	authority: the registry authority URL the URL to the registry (e.g. "docker.io", "localhost:5000", etc.) (env: SYFT_REGISTRY_AUTH_AUTHORITY)
    67  	username: a username if using basic credentials (env: SYFT_REGISTRY_AUTH_USERNAME)
    68  	password: a corresponding password (env: SYFT_REGISTRY_AUTH_PASSWORD)
    69  	token: a token if using token-based authentication, mutually exclusive with username/password (env: SYFT_REGISTRY_AUTH_TOKEN)
    70  	tls-cert: filepath to the client certificate used for TLS authentication to the registry (env: SYFT_REGISTRY_AUTH_TLS_CERT)
    71  	tls-key: filepath to the client key used for TLS authentication to the registry (env: SYFT_REGISTRY_AUTH_TLS_KEY)
    72  `)
    73  }
    74  
    75  func hasNonEmptyCredentials(username, password, token, tlsCert, tlsKey string) bool {
    76  	hasUserPass := username != "" && password != ""
    77  	hasToken := token != ""
    78  	hasTLSMaterial := tlsCert != "" && tlsKey != ""
    79  	return hasUserPass || hasToken || hasTLSMaterial
    80  }
    81  
    82  func (cfg *registryConfig) ToOptions() *image.RegistryOptions {
    83  	var auth = make([]image.RegistryCredentials, len(cfg.Auth))
    84  	for i, a := range cfg.Auth {
    85  		auth[i] = image.RegistryCredentials{
    86  			Authority:  a.Authority,
    87  			Username:   a.Username.String(),
    88  			Password:   a.Password.String(),
    89  			Token:      a.Token.String(),
    90  			ClientCert: a.TLSCert,
    91  			ClientKey:  a.TLSKey,
    92  		}
    93  	}
    94  
    95  	return &image.RegistryOptions{
    96  		InsecureSkipTLSVerify: cfg.InsecureSkipTLSVerify,
    97  		InsecureUseHTTP:       cfg.InsecureUseHTTP,
    98  		Credentials:           auth,
    99  		CAFileOrDir:           cfg.CACert,
   100  	}
   101  }