Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CECO-743] Secret backend configuration #1395

Merged
merged 6 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions api/datadoghq/common/envvar.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ const (
DDSBOMHostEnabled = "DD_SBOM_HOST_ENABLED"
DDSBOMHostAnalyzers = "DD_SBOM_HOST_ANALYZERS"
DDSecretBackendCommand = "DD_SECRET_BACKEND_COMMAND"
DDSecretBackendArguments = "DD_SECRET_BACKEND_ARGUMENTS"
DDSecretBackendTimeout = "DD_SECRET_BACKEND_TIMEOUT"
DDSite = "DD_SITE"
DDSystemProbeAgentEnabled = "DD_SYSTEM_PROBE_ENABLED"
DDSystemProbeBPFDebugEnabled = DDSystemProbeEnvPrefix + "BPF_DEBUG"
Expand Down
44 changes: 41 additions & 3 deletions api/datadoghq/v2alpha1/datadogagent_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1245,6 +1245,10 @@ type GlobalConfig struct {

// FIPS contains configuration used to customize the FIPS proxy sidecar.
FIPS *FIPSConfig `json:"fips,omitempty"`

// Configure the secret backend feature https://docs.datadoghq.com/agent/guide/secrets-management
// See also: https://github.com/DataDog/datadog-operator/blob/main/docs/secret_management.md
SecretBackend *SecretBackendConfig `json:"secretBackend,omitempty"`
}

// DatadogCredentials is a generic structure that holds credentials to access Datadog.
Expand All @@ -1271,13 +1275,47 @@ type DatadogCredentials struct {
AppSecret *SecretConfig `json:"appSecret,omitempty"`
}

// SecretBackendRolesConfig provides configuration of the secrets Datadog agents can read for the SecretBackend feature
// +k8s:openapi-gen=true
type SecretBackendRolesConfig struct {
// Namespace defines the namespace in which the secrets reside.
// +required
Namespace *string `json:"namespace,omitempty"`

// Secrets defines the list of secrets for which a role should be created.
// +required
// +listType=set
Secrets []string `json:"secrets,omitempty"`
}

// SecretBackendConfig provides configuration for the secret backend.
// +k8s:openapi-gen=true
type SecretBackendConfig struct {
// Command defines the secret backend command to use
// The secret backend command to use. Datadog provides a pre-defined binary `/readsecret_multiple_providers.sh`.
// Read more about `/readsecret_multiple_providers.sh` at https://docs.datadoghq.com/agent/configuration/secrets-management/?tab=linux#script-for-reading-from-multiple-secret-providers.
Command *string `json:"command,omitempty"`

// Args defines the list of arguments to pass to the command
Args []string `json:"args,omitempty"`
// List of arguments to pass to the command (space-separated strings).
// +optional
Args *string `json:"args,omitempty"`

// The command timeout in seconds.
// Default: `30`.
// +optional
Timeout *int32 `json:"timeout,omitempty"`

// Whether to create a global permission allowing Datadog agents to read all Kubernetes secrets.
// Default: `false`.
// +optional
EnableGlobalPermissions *bool `json:"enableGlobalPermissions,omitempty"`

// Roles for Datadog to read the specified secrets, replacing `enableGlobalPermissions`.
// They are defined as a list of namespace/secrets.
// Each defined namespace needs to be present in the DatadogAgent controller using `WATCH_NAMESPACE` or `DD_AGENT_WATCH_NAMESPACE`.
// See also: https://github.com/DataDog/datadog-operator/blob/main/docs/secret_management.md#how-to-deploy-the-agent-components-using-the-secret-backend-feature-with-datadogagent.
// +optional
// +listType=atomic
Roles []*SecretBackendRolesConfig `json:"roles,omitempty"`
}

// NetworkPolicyFlavor specifies which flavor of Network Policy to use.
Expand Down
28 changes: 28 additions & 0 deletions api/datadoghq/v2alpha1/test/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,34 @@ func (builder *DatadogAgentBuilder) WithRegistry(registry string) *DatadogAgentB
return builder
}

// Global SecretBackend

