diff --git a/apis/datadoghq/v2alpha1/datadogagent_types.go b/apis/datadoghq/v2alpha1/datadogagent_types.go index e0827990e..98198ca70 100644 --- a/apis/datadoghq/v2alpha1/datadogagent_types.go +++ b/apis/datadoghq/v2alpha1/datadogagent_types.go @@ -781,6 +781,11 @@ type GlobalConfig struct { // +optional CriSocketPath *string `json:"criSocketPath,omitempty"` + // Set DisableNonResourceRules to exclude NonResourceURLs from default ClusterRoles. + // Required 'true' for Google Cloud Marketplace. + // +optional + DisableNonResourceRules *bool `json:"disableNonResourceRules,omitempty"` + // ContainerStrategy determines whether agents run in a single or multiple containers. // Default: 'optimized' // +optional diff --git a/apis/datadoghq/v2alpha1/zz_generated.deepcopy.go b/apis/datadoghq/v2alpha1/zz_generated.deepcopy.go index c43295b6b..344180713 100644 --- a/apis/datadoghq/v2alpha1/zz_generated.deepcopy.go +++ b/apis/datadoghq/v2alpha1/zz_generated.deepcopy.go @@ -1093,6 +1093,11 @@ func (in *GlobalConfig) DeepCopyInto(out *GlobalConfig) { *out = new(string) **out = **in } + if in.DisableNonResourceRules != nil { + in, out := &in.DisableNonResourceRules, &out.DisableNonResourceRules + *out = new(bool) + **out = **in + } if in.ContainerStrategy != nil { in, out := &in.ContainerStrategy, &out.ContainerStrategy *out = new(ContainerStrategyType) diff --git a/config/crd/bases/v1/datadoghq.com_datadogagents.yaml b/config/crd/bases/v1/datadoghq.com_datadogagents.yaml index ce4791e20..79689a789 100644 --- a/config/crd/bases/v1/datadoghq.com_datadogagents.yaml +++ b/config/crd/bases/v1/datadoghq.com_datadogagents.yaml @@ -8468,6 +8468,9 @@ spec: criSocketPath: description: Path to the container runtime socket (if different from Docker). type: string + disableNonResourceRules: + description: Set DisableNonResourceRules to exclude NonResourceURLs from default ClusterRoles. Required 'true' for Google Cloud Marketplace. + type: boolean dockerSocketPath: description: Path to the docker runtime socket. type: string diff --git a/config/crd/bases/v1beta1/datadoghq.com_datadogagents.yaml b/config/crd/bases/v1beta1/datadoghq.com_datadogagents.yaml index 72bddce30..345163296 100644 --- a/config/crd/bases/v1beta1/datadoghq.com_datadogagents.yaml +++ b/config/crd/bases/v1beta1/datadoghq.com_datadogagents.yaml @@ -16018,6 +16018,9 @@ spec: criSocketPath: description: Path to the container runtime socket (if different from Docker). type: string + disableNonResourceRules: + description: Set DisableNonResourceRules to exclude NonResourceURLs from default ClusterRoles. Required 'true' for Google Cloud Marketplace. + type: boolean dockerSocketPath: description: Path to the docker runtime socket. type: string diff --git a/controllers/datadogagent/clusteragent.go b/controllers/datadogagent/clusteragent.go index 5b8a07991..c39beb47c 100644 --- a/controllers/datadogagent/clusteragent.go +++ b/controllers/datadogagent/clusteragent.go @@ -952,7 +952,7 @@ func buildClusterRole(dda *datadoghqv1alpha1.DatadogAgent, needClusterLevelRBAC }, } - rbacRules := agent.GetDefaultAgentClusterRolePolicyRules() + rbacRules := agent.GetDefaultAgentClusterRolePolicyRules(false) // If the secret backend uses the provided `/readsecret_multiple_providers.sh` script, then we need to add secrets GET permissions if *dda.Spec.Credentials.UseSecretBackend && diff --git a/controllers/datadogagent/component/agent/rbac.go b/controllers/datadogagent/component/agent/rbac.go index a802c2254..31b5770e3 100644 --- a/controllers/datadogagent/component/agent/rbac.go +++ b/controllers/datadogagent/component/agent/rbac.go @@ -20,13 +20,18 @@ func GetAgentRoleName(dda metav1.Object) string { } // GetDefaultAgentClusterRolePolicyRules returns the default policy rules for the Agent cluster role -func GetDefaultAgentClusterRolePolicyRules() []rbacv1.PolicyRule { - return []rbacv1.PolicyRule{ - getMetricsEndpointPolicyRule(), +func GetDefaultAgentClusterRolePolicyRules(excludeNonResourceRules bool) []rbacv1.PolicyRule { + policyRule := []rbacv1.PolicyRule{ getKubeletPolicyRule(), getEndpointsPolicyRule(), getLeaderElectionPolicyRule(), } + + if !excludeNonResourceRules { + policyRule = append(policyRule, getMetricsEndpointPolicyRule()) + } + + return policyRule } func getMetricsEndpointPolicyRule() rbacv1.PolicyRule { diff --git a/controllers/datadogagent/component/clusterchecksrunner/default.go b/controllers/datadogagent/component/clusterchecksrunner/default.go index ae30d1eec..c22c13038 100644 --- a/controllers/datadogagent/component/clusterchecksrunner/default.go +++ b/controllers/datadogagent/component/clusterchecksrunner/default.go @@ -82,12 +82,8 @@ func NewDefaultClusterChecksRunnerPodTemplateSpec(dda metav1.Object) *corev1.Pod } // GetDefaultClusterChecksRunnerClusterRolePolicyRules returns the default Cluster Role Policy Rules for the Cluster Checks Runner -func GetDefaultClusterChecksRunnerClusterRolePolicyRules(dda metav1.Object) []rbacv1.PolicyRule { - return []rbacv1.PolicyRule{ - { - NonResourceURLs: []string{rbac.MetricsURL}, - Verbs: []string{rbac.GetVerb}, - }, +func GetDefaultClusterChecksRunnerClusterRolePolicyRules(dda metav1.Object, excludeNonResourceRules bool) []rbacv1.PolicyRule { + policyRule := []rbacv1.PolicyRule{ { APIGroups: []string{rbac.CoreAPIGroup}, Resources: []string{ @@ -183,6 +179,15 @@ func GetDefaultClusterChecksRunnerClusterRolePolicyRules(dda metav1.Object) []rb }, }, } + + if !excludeNonResourceRules { + policyRule = append(policyRule, rbacv1.PolicyRule{ + NonResourceURLs: []string{rbac.MetricsURL}, + Verbs: []string{rbac.GetVerb}, + }) + } + + return policyRule } // GetDefaultServiceAccountName return the default Cluster-Agent ServiceAccountName diff --git a/controllers/datadogagent/feature/enabledefault/feature.go b/controllers/datadogagent/feature/enabledefault/feature.go index 450627afe..c8efe2423 100644 --- a/controllers/datadogagent/feature/enabledefault/feature.go +++ b/controllers/datadogagent/feature/enabledefault/feature.go @@ -60,12 +60,13 @@ func buildDefaultFeature(options *feature.Options) feature.Feature { type defaultFeature struct { owner metav1.Object - credentialsInfo credentialsInfo - dcaTokenInfo dcaTokenInfo - clusterAgent clusterAgentConfig - agent agentConfig - clusterChecksRunner clusterChecksRunnerConfig - logger logr.Logger + credentialsInfo credentialsInfo + dcaTokenInfo dcaTokenInfo + clusterAgent clusterAgentConfig + agent agentConfig + clusterChecksRunner clusterChecksRunnerConfig + logger logr.Logger + disableNonResourceRules bool customConfigAnnotationKey string customConfigAnnotationValue string @@ -119,6 +120,10 @@ func (f *defaultFeature) Configure(dda *v2alpha1.DatadogAgent) feature.RequiredC f.clusterChecksRunner.serviceAccountName = v2alpha1.GetClusterChecksRunnerServiceAccount(dda) if dda.Spec.Global != nil { + if dda.Spec.Global.DisableNonResourceRules != nil && *dda.Spec.Global.DisableNonResourceRules { + f.disableNonResourceRules = true + } + if dda.Spec.Global.Credentials != nil { creds := dda.Spec.Global.Credentials @@ -309,7 +314,7 @@ func (f *defaultFeature) agentDependencies(managers feature.ResourceManagers, re } // ClusterRole creation - if err := managers.RBACManager().AddClusterPolicyRules(f.owner.GetNamespace(), agent.GetAgentRoleName(f.owner), f.agent.serviceAccountName, agent.GetDefaultAgentClusterRolePolicyRules()); err != nil { + if err := managers.RBACManager().AddClusterPolicyRules(f.owner.GetNamespace(), agent.GetAgentRoleName(f.owner), f.agent.serviceAccountName, agent.GetDefaultAgentClusterRolePolicyRules(f.disableNonResourceRules)); err != nil { errs = append(errs, err) } @@ -366,7 +371,7 @@ func (f *defaultFeature) clusterChecksRunnerDependencies(managers feature.Resour } // ClusterRole creation - if err := managers.RBACManager().AddClusterPolicyRulesByComponent(f.owner.GetNamespace(), componentccr.GetCCRRbacResourcesName(f.owner), f.clusterChecksRunner.serviceAccountName, componentccr.GetDefaultClusterChecksRunnerClusterRolePolicyRules(f.owner), string(v2alpha1.ClusterChecksRunnerComponentName)); err != nil { + if err := managers.RBACManager().AddClusterPolicyRulesByComponent(f.owner.GetNamespace(), componentccr.GetCCRRbacResourcesName(f.owner), f.clusterChecksRunner.serviceAccountName, componentccr.GetDefaultClusterChecksRunnerClusterRolePolicyRules(f.owner, f.disableNonResourceRules), string(v2alpha1.ClusterChecksRunnerComponentName)); err != nil { errs = append(errs, err) } } diff --git a/docs/configuration.v2alpha1.md b/docs/configuration.v2alpha1.md index d1417988b..3dde73949 100644 --- a/docs/configuration.v2alpha1.md +++ b/docs/configuration.v2alpha1.md @@ -141,6 +141,7 @@ spec: | global.credentials.appSecret.keyName | KeyName is the key of the secret to use. | | global.credentials.appSecret.secretName | SecretName is the name of the secret. | | global.criSocketPath | Path to the container runtime socket (if different from Docker). | +| global.disableNonResourceRules | Set DisableNonResourceRules to exclude NonResourceURLs from default ClusterRoles. Required 'true' for Google Cloud Marketplace. | | global.dockerSocketPath | Path to the docker runtime socket. | | global.endpoint.credentials.apiKey | APIKey configures your Datadog API key. See also: https://app.datadoghq.com/account/settings#agent/kubernetes | | global.endpoint.credentials.apiSecret.keyName | KeyName is the key of the secret to use. |