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

fix(notifications): Include ClusterRole manifests in cluster-wide installation #16153

Closed
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
7 changes: 4 additions & 3 deletions docs/operator-manual/app-any-namespace.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ To enable annotation based resource tracking, refer to the documentation about [

In order for an application to be managed and reconciled outside the Argo CD's control plane namespace, two prerequisites must match:

1. The `Application`'s namespace must be explicitly enabled using the `--application-namespaces` parameter for the `argocd-application-controller` and `argocd-server` workloads. This parameter controls the list of namespaces that Argo CD will be allowed to source `Application` resources from globally. Any namespace not configured here cannot be used from any `AppProject`.
1. The `Application`'s namespace must be explicitly enabled using the `--application-namespaces` parameter for the `argocd-application-controller`, `argocd-server`, and `argocd-notifications-controller` workloads. This parameter controls the list of namespaces that Argo CD will be allowed to source `Application` resources from globally. Any namespace not configured here cannot be used from any `AppProject`.
1. The `AppProject` referenced by the `.spec.project` field of the `Application` must have the namespace listed in its `.spec.sourceNamespaces` field. This setting will determine whether an `Application` may use a certain `AppProject`. If an `Application` specifies an `AppProject` that is not allowed, Argo CD refuses to process this `Application`. As stated above, any namespace configured in the `.spec.sourceNamespaces` field must also be enabled globally.

`Applications` in different namespaces can be created and managed just like any other `Application` in the `argocd` namespace previously, either declaratively or through the Argo CD API (e.g. using the CLI, the web UI, the REST API, etc).
Expand All @@ -43,11 +43,11 @@ In order for an application to be managed and reconciled outside the Argo CD's c

#### Change workload startup parameters

In order to enable this feature, the Argo CD administrator must reconfigure the `argocd-server` and `argocd-application-controller` workloads to add the `--application-namespaces` parameter to the container's startup command.
In order to enable this feature, the Argo CD administrator must reconfigure the `argocd-server`, `argocd-application-controller`, and `argocd-notifications-controller` workloads to add the `--application-namespaces` parameter to the container's startup command.

The `--application-namespaces` parameter takes a comma-separated list of namespaces where `Applications` are to be allowed in. Each entry of the list supports shell-style wildcards such as `*`, so for example the entry `app-team-*` would match `app-team-one` and `app-team-two`. To enable all namespaces on the cluster where Argo CD is running on, you can just specify `*`, i.e. `--application-namespaces=*`.

The startup parameters for both, the `argocd-server` and the `argocd-application-controller` can also be conveniently set up and kept in sync by specifying the `application.namespaces` settings in the `argocd-cmd-params-cm` ConfigMap _instead_ of changing the manifests for the respective workloads. For example:
The startup parameters, for all of `argocd-server`, `argocd-application-controller`, and `argocd-notifications-controller`, can also be conveniently set up and kept in sync by specifying the `application.namespaces` settings in the `argocd-cmd-params-cm` ConfigMap _instead_ of changing the manifests for the respective workloads. For example:

```yaml
data:
Expand All @@ -59,6 +59,7 @@ would allow the `app-team-one` and `app-team-two` namespaces for managing `Appli
```bash
kubectl rollout restart -n argocd deployment argocd-server
kubectl rollout restart -n argocd statefulset argocd-application-controller
kubectl rollout restart -n argocd deployment argocd-notifications-controller
```

#### Adapt Kubernetes RBAC
Expand Down
1 change: 1 addition & 0 deletions manifests/cluster-rbac/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ kind: Kustomization

resources:
- ./application-controller
- ./notification
- ./server
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/component: notifications-controller
app.kubernetes.io/name: argocd-notifications-controller
app.kubernetes.io/part-of: argocd
name: argocd-notifications-controller
rules:
- apiGroups:
- "argoproj.io"
resources:
- "applications"
verbs:
- get
- list
- watch
- update
- patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/component: notifications-controller
app.kubernetes.io/name: argocd-notifications-controller
app.kubernetes.io/part-of: argocd
name: argocd-notifications-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: argocd-notifications-controller
subjects:
- kind: ServiceAccount
name: argocd-notifications-controller
namespace: argocd
6 changes: 6 additions & 0 deletions manifests/cluster-rbac/notification/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- argocd-notifications-controller-clusterrole.yaml
- argocd-notifications-controller-clusterrolebinding.yaml
37 changes: 37 additions & 0 deletions manifests/ha/install.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20577,6 +20577,26 @@ rules:
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/component: notifications-controller
app.kubernetes.io/name: argocd-notifications-controller
app.kubernetes.io/part-of: argocd
name: argocd-notifications-controller
rules:
- apiGroups:
- argoproj.io
resources:
- applications
verbs:
- get
- list
- watch
- update
- patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/component: server
Expand Down Expand Up @@ -20757,6 +20777,23 @@ subjects:
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/component: notifications-controller
app.kubernetes.io/name: argocd-notifications-controller
app.kubernetes.io/part-of: argocd
name: argocd-notifications-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: argocd-notifications-controller
subjects:
- kind: ServiceAccount
name: argocd-notifications-controller
namespace: argocd
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/component: server
Expand Down
37 changes: 37 additions & 0 deletions manifests/install.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20536,6 +20536,26 @@ rules:
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/component: notifications-controller
app.kubernetes.io/name: argocd-notifications-controller
app.kubernetes.io/part-of: argocd
name: argocd-notifications-controller
rules:
- apiGroups:
- argoproj.io
resources:
- applications
verbs:
- get
- list
- watch
- update
- patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/component: server
Expand Down Expand Up @@ -20684,6 +20704,23 @@ subjects:
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/component: notifications-controller
app.kubernetes.io/name: argocd-notifications-controller
app.kubernetes.io/part-of: argocd
name: argocd-notifications-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: argocd-notifications-controller
subjects:
- kind: ServiceAccount
name: argocd-notifications-controller
namespace: argocd
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/component: server
Expand Down
11 changes: 6 additions & 5 deletions notification_controller/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func NewController(
if !ok {
return false, ""
}
if checkAppNotInAdditionalNamespaces(app, namespace, applicationNamespaces) {
if !isAppNamespaceAllowed(app, namespace, applicationNamespaces) {
return true, "app is not in one of the application-namespaces, nor the notification controller namespace"
}
return !isAppSyncStatusRefreshed(app, log.WithField("app", obj.GetName())), "sync status out of date"
Expand All @@ -99,9 +99,10 @@ func NewController(
return res
}

// Check if app is not in the namespace where the controller is in, and also app is not in one of the applicationNamespaces
func checkAppNotInAdditionalNamespaces(app *unstructured.Unstructured, namespace string, applicationNamespaces []string) bool {
return namespace != app.GetNamespace() && !glob.MatchStringInList(applicationNamespaces, app.GetNamespace(), false)
// isAppNamespaceAllowed returns whether app is in the namespace where the controller is in,
// or app is in one of the applicationNamespaces.
func isAppNamespaceAllowed(app *unstructured.Unstructured, namespace string, applicationNamespaces []string) bool {
return namespace == app.GetNamespace() || glob.MatchStringInList(applicationNamespaces, app.GetNamespace(), false)
}

func (c *notificationController) alterDestinations(obj v1.Object, destinations services.Destinations, cfg api.Config) services.Destinations {
Expand Down Expand Up @@ -130,7 +131,7 @@ func newInformer(resClient dynamic.ResourceInterface, controllerNamespace string
}
newItems := []unstructured.Unstructured{}
for _, res := range appList.Items {
if controllerNamespace == res.GetNamespace() || glob.MatchStringInList(applicationNamespaces, res.GetNamespace(), false) {
if isAppNamespaceAllowed(&res, controllerNamespace, applicationNamespaces) {
newItems = append(newItems, res)
}
}
Expand Down
8 changes: 4 additions & 4 deletions notification_controller/controller/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ func TestInitTimeout(t *testing.T) {
assert.Equal(t, "Timed out waiting for caches to sync", err.Error())
}

func TestCheckAppNotInAdditionalNamespaces(t *testing.T) {
func TestIsAppNamespaceAllowed(t *testing.T) {
app := &unstructured.Unstructured{
Object: map[string]interface{}{
"spec": map[string]interface{}{},
Expand All @@ -180,13 +180,13 @@ func TestCheckAppNotInAdditionalNamespaces(t *testing.T) {

// app is in same namespace as controller's namespace
app.SetNamespace(namespace)
assert.False(t, checkAppNotInAdditionalNamespaces(app, namespace, applicationNamespaces))
assert.True(t, isAppNamespaceAllowed(app, namespace, applicationNamespaces))

// app is not in the namespace as controller's namespace, but it is in one of the applicationNamespaces
app.SetNamespace("namespace2")
assert.False(t, checkAppNotInAdditionalNamespaces(app, "", applicationNamespaces))
assert.True(t, isAppNamespaceAllowed(app, "", applicationNamespaces))

// app is not in the namespace as controller's namespace, and it is not in any of the applicationNamespaces
app.SetNamespace("namespace3")
assert.True(t, checkAppNotInAdditionalNamespaces(app, "", applicationNamespaces))
assert.False(t, isAppNamespaceAllowed(app, "", applicationNamespaces))
}
Loading