From 491cf57260628d84ba64966fa433dd9d2e40a693 Mon Sep 17 00:00:00 2001 From: Eugene Dobry Date: Fri, 31 Jan 2025 18:43:18 -0500 Subject: [PATCH] implement ns-authz --- ns-authz/Chart.yaml | 6 ++++ ns-authz/README.md | 35 ++++++++++++++++++++++ ns-authz/templates/clusterrolebinding.yaml | 12 ++++++++ ns-authz/templates/configmap.yaml | 7 +++++ ns-authz/templates/deployment.yaml | 32 ++++++++++++++++++++ ns-authz/templates/serviceaccount.yaml | 7 +++++ ns-authz/values.yaml | 18 +++++++++++ ns-authz/watcher.sh | 32 ++++++++++++++++++++ 8 files changed, 149 insertions(+) create mode 100644 ns-authz/Chart.yaml create mode 100644 ns-authz/README.md create mode 100644 ns-authz/templates/clusterrolebinding.yaml create mode 100644 ns-authz/templates/configmap.yaml create mode 100644 ns-authz/templates/deployment.yaml create mode 100644 ns-authz/templates/serviceaccount.yaml create mode 100644 ns-authz/values.yaml create mode 100755 ns-authz/watcher.sh diff --git a/ns-authz/Chart.yaml b/ns-authz/Chart.yaml new file mode 100644 index 0000000..1adaa28 --- /dev/null +++ b/ns-authz/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: ns-authz +description: A Helm chart to automatically grant cluster-admin to the default ServiceAccount in every new namespace. +type: application +version: 0.1.0 +appVersion: "1.0.0" diff --git a/ns-authz/README.md b/ns-authz/README.md new file mode 100644 index 0000000..a6942e0 --- /dev/null +++ b/ns-authz/README.md @@ -0,0 +1,35 @@ +# ns-authz Helm Chart + +This chart deploys a lightweight namespace watcher that automatically grants the \`cluster-admin\` role to the default ServiceAccount in every new namespace. + +## Features + +- Automatic Namespace Detection +- RoleBinding Creation for each new namespace +- Idempotent operation +- Minimal logging +- Self-contained using a lightweight kubectl image +- Helm-based install/uninstall + +## Installation + +```bash +helm install ns-authz ./ns-authz --namespace kube-system +``` + +## Uninstallation + +```bash +helm uninstall ns-authz --namespace kube-system +``` + +## Verification + +1. Create a new namespace: + ```bash + kubectl create namespace test-ns + ``` +2. Check the watcher pod logs: + ```bash + kubectl logs -l app=ns-authz -n kube-system + ``` diff --git a/ns-authz/templates/clusterrolebinding.yaml b/ns-authz/templates/clusterrolebinding.yaml new file mode 100644 index 0000000..cf22004 --- /dev/null +++ b/ns-authz/templates/clusterrolebinding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: ns-authz-crb +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: +- kind: ServiceAccount + name: {{ .Values.serviceAccount.name }} + namespace: {{ .Release.Namespace }} diff --git a/ns-authz/templates/configmap.yaml b/ns-authz/templates/configmap.yaml new file mode 100644 index 0000000..de69d34 --- /dev/null +++ b/ns-authz/templates/configmap.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: ns-authz-script +data: + watcher.sh: |- +{{ (.Files.Get "watcher.sh") | indent 4 }} diff --git a/ns-authz/templates/deployment.yaml b/ns-authz/templates/deployment.yaml new file mode 100644 index 0000000..f5cbcd8 --- /dev/null +++ b/ns-authz/templates/deployment.yaml @@ -0,0 +1,32 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ns-authz + labels: + app: ns-authz +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: ns-authz + template: + metadata: + labels: + app: ns-authz + spec: + serviceAccountName: {{ .Values.serviceAccount.name }} + containers: + - name: ns-authz + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: ["/bin/sh", "/scripts/watcher.sh"] + volumeMounts: + - name: script-volume + mountPath: /scripts + volumes: + - name: script-volume + configMap: + name: ns-authz-script + nodeSelector: {{ toYaml .Values.nodeSelector | nindent 8 }} + tolerations: {{ toYaml .Values.tolerations | nindent 8 }} + affinity: {{ toYaml .Values.affinity | nindent 8 }} diff --git a/ns-authz/templates/serviceaccount.yaml b/ns-authz/templates/serviceaccount.yaml new file mode 100644 index 0000000..755e5ac --- /dev/null +++ b/ns-authz/templates/serviceaccount.yaml @@ -0,0 +1,7 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.serviceAccount.name }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/ns-authz/values.yaml b/ns-authz/values.yaml new file mode 100644 index 0000000..579330d --- /dev/null +++ b/ns-authz/values.yaml @@ -0,0 +1,18 @@ +replicaCount: 1 + +image: + repository: bitnami/kubectl + tag: latest + pullPolicy: IfNotPresent + +serviceAccount: + name: ns-authz-sa + create: true + +resources: {} + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/ns-authz/watcher.sh b/ns-authz/watcher.sh new file mode 100755 index 0000000..9437a45 --- /dev/null +++ b/ns-authz/watcher.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +ROLEBINDING_NAME="cluster-admin-binding" + +echo "starting namespace watcher..." + +ensureClusterRoleBinding() { + local ns="$1" + local sa="$2" + + # Strip off the leading 'namespace/' + local nsName="${1#namespace/}" + local clusterRoleBindingName="${ROLEBINDING_NAME}-${nsName}-${sa}" + + echo "ensuring CRB '$clusterRoleBindingName'..." + + if kubectl get clusterrolebinding "$clusterRoleBindingName" -o name >/dev/null 2>&1; then + echo "CRB already exists, skipping" + return + fi + + echo "creating CRB '$clusterRoleBindingName'..." + + kubectl create clusterrolebinding "$clusterRoleBindingName" \ + --clusterrole=cluster-admin \ + --serviceaccount="${nsName}:${sa}" +} + +kubectl get namespaces --watch -o name | while read ns; do + ensureClusterRoleBinding $ns "default" + ensureClusterRoleBinding $ns "kurtosis-api" +done