mirror of
https://github.com/anchore/syft.git
synced 2026-10-30 14:02:26 +01:00
Add registry certificate verification support (#1734)
* add registry certificate verification support * replace stereoscope version * modify go.mod * pull in stereoscope update Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * rename registry cert options, add docs, and add test Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * update to account for changes in anchore/stereoscope#195 Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix cli tests Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> --------- Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> Co-authored-by: lishituo <24578666@qq.com> Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
co-authored by
lishituo
Alex Goodman
parent
cedfa05e93
commit
b03e9c6868
@@ -16,30 +16,37 @@ type RegistryCredentials struct {
|
||||
Password string `yaml:"-" json:"-" mapstructure:"password"`
|
||||
// IMPORTANT: do not show the token in any YAML/JSON output (sensitive information)
|
||||
Token string `yaml:"-" json:"-" mapstructure:"token"`
|
||||
|
||||
TLSCert string `yaml:"tls-cert,omitempty" json:"tls-cert,omitempty" mapstructure:"tls-cert"`
|
||||
TLSKey string `yaml:"tls-key,omitempty" json:"tls-key,omitempty" mapstructure:"tls-key"`
|
||||
}
|
||||
|
||||
type registry struct {
|
||||
InsecureSkipTLSVerify bool `yaml:"insecure-skip-tls-verify" json:"insecure-skip-tls-verify" mapstructure:"insecure-skip-tls-verify"`
|
||||
InsecureUseHTTP bool `yaml:"insecure-use-http" json:"insecure-use-http" mapstructure:"insecure-use-http"`
|
||||
Auth []RegistryCredentials `yaml:"auth" json:"auth" mapstructure:"auth"`
|
||||
CACert string `yaml:"ca-cert" json:"ca-cert" mapstructure:"ca-cert"`
|
||||
}
|
||||
|
||||
func (cfg registry) loadDefaultValues(v *viper.Viper) {
|
||||
v.SetDefault("registry.insecure-skip-tls-verify", false)
|
||||
v.SetDefault("registry.insecure-use-http", false)
|
||||
v.SetDefault("registry.auth", []RegistryCredentials{})
|
||||
v.SetDefault("registry.ca-cert", "")
|
||||
}
|
||||
|
||||
//nolint:unparam
|
||||
func (cfg *registry) parseConfigValues() error {
|
||||
// there may be additional credentials provided by env var that should be appended to the set of credentials
|
||||
authority, username, password, token :=
|
||||
authority, username, password, token, tlsCert, tlsKey :=
|
||||
os.Getenv("SYFT_REGISTRY_AUTH_AUTHORITY"),
|
||||
os.Getenv("SYFT_REGISTRY_AUTH_USERNAME"),
|
||||
os.Getenv("SYFT_REGISTRY_AUTH_PASSWORD"),
|
||||
os.Getenv("SYFT_REGISTRY_AUTH_TOKEN")
|
||||
os.Getenv("SYFT_REGISTRY_AUTH_TOKEN"),
|
||||
os.Getenv("SYFT_REGISTRY_AUTH_TLS_CERT"),
|
||||
os.Getenv("SYFT_REGISTRY_AUTH_TLS_KEY")
|
||||
|
||||
if hasNonEmptyCredentials(username, password, token) {
|
||||
if hasNonEmptyCredentials(username, password, token, tlsCert, tlsKey) {
|
||||
// note: we prepend the credentials such that the environment variables take precedence over on-disk configuration.
|
||||
cfg.Auth = append([]RegistryCredentials{
|
||||
{
|
||||
@@ -47,29 +54,38 @@ func (cfg *registry) parseConfigValues() error {
|
||||
Username: username,
|
||||
Password: password,
|
||||
Token: token,
|
||||
TLSCert: tlsCert,
|
||||
TLSKey: tlsKey,
|
||||
},
|
||||
}, cfg.Auth...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func hasNonEmptyCredentials(username, password, token string) bool {
|
||||
return password != "" && username != "" || token != ""
|
||||
func hasNonEmptyCredentials(username, password, token, tlsCert, tlsKey string) bool {
|
||||
hasUserPass := username != "" && password != ""
|
||||
hasToken := token != ""
|
||||
hasTLSMaterial := tlsCert != "" && tlsKey != ""
|
||||
return hasUserPass || hasToken || hasTLSMaterial
|
||||
}
|
||||
|
||||
func (cfg *registry) ToOptions() *image.RegistryOptions {
|
||||
var auth = make([]image.RegistryCredentials, len(cfg.Auth))
|
||||
for i, a := range cfg.Auth {
|
||||
auth[i] = image.RegistryCredentials{
|
||||
Authority: a.Authority,
|
||||
Username: a.Username,
|
||||
Password: a.Password,
|
||||
Token: a.Token,
|
||||
Authority: a.Authority,
|
||||
Username: a.Username,
|
||||
Password: a.Password,
|
||||
Token: a.Token,
|
||||
ClientCert: a.TLSCert,
|
||||
ClientKey: a.TLSKey,
|
||||
}
|
||||
}
|
||||
|
||||
return &image.RegistryOptions{
|
||||
InsecureSkipTLSVerify: cfg.InsecureSkipTLSVerify,
|
||||
InsecureUseHTTP: cfg.InsecureUseHTTP,
|
||||
Credentials: auth,
|
||||
CAFileOrDir: cfg.CACert,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,48 +11,60 @@ import (
|
||||
|
||||
func TestHasNonEmptyCredentials(t *testing.T) {
|
||||
tests := []struct {
|
||||
username, password, token string
|
||||
expected bool
|
||||
username, password, token, cert, key string
|
||||
expected bool
|
||||
}{
|
||||
|
||||
{
|
||||
"", "", "",
|
||||
"", "", "", "", "",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"user", "", "",
|
||||
"user", "", "", "", "",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"", "pass", "",
|
||||
"", "pass", "", "", "",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"", "pass", "tok",
|
||||
"", "pass", "tok", "", "",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"user", "", "tok",
|
||||
"user", "", "tok", "", "",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"", "", "tok",
|
||||
"", "", "tok", "", "",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"user", "pass", "tok",
|
||||
"user", "pass", "tok", "", "",
|
||||
true,
|
||||
},
|
||||
|
||||
{
|
||||
"user", "pass", "",
|
||||
"user", "pass", "", "", "",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"", "", "", "cert", "key",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"", "", "", "cert", "",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"", "", "", "", "key",
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(fmt.Sprintf("%+v", test), func(t *testing.T) {
|
||||
assert.Equal(t, test.expected, hasNonEmptyCredentials(test.username, test.password, test.token))
|
||||
assert.Equal(t, test.expected, hasNonEmptyCredentials(test.username, test.password, test.token, test.cert, test.key))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -102,6 +114,29 @@ func Test_registry_ToOptions(t *testing.T) {
|
||||
Credentials: []image.RegistryCredentials{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "provide all tls configuration",
|
||||
input: registry{
|
||||
CACert: "ca.crt",
|
||||
InsecureSkipTLSVerify: true,
|
||||
Auth: []RegistryCredentials{
|
||||
{
|
||||
TLSCert: "client.crt",
|
||||
TLSKey: "client.key",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: image.RegistryOptions{
|
||||
CAFileOrDir: "ca.crt",
|
||||
InsecureSkipTLSVerify: true,
|
||||
Credentials: []image.RegistryCredentials{
|
||||
{
|
||||
ClientCert: "client.crt",
|
||||
ClientKey: "client.key",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
Reference in New Issue
Block a user