Skip to content

Commit fc4f74d

Browse files
authored
feat: Add default rbac for OIDC integration (#37)
1 parent a443b28 commit fc4f74d

File tree

5 files changed

+295
-66
lines changed

5 files changed

+295
-66
lines changed

applications/base/services/keycloak/20-keycloak/kustomization.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@ kind: Kustomization
44
namespace: keycloak
55
resources:
66
- "keycloak-cr.yaml"
7-
- "rbac/"

applications/base/services/keycloak/20-keycloak/rbac/k8s-ops-cluster-role.yaml

Lines changed: 0 additions & 64 deletions
This file was deleted.
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Default RBAC Configuration (OIDC + rbac-manager)
2+
3+
This configuration provides a **structured and scalable role-based access control (RBAC)** setup for Kubernetes clusters integrated with **OIDC providers such as Keycloak**.
4+
It defines clear access boundaries for different teams (admins, observability, platform, security, namespace admins, etc.) and leverages **rbac-manager** for automated creation and reconciliation of RBAC bindings.
5+
6+
By using **namespace labels** and centralized **OIDC groups**, the configuration enables **multi-team, least-privilege access management** that is both **GitOps-friendly and self-maintaining**.
7+
8+
---
9+
10+
## Prerequisites
11+
12+
1. **[rbac-manager](https://github.com/FairwindsOps/rbac-manager)** must be installed in the cluster.
13+
- This controller manages `RBACDefinition` CRDs and automatically creates RoleBindings and ClusterRoleBindings defined in this configuration.
14+
15+
2. **OIDC integration** must be enabled on the Kubernetes API server.
16+
- The OIDC provider (e.g., Keycloak) should expose user groups (such as `oidc:cluster-admins`, `oidc:observability`, etc.) in the `groups` claim of the OIDC token.
17+
18+
---
19+
20+
## What this configuration enables
21+
22+
| Group | Description |
23+
|--------|--------------|
24+
| **oidc:cluster-admins** | Full cluster-admin access to manage all resources. |
25+
| **oidc:read-only** | Cluster-wide read-only access using the built-in `view` role. |
26+
| **oidc:namespace-admins** | Admin rights only in namespaces labeled `rbac.opencenter.io/admin="true"`. |
27+
| **oidc:security-team** | Cluster-wide read access + admin rights in security-labeled namespaces. |
28+
| **oidc:observability** | Read access to workloads, nodes, logs, metrics, and monitoring CRDs (no Secrets). |
29+
| **oidc:platform-team** | Permission to manage only `RBACDefinition` CRDs used by rbac-manager. |
30+
| **oidc:k8s-ops** | Broad, read-only cluster visibility for operations teams. |
31+
32+
---
33+
34+
## Namespace Label Usage
35+
36+
Namespace labels provide **dynamic, label-driven authorization** so that access adjusts automatically without editing RBAC definitions whenever a new namespace is created.
37+
38+
| Label | Purpose |
39+
|--------|----------|
40+
| `rbac.opencenter.io/admin="true"` | Grants admin privileges to members of `oidc:namespace-admins`. |
41+
| `security.opencenter.io/managed="true"` | Grants admin privileges to `oidc:security-team` in those namespaces. |
42+
43+
**NOTE:** When these labels are added or removed, **rbac-manager automatically updates** the corresponding RoleBindings - ensuring RBAC stays consistent with namespace state.
44+
45+
---
46+
47+
## Deployment
48+
49+
For both **in-cluster IDP (Keycloak)** and **external OIDC providers**, the default RBAC configuration can be deployed via your **GitOps tool (FluxCD)** from your overlay cluster repository.
50+
Just make sure the required **OIDC groups** (`oidc:cluster-admins`, `oidc:observability`, `oidc:namespace-admins`, etc.) are created in the identity provider before users attempt to log in.
51+
52+
---
53+
54+
## Structure Overview
55+
56+
- **ClusterRole: `observability-extras`** - Extends `view` with nodes, logs, metrics, and monitoring CRDs.
57+
- **ClusterRole: `rbacmanager-crd-admin`** - Manages rbac-manager `RBACDefinition` CRDs.
58+
- **ClusterRole: `k8s-ops`** - Provides consolidated, read-only access for operations teams.
59+
- **RBACDefinitions:**
60+
- `oidc-cluster-admins` - Full cluster control
61+
- `oidc-read-only` - Safe cluster-wide read access
62+
- `oidc-observability` - Read + observability extras
63+
- `oidc-namespace-admins` - Admin in namespaces labeled for delegation
64+
- `oidc-security-team` - Cluster read + admin in security namespaces
65+
- `oidc-platform-team` - Manage rbac-manager CRDs
66+
- `oidc-k8s-ops` - Bind OIDC ops group to `k8s-ops` role
67+
68+
---
69+
70+
## Summary
71+
72+
This RBAC configuration provides a **secure, modular, and OIDC-driven access model** for Kubernetes clusters.
73+
It separates team privileges, leverages **namespace labels for delegated control**, and uses **rbac-manager** to keep bindings synchronized automatically.
74+
Whether you're running an **in-cluster Keycloak** or connecting to an **external IdP**, this setup ensures consistent, auditable, and GitOps-friendly RBAC management across all environments.
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
# oidc-cluster-admins - Full cluster-admin access for OIDC cluster admins
2+
# oidc-read-only - Cluster-wide read-only access
3+
# oidc-namespace-admins - Admin rights in namespaces labeled `rbac.opencenter.io/admin="true"`
4+
# oidc-security-team - Security team: view cluster + admin in namespaces labeled `security.opencenter.io/managed="true"`
5+
# oidc-observability - Observability group: view + extras for metrics/logs/monitoring
6+
# oidc-platform-team - Platform team: manage only rbac-manager CRDs
7+
# oidc-k8s-ops – bind ops group to k8s-ops
8+
# k8s-ops - broad read-only (no Secrets, no write) for ops team
9+
# observability-extras - Adds metrics/logs/nodes access to 'view' for observability
10+
# rbacmanager-crd-admin - Manages rbac-manager RBACDefinition CRDs
11+
12+
# ClusterRole: k8s-ops – broad read-only (no Secrets, no write)
13+
apiVersion: rbac.authorization.k8s.io/v1
14+
kind: ClusterRole
15+
metadata:
16+
name: k8s-ops
17+
rules:
18+
- apiGroups: [""]
19+
resources:
20+
- pods
21+
- pods/log
22+
- services
23+
- endpoints
24+
- configmaps
25+
- serviceaccounts
26+
- resourcequotas
27+
- limitranges
28+
- persistentvolumeclaims
29+
- replicationcontrollers
30+
- events
31+
verbs: ["get", "list", "watch"]
32+
- apiGroups: [""]
33+
resources: ["nodes", "namespaces", "persistentvolumes"]
34+
verbs: ["get", "list", "watch"]
35+
- apiGroups: ["apps"]
36+
resources: ["deployments", "daemonsets", "statefulsets", "replicasets"]
37+
verbs: ["get", "list", "watch"]
38+
- apiGroups: ["batch"]
39+
resources: ["jobs", "cronjobs"]
40+
verbs: ["get", "list", "watch"]
41+
- apiGroups: ["networking.k8s.io"]
42+
resources: ["ingresses", "networkpolicies", "ingressclasses"]
43+
verbs: ["get", "list", "watch"]
44+
- apiGroups: ["discovery.k8s.io"]
45+
resources: ["endpointslices"]
46+
verbs: ["get", "list", "watch"]
47+
- apiGroups: ["storage.k8s.io"]
48+
resources:
49+
["storageclasses", "csidrivers", "csinodes", "csistoragecapacities"]
50+
verbs: ["get", "list", "watch"]
51+
- apiGroups: ["coordination.k8s.io"]
52+
resources: ["leases"]
53+
verbs: ["get", "list", "watch"]
54+
- apiGroups: ["events.k8s.io"]
55+
resources: ["events"]
56+
verbs: ["get", "list", "watch"]
57+
- apiGroups: ["metrics.k8s.io"]
58+
resources: ["nodes", "pods"]
59+
verbs: ["get", "list", "watch"]
60+
- nonResourceURLs: ["/healthz", "/readyz", "/livez", "/version"]
61+
verbs: ["get"]
62+
---
63+
# 'observability-extras' ClusterRole – adds metrics/logs/nodes access to 'view'
64+
apiVersion: rbac.authorization.k8s.io/v1
65+
kind: ClusterRole
66+
metadata:
67+
name: observability-extras
68+
rules:
69+
- apiGroups: [""]
70+
resources:
71+
[nodes, nodes/proxy, nodes/metrics, nodes/stats, services/proxy, pods/log]
72+
verbs: [get, list, watch]
73+
- nonResourceURLs: ["/metrics", "/healthz", "/readyz", "/livez", "/version"]
74+
verbs: [get]
75+
- apiGroups: ["monitoring.coreos.com"]
76+
resources:
77+
[
78+
prometheuses,
79+
servicemonitors,
80+
podmonitors,
81+
alertmanagers,
82+
thanosrulers,
83+
prometheusrules,
84+
alertmanagerconfigs,
85+
]
86+
verbs: [get, list, watch]
87+
88+
---
89+
# Let "platform team" manage only rbac-manager CRDs
90+
apiVersion: rbac.authorization.k8s.io/v1
91+
kind: ClusterRole
92+
metadata:
93+
name: rbacmanager-crd-admin
94+
rules:
95+
- apiGroups: ["rbacmanager.reactiveops.io"]
96+
resources: ["rbacdefinitions"]
97+
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
98+
99+
---
100+
# Cluster admins
101+
apiVersion: rbacmanager.reactiveops.io/v1beta1
102+
kind: RBACDefinition
103+
metadata:
104+
name: oidc-cluster-admins
105+
namespace: rbac-system
106+
rbacBindings:
107+
- name: cluster-admins
108+
subjects:
109+
- kind: Group
110+
name: "oidc:cluster-admins"
111+
clusterRoleBindings:
112+
- clusterRole: cluster-admin
113+
114+
---
115+
# Cluster viewers
116+
apiVersion: rbacmanager.reactiveops.io/v1beta1
117+
kind: RBACDefinition
118+
metadata:
119+
name: oidc-read-only
120+
namespace: rbac-system
121+
rbacBindings:
122+
- name: cluster-view
123+
subjects:
124+
- kind: Group
125+
name: "oidc:read-only"
126+
clusterRoleBindings:
127+
- clusterRole: view
128+
129+
---
130+
# Observability — 'view' plus extras, cluster-scoped
131+
apiVersion: rbacmanager.reactiveops.io/v1beta1
132+
kind: RBACDefinition
133+
metadata:
134+
name: oidc-observability
135+
namespace: rbac-system
136+
rbacBindings:
137+
- name: observability-view
138+
subjects:
139+
- kind: Group
140+
name: "oidc:observability"
141+
clusterRoleBindings:
142+
- clusterRole: view
143+
- name: observability-extras
144+
subjects:
145+
- kind: Group
146+
name: "oidc:observability"
147+
clusterRoleBindings:
148+
- clusterRole: observability-extras
149+
150+
---
151+
# Namespace admins
152+
apiVersion: rbacmanager.reactiveops.io/v1beta1
153+
kind: RBACDefinition
154+
metadata:
155+
name: oidc-namespace-admins
156+
namespace: rbac-system
157+
rbacBindings:
158+
- name: ns-admins
159+
subjects:
160+
- kind: Group
161+
name: "oidc:namespace-admins"
162+
roleBindings:
163+
- clusterRole: admin
164+
namespaceSelector:
165+
matchLabels:
166+
rbac.opencenter.io/admin: "true"
167+
168+
---
169+
# Security team — cluster read + admin in security namespaces
170+
apiVersion: rbacmanager.reactiveops.io/v1beta1
171+
kind: RBACDefinition
172+
metadata:
173+
name: oidc-security-team
174+
namespace: rbac-system
175+
rbacBindings:
176+
- name: security-read
177+
subjects:
178+
- kind: Group
179+
name: "oidc:security-team"
180+
clusterRoleBindings:
181+
- clusterRole: view
182+
- name: security-ns-admin
183+
subjects:
184+
- kind: Group
185+
name: "oidc:security-team"
186+
roleBindings:
187+
- clusterRole: admin
188+
namespaceSelector:
189+
matchLabels:
190+
security.opencenter.io/managed: "true"
191+
192+
---
193+
# Platform team — manage only rbac-manager CRDs
194+
apiVersion: rbacmanager.reactiveops.io/v1beta1
195+
kind: RBACDefinition
196+
metadata:
197+
name: oidc-platform-team
198+
namespace: rbac-system
199+
rbacBindings:
200+
- name: platform-rbacdefs-admin
201+
subjects:
202+
- kind: Group
203+
name: "oidc:platform-team"
204+
clusterRoleBindings:
205+
- clusterRole: rbacmanager-crd-admin
206+
---
207+
# oidc-k8s-ops – bind ops group to k8s-ops
208+
apiVersion: rbacmanager.reactiveops.io/v1beta1
209+
kind: RBACDefinition
210+
metadata:
211+
name: oidc-k8s-ops
212+
namespace: rbac-system
213+
rbacBindings:
214+
- name: k8s-ops
215+
subjects:
216+
- kind: Group
217+
name: "oidc:k8s-ops"
218+
apiGroup: rbac.authorization.k8s.io
219+
clusterRoleBindings:
220+
- clusterRole: k8s-ops

applications/base/services/keycloak/20-keycloak/rbac/kustomization.yaml renamed to applications/base/services/keycloak/30-oidc-rbac/kustomization.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
apiVersion: kustomize.config.k8s.io/v1beta1
33
kind: Kustomization
44
resources:
5-
- "k8s-ops-cluster-role.yaml"
5+
- "default-rbac.yaml"

0 commit comments

Comments
 (0)