Repository: stolostron/cluster-proxy
Pull request #314: Add permissions needed for impersonation.
Author: login: xuezhaojun
Labels: name: lgtm
name: approved
name: dco-signoff: yes
Created: 2025-04-01T08:13:30Z | Merged: 2025-04-20T13:34:06Z

Related Story: https://issues.redhat.com/browse/ACM-19584


Diff:
diff --git a/pkg/proxyagent/agent/agent.go b/pkg/proxyagent/agent/agent.go
index a3119e110..b862e3e80 100644
--- a/pkg/proxyagent/agent/agent.go
+++ b/pkg/proxyagent/agent/agent.go
@@ -129,6 +129,34 @@ func NewAgentAddon(
 						},
 					},
 				}).
+				WithStaticClusterRole(&rbacv1.ClusterRole{
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "cluster-proxy-addon-agent-tokenreview",
+					},
+					Rules: []rbacv1.PolicyRule{
+						{
+							APIGroups: []string{"authentication.k8s.io"},
+							Verbs:     []string{"create"},
+							Resources: []string{"tokenreviews"},
+						},
+					},
+				}).
+				WithStaticClusterRoleBinding(&rbacv1.ClusterRoleBinding{
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "cluster-proxy-addon-agent-tokenreview",
+					},
+					RoleRef: rbacv1.RoleRef{
+						Kind: "ClusterRole",
+						Name: "cluster-proxy-addon-agent-tokenreview",
+					},
+					Subjects: []rbacv1.Subject{
+						{
+							Kind:     rbacv1.GroupKind,
+							Name:     common.SubjectGroupClusterProxy,
+							APIGroup: rbacv1.GroupName,
+						},
+					},
+				}).
 				Build(),
 			CSRSign: CustomSignerWithExpiry(ProxyAgentSignerName, caKeyData, caCertData, time.Hour*24*180),
 		}).
