Skip to content

Commit

Permalink
feat(helm): namespace scoped roles for policy/data loading from confi…
Browse files Browse the repository at this point in the history
…gmaps

Resolves #212

Signed-off-by: Ievgenii Shepeliuk <[email protected]>
  • Loading branch information
eshepelyuk committed Oct 26, 2023
1 parent a7a7b12 commit b50799a
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 25 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
- "logo/**"
- "examples/**"
- "README.md"
- "charts/opa-kube-mgmt/README.md"
branches:
- "master"
pull_request:
Expand Down
11 changes: 4 additions & 7 deletions charts/opa-kube-mgmt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ engine designed for cloud-native environments.

## Overview

This helm chart installs `OPA` together with `kube-mgmt` sidecar,
that allows to manage OPA policies and data via Kubernetes ConfigMaps.
This helm chart installs `OPA` together with `kube-mgmt` sidecar,
that allows to manage OPA policies and data via Kubernetes ``ConfigMaps`.

Optionally, the chart allows to install a [Kubernetes admission
controller](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/).
Expand All @@ -27,9 +27,9 @@ helm repo update
helm upgrade -i -n opa --create-namespace opa opa/opa-kube-mgmt
```

Once installed, the OPA will download a sample bundle from https://www.openpolicyagent.org.
Once installed, the OPA will download a sample bundle from https://www.openpolicyagent.org.
It contains a simple policy that restricts the hostnames that can be specified on Ingress objects created in the
`opa-example` namespace.
`opa-example` namespace.

You can download the bundle and inspect it yourself:

