Skip to content

Commit

Permalink
(fleet) add username/password login for the OCI client (#29535)
Browse files Browse the repository at this point in the history
  • Loading branch information
arbll authored Sep 25, 2024
1 parent 456feb4 commit ba4cc7a
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 3 deletions.
2 changes: 2 additions & 0 deletions pkg/config/setup/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -975,6 +975,8 @@ func InitConfig(config pkgconfigmodel.Config) {
config.BindEnvAndSetDefault("remote_policies", false)
config.BindEnvAndSetDefault("installer.registry.url", "")
config.BindEnvAndSetDefault("installer.registry.auth", "")
config.BindEnvAndSetDefault("installer.registry.username", "")
config.BindEnvAndSetDefault("installer.registry.password", "")
config.BindEnv("fleet_policies_dir")
config.SetDefault("fleet_layers", []string{})

Expand Down
24 changes: 24 additions & 0 deletions pkg/fleet/env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const (
envRemotePolicies = "DD_REMOTE_POLICIES"
envRegistryURL = "DD_INSTALLER_REGISTRY_URL"
envRegistryAuth = "DD_INSTALLER_REGISTRY_AUTH"
envRegistryUsername = "DD_INSTALLER_REGISTRY_USERNAME"
envRegistryPassword = "DD_INSTALLER_REGISTRY_PASSWORD"
envDefaultPackageVersion = "DD_INSTALLER_DEFAULT_PKG_VERSION"
envDefaultPackageInstall = "DD_INSTALLER_DEFAULT_PKG_INSTALL"
envApmLibraries = "DD_APM_INSTRUMENTATION_LIBRARIES"
Expand All @@ -38,8 +40,12 @@ var defaultEnv = Env{

RegistryOverride: "",
RegistryAuthOverride: "",
RegistryUsername: "",
RegistryPassword: "",
RegistryOverrideByImage: map[string]string{},
RegistryAuthOverrideByImage: map[string]string{},
RegistryUsernameByImage: map[string]string{},
RegistryPasswordByImage: map[string]string{},

DefaultPackagesInstallOverride: map[string]bool{},
DefaultPackagesVersionOverride: map[string]string{},
Expand All @@ -64,8 +70,12 @@ type Env struct {

RegistryOverride string
RegistryAuthOverride string
RegistryUsername string
RegistryPassword string
RegistryOverrideByImage map[string]string
RegistryAuthOverrideByImage map[string]string
RegistryUsernameByImage map[string]string
RegistryPasswordByImage map[string]string

DefaultPackagesInstallOverride map[string]bool
DefaultPackagesVersionOverride map[string]string
Expand All @@ -88,8 +98,12 @@ func FromEnv() *Env {

RegistryOverride: getEnvOrDefault(envRegistryURL, defaultEnv.RegistryOverride),
RegistryAuthOverride: getEnvOrDefault(envRegistryAuth, defaultEnv.RegistryAuthOverride),
RegistryUsername: getEnvOrDefault(envRegistryUsername, defaultEnv.RegistryUsername),
RegistryPassword: getEnvOrDefault(envRegistryPassword, defaultEnv.RegistryPassword),
RegistryOverrideByImage: overridesByNameFromEnv(envRegistryURL, func(s string) string { return s }),
RegistryAuthOverrideByImage: overridesByNameFromEnv(envRegistryAuth, func(s string) string { return s }),
RegistryUsernameByImage: overridesByNameFromEnv(envRegistryUsername, func(s string) string { return s }),
RegistryPasswordByImage: overridesByNameFromEnv(envRegistryPassword, func(s string) string { return s }),

DefaultPackagesInstallOverride: overridesByNameFromEnv(envDefaultPackageInstall, func(s string) bool { return strings.ToLower(s) == "true" }),
DefaultPackagesVersionOverride: overridesByNameFromEnv(envDefaultPackageVersion, func(s string) string { return s }),
Expand All @@ -112,6 +126,8 @@ func FromConfig(config model.Reader) *Env {
RemotePolicies: config.GetBool("remote_policies"),
RegistryOverride: config.GetString("installer.registry.url"),
RegistryAuthOverride: config.GetString("installer.registry.auth"),
RegistryUsername: config.GetString("installer.registry.username"),
RegistryPassword: config.GetString("installer.registry.password"),
}
}

Expand All @@ -136,6 +152,12 @@ func (e *Env) ToEnv() []string {
if e.RegistryAuthOverride != "" {
env = append(env, envRegistryAuth+"="+e.RegistryAuthOverride)
}
if e.RegistryUsername != "" {
env = append(env, envRegistryUsername+"="+e.RegistryUsername)
}
if e.RegistryPassword != "" {
env = append(env, envRegistryPassword+"="+e.RegistryPassword)
}
if len(e.ApmLibraries) > 0 {
libraries := []string{}
for l, v := range e.ApmLibraries {
Expand All @@ -150,6 +172,8 @@ func (e *Env) ToEnv() []string {
}
env = append(env, overridesByNameToEnv(envRegistryURL, e.RegistryOverrideByImage)...)
env = append(env, overridesByNameToEnv(envRegistryAuth, e.RegistryAuthOverrideByImage)...)
env = append(env, overridesByNameToEnv(envRegistryUsername, e.RegistryUsernameByImage)...)
env = append(env, overridesByNameToEnv(envRegistryPassword, e.RegistryPasswordByImage)...)
env = append(env, overridesByNameToEnv(envDefaultPackageInstall, e.DefaultPackagesInstallOverride)...)
env = append(env, overridesByNameToEnv(envDefaultPackageVersion, e.DefaultPackagesVersionOverride)...)
return env
Expand Down
40 changes: 40 additions & 0 deletions pkg/fleet/env/env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@ func TestFromEnv(t *testing.T) {
Site: "datadoghq.com",
RegistryOverride: "",
RegistryAuthOverride: "",
RegistryUsername: "",
RegistryPassword: "",
RegistryOverrideByImage: map[string]string{},
RegistryAuthOverrideByImage: map[string]string{},
RegistryUsernameByImage: map[string]string{},
RegistryPasswordByImage: map[string]string{},
DefaultPackagesInstallOverride: map[string]bool{},
DefaultPackagesVersionOverride: map[string]string{},
ApmLibraries: map[ApmLibLanguage]ApmLibVersion{},
Expand All @@ -44,10 +48,16 @@ func TestFromEnv(t *testing.T) {
envRemotePolicies: "true",
envRegistryURL: "registry.example.com",
envRegistryAuth: "auth",
envRegistryUsername: "username",
envRegistryPassword: "password",
envRegistryURL + "_IMAGE": "another.registry.example.com",
envRegistryURL + "_ANOTHER_IMAGE": "yet.another.registry.example.com",
envRegistryAuth + "_IMAGE": "another.auth",
envRegistryAuth + "_ANOTHER_IMAGE": "yet.another.auth",
envRegistryUsername + "_IMAGE": "another.username",
envRegistryUsername + "_ANOTHER_IMAGE": "yet.another.username",
envRegistryPassword + "_IMAGE": "another.password",
envRegistryPassword + "_ANOTHER_IMAGE": "yet.another.password",
envDefaultPackageInstall + "_PACKAGE": "true",
envDefaultPackageInstall + "_ANOTHER_PACKAGE": "false",
envDefaultPackageVersion + "_PACKAGE": "1.2.3",
Expand All @@ -62,6 +72,8 @@ func TestFromEnv(t *testing.T) {
RemotePolicies: true,
RegistryOverride: "registry.example.com",
RegistryAuthOverride: "auth",
RegistryUsername: "username",
RegistryPassword: "password",
RegistryOverrideByImage: map[string]string{
"image": "another.registry.example.com",
"another-image": "yet.another.registry.example.com",
Expand All @@ -70,6 +82,14 @@ func TestFromEnv(t *testing.T) {
"image": "another.auth",
"another-image": "yet.another.auth",
},
RegistryUsernameByImage: map[string]string{
"image": "another.username",
"another-image": "yet.another.username",
},
RegistryPasswordByImage: map[string]string{
"image": "another.password",
"another-image": "yet.another.password",
},
DefaultPackagesInstallOverride: map[string]bool{
"package": true,
"another-package": false,
Expand Down Expand Up @@ -100,6 +120,8 @@ func TestFromEnv(t *testing.T) {
RegistryAuthOverride: "",
RegistryOverrideByImage: map[string]string{},
RegistryAuthOverrideByImage: map[string]string{},
RegistryUsernameByImage: map[string]string{},
RegistryPasswordByImage: map[string]string{},
DefaultPackagesInstallOverride: map[string]bool{},
DefaultPackagesVersionOverride: map[string]string{},
ApmLibraries: map[ApmLibLanguage]ApmLibVersion{
Expand Down Expand Up @@ -133,6 +155,8 @@ func TestFromEnv(t *testing.T) {
},
RegistryOverrideByImage: map[string]string{},
RegistryAuthOverrideByImage: map[string]string{},
RegistryUsernameByImage: map[string]string{},
RegistryPasswordByImage: map[string]string{},
DefaultPackagesInstallOverride: map[string]bool{},
DefaultPackagesVersionOverride: map[string]string{},
},
Expand Down Expand Up @@ -171,6 +195,8 @@ func TestToEnv(t *testing.T) {
RemotePolicies: true,
RegistryOverride: "registry.example.com",
RegistryAuthOverride: "auth",
RegistryUsername: "username",
RegistryPassword: "password",
RegistryOverrideByImage: map[string]string{
"image": "another.registry.example.com",
"another-image": "yet.another.registry.example.com",
Expand All @@ -179,6 +205,14 @@ func TestToEnv(t *testing.T) {
"image": "another.auth",
"another-image": "yet.another.auth",
},
RegistryUsernameByImage: map[string]string{
"image": "another.username",
"another-image": "yet.another.username",
},
RegistryPasswordByImage: map[string]string{
"image": "another.password",
"another-image": "yet.another.password",
},
DefaultPackagesInstallOverride: map[string]bool{
"package": true,
"another-package": false,
Expand All @@ -200,11 +234,17 @@ func TestToEnv(t *testing.T) {
"DD_REMOTE_POLICIES=true",
"DD_INSTALLER_REGISTRY_URL=registry.example.com",
"DD_INSTALLER_REGISTRY_AUTH=auth",
"DD_INSTALLER_REGISTRY_USERNAME=username",
"DD_INSTALLER_REGISTRY_PASSWORD=password",
"DD_APM_INSTRUMENTATION_LIBRARIES=dotnet:latest,java,ruby:1.2",
"DD_INSTALLER_REGISTRY_URL_IMAGE=another.registry.example.com",
"DD_INSTALLER_REGISTRY_URL_ANOTHER_IMAGE=yet.another.registry.example.com",
"DD_INSTALLER_REGISTRY_AUTH_IMAGE=another.auth",
"DD_INSTALLER_REGISTRY_AUTH_ANOTHER_IMAGE=yet.another.auth",
"DD_INSTALLER_REGISTRY_USERNAME_IMAGE=another.username",
"DD_INSTALLER_REGISTRY_USERNAME_ANOTHER_IMAGE=yet.another.username",
"DD_INSTALLER_REGISTRY_PASSWORD_IMAGE=another.password",
"DD_INSTALLER_REGISTRY_PASSWORD_ANOTHER_IMAGE=yet.another.password",
"DD_INSTALLER_DEFAULT_PKG_INSTALL_PACKAGE=true",
"DD_INSTALLER_DEFAULT_PKG_INSTALL_ANOTHER_PACKAGE=false",
"DD_INSTALLER_DEFAULT_PKG_VERSION_PACKAGE=1.2.3",
Expand Down
25 changes: 22 additions & 3 deletions pkg/fleet/internal/oci/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ const (
RegistryAuthGCR string = "gcr"
// RegistryAuthECR is the Amazon Elastic Container Registry authentication method.
RegistryAuthECR string = "ecr"
// RegistryAuthPassword is the password registry authentication method.
RegistryAuthPassword string = "password"
)

const (
Expand Down Expand Up @@ -132,12 +134,17 @@ func (d *Downloader) Download(ctx context.Context, packageURL string) (*Download
}, nil
}

func getKeychain(auth string) authn.Keychain {
func getKeychain(auth string, username string, password string) authn.Keychain {
switch auth {
case RegistryAuthGCR:
return google.Keychain
case RegistryAuthECR:
return authn.NewKeychainFromHelper(ecr.NewECRHelper())
case RegistryAuthPassword:
return usernamePasswordKeychain{
username: username,
password: password,
}
case RegistryAuthDefault, "":
return authn.DefaultKeychain
default:
Expand Down Expand Up @@ -169,10 +176,10 @@ func getRefAndKeychain(env *env.Env, url string) urlWithKeychain {
}
ref = registryOverride + imageWithIdentifier
}
keychain := getKeychain(env.RegistryAuthOverride)
keychain := getKeychain(env.RegistryAuthOverride, env.RegistryUsername, env.RegistryPassword)
for image, override := range env.RegistryAuthOverrideByImage {
if strings.HasPrefix(imageWithIdentifier, image+":") || strings.HasPrefix(imageWithIdentifier, image+"@") {
keychain = getKeychain(override)
keychain = getKeychain(override, env.RegistryUsername, env.RegistryPassword)
break
}
}
Expand Down Expand Up @@ -313,3 +320,15 @@ func isStreamResetError(err error) bool {
}
return false
}

type usernamePasswordKeychain struct {
username string
password string
}

func (k usernamePasswordKeychain) Resolve(_ authn.Resource) (authn.Authenticator, error) {
return authn.FromConfig(authn.AuthConfig{
Username: k.username,
Password: k.password,
}), nil
}

0 comments on commit ba4cc7a

Please sign in to comment.