func (builder *DatadogAgentBuilder) WithGlobalSecretBackendGlobalPerms(command string, args string, timeout int32) *DatadogAgentBuilder {
builder.datadogAgent.Spec.Global.SecretBackend = &v2alpha1.SecretBackendConfig{
Command: apiutils.NewStringPointer(command),
Args: apiutils.NewStringPointer(args),
Timeout: apiutils.NewInt32Pointer(timeout),
EnableGlobalPermissions: apiutils.NewBoolPointer(true),
}
return builder
}

func (builder *DatadogAgentBuilder) WithGlobalSecretBackendSpecificRoles(command string, args string, timeout int32, secretNs string, secretNames []string) *DatadogAgentBuilder {
builder.datadogAgent.Spec.Global.SecretBackend = &v2alpha1.SecretBackendConfig{
Command: apiutils.NewStringPointer(command),
Args: apiutils.NewStringPointer(args),
Timeout: apiutils.NewInt32Pointer(timeout),
EnableGlobalPermissions: apiutils.NewBoolPointer(false),
Roles: []*v2alpha1.SecretBackendRolesConfig{
{
Namespace: apiutils.NewStringPointer(secretNs),
Secrets: secretNames,
},
},
}
return builder
}

// Override

func (builder *DatadogAgentBuilder) WithComponentOverride(componentName v2alpha1.ComponentName, override v2alpha1.DatadogAgentComponentOverride) *DatadogAgentBuilder {
Expand Down
55 changes: 53 additions & 2 deletions api/datadoghq/v2alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

103 changes: 103 additions & 0 deletions api/datadoghq/v2alpha1/zz_generated.openapi.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 46 additions & 0 deletions config/crd/bases/v1/datadoghq.com_datadogagents.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2057,6 +2057,52 @@ spec:
Use 'docker.io/datadog' for DockerHub.
Default: 'gcr.io/datadoghq'
type: string
secretBackend:
description: |-
Configure the secret backend feature https://docs.datadoghq.com/agent/guide/secrets-management
See also: https://github.com/DataDog/datadog-operator/blob/main/docs/secret_management.md
properties:
args:
description: List of arguments to pass to the command (space-separated strings).
type: string
command:
description: |-
The secret backend command to use. Datadog provides a pre-defined binary `/readsecret_multiple_providers.sh`.
Read more about `/readsecret_multiple_providers.sh` at https://docs.datadoghq.com/agent/configuration/secrets-management/?tab=linux#script-for-reading-from-multiple-secret-providers.
type: string
enableGlobalPermissions:
description: |-
Whether to create a global permission allowing Datadog agents to read all Kubernetes secrets.
Default: `false`.
type: boolean
roles:
description: |-
Roles for Datadog to read the specified secrets, replacing `enableGlobalPermissions`.
They are defined as a list of namespace/secrets.
Each defined namespace needs to be present in the DatadogAgent controller using `WATCH_NAMESPACE` or `DD_AGENT_WATCH_NAMESPACE`.
See also: https://github.com/DataDog/datadog-operator/blob/main/docs/secret_management.md#how-to-deploy-the-agent-components-using-the-secret-backend-feature-with-datadogagent.
items:
description: SecretBackendRolesConfig provides configuration of the secrets Datadog agents can read for the SecretBackend feature
properties:
namespace:
description: Namespace defines the namespace in which the secrets reside.
type: string
secrets:
description: Secrets defines the list of secrets for which a role should be created.
items:
type: string
type: array
x-kubernetes-list-type: set
type: object
type: array
x-kubernetes-list-type: atomic
timeout:
description: |-
The command timeout in seconds.
Default: `30`.
format: int32
type: integer
type: object
site:
description: |-
Site is the Datadog intake site Agent data are sent to.
Expand Down
5 changes: 5 additions & 0 deletions docs/configuration.v2alpha1.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,11 @@ spec:
| global.podAnnotationsAsTags | Provide a mapping of Kubernetes Annotations to Datadog Tags. <KUBERNETES_ANNOTATIONS>: <DATADOG_TAG_KEY> |
| global.podLabelsAsTags | Provide a mapping of Kubernetes Labels to Datadog Tags. <KUBERNETES_LABEL>: <DATADOG_TAG_KEY> |
| global.registry | Registry is the image registry to use for all Agent images. Use 'public.ecr.aws/datadog' for AWS ECR. Use 'datadoghq.azurecr.io' for Azure Container Registry. Use 'gcr.io/datadoghq' for Google Container Registry. Use 'eu.gcr.io/datadoghq' for Google Container Registry in the EU region. Use 'asia.gcr.io/datadoghq' for Google Container Registry in the Asia region. Use 'docker.io/datadog' for DockerHub. Default: 'gcr.io/datadoghq' |
| global.secretBackend.args | List of arguments to pass to the command (space-separated strings). |
| global.secretBackend.command | The secret backend command to use. Datadog provides a pre-defined binary `/readsecret_multiple_providers.sh`. Read more about `/readsecret_multiple_providers.sh` at https://docs.datadoghq.com/agent/configuration/secrets-management/?tab=linux#script-for-reading-from-multiple-secret-providers. |
| global.secretBackend.enableGlobalPermissions | Whether to create a global permission allowing Datadog agents to read all Kubernetes secrets. Default: `false`. |
| global.secretBackend.roles | Roles for Datadog to read the specified secrets, replacing `enableGlobalPermissions`. They are defined as a list of namespace/secrets. Each defined namespace needs to be present in the DatadogAgent controller using `WATCH_NAMESPACE` or `DD_AGENT_WATCH_NAMESPACE`. See also: https://github.com/DataDog/datadog-operator/blob/main/docs/secret_management.md#how-to-deploy-the-agent-components-using-the-secret-backend-feature-with-datadogagent. |
| global.secretBackend.timeout | The command timeout in seconds. Default: `30`. |
| global.site | Site is the Datadog intake site Agent data are sent to. Set to 'datadoghq.com' to send data to the US1 site (default). Set to 'datadoghq.eu' to send data to the EU site. Set to 'us3.datadoghq.com' to send data to the US3 site. Set to 'us5.datadoghq.com' to send data to the US5 site. Set to 'ddog-gov.com' to send data to the US1-FED site. Set to 'ap1.datadoghq.com' to send data to the AP1 site. Default: 'datadoghq.com' |
| global.tags | Tags contains a list of tags to attach to every metric, event and service check collected. Learn more about tagging: https://docs.datadoghq.com/tagging/ |
| override | Override the default configurations of the agents |
Expand Down
12 changes: 9 additions & 3 deletions internal/controller/datadogagent/merger/rbac.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
type RBACManager interface {
AddServiceAccount(namespace string, name string) error
AddServiceAccountByComponent(namespace, name, component string) error
AddPolicyRules(namespace string, roleName string, saName string, policies []rbacv1.PolicyRule) error
AddPolicyRules(namespace string, roleName string, saName string, policies []rbacv1.PolicyRule, saNamespace ...string) error
AddPolicyRulesByComponent(namespace string, roleName string, saName string, policies []rbacv1.PolicyRule, component string) error
AddRoleBinding(roleNamespace, roleName, saNamespace, saName string, roleRef rbacv1.RoleRef) error
AddClusterPolicyRules(namespace string, roleName string, saName string, policies []rbacv1.PolicyRule) error
Expand Down Expand Up @@ -87,7 +87,7 @@ func (m *rbacManagerImpl) DeleteServiceAccountByComponent(component, namespace s
}

// AddPolicyRules is used to add PolicyRules to a Role. It also creates the RoleBinding.
func (m *rbacManagerImpl) AddPolicyRules(namespace string, roleName string, saName string, policies []rbacv1.PolicyRule) error {
func (m *rbacManagerImpl) AddPolicyRules(namespace string, roleName string, saName string, policies []rbacv1.PolicyRule, saNamespace ...string) error {
obj, _ := m.store.GetOrCreate(kubernetes.RolesKind, namespace, roleName)
role, ok := obj.(*rbacv1.Role)
if !ok {
Expand All @@ -106,7 +106,13 @@ func (m *rbacManagerImpl) AddPolicyRules(namespace string, roleName string, saNa
Name: roleName,
}

return m.AddRoleBinding(namespace, roleName, namespace, saName, roleRef)
// If saNamespace is not provided, defaults to using role namespace.
targetSaNamespace := namespace
if len(saNamespace) > 0 {
targetSaNamespace = saNamespace[0]
}

return m.AddRoleBinding(namespace, roleName, targetSaNamespace, saName, roleRef)
}

// AddPolicyRulesByComponent is used to add PolicyRules to a Role, create a RoleBinding, and associate them with a component
Expand Down
Loading
Loading