diff --git a/pkg/proxyagent/agent/agent_test.go b/pkg/proxyagent/agent/agent_test.go
index ad9bfbcb6..6af77e218 100644
--- a/pkg/proxyagent/agent/agent_test.go
+++ b/pkg/proxyagent/agent/agent_test.go
@@ -438,7 +438,7 @@ func TestAgentAddonRegistrationOption(t *testing.T) {
 			err = options.Registration.PermissionConfig(c.cluster, c.addon)
 			assert.NoError(t, err)
 			actions := fakeKubeClient.Actions()
-			assert.Len(t, actions, 4)
+			assert.Len(t, actions, 8)
 			role := actions[1].(clienttesting.CreateAction).GetObject().(*rbacv1.Role)
 			assert.Equal(t, "cluster-proxy-addon-agent", role.Name)
 			rolebinding := actions[3].(clienttesting.CreateAction).GetObject().(*rbacv1.RoleBinding)
@@ -466,6 +466,8 @@ func TestNewAgentAddon(t *testing.T) {
 		addOnName,                   // namespace
 		"cluster-proxy",             // service account
 		"cluster-proxy-service-proxy-server-certificates",
+		"cluster-proxy-addon-agent-impersonator", // clusterrole for impersonation
+		"cluster-proxy-addon-agent-impersonator", // clusterrolebinding for impersonation
 	}
 
 	expectedManifestNamesWithoutClusterService := []string{
@@ -476,6 +478,8 @@ func TestNewAgentAddon(t *testing.T) {
 		addOnName,                   // namespace
 		"cluster-proxy",             // service account
 		"cluster-proxy-service-proxy-server-certificates",
+		"cluster-proxy-addon-agent-impersonator", // clusterrole for impersonation
+		"cluster-proxy-addon-agent-impersonator", // clusterrolebinding for impersonation
 	}
 
 	cases := []struct {
diff --git a/pkg/proxyagent/agent/manifests/charts/addon-agent/templates/addon-agent-clusterrole.yaml b/pkg/proxyagent/agent/manifests/charts/addon-agent/templates/addon-agent-clusterrole.yaml
new file mode 100644
index 000000000..4cdfc6b87
--- /dev/null
+++ b/pkg/proxyagent/agent/manifests/charts/addon-agent/templates/addon-agent-clusterrole.yaml
@@ -0,0 +1,13 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: cluster-proxy-addon-agent-impersonator
+rules:
+{{- if ne (toString .Values.impersonatePermissionEnabled) "false" }}
+- apiGroups: [""]
+  resources: ["users", "groups", "serviceaccounts"]
+  verbs: ["impersonate"]
+{{- end }}
+- apiGroups: ["authentication.k8s.io"]
+  resources: ["tokenreviews"]
+  verbs: ["create"]
diff --git a/pkg/proxyagent/agent/manifests/charts/addon-agent/templates/addon-agent-clusterrolebinding.yaml b/pkg/proxyagent/agent/manifests/charts/addon-agent/templates/addon-agent-clusterrolebinding.yaml
new file mode 100644
index 000000000..e0968dd0c
--- /dev/null
+++ b/pkg/proxyagent/agent/manifests/charts/addon-agent/templates/addon-agent-clusterrolebinding.yaml
@@ -0,0 +1,12 @@
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: cluster-proxy-addon-agent-impersonator
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: cluster-proxy-addon-agent-impersonator
+subjects:
+  - kind: ServiceAccount
+    name: cluster-proxy
+    namespace: {{ .Release.Namespace }}
diff --git a/pkg/proxyagent/agent/manifests/charts/addon-agent/templates/addon-agent-deployment.yaml b/pkg/proxyagent/agent/manifests/charts/addon-agent/templates/addon-agent-deployment.yaml
index c8d451ead..5ea1e44ef 100644
--- a/pkg/proxyagent/agent/manifests/charts/addon-agent/templates/addon-agent-deployment.yaml
+++ b/pkg/proxyagent/agent/manifests/charts/addon-agent/templates/addon-agent-deployment.yaml
@@ -129,6 +129,7 @@ spec:
             - --ocpservice-ca=/ocpservice-ca/service-ca.crt
             - --cert=/server-cert/tls.crt
             - --key=/server-cert/tls.key
+            - --hub-kubeconfig=/etc/kubeconfig/kubeconfig
           livesnessProbe:
             httpGet:
               path: /healthz
@@ -144,6 +145,12 @@ spec:
             runAsNonRoot: true
             readOnlyRootFilesystem: true
           volumeMounts:
+            - name: hub-kubeconfig
+              mountPath: /etc/kubeconfig/
+              readOnly: true
+            - name: hub
+              mountPath: /etc/tls
+              readOnly: true
             - name: ocpservice-ca
               mountPath: /ocpservice-ca
               readOnly: true
diff --git a/pkg/proxyagent/agent/manifests/charts/addon-agent/values.yaml b/pkg/proxyagent/agent/manifests/charts/addon-agent/values.yaml
index 58cfb53c7..7d1d30880 100644
--- a/pkg/proxyagent/agent/manifests/charts/addon-agent/values.yaml
+++ b/pkg/proxyagent/agent/manifests/charts/addon-agent/values.yaml
@@ -45,3 +45,5 @@ proxyConfig:
   HTTP_PROXY: null
   HTTPS_PROXY: null
   NO_PROXY: null
+
+impersonatePermissionEnabled: "true"


Reviews:
user: login: qiujian16
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-10T02:00:23Z
user: login: xuezhaojun
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-10T02:52:09Z
user: login: qiujian16
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-10T07:32:46Z
user: login: xuezhaojun
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-11T02:26:10Z
user: login: qiujian16
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-11T07:38:25Z
user: login: xuezhaojun
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-13T13:34:45Z

Review comments:
diff_hunk: @@ -0,0 +1,11 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: cluster-proxy-addon-agent-impersonator
+rules:
+- apiGroups: [""]
+  resources: ["users", "groups", "serviceaccounts"]
+  verbs: ["impersonate"]
path: pkg/proxyagent/agent/manifests/charts/addon-agent/templates/addon-agent-clusterrole.yaml
user: login: qiujian16
body: should we add a flag on impersonate and use managedclusteraddonconfig to control whether impersonate should be enabled?
created_at: 2025-04-10T02:00:16Z
author_association: NONE
diff_hunk: @@ -0,0 +1,11 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: cluster-proxy-addon-agent-impersonator
+rules:
+- apiGroups: [""]
+  resources: ["users", "groups", "serviceaccounts"]
+  verbs: ["impersonate"]
path: pkg/proxyagent/agent/manifests/charts/addon-agent/templates/addon-agent-clusterrole.yaml
user: login: xuezhaojun
body: I think impersonate can always be enabled, because it doesn't affect our "old" use cases that use managed cluster token. They will always use the non-impersonate way.

For new use cases, adding a flag could be a tedious step. If we want to push CNV integration to GA, the flag will always be enabled.
created_at: 2025-04-10T02:52:09Z
author_association: NONE
diff_hunk: @@ -0,0 +1,11 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: cluster-proxy-addon-agent-impersonator
+rules:
+- apiGroups: [""]
+  resources: ["users", "groups", "serviceaccounts"]
+  verbs: ["impersonate"]
path: pkg/proxyagent/agent/manifests/charts/addon-agent/templates/addon-agent-clusterrole.yaml
user: login: qiujian16
body: I am concerned about always adding the impersonate permission.
created_at: 2025-04-10T07:32:46Z
author_association: NONE
diff_hunk: @@ -0,0 +1,11 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: cluster-proxy-addon-agent-impersonator
+rules:
+- apiGroups: [""]
+  resources: ["users", "groups", "serviceaccounts"]
+  verbs: ["impersonate"]
path: pkg/proxyagent/agent/manifests/charts/addon-agent/templates/addon-agent-clusterrole.yaml
user: login: xuezhaojun
body: Got it, I think we can have a flag to control whether the impersonation permission will be added, but I prefer keep the logic of serve request the same to reduce code complexity.

And will there be a flag to enable/disable acm virtualization ingeration?  Like flightctl we enable it from MCH. 

If it doesn't have such a flag(the virtualzation integration is by default always enabled), I don't see the good time that we can set impersonation flag from false to true.
created_at: 2025-04-11T02:26:10Z
author_association: NONE
diff_hunk: @@ -0,0 +1,11 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: cluster-proxy-addon-agent-impersonator
+rules:
+- apiGroups: [""]
+  resources: ["users", "groups", "serviceaccounts"]
+  verbs: ["impersonate"]
path: pkg/proxyagent/agent/manifests/charts/addon-agent/templates/addon-agent-clusterrole.yaml
user: login: qiujian16
body: my point is always set impersonate permission and it cannot be turned off. 
created_at: 2025-04-11T07:38:25Z
author_association: NONE
diff_hunk: @@ -0,0 +1,11 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: cluster-proxy-addon-agent-impersonator
+rules:
+- apiGroups: [""]
+  resources: ["users", "groups", "serviceaccounts"]
+  verbs: ["impersonate"]
path: pkg/proxyagent/agent/manifests/charts/addon-agent/templates/addon-agent-clusterrole.yaml
user: login: xuezhaojun
body: Got it, PR updated, now we are able to disable impersonate permission be set `impersonatePermissionEnabled` to `false` via the `AddonDeploymentConfig.CustomizedVariables`. 

And by default, it's enabled.
created_at: 2025-04-13T13:34:45Z
author_association: NONE

PR comments:
user: login: xuezhaojun
created_at: 2025-04-07T06:31:47Z
body: /hold
author_association: NONE
user: login: xuezhaojun
created_at: 2025-04-09T10:00:30Z
body: /unhold
author_association: NONE
user: login: xuezhaojun
created_at: 2025-04-09T10:00:57Z
body: /assign @qiujian16 
author_association: NONE
user: login: sonarqubecloud[bot]
created_at: 2025-04-13T14:36:26Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=open-cluster-management_cluster-proxy&pullRequest=314) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [1 New issue](https://sonarcloud.io/project/issues?id=open-cluster-management_cluster-proxy&pullRequest=314&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=open-cluster-management_cluster-proxy&pullRequest=314&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=open-cluster-management_cluster-proxy&pullRequest=314&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=open-cluster-management_cluster-proxy&pullRequest=314&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=open-cluster-management_cluster-proxy&pullRequest=314&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=open-cluster-management_cluster-proxy&pullRequest=314)


author_association: NONE
user: login: qiujian16
created_at: 2025-04-14T13:17:33Z
body: /approve
/lgtm
author_association: NONE
user: login: openshift-ci[bot]
created_at: 2025-04-14T13:17:42Z
body: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/stolostron/cluster-proxy/pull/314#issuecomment-2801685522" title="LGTM">qiujian16</a>*, *<a href="https://github.com/stolostron/cluster-proxy/pull/314#" title="Author self-approved">xuezhaojun</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=stolostron%2Fcluster-proxy).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/stolostron/cluster-proxy/blob/main/OWNERS)~~ [qiujian16,xuezhaojun]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
author_association: NONE