Expand All @@ -38,9 +38,6 @@ mkdir example && cd example
curl -s -L https://www.openpolicyagent.org/bundles/kubernetes/admission | tar xzv
```

See the [NOTES.txt](./templates/NOTES.txt) file for examples of how to exercise
the admission controller.

## Configuration

All configuration settings are contained and described in [values.yaml](values.yaml).
Expand Down
7 changes: 4 additions & 3 deletions charts/opa-kube-mgmt/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,10 @@ spec:
{{- end }}
- --opa-url={{ .Values.useHttps | ternary "https" "http" }}://127.0.0.1:{{ .Values.port }}/v1
- --opa-allow-insecure
- --namespaces={{ coalesce .Values.mgmt.namespaces (list .Release.Namespace) | join "," }}
- --enable-data={{ .Values.mgmt.data.enabled }}
- --enable-policies={{ .Values.mgmt.policies.enabled }}
- "--namespaces={{ coalesce .Values.mgmt.namespaces (list .Release.Namespace) | join "," }}"
- "--enable-data={{ .Values.mgmt.data.enabled }}"
- "--enable-policies={{ .Values.mgmt.policies.enabled }}"

- "--replicate-path={{ .Values.mgmt.replicate.path }}"
{{- range .Values.mgmt.replicate.namespace }}
- "--replicate={{ . }}"
Expand Down
88 changes: 76 additions & 12 deletions charts/opa-kube-mgmt/templates/rbac-mgmt.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
{{- define "opa.rbac.cm.rules" -}}
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "watch", "update", "patch"]
{{- end -}}

{{- if and .Values.rbac.create .Values.mgmt.enabled -}}
{{- if eq (.Values.mgmt.namespaces | join ",") "*" }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
Expand All @@ -9,18 +17,7 @@ metadata:
release: {{ .Release.Name }}
component: mgmt
name: {{ template "opa.mgmtfullname" . }}
rules:
# Allow kube-mgmt to have "get", "list" and "watch" actions over ConfigMaps at a cluster level
# to allow loading policies from any namespace.
# Additionally, allow "patch" and "update" actionson ConfigMaps so kube-mgmt can
# annotate the ConfigMaps to indicate if they were loaded successfully or not.
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "watch", "update", "patch"]

- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get", "list", "watch"]
{{ include "opa.rbac.cm.rules" . }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
Expand All @@ -39,4 +36,71 @@ subjects:
- kind: ServiceAccount
name: {{ template "opa.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- else if and (eq (kindOf .Values.mgmt.namespaces) "slice") (gt (len .Values.mgmt.namespaces) 0) }}
{{- range .Values.mgmt.namespaces }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app: {{ template "opa.name" $ }}
chart: {{ template "opa.chart" $ }}
release: {{ $.Release.Name }}
component: mgmt
name: {{ template "opa.mgmtfullname" $ }}
namespace: {{ . }}
{{ include "opa.rbac.cm.rules" $ }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app: {{ template "opa.name" $ }}
chart: {{ template "opa.chart" $ }}
release: {{ $.Release.Name }}
component: mgmt
name: {{ template "opa.mgmtfullname" $ }}
namespace: {{ . }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ template "opa.mgmtfullname" $ }}
subjects:
- kind: ServiceAccount
name: {{ template "opa.serviceAccountName" $ }}
namespace: {{ $.Release.Namespace }}
{{- end }}
{{- else }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app: {{ template "opa.name" . }}
chart: {{ template "opa.chart" . }}
release: {{ .Release.Name }}
component: mgmt
name: {{ template "opa.mgmtfullname" . }}
namespace: {{ .Release.Namespace }}
{{ include "opa.rbac.cm.rules" . }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app: {{ template "opa.name" . }}
chart: {{ template "opa.chart" . }}
release: {{ .Release.Name }}
component: mgmt
name: {{ template "opa.mgmtfullname" . }}
namespace: {{ .Release.Namespace }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ template "opa.mgmtfullname" . }}
subjects:
- kind: ServiceAccount
name: {{ template "opa.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end }}
{{- end -}}
3 changes: 3 additions & 0 deletions charts/opa-kube-mgmt/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ mgmt:
extraArgs: []
extraEnv: []
resources: {}

# if empty - the current namespaces is watched
# if `*` - all namespaces are watched
namespaces: []

# kube-mgmt container will wait until OPA container comes to running state.
Expand Down
29 changes: 29 additions & 0 deletions test/unit/kube-mgmt_args_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,44 @@ templates:
tests:
- it: should have default args
asserts:
- contains:
path: spec.template.spec.containers[1].args
content: "--enable-data=true"
- contains:
path: spec.template.spec.containers[1].args
content: "--enable-data=true"
- contains:
path: spec.template.spec.containers[1].args
content: "--namespaces=NAMESPACE"
- contains:
path: spec.template.spec.containers[1].args
content: "--replicate-ignore-namespaces="
- it: should override args
set:
mgmt:
namespaces: ["111", "222"]
replicate:
ignoreNs: ["qwe", "asd"]
asserts:
- contains:
path: spec.template.spec.containers[1].args
content: "--replicate-ignore-namespaces=qwe,asd"
- contains:
path: spec.template.spec.containers[1].args
content: "--namespaces=111,222"
- it: should override all namespaces 1
set:
mgmt:
namespaces: ["*"]
asserts:
- contains:
path: spec.template.spec.containers[1].args
content: "--namespaces=*"
- it: should override all namespaces 2
set:
mgmt:
namespaces: "*"
asserts:
- contains:
path: spec.template.spec.containers[1].args
content: "--namespaces=*"
68 changes: 65 additions & 3 deletions test/unit/rbac_cm_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,68 @@ suite: test configmap rbac
templates:
- rbac-mgmt.yaml
tests:
- it: should create cluster role by default
- it: should create current namespace role by default
asserts:
- hasDocuments:
count: 2
- containsDocument:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
namespace: NAMESPACE
any: true
- containsDocument:
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
namespace: NAMESPACE
any: true

- it: should create namespace roles when namespaces configured
set:
mgmt:
namespaces: ["qwe", "asd"]
asserts:
- hasDocuments:
count: 4
- containsDocument:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
namespace: "qwe"
any: true
- containsDocument:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
namespace: "asd"
any: true
- containsDocument:
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
namespace: "qwe"
any: true
- containsDocument:
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
namespace: "asd"
any: true

- it: should create cluster role if namespace is asterisk
set:
mgmt:
namespaces: "*"
asserts:
- hasDocuments:
count: 2
- containsDocument:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
any: true
- containsDocument:
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
any: true
- it: should create cluster role if namespace is single item array with asterisk
set:
mgmt:
namespaces: ["*"]
asserts:
- hasDocuments:
count: 2
Expand All @@ -14,14 +75,15 @@ tests:
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
any: true
- it: should not create cluster role if rbac disabled

- it: should not create roles if rbac disabled
set:
rbac:
create: false
asserts:
- hasDocuments:
count: 0
- it: should not create cluster role if mgmt disabled
- it: should not create roles if mgmt disabled
set:
mgmt:
enabled: false
Expand Down

0 comments on commit b50799a

Please sign in to comment.