Repository: argoproj-labs/argocd-operator
Pull request #672 (2022-06-02 12:45:54)

fix: mount secret to service account for dex if its not there
Signed-off-by: rishabh625 <rishabhmishra625@gmail.com>

**What type of PR is this?**
> Uncomment only one ` /kind` line, and delete the rest.
> For example, `> /kind bug` would simply become: `/kind bug`

/kind bug

> /kind bug
> /kind chore
> /kind cleanup
> /kind failing-test
> /kind enhancement
> /kind documentation
> /kind code-refactoring


**What does this PR do / why we need it**:

since k8s v1.24 secret is not auto mounted to SA , dex creation fails as oauth client used for dex is service account. This PR creates a token and adds the token to service account

**Have you updated the necessary documentation?**

* [ ] Documentation update is required by this PR.
* [ ] Documentation has been updated.

**Which issue(s) this PR fixes**:

Fixes  [326](https://github.com/redhat-developer/gitops-operator/issues/326)

**How to test changes / Special notes to the reviewer**:
Run this on ocp v4.11 and on lower version to check backward compatibility


chetan-rns: Can we include a unit test for this change?
rishabh625: @iam-veeramalla @chetan-rns : it's difficult to add test for this here , as code is specific to openshift and will fail in CI if added

was planning for below test , but later realize that cannot add
```
+//TestReconcileArgoCD_reconcileDexOAuthClientSecret This test make sures that if dex is enabled a service account is created with token stored in a secret which is used for oauth
+func TestReconcileArgoCD_reconcileDexOAuthClientSecret(t *testing.T) {
+       logf.SetLogger(ZapLogger(true))
+       a := makeTestArgoCD()
+       a.Spec.Dex.OpenShiftOAuth = true
+       r := makeTestReconciler(t, a)
+       assert.NoError(t, createNamespace(r, a.Namespace, ""))
+       assert.NoError(t, r.reconcileDexServiceAccount(a))
+       sa := &corev1.ServiceAccount{}
+       assert.NoError(t, argoutil.FetchObject(r.Client, a.Namespace, common.ArgoCDDefaultDexServiceAccountName, sa))
+       tokenExists := false
+       for _, saSecret := range sa.Secrets {
+               if strings.Contains(saSecret.Name, "dex-server-token") {
+                       tokenExists = true
+               }
+       }
+       assert.True(t, tokenExists, "Dex is enabled but unable to create oauth client secret")
+}
```
rishabh625: Hi ,
since we cannot call reconcilation on 	testClient := testclient.NewSimpleClientset()
i am finding difficult to add unit test , can anyone guide on this please?
rishabh625: > Hi , since we cannot call reconcilation on testClient := testclient.NewSimpleClientset() i am finding difficult to add unit test , can anyone guide on this please?

@chetan-rns @iam-veeramalla Added the unit test case

Patch:
diff --git a/bundle/manifests/argocd-operator.clusterserviceversion.yaml b/bundle/manifests/argocd-operator.clusterserviceversion.yaml
index c31e9d9c..e8652b5b 100644
--- a/bundle/manifests/argocd-operator.clusterserviceversion.yaml
+++ b/bundle/manifests/argocd-operator.clusterserviceversion.yaml
@@ -904,6 +904,14 @@ spec:
           - jobs
           verbs:
           - '*'
+        - apiGroups:
+          - config.openshift.io
+          resources:
+          - clusterversions
+          verbs:
+          - get
+          - list
+          - watch
         - apiGroups:
           - monitoring.coreos.com
           resources:
diff --git a/common/defaults.go b/common/defaults.go
index 16e0e7e5..46a6f730 100644
--- a/common/defaults.go
+++ b/common/defaults.go
@@ -30,7 +30,10 @@ const (
 	// ArgoCDServerComponent is the name of the Dex server control plane component
 	ArgoCDServerComponent = "argocd-server"
 
-	// ArgoCDRedisHAComponent is the name of the Redis control plane component
+	// ArgoCDRedisComponent is the name of the Redis control plane component
+	ArgoCDRedisComponent = "argocd-redis"
+
+	// ArgoCDRedisHAComponent is the name of the Redis HA control plane component
 	ArgoCDRedisHAComponent = "argocd-redis-ha"
 
 	// ArgoCDDexServerComponent is the name of the Dex server control plane component
@@ -39,6 +42,9 @@ const (
 	// ArgoCDNotificationsControllerComponent is the name of the Notifications controller control plane component
 	ArgoCDNotificationsControllerComponent = "argocd-notifications-controller"
 
+	// ArgoCDOperatorGrafanaComponent is the name of the Grafana control plane component
+	ArgoCDOperatorGrafanaComponent = "argocd-grafana"
+
 	// ArgoCDDefaultAdminPasswordLength is the length of the generated default admin password.
 	ArgoCDDefaultAdminPasswordLength = 32
 
diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml
index c2dd4fc4..3dab5fd1 100644
--- a/config/rbac/role.yaml
+++ b/config/rbac/role.yaml
@@ -87,6 +87,14 @@ rules:
   - jobs
   verbs:
   - '*'
+- apiGroups:
+  - config.openshift.io
+  resources:
+  - clusterversions
+  verbs:
+  - get
+  - list
+  - watch
 - apiGroups:
   - monitoring.coreos.com
   resources:
diff --git a/controllers/argocd/applicationset.go b/controllers/argocd/applicationset.go
index f9ebb304..f1daa4fe 100644
--- a/controllers/argocd/applicationset.go
+++ b/controllers/argocd/applicationset.go
@@ -133,6 +133,7 @@ func (r *ReconcileArgoCD) reconcileApplicationSetDeployment(cr *argoprojv1a1.Arg
 	podSpec.Containers = []corev1.Container{
 		applicationSetContainer(cr),
 	}
+	AddSeccompProfileForOpenShift(r.Client, podSpec)
 
 	if existing := newDeploymentWithSuffix("applicationset-controller", "controller", cr); argoutil.IsObjectFound(r.Client, cr.Namespace, existing.Name, existing) {
 
diff --git a/controllers/argocd/argocd_controller.go b/controllers/argocd/argocd_controller.go
index 490d0141..5f282d87 100644
--- a/controllers/argocd/argocd_controller.go
+++ b/controllers/argocd/argocd_controller.go
@@ -53,6 +53,7 @@ var log = logr.Log.WithName("controller_argocd")
 //+kubebuilder:rbac:groups=argoproj.io,resources=argocds;argocds/finalizers;argocds/status,verbs=*
 //+kubebuilder:rbac:groups=autoscaling,resources=horizontalpodautoscalers,verbs=*
 //+kubebuilder:rbac:groups=batch,resources=cronjobs;jobs,verbs=*
+//+kubebuilder:rbac:groups=config.openshift.io,resources=clusterversions,verbs=get;list;watch
 //+kubebuilder:rbac:groups=networking.k8s.io,resources=ingresses,verbs=*
 //+kubebuilder:rbac:groups=monitoring.coreos.com,resources=prometheuses;servicemonitors,verbs=*
 //+kubebuilder:rbac:groups=route.openshift.io,resources=routes;routes/custom-host,verbs=*
diff --git a/controllers/argocd/deployment.go b/controllers/argocd/deployment.go
index 7ccb6c16..86f2e4b1 100644
--- a/controllers/argocd/deployment.go
+++ b/controllers/argocd/deployment.go
@@ -425,6 +425,9 @@ func (r *ReconcileArgoCD) reconcileDeployments(cr *argoprojv1a1.ArgoCD, useTLSFo
 // reconcileDexDeployment will ensure the Deployment resource is present for the ArgoCD Dex component.
 func (r *ReconcileArgoCD) reconcileDexDeployment(cr *argoprojv1a1.ArgoCD) error {
 	deploy := newDeploymentWithSuffix("dex-server", "dex-server", cr)
+
+	AddSeccompProfileForOpenShift(r.Client, &deploy.Spec.Template.Spec)
+
 	deploy.Spec.Template.Spec.Containers = []corev1.Container{{
 		Command: []string{
 			"/shared/argocd-dex",
@@ -457,6 +460,15 @@ func (r *ReconcileArgoCD) reconcileDexDeployment(cr *argoprojv1a1.ArgoCD) error
 			},
 		},
 		Resources: getDexResources(cr),
+		SecurityContext: &corev1.SecurityContext{
+			AllowPrivilegeEscalation: boolPtr(false),
+			Capabilities: &corev1.Capabilities{
+				Drop: []corev1.Capability{
+					"ALL",
+				},
+			},
+			RunAsNonRoot: boolPtr(true),
+		},
 		VolumeMounts: []corev1.VolumeMount{{
 			Name:      "static-files",
 			MountPath: "/shared",
@@ -475,6 +487,15 @@ func (r *ReconcileArgoCD) reconcileDexDeployment(cr *argoprojv1a1.ArgoCD) error
 		ImagePullPolicy: corev1.PullAlways,
 		Name:            "copyutil",
 		Resources:       getDexResources(cr),
+		SecurityContext: &corev1.SecurityContext{
+			AllowPrivilegeEscalation: boolPtr(false),
+			Capabilities: &corev1.Capabilities{
+				Drop: []corev1.Capability{
+					"ALL",
+				},
+			},
+			RunAsNonRoot: boolPtr(true),
+		},
 		VolumeMounts: []corev1.VolumeMount{{
 			Name:      "static-files",
 			MountPath: "/shared",
@@ -555,6 +576,7 @@ func (r *ReconcileArgoCD) reconcileDexDeployment(cr *argoprojv1a1.ArgoCD) error
 func (r *ReconcileArgoCD) reconcileGrafanaDeployment(cr *argoprojv1a1.ArgoCD) error {
 	deploy := newDeploymentWithSuffix("grafana", "grafana", cr)
 	deploy.Spec.Replicas = getGrafanaReplicas(cr)
+	AddSeccompProfileForOpenShift(r.Client, &deploy.Spec.Template.Spec)
 	deploy.Spec.Template.Spec.Containers = []corev1.Container{{
 		Image:           getGrafanaContainerImage(cr),
 		ImagePullPolicy: corev1.PullAlways,
@@ -566,6 +588,16 @@ func (r *ReconcileArgoCD) reconcileGrafanaDeployment(cr *argoprojv1a1.ArgoCD) er
 		},
 		Env:       proxyEnvVars(),
 		Resources: getGrafanaResources(cr),
+		SecurityContext: &corev1.SecurityContext{
+			AllowPrivilegeEscalation: boolPtr(false),
+			Capabilities: &corev1.Capabilities{
+				Drop: []corev1.Capability{
+					"ALL",
+				},
+			},
+			RunAsNonRoot: boolPtr(true),
+			RunAsUser:    int64Ptr(472),
+		},
 		VolumeMounts: []corev1.VolumeMount{
 			{
 				Name:      "grafana-config",
@@ -583,6 +615,7 @@ func (r *ReconcileArgoCD) reconcileGrafanaDeployment(cr *argoprojv1a1.ArgoCD) er
 		},
 	}}
 
+	deploy.Spec.Template.Spec.ServiceAccountName = fmt.Sprintf("%s-%s", cr.Name, "argocd-grafana")
 	deploy.Spec.Template.Spec.Volumes = []corev1.Volume{
 		{
 			Name: "grafana-config",
@@ -674,6 +707,9 @@ func (r *ReconcileArgoCD) reconcileGrafanaDeployment(cr *argoprojv1a1.ArgoCD) er
 // reconcileRedisDeployment will ensure the Deployment resource is present for the ArgoCD Redis component.
 func (r *ReconcileArgoCD) reconcileRedisDeployment(cr *argoprojv1a1.ArgoCD, useTLS bool) error {
 	deploy := newDeploymentWithSuffix("redis", "redis", cr)
+
+	AddSeccompProfileForOpenShift(r.Client, &deploy.Spec.Template.Spec)
+
 	deploy.Spec.Template.Spec.Containers = []corev1.Container{{
 		Args:            getArgoRedisArgs(useTLS),
 		Image:           getRedisContainerImage(cr),
@@ -686,6 +722,16 @@ func (r *ReconcileArgoCD) reconcileRedisDeployment(cr *argoprojv1a1.ArgoCD, useT
 		},
 		Resources: getRedisResources(cr),
 		Env:       proxyEnvVars(),
+		SecurityContext: &corev1.SecurityContext{
+			AllowPrivilegeEscalation: boolPtr(false),
+			Capabilities: &corev1.Capabilities{
+				Drop: []corev1.Capability{
+					"ALL",
+				},
+			},
+			RunAsNonRoot: boolPtr(true),
+			RunAsUser:    int64Ptr(999),
+		},
 		VolumeMounts: []corev1.VolumeMount{
 			{
 				Name:      common.ArgoCDRedisServerTLSSecretName,
@@ -694,6 +740,7 @@ func (r *ReconcileArgoCD) reconcileRedisDeployment(cr *argoprojv1a1.ArgoCD, useT
 		},
 	}}
 
+	deploy.Spec.Template.Spec.ServiceAccountName = fmt.Sprintf("%s-%s", cr.Name, "argocd-redis")
 	deploy.Spec.Template.Spec.Volumes = []corev1.Volume{
 		{
 			Name: common.ArgoCDRedisServerTLSSecretName,
@@ -837,6 +884,15 @@ func (r *ReconcileArgoCD) reconcileRedisHAProxyDeployment(cr *argoprojv1a1.ArgoC
 			},
 		},
 		Resources: getRedisHAProxyResources(cr),
+		SecurityContext: &corev1.SecurityContext{
+			AllowPrivilegeEscalation: boolPtr(false),
+			Capabilities: &corev1.Capabilities{
+				Drop: []corev1.Capability{
+					"ALL",
+				},
+			},
+			RunAsNonRoot: boolPtr(true),
+		},
 		VolumeMounts: []corev1.VolumeMount{
 			{
 				Name:      "data",
@@ -865,6 +921,14 @@ func (r *ReconcileArgoCD) reconcileRedisHAProxyDeployment(cr *argoprojv1a1.ArgoC
 		Name:            "config-init",
 		Env:             proxyEnvVars(),
 		Resources:       getRedisHAProxyResources(cr),
+		SecurityContext: &corev1.SecurityContext{
+			AllowPrivilegeEscalation: boolPtr(false),
+			Capabilities: &corev1.Capabilities{
+				Drop: []corev1.Capability{
+					"ALL",
+				},
+			},
+		},
 		VolumeMounts: []corev1.VolumeMount{
 			{
 				Name:      "config-volume",
@@ -912,6 +976,13 @@ func (r *ReconcileArgoCD) reconcileRedisHAProxyDeployment(cr *argoprojv1a1.ArgoC
 		},
 	}
 
+	deploy.Spec.Template.Spec.SecurityContext = &corev1.PodSecurityContext{
+		RunAsNonRoot: boolPtr(true),
+		RunAsUser:    int64Ptr(1000),
+		FSGroup:      int64Ptr(1000),
+	}
+	AddSeccompProfileForOpenShift(r.Client, &deploy.Spec.Template.Spec)
+
 	deploy.Spec.Template.Spec.ServiceAccountName = fmt.Sprintf("%s-%s", cr.Name, "argocd-redis-ha")
 
 	if err := applyReconcilerHook(cr, deploy, ""); err != nil {
@@ -946,6 +1017,8 @@ func (r *ReconcileArgoCD) reconcileRepoDeployment(cr *argoprojv1a1.ArgoCD, useTL
 		repoEnv = argoutil.EnvMerge(repoEnv, []corev1.EnvVar{{Name: "ARGOCD_EXEC_TIMEOUT", Value: fmt.Sprintf("%d", *cr.Spec.Repo.ExecTimeout)}}, true)
 	}
 
+	AddSeccompProfileForOpenShift(r.Client, &deploy.Spec.Template.Spec)
+
 	deploy.Spec.Template.Spec.InitContainers = []corev1.Container{{
 		Name:            "copyutil",
 		Image:           getArgoContainerImage(cr),
@@ -953,6 +1026,15 @@ func (r *ReconcileArgoCD) reconcileRepoDeployment(cr *argoprojv1a1.ArgoCD, useTL
 		ImagePullPolicy: corev1.PullAlways,
 		Resources:       getArgoRepoResources(cr),
 		Env:             proxyEnvVars(),
+		SecurityContext: &corev1.SecurityContext{
+			AllowPrivilegeEscalation: boolPtr(false),
+			Capabilities: &corev1.Capabilities{
+				Drop: []corev1.Capability{
+					"ALL",
+				},
+			},
+			RunAsNonRoot: boolPtr(true),
+		},
 		VolumeMounts: []corev1.VolumeMount{
 			{
 				Name:      "var-files",
@@ -1037,7 +1119,16 @@ func (r *ReconcileArgoCD) reconcileRepoDeployment(cr *argoprojv1a1.ArgoCD, useTL
 			InitialDelaySeconds: 5,
 			PeriodSeconds:       10,
 		},
-		Resources:    getArgoRepoResources(cr),
+		Resources: getArgoRepoResources(cr),
+		SecurityContext: &corev1.SecurityContext{
+			AllowPrivilegeEscalation: boolPtr(false),
+			Capabilities: &corev1.Capabilities{
+				Drop: []corev1.Capability{
+					"ALL",
+				},
+			},
+			RunAsNonRoot: boolPtr(true),
+		},
 		VolumeMounts: repoServerVolumeMounts,
 	}}
 
@@ -1199,6 +1290,7 @@ func (r *ReconcileArgoCD) reconcileServerDeployment(cr *argoprojv1a1.ArgoCD, use
 	deploy := newDeploymentWithSuffix("server", "server", cr)
 	serverEnv := cr.Spec.Server.Env
 	serverEnv = argoutil.EnvMerge(serverEnv, proxyEnvVars(), false)
+	AddSeccompProfileForOpenShift(r.Client, &deploy.Spec.Template.Spec)
 	deploy.Spec.Template.Spec.Containers = []corev1.Container{{
 		Command:         getArgoServerCommand(cr, useTLSForRedis),
 		Image:           getArgoContainerImage(cr),
@@ -1233,6 +1325,15 @@ func (r *ReconcileArgoCD) reconcileServerDeployment(cr *argoprojv1a1.ArgoCD, use
 			PeriodSeconds:       30,
 		},
 		Resources: getArgoServerResources(cr),
+		SecurityContext: &corev1.SecurityContext{
+			AllowPrivilegeEscalation: boolPtr(false),
+			Capabilities: &corev1.Capabilities{
+				Drop: []corev1.Capability{
+					"ALL",
+				},
+			},
+			RunAsNonRoot: boolPtr(true),
+		},
 		VolumeMounts: []corev1.VolumeMount{
 			{
 				Name:      "ssh-known-hosts",
diff --git a/controllers/argocd/notifications.go b/controllers/argocd/notifications.go
index 08cfbdb1..902dfa7d 100644
--- a/controllers/argocd/notifications.go
+++ b/controllers/argocd/notifications.go
@@ -257,7 +257,6 @@ func (r *ReconcileArgoCD) reconcileNotificationsRoleBinding(cr *argoprojv1a1.Arg
 
 func (r *ReconcileArgoCD) reconcileNotificationsDeployment(cr *argoprojv1a1.ArgoCD, sa *corev1.ServiceAccount) error {
 
-	var runAsNonRoot bool = true
 	desiredDeployment := newDeploymentWithSuffix("notifications-controller", "controller", cr)
 
 	desiredDeployment.Spec.Strategy = appsv1.DeploymentStrategy{
@@ -270,8 +269,9 @@ func (r *ReconcileArgoCD) reconcileNotificationsDeployment(cr *argoprojv1a1.Argo
 
 	podSpec := &desiredDeployment.Spec.Template.Spec
 	podSpec.SecurityContext = &corev1.PodSecurityContext{
-		RunAsNonRoot: &runAsNonRoot,
+		RunAsNonRoot: boolPtr(true),
 	}
+	AddSeccompProfileForOpenShift(r.Client, podSpec)
 	podSpec.ServiceAccountName = sa.ObjectMeta.Name
 	podSpec.Volumes = []corev1.Volume{
 		{
@@ -310,6 +310,14 @@ func (r *ReconcileArgoCD) reconcileNotificationsDeployment(cr *argoprojv1a1.Argo
 				},
 			},
 		},
+		SecurityContext: &corev1.SecurityContext{
+			AllowPrivilegeEscalation: boolPtr(false),
+			Capabilities: &corev1.Capabilities{
+				Drop: []corev1.Capability{
+					"ALL",
+				},
+			},
+		},
 		VolumeMounts: []corev1.VolumeMount{
 			{
 				Name:      "tls-certs",
diff --git a/controllers/argocd/policyrule.go b/controllers/argocd/policyrule.go
index daa4428d..f8d8e399 100644
--- a/controllers/argocd/policyrule.go
+++ b/controllers/argocd/policyrule.go
@@ -1,9 +1,14 @@
 package argocd
 
 import (
-	v1 "k8s.io/api/rbac/v1"
+	"fmt"
+
+	"golang.org/x/mod/semver"
 
 	"github.com/argoproj-labs/argocd-operator/common"
+
+	v1 "k8s.io/api/rbac/v1"
+	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
 func policyRuleForApplicationController() []v1.PolicyRule {
@@ -23,7 +28,17 @@ func policyRuleForApplicationController() []v1.PolicyRule {
 	}
 }
 
-func policyRuleForRedisHa() []v1.PolicyRule {
+func policyRuleForRedis(client client.Client) []v1.PolicyRule {
+	rules := []v1.PolicyRule{}
+
+	// Need additional policy rules if we are running on openshift, else the stateful set won't have the right
+	// permissions to start
+	rules = appendOpenShiftNonRootSCC(rules, client)
+
+	return rules
+}
+
+func policyRuleForRedisHa(client client.Client) []v1.PolicyRule {
 
 	rules := []v1.PolicyRule{
 		{
@@ -41,23 +56,7 @@ func policyRuleForRedisHa() []v1.PolicyRule {
 
 	// Need additional policy rules if we are running on openshift, else the stateful set won't have the right
 	// permissions to start
-	if IsRouteAPIAvailable() {
-		orules := v1.PolicyRule{
-			APIGroups: []string{
-				"security.openshift.io",
-			},
-			ResourceNames: []string{
-				"nonroot",
-			},
-			Resources: []string{
-				"securitycontextconstraints",
-			},
-			Verbs: []string{
-				"use",
-			},
-		}
-		rules = append(rules, orules)
-	}
+	rules = appendOpenShiftNonRootSCC(rules, client)
 
 	return rules
 }
@@ -239,7 +238,17 @@ func policyRuleForServerClusterRole() []v1.PolicyRule {
 	}
 }
 
-func getPolicyRuleList() []struct {
+func policyRuleForGrafana(client client.Client) []v1.PolicyRule {
+	rules := []v1.PolicyRule{}
+
+	// Need additional policy rules if we are running on openshift, else the stateful set won't have the right
+	// permissions to start
+	rules = appendOpenShiftNonRootSCC(rules, client)
+
+	return rules
+}
+
+func getPolicyRuleList(client client.Client) []struct {
 	name       string
 	policyRule []v1.PolicyRule
 } {
@@ -258,7 +267,13 @@ func getPolicyRuleList() []struct {
 			policyRule: policyRuleForServer(),
 		}, {
 			name:       common.ArgoCDRedisHAComponent,
-			policyRule: policyRuleForRedisHa(),
+			policyRule: policyRuleForRedisHa(client),
+		}, {
+			name:       common.ArgoCDRedisComponent,
+			policyRule: policyRuleForRedis(client),
+		}, {
+			name:       common.ArgoCDOperatorGrafanaComponent,
+			policyRule: policyRuleForGrafana(client),
 		},
 	}
 }
@@ -280,3 +295,33 @@ func getPolicyRuleClusterRoleList() []struct {
 		},
 	}
 }
+
+func appendOpenShiftNonRootSCC(rules []v1.PolicyRule, client client.Client) []v1.PolicyRule {
+	if IsVersionAPIAvailable() {
+		// Starting with OpenShift 4.11, we need to use the resource name "nonroot-v2" instead of "nonroot"
+		resourceName := "nonroot"
+		version, err := getClusterVersion(client)
+		if err != nil {
+			log.Error(err, "couldn't get OpenShift version")
+		}
+		if version == "" || semver.Compare(fmt.Sprintf("v%s", version), "v4.10.999") > 0 {
+			resourceName = "nonroot-v2"
+		}
+		orules := v1.PolicyRule{
+			APIGroups: []string{
+				"security.openshift.io",
+			},
+			ResourceNames: []string{
+				resourceName,
+			},
+			Resources: []string{
+				"securitycontextconstraints",
+			},
+			Verbs: []string{
+				"use",
+			},
+		}
+		rules = append(rules, orules)
+	}
+	return rules
+}
diff --git a/controllers/argocd/role.go b/controllers/argocd/role.go
index 470c6f1b..32945433 100644
--- a/controllers/argocd/role.go
+++ b/controllers/argocd/role.go
@@ -52,7 +52,7 @@ func newClusterRole(name string, rules []v1.PolicyRule, cr *argoprojv1a1.ArgoCD)
 
 // reconcileRoles will ensure that all ArgoCD Service Accounts are configured.
 func (r *ReconcileArgoCD) reconcileRoles(cr *argoprojv1a1.ArgoCD) error {
-	params := getPolicyRuleList()
+	params := getPolicyRuleList(r.Client)
 
 	for _, param := range params {
 		if _, err := r.reconcileRole(param.name, param.policyRule, cr); err != nil {
diff --git a/controllers/argocd/rolebinding.go b/controllers/argocd/rolebinding.go
index 34e6933a..d2e5030e 100644
--- a/controllers/argocd/rolebinding.go
+++ b/controllers/argocd/rolebinding.go
@@ -69,7 +69,7 @@ func newRoleBindingWithname(name string, cr *argoprojv1a1.ArgoCD) *v1.RoleBindin
 // reconcileRoleBindings will ensure that all ArgoCD RoleBindings are configured.
 func (r *ReconcileArgoCD) reconcileRoleBindings(cr *argoprojv1a1.ArgoCD) error {
 
-	params := getPolicyRuleList()
+	params := getPolicyRuleList(r.Client)
 
 	for _, param := range params {
 		if err := r.reconcileRoleBinding(param.name, param.policyRule, cr); err != nil {
diff --git a/controllers/argocd/service_account.go b/controllers/argocd/service_account.go
index dec6143c..885f10bb 100644
--- a/controllers/argocd/service_account.go
+++ b/controllers/argocd/service_account.go
@@ -60,7 +60,7 @@ func newServiceAccountWithName(name string, cr *argoprojv1a1.ArgoCD) *corev1.Ser
 
 // reconcileServiceAccounts will ensure that all ArgoCD Service Accounts are configured.
 func (r *ReconcileArgoCD) reconcileServiceAccounts(cr *argoprojv1a1.ArgoCD) error {
-	params := getPolicyRuleList()
+	params := getPolicyRuleList(r.Client)
 
 	for _, param := range params {
 		if err := r.reconcileServiceAccountPermissions(param.name, param.policyRule, cr); err != nil {
diff --git a/controllers/argocd/statefulset.go b/controllers/argocd/statefulset.go
index ca7b43b5..ce236bf6 100644
--- a/controllers/argocd/statefulset.go
+++ b/controllers/argocd/statefulset.go
@@ -202,6 +202,15 @@ func (r *ReconcileArgoCD) reconcileRedisStatefulSet(cr *argoprojv1a1.ArgoCD) err
 				TimeoutSeconds:      int32(15),
 			},
 			Resources: getRedisResources(cr),
+			SecurityContext: &corev1.SecurityContext{
+				AllowPrivilegeEscalation: boolPtr(false),
+				Capabilities: &corev1.Capabilities{
+					Drop: []corev1.Capability{
+						"ALL",
+					},
+				},
+				RunAsNonRoot: boolPtr(true),
+			},
 			VolumeMounts: []corev1.VolumeMount{
 				{
 					MountPath: "/data",
@@ -264,6 +273,15 @@ func (r *ReconcileArgoCD) reconcileRedisStatefulSet(cr *argoprojv1a1.ArgoCD) err
 				TimeoutSeconds:      int32(15),
 			},
 			Resources: getRedisResources(cr),
+			SecurityContext: &corev1.SecurityContext{
+				AllowPrivilegeEscalation: boolPtr(false),
+				Capabilities: &corev1.Capabilities{
+					Drop: []corev1.Capability{
+						"ALL",
+					},
+				},
+				RunAsNonRoot: boolPtr(true),
+			},
 			VolumeMounts: []corev1.VolumeMount{
 				{
 					MountPath: "/data",
@@ -306,6 +324,15 @@ func (r *ReconcileArgoCD) reconcileRedisStatefulSet(cr *argoprojv1a1.ArgoCD) err
 		ImagePullPolicy: corev1.PullIfNotPresent,
 		Name:            "config-init",
 		Resources:       getRedisResources(cr),
+		SecurityContext: &corev1.SecurityContext{
+			AllowPrivilegeEscalation: boolPtr(false),
+			Capabilities: &corev1.Capabilities{
+				Drop: []corev1.Capability{
+					"ALL",
+				},
+			},
+			RunAsNonRoot: boolPtr(true),
+		},
 		VolumeMounts: []corev1.VolumeMount{
 			{
 				MountPath: "/readonly-config",
@@ -332,6 +359,7 @@ func (r *ReconcileArgoCD) reconcileRedisStatefulSet(cr *argoprojv1a1.ArgoCD) err
 		RunAsNonRoot: &runAsNonRoot,
 		RunAsUser:    &runAsUser,
 	}
+	AddSeccompProfileForOpenShift(r.Client, &ss.Spec.Template.Spec)
 
 	ss.Spec.Template.Spec.ServiceAccountName = nameWithSuffix("argocd-redis-ha", cr)
 
@@ -452,6 +480,15 @@ func (r *ReconcileArgoCD) reconcileApplicationControllerStatefulSet(cr *argoproj
 			PeriodSeconds:       10,
 		},
 		Resources: getArgoApplicationControllerResources(cr),
+		SecurityContext: &corev1.SecurityContext{
+			AllowPrivilegeEscalation: boolPtr(false),
+			Capabilities: &corev1.Capabilities{
+				Drop: []corev1.Capability{
+					"ALL",
+				},
+			},
+			RunAsNonRoot: boolPtr(true),
+		},
 		VolumeMounts: []corev1.VolumeMount{
 			{
 				Name:      "argocd-repo-server-tls",
@@ -463,6 +500,7 @@ func (r *ReconcileArgoCD) reconcileApplicationControllerStatefulSet(cr *argoproj
 			},
 		},
 	}}
+	AddSeccompProfileForOpenShift(r.Client, podSpec)
 	podSpec.ServiceAccountName = nameWithSuffix("argocd-application-controller", cr)
 	podSpec.Volumes = []corev1.Volume{
 		{
@@ -524,7 +562,16 @@ func (r *ReconcileArgoCD) reconcileApplicationControllerStatefulSet(cr *argoproj
 			Image:           getArgoImportContainerImage(export),
 			ImagePullPolicy: corev1.PullAlways,
 			Name:            "argocd-import",
-			VolumeMounts:    getArgoImportVolumeMounts(),
+			SecurityContext: &corev1.SecurityContext{
+				AllowPrivilegeEscalation: boolPtr(false),
+				Capabilities: &corev1.Capabilities{
+					Drop: []corev1.Capability{
+						"ALL",
+					},
+				},
+				RunAsNonRoot: boolPtr(true),
+			},
+			VolumeMounts: getArgoImportVolumeMounts(),
 		}}
 
 		podSpec.Volumes = getArgoImportVolumes(export)
diff --git a/controllers/argocd/util.go b/controllers/argocd/util.go
index 8c7459ad..2df5cddb 100644
--- a/controllers/argocd/util.go
+++ b/controllers/argocd/util.go
@@ -29,6 +29,7 @@ import (
 	"text/template"
 
 	"sigs.k8s.io/controller-runtime/pkg/builder"
+	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
 
 	"gopkg.in/yaml.v2"
 
@@ -39,9 +40,11 @@ import (
 
 	monitoringv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1"
 	oappsv1 "github.com/openshift/api/apps/v1"
+	configv1 "github.com/openshift/api/config/v1"
 	routev1 "github.com/openshift/api/route/v1"
 	configv1client "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1"
 	"github.com/sethvargo/go-password/password"
+	"golang.org/x/mod/semver"
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
 	networkingv1 "k8s.io/api/networking/v1"
@@ -61,6 +64,25 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/source"
 )
 
+var (
+	versionAPIFound = false
+)
+
+// IsVersionAPIAvailable returns true if the version api is present
+func IsVersionAPIAvailable() bool {
+	return versionAPIFound
+}
+
+// verifyVersionAPI will verify that the template API is present.
+func verifyVersionAPI() error {
+	found, err := argoutil.VerifyAPI(configv1.GroupName, configv1.GroupVersion.Version)
+	if err != nil {
+		return err
+	}
+	versionAPIFound = found
+	return nil
+}
+
 // DexConnector represents an authentication connector for Dex.
 type DexConnector struct {
 	Config map[string]interface{} `yaml:"config,omitempty"`
@@ -353,7 +375,6 @@ func (r *ReconcileArgoCD) getDexOAuthClientSecret(cr *argoprojv1a1.ArgoCD) (*str
 	if err := argoutil.FetchObject(r.Client, cr.Namespace, sa.Name, sa); err != nil {
 		return nil, err
 	}
-
 	// Find the token secret
 	var tokenSecret *corev1.ObjectReference
 	for _, saSecret := range sa.Secrets {
@@ -364,7 +385,34 @@ func (r *ReconcileArgoCD) getDexOAuthClientSecret(cr *argoprojv1a1.ArgoCD) (*str
 	}
 
 	if tokenSecret == nil {
-		return nil, errors.New("unable to locate ServiceAccount token for OAuth client secret")
+		// This change of creating secret for dex service account,is due to change of reduction of secret-based service account tokens in k8s v1.24 so from k8s v1.24 no default secret for service account is created, but for dex to work we need to provide token of secret used by dex service account as a oauth token, this change helps to achieve it, in long run we should see do dex really requires a secret or it manages to create one using TokenRequest API or may be change how dex is used or configured by operator
+		secret := &corev1.Secret{
+			ObjectMeta: metav1.ObjectMeta{
+				GenerateName: "argocd-dex-server-token-",
+				Namespace:    cr.Namespace,
+				Annotations: map[string]string{
+					corev1.ServiceAccountNameKey: sa.Name,
+				},
+			},
+			Type: corev1.SecretTypeServiceAccountToken,
+		}
+		err := r.Client.Create(context.TODO(), secret)
+		if err != nil {
+			return nil, errors.New("unable to locate and create ServiceAccount token for OAuth client secret")
+		}
+		err = controllerutil.SetControllerReference(cr, secret, r.Scheme)
+		if err != nil {
+			return nil, err
+		}
+		tokenSecret = &corev1.ObjectReference{
+			Name:      secret.Name,
+			Namespace: cr.Namespace,
+		}
+		sa.Secrets = append(sa.Secrets, *tokenSecret)
+		err = r.Client.Update(context.TODO(), sa)
+		if err != nil {
+			return nil, errors.New("failed to add ServiceAccount token for OAuth client secret")
+		}
 	}
 
 	// Fetch the secret to obtain the token
@@ -727,6 +775,10 @@ func InspectCluster() error {
 	if err := verifyTemplateAPI(); err != nil {
 		return err
 	}
+
+	if err := verifyVersionAPI(); err != nil {
+		return err
+	}
 	return nil
 }
 
@@ -1168,6 +1220,10 @@ func boolPtr(val bool) *bool {
 	return &val
 }
 
+func int64Ptr(val int64) *int64 {
+	return &val
+}
+
 // triggerRollout will trigger a rollout of a Kubernetes resource specified as
 // obj. It currently supports Deployment and StatefulSet resources.
 func (r *ReconcileArgoCD) triggerRollout(obj interface{}, key string) error {
@@ -1477,6 +1533,43 @@ func getOpenShiftAPIURL() string {
 	return out
 }
 
+func AddSeccompProfileForOpenShift(client client.Client, podspec *corev1.PodSpec) {
+	if !IsVersionAPIAvailable() {
+		return
+	}
+	version, err := getClusterVersion(client)
+	if err != nil {
+		log.Error(err, "couldn't get OpenShift version")
+	}
+	if version == "" || semver.Compare(fmt.Sprintf("v%s", version), "v4.10.999") > 0 {
+		if podspec.SecurityContext == nil {
+			podspec.SecurityContext = &corev1.PodSecurityContext{}
+		}
+		if podspec.SecurityContext.SeccompProfile == nil {
+			podspec.SecurityContext.SeccompProfile = &corev1.SeccompProfile{}
+		}
+		if len(podspec.SecurityContext.SeccompProfile.Type) == 0 {
+			podspec.SecurityContext.SeccompProfile.Type = corev1.SeccompProfileTypeRuntimeDefault
+		}
+	}
+}
+
+// getClusterVersion returns the OpenShift Cluster version in which the operator is installed
+func getClusterVersion(client client.Client) (string, error) {
+	if !IsVersionAPIAvailable() {
+		return "", nil
+	}
+	clusterVersion := &configv1.ClusterVersion{}
+	err := client.Get(context.TODO(), types.NamespacedName{Name: "version"}, clusterVersion)
+	if err != nil {
+		if apierrors.IsNotFound(err) {
+			return "", nil
+		}
+		return "", err
+	}
+	return clusterVersion.Status.Desired.Version, nil
+}
+
 // generateRandomBytes returns a securely generated random bytes.
 func generateRandomBytes(n int) []byte {
 	b := make([]byte, n)
diff --git a/controllers/argocdexport/job.go b/controllers/argocdexport/job.go
index 663812b7..aeda5d91 100644
--- a/controllers/argocdexport/job.go
+++ b/controllers/argocdexport/job.go
@@ -28,6 +28,7 @@ import (
 
 	argoprojv1a1 "github.com/argoproj-labs/argocd-operator/api/v1alpha1"
 	"github.com/argoproj-labs/argocd-operator/common"
+	"github.com/argoproj-labs/argocd-operator/controllers/argocd"
 	"github.com/argoproj-labs/argocd-operator/controllers/argoutil"
 )
 
@@ -164,16 +165,29 @@ func newCronJob(cr *argoprojv1a1.ArgoCDExport) *batchv1.CronJob {
 	}
 }
 
-func newExportPodSpec(cr *argoprojv1a1.ArgoCDExport, argocdName string) corev1.PodSpec {
+func newExportPodSpec(cr *argoprojv1a1.ArgoCDExport, argocdName string, client client.Client) corev1.PodSpec {
 	pod := corev1.PodSpec{}
 
+	boolPtr := func(value bool) *bool {
+		return &value
+	}
+
 	pod.Containers = []corev1.Container{{
 		Command:         getArgoExportCommand(cr),
 		Env:             getArgoExportContainerEnv(cr),
 		Image:           getArgoExportContainerImage(cr),
 		ImagePullPolicy: corev1.PullAlways,
 		Name:            "argocd-export",
-		VolumeMounts:    getArgoExportVolumeMounts(),
+		SecurityContext: &corev1.SecurityContext{
+			AllowPrivilegeEscalation: boolPtr(false),
+			Capabilities: &corev1.Capabilities{
+				Drop: []corev1.Capability{
+					"ALL",
+				},
+			},
+			RunAsNonRoot: boolPtr(true),
+		},
+		VolumeMounts: getArgoExportVolumeMounts(),
 	}}
 
 	pod.RestartPolicy = corev1.RestartPolicyOnFailure
@@ -191,18 +205,19 @@ func newExportPodSpec(cr *argoprojv1a1.ArgoCDExport, argocdName string) corev1.P
 		RunAsGroup: &id,
 		FSGroup:    &id,
 	}
+	argocd.AddSeccompProfileForOpenShift(client, &pod)
 
 	return pod
 }
 
-func newPodTemplateSpec(cr *argoprojv1a1.ArgoCDExport, argocdName string) corev1.PodTemplateSpec {
+func newPodTemplateSpec(cr *argoprojv1a1.ArgoCDExport, argocdName string, client client.Client) corev1.PodTemplateSpec {
 	return corev1.PodTemplateSpec{
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      cr.Name,
 			Namespace: cr.Namespace,
 			Labels:    common.DefaultLabels(cr.Name),
 		},
-		Spec: newExportPodSpec(cr, argocdName),
+		Spec: newExportPodSpec(cr, argocdName, client),
 	}
 }
 
@@ -231,7 +246,7 @@ func (r *ReconcileArgoCDExport) reconcileCronJob(cr *argoprojv1a1.ArgoCDExport)
 		return err
 	}
 	job := newJob(cr)
-	job.Spec.Template = newPodTemplateSpec(cr, argocdName)
+	job.Spec.Template = newPodTemplateSpec(cr, argocdName, r.Client)
 
 	cj.Spec.JobTemplate.Spec = job.Spec
 
@@ -264,7 +279,7 @@ func (r *ReconcileArgoCDExport) reconcileJob(cr *argoprojv1a1.ArgoCDExport) erro
 	if err != nil {
 		return err
 	}
-	job.Spec.Template = newPodTemplateSpec(cr, argocdName)
+	job.Spec.Template = newPodTemplateSpec(cr, argocdName, r.Client)
 
 	if err := controllerutil.SetControllerReference(cr, job, r.Scheme); err != nil {
 		return err
diff --git a/deploy/olm-catalog/argocd-operator/0.4.0/argocd-operator.v0.4.0.clusterserviceversion.yaml b/deploy/olm-catalog/argocd-operator/0.4.0/argocd-operator.v0.4.0.clusterserviceversion.yaml
index c31e9d9c..e8652b5b 100644
--- a/deploy/olm-catalog/argocd-operator/0.4.0/argocd-operator.v0.4.0.clusterserviceversion.yaml
+++ b/deploy/olm-catalog/argocd-operator/0.4.0/argocd-operator.v0.4.0.clusterserviceversion.yaml
@@ -904,6 +904,14 @@ spec:
           - jobs
           verbs:
           - '*'
+        - apiGroups:
+          - config.openshift.io
+          resources:
+          - clusterversions
+          verbs:
+          - get
+          - list
+          - watch
         - apiGroups:
           - monitoring.coreos.com
           resources:
diff --git a/go.mod b/go.mod
index ba8677b1..97cdac72 100644
--- a/go.mod
+++ b/go.mod
@@ -17,6 +17,7 @@ require (
 	github.com/pkg/errors v0.9.1
 	github.com/sethvargo/go-password v0.2.0
 	github.com/stretchr/testify v1.7.0
+	golang.org/x/mod v0.5.1-0.20210830214625-1b1db11ec8f4
 	gopkg.in/yaml.v2 v2.4.0
 	k8s.io/api v0.23.1
 	k8s.io/apimachinery v0.23.1
diff --git a/go.sum b/go.sum
index d84a71b6..e7d5e18b 100644
--- a/go.sum
+++ b/go.sum
@@ -1318,6 +1318,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.5.1-0.20210830214625-1b1db11ec8f4 h1:7Qds88gNaRx0Dz/1wOwXlR7asekh1B1u26wEwN6FcEI=
+golang.org/x/mod v0.5.1-0.20210830214625-1b1db11ec8f4/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
diff --git a/main.go b/main.go
index 656c2a42..e3555702 100644
--- a/main.go
+++ b/main.go
@@ -25,6 +25,7 @@ import (
 
 	monitoringv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1"
 	appsv1 "github.com/openshift/api/apps/v1"
+	configv1 "github.com/openshift/api/config/v1"
 	oauthv1 "github.com/openshift/api/oauth/v1"
 	routev1 "github.com/openshift/api/route/v1"
 	templatev1 "github.com/openshift/api/template/v1"
@@ -152,6 +153,14 @@ func main() {
 		}
 	}
 
+	// Set up the scheme for openshift config if available
+	if argocd.IsVersionAPIAvailable() {
+		if err := configv1.Install(mgr.GetScheme()); err != nil {
+			setupLog.Error(err, "")
+			os.Exit(1)
+		}
+	}
+
 	// Setup Schemes for SSO if template instance is available.
 	if argocd.IsTemplateAPIAvailable() {
 		if err := templatev1.Install(mgr.GetScheme()); err != nil {


Test patch:
diff --git a/controllers/argocd/deployment_test.go b/controllers/argocd/deployment_test.go
index 843c01b7..316423db 100644
--- a/controllers/argocd/deployment_test.go
+++ b/controllers/argocd/deployment_test.go
@@ -866,6 +866,15 @@ func TestReconcileArgoCD_reconcileDexDeployment(t *testing.T) {
 					"/usr/local/bin/argocd",
 					"/shared/argocd-dex",
 				},
+				SecurityContext: &corev1.SecurityContext{
+					AllowPrivilegeEscalation: boolPtr(false),
+					Capabilities: &corev1.Capabilities{
+						Drop: []corev1.Capability{
+							"ALL",
+						},
+					},
+					RunAsNonRoot: boolPtr(true),
+				},
 				VolumeMounts: []corev1.VolumeMount{
 					{
 						Name:      "static-files",
@@ -907,6 +916,15 @@ func TestReconcileArgoCD_reconcileDexDeployment(t *testing.T) {
 						ContainerPort: 5558,
 					},
 				},
+				SecurityContext: &corev1.SecurityContext{
+					AllowPrivilegeEscalation: boolPtr(false),
+					Capabilities: &corev1.Capabilities{
+						Drop: []corev1.Capability{
+							"ALL",
+						},
+					},
+					RunAsNonRoot: boolPtr(true),
+				},
 				VolumeMounts: []corev1.VolumeMount{
 					{Name: "static-files", MountPath: "/shared"}},
 				ImagePullPolicy: corev1.PullAlways,
@@ -958,6 +976,15 @@ func TestReconcileArgoCD_reconcileDexDeployment_withUpdate(t *testing.T) {
 					"/usr/local/bin/argocd",
 					"/shared/argocd-dex",
 				},
+				SecurityContext: &corev1.SecurityContext{
+					AllowPrivilegeEscalation: boolPtr(false),
+					Capabilities: &corev1.Capabilities{
+						Drop: []corev1.Capability{
+							"ALL",
+						},
+					},
+					RunAsNonRoot: boolPtr(true),
+				},
 				VolumeMounts: []corev1.VolumeMount{
 					{
 						Name:      "static-files",
@@ -999,6 +1026,15 @@ func TestReconcileArgoCD_reconcileDexDeployment_withUpdate(t *testing.T) {
 						ContainerPort: 5558,
 					},
 				},
+				SecurityContext: &corev1.SecurityContext{
+					AllowPrivilegeEscalation: boolPtr(false),
+					Capabilities: &corev1.Capabilities{
+						Drop: []corev1.Capability{
+							"ALL",
+						},
+					},
+					RunAsNonRoot: boolPtr(true),
+				},
 				VolumeMounts: []corev1.VolumeMount{
 					{Name: "static-files", MountPath: "/shared"}},
 				ImagePullPolicy: corev1.PullAlways,
@@ -1126,6 +1162,15 @@ func TestReconcileArgoCD_reconcileServerDeployment(t *testing.T) {
 					InitialDelaySeconds: 3,
 					PeriodSeconds:       30,
 				},
+				SecurityContext: &corev1.SecurityContext{
+					AllowPrivilegeEscalation: boolPtr(false),
+					Capabilities: &corev1.Capabilities{
+						Drop: []corev1.Capability{
+							"ALL",
+						},
+					},
+					RunAsNonRoot: boolPtr(true),
+				},
 				VolumeMounts: serverDefaultVolumeMounts(),
 			},
 		},
@@ -1331,6 +1376,15 @@ func TestReconcileArgoCD_reconcileServerDeploymentWithInsecure(t *testing.T) {
 					InitialDelaySeconds: 3,
 					PeriodSeconds:       30,
 				},
+				SecurityContext: &corev1.SecurityContext{
+					AllowPrivilegeEscalation: boolPtr(false),
+					Capabilities: &corev1.Capabilities{
+						Drop: []corev1.Capability{
+							"ALL",
+						},
+					},
+					RunAsNonRoot: boolPtr(true),
+				},
 				VolumeMounts: serverDefaultVolumeMounts(),
 			},
 		},
@@ -1407,6 +1461,15 @@ func TestReconcileArgoCD_reconcileServerDeploymentChangedToInsecure(t *testing.T
 					InitialDelaySeconds: 3,
 					PeriodSeconds:       30,
 				},
+				SecurityContext: &corev1.SecurityContext{
+					AllowPrivilegeEscalation: boolPtr(false),
+					Capabilities: &corev1.Capabilities{
+						Drop: []corev1.Capability{
+							"ALL",
+						},
+					},
+					RunAsNonRoot: boolPtr(true),
+				},
 				VolumeMounts: serverDefaultVolumeMounts(),
 			},
 		},
diff --git a/controllers/argocd/notifications_test.go b/controllers/argocd/notifications_test.go
index 143a7add..23ab0f5f 100644
--- a/controllers/argocd/notifications_test.go
+++ b/controllers/argocd/notifications_test.go
@@ -148,6 +148,14 @@ func TestReconcileNotifications_CreateDeployments(t *testing.T) {
 		Image:           argoutil.CombineImageTag(common.ArgoCDDefaultArgoImage, common.ArgoCDDefaultArgoVersion),
 		ImagePullPolicy: corev1.PullAlways,
 		Name:            "argocd-notifications-controller",
+		SecurityContext: &corev1.SecurityContext{
+			AllowPrivilegeEscalation: boolPtr(false),
+			Capabilities: &corev1.Capabilities{
+				Drop: []corev1.Capability{
+					"ALL",
+				},
+			},
+		},
 		VolumeMounts: []corev1.VolumeMount{
 			{
 				Name:      "tls-certs",
diff --git a/controllers/argocd/role_test.go b/controllers/argocd/role_test.go
index 12e88273..615bef0c 100644
--- a/controllers/argocd/role_test.go
+++ b/controllers/argocd/role_test.go
@@ -37,7 +37,7 @@ func TestReconcileArgoCD_reconcileRole(t *testing.T) {
 	assert.Equal(t, expectedRules, reconciledRole.Rules)
 
 	// update reconciledRole policy rules to RedisHa policy rules
-	reconciledRole.Rules = policyRuleForRedisHa()
+	reconciledRole.Rules = policyRuleForRedisHa(r.Client)
 	assert.NoError(t, r.Client.Update(context.TODO(), reconciledRole))
 
 	// Check if the RedisHa policy rules are overwritten to Application Controller
@@ -66,7 +66,7 @@ func TestReconcileArgoCD_reconcileRole_for_new_namespace(t *testing.T) {
 	assert.Equal(t, expectedRoleNamespace, dexRoles[0].ObjectMeta.Namespace)
 	// check no redisHa role is created for the new namespace with managed-by label
 	workloadIdentifier = common.ArgoCDRedisHAComponent
-	expectedRedisHaRules := policyRuleForRedisHa()
+	expectedRedisHaRules := policyRuleForRedisHa(r.Client)
 	redisHaRoles, err := r.reconcileRole(workloadIdentifier, expectedRedisHaRules, a)
 	assert.NoError(t, err)
 	assert.Equal(t, expectedNumberOfRoles, len(redisHaRoles))
@@ -126,7 +126,7 @@ func TestReconcileArgoCD_reconcileClusterRole(t *testing.T) {
 	assert.Equal(t, expectedRules, reconciledClusterRole.Rules)
 
 	// update reconciledRole policy rules to RedisHa policy rules
-	reconciledClusterRole.Rules = policyRuleForRedisHa()
+	reconciledClusterRole.Rules = policyRuleForRedisHa(r.Client)
 	assert.NoError(t, r.Client.Update(context.TODO(), reconciledClusterRole))
 
 	// Check if the RedisHa policy rules are overwritten to Application Controller
diff --git a/controllers/argocd/rolebinding_test.go b/controllers/argocd/rolebinding_test.go
index 45435567..fb3ab833 100644
--- a/controllers/argocd/rolebinding_test.go
+++ b/controllers/argocd/rolebinding_test.go
@@ -63,7 +63,7 @@ func TestReconcileArgoCD_reconcileRoleBinding_for_new_namespace(t *testing.T) {
 
 	// check no redisHa rolebinding is created for the new namespace with managed-by label
 	workloadIdentifier = common.ArgoCDRedisHAComponent
-	expectedRedisHaRules := policyRuleForRedisHa()
+	expectedRedisHaRules := policyRuleForRedisHa(r.Client)
 	assert.NoError(t, r.reconcileRoleBinding(workloadIdentifier, expectedRedisHaRules, a))
 	assert.Error(t, r.Client.Get(context.TODO(), types.NamespacedName{Name: expectedName, Namespace: "newTestNamespace"}, roleBinding))
 }
diff --git a/controllers/argocd/route_test.go b/controllers/argocd/route_test.go
index 0f1e8e55..2272335e 100644
--- a/controllers/argocd/route_test.go
+++ b/controllers/argocd/route_test.go
@@ -17,6 +17,7 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/reconcile"
 
 	"github.com/google/go-cmp/cmp"
+	configv1 "github.com/openshift/api/config/v1"
 	routev1 "github.com/openshift/api/route/v1"
 
 	argov1alpha1 "github.com/argoproj-labs/argocd-operator/api/v1alpha1"
@@ -205,6 +206,7 @@ func makeReconciler(t *testing.T, acd *argov1alpha1.ArgoCD, objs ...runtime.Obje
 	s := scheme.Scheme
 	s.AddKnownTypes(argov1alpha1.GroupVersion, acd)
 	routev1.Install(s)
+	configv1.Install(s)
 	cl := fake.NewFakeClient(objs...)
 	return &ReconcileArgoCD{
 		Client: cl,
diff --git a/controllers/argocd/service_account_test.go b/controllers/argocd/service_account_test.go
index c7a700ab..f3c5d227 100644
--- a/controllers/argocd/service_account_test.go
+++ b/controllers/argocd/service_account_test.go
@@ -53,7 +53,7 @@ func TestReconcileArgoCD_reconcileServiceAccountPermissions(t *testing.T) {
 	assert.Equal(t, expectedRules, reconciledRole.Rules)
 
 	// undesirable changes
-	reconciledRole.Rules = policyRuleForRedisHa()
+	reconciledRole.Rules = policyRuleForRedisHa(r.Client)
 	assert.NoError(t, r.Client.Update(context.TODO(), reconciledRole))
 
 	// fetch it
diff --git a/controllers/argocd/util_test.go b/controllers/argocd/util_test.go
index 0acfe5b7..df44e120 100644
--- a/controllers/argocd/util_test.go
+++ b/controllers/argocd/util_test.go
@@ -10,6 +10,7 @@ import (
 	"time"
 
 	"github.com/stretchr/testify/assert"
+	logf "sigs.k8s.io/controller-runtime/pkg/log"
 
 	argoprojv1alpha1 "github.com/argoproj-labs/argocd-operator/api/v1alpha1"
 	"github.com/argoproj-labs/argocd-operator/common"
@@ -627,34 +628,6 @@ func TestSetManagedNamespaces(t *testing.T) {
 	}
 }
 
-func TestGetRedisConf(t *testing.T) {
-	s1 := getRedisConf(true)
-	//assert.Equal(t, "", s1)
-
-	s1 = getRedisConf(false)
-	//assert.Equal(t, "", s1)
-
-	s1 = getRedisSentinelConf(true)
-	//assert.Equal(t, "", s1)
-
-	s1 = getRedisSentinelConf(false)
-	//assert.Equal(t, "", s1)
-
-	a := makeTestArgoCD()
-
-	s1 = getRedisInitScript(a, true)
-	//assert.Equal(t, "", s1)
-
-	s1 = getRedisLivenessScript(false)
-	//assert.Equal(t, "", s1)
-
-	s1 = getRedisReadinessScript(true)
-	//assert.Equal(t, "", s1)
-
-	s1 = getSentinelLivenessScript(true)
-	assert.Equal(t, "", s1)
-}
-
 func TestGenerateRandomString(t *testing.T) {
 
 	// verify the creation of unique strings
@@ -680,3 +653,25 @@ func generateEncodedPEM(t *testing.T, host string) []byte {
 	encoded := argoutil.EncodeCertificatePEM(cert)
 	return encoded
 }
+
+// TestReconcileArgoCD_reconcileDexOAuthClientSecret This test make sures that if dex is enabled a service account is created with token stored in a secret which is used for oauth
+func TestReconcileArgoCD_reconcileDexOAuthClientSecret(t *testing.T) {
+	logf.SetLogger(ZapLogger(true))
+	a := makeTestArgoCD()
+	a.Spec.Dex.OpenShiftOAuth = true
+	r := makeTestReconciler(t, a)
+	assert.NoError(t, createNamespace(r, a.Namespace, ""))
+	_, err := r.reconcileServiceAccount(common.ArgoCDDefaultDexServiceAccountName, a)
+	assert.NoError(t, err)
+	_, err = r.getDexOAuthClientSecret(a)
+	assert.NoError(t, err)
+	sa := newServiceAccountWithName(common.ArgoCDDefaultDexServiceAccountName, a)
+	assert.NoError(t, argoutil.FetchObject(r.Client, a.Namespace, sa.Name, sa))
+	tokenExists := false
+	for _, saSecret := range sa.Secrets {
+		if strings.Contains(saSecret.Name, "dex-server-token") {
+			tokenExists = true
+		}
+	}
+	assert.True(t, tokenExists, "Dex is enabled but unable to create oauth client secret")
+}
diff --git a/tests/k8s/1-005_validate-custom-argocd-namespace/02-assert.yaml b/tests/k8s/1-005_validate-custom-argocd-namespace/02-assert.yaml
index f4303c51..4f2b135d 100644
--- a/tests/k8s/1-005_validate-custom-argocd-namespace/02-assert.yaml
+++ b/tests/k8s/1-005_validate-custom-argocd-namespace/02-assert.yaml
@@ -1,3 +1,7 @@
+apiVersion: kuttl.dev/v1beta1
+kind: TestAssert
+timeout: 600
+---
 apiVersion: argoproj.io/v1alpha1
 kind: Application
 metadata: