diff --git a/README.md b/README.md index 893cb97..d1fb07e 100644 --- a/README.md +++ b/README.md @@ -96,3 +96,53 @@ $ kubectl delete crd workspaces.app.terraform.io ``` If the CRD is not updated correctly, you will not be able to create a Workspace Custom Resource. + + + +### Helm Chart + +The Helm chart consists of several components. The Kubernetes configurations associated with the Helm chart are located under `crds/` and `templates/`. + +#### Custom Resource Definition + +Helm starts by deploying the Custom Resource Definition for the Workspace. Custom Resource Definitions extend the Kubernetes API. It looks for definitions in the `crds/` of the chart. + +The Custom Resource Definition under `crds/app.terraform.io_workspaces_crd.yaml` defines that the Workspace Custom Resource schema. + +#### Role-Based Access Control + +In order to scope the operator to a namespace, Helm assigns a role and service account to the namespace. The role has access to Pods, Secrets, Services, and ConfigMaps. This configuration is located in `templates/`. + +#### Namespace Scope + +To ensure the operator does not have access to secrets or resource beyond the namespace, the Helm chart scopes the operator's deployment to a namespace. + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: terraform-k8s +spec: + # some sections omitted for clarity + template: + metadata: + labels: + name: terraform-k8s + spec: + serviceAccountName: terraform-k8s + containers: + - name: terraform-k8s + command: + - /bin/terraform-k8s + - "--k8s-watch-namespace=$(POD_NAMESPACE)" + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace +``` + +When deploying, if you want to explicitly watch all namespaces, +then you'll need to set `watchAllNamespaces: true`. Otherwise, +the default behaviour will be to watch the Release namespace or +the namespace provided in the `k8WatchNamespace` value. diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl index 4ae0f90..a0778e9 100644 --- a/templates/_helpers.tpl +++ b/templates/_helpers.tpl @@ -59,3 +59,14 @@ Inject extra environment vars in the format key:value, if populated {{- end -}} {{- end -}} {{- end -}} + +{{/* +Define the kind of Role to use +*/}} +{{- define "terraform.getRole" -}} +{{- if .Values.syncWorkspace.watchAllNamespaces -}} +{{- "ClusterRole" -}} +{{- else -}} +{{- (ternary "Role" "ClusterRole" (or (empty .Values.syncWorkspace.k8WatchNamespace) (eq (.Values.syncWorkspace.k8WatchNamespace | toString) .Release.Namespace))) -}} +{{- end -}} +{{- end -}} diff --git a/templates/sync-workspace-deployment.yaml b/templates/sync-workspace-deployment.yaml index 73557a2..70892cf 100644 --- a/templates/sync-workspace-deployment.yaml +++ b/templates/sync-workspace-deployment.yaml @@ -66,7 +66,9 @@ spec: - /bin/terraform-k8s args: - --enable-leader-election + {{- if not .Values.syncWorkspace.watchAllNamespaces }} - --k8s-watch-namespace={{ default .Release.Namespace .Values.syncWorkspace.k8WatchNamespace}} + {{- end }} {{- if .Values.syncWorkspace.logLevel }} - --zap-log-level={{ .Values.syncWorkspace.logLevel }} {{- end }} diff --git a/templates/sync-workspace-role.yaml b/templates/sync-workspace-role.yaml index 76e58b4..34d8f50 100644 --- a/templates/sync-workspace-role.yaml +++ b/templates/sync-workspace-role.yaml @@ -1,8 +1,7 @@ {{- $syncEnabled := (or (and (ne (.Values.syncWorkspace.enabled | toString) "-") .Values.syncWorkspace.enabled) (and (eq (.Values.syncWorkspace.enabled | toString) "-") .Values.global.enabled)) }} {{- if $syncEnabled }} apiVersion: rbac.authorization.k8s.io/v1 -{{- $kind := (ternary "Role" "ClusterRole" (or (empty .Values.syncWorkspace.k8WatchNamespace) (eq (.Values.syncWorkspace.k8WatchNamespace | toString) .Release.Namespace))) }} -kind: {{ $kind }} +kind: {{ template "terraform.getRole" . }} metadata: name: {{ template "terraform.fullname" . }}-sync-workspace labels: diff --git a/templates/sync-workspace-rolebinding.yaml b/templates/sync-workspace-rolebinding.yaml index d811b31..35deb6a 100644 --- a/templates/sync-workspace-rolebinding.yaml +++ b/templates/sync-workspace-rolebinding.yaml @@ -1,8 +1,7 @@ {{- $syncEnabled := (or (and (ne (.Values.syncWorkspace.enabled | toString) "-") .Values.syncWorkspace.enabled) (and (eq (.Values.syncWorkspace.enabled | toString) "-") .Values.global.enabled)) }} {{- if $syncEnabled }} apiVersion: rbac.authorization.k8s.io/v1 -{{- $kind := (ternary "Role" "ClusterRole" (or (empty .Values.syncWorkspace.k8WatchNamespace) (eq (.Values.syncWorkspace.k8WatchNamespace | toString) .Release.Namespace))) }} -kind: {{ ternary "RoleBinding" "ClusterRoleBinding" (eq $kind "Role") }} +kind: {{ template "terraform.getRole" . }}Binding metadata: name: {{ template "terraform.fullname" . }}-sync-workspace labels: @@ -15,7 +14,7 @@ subjects: name: {{ template "terraform.fullname" . }}-sync-workspace namespace: {{ .Release.Namespace }} roleRef: - kind: {{ $kind }} + kind: {{ template "terraform.getRole" . }} name: {{ template "terraform.fullname" . }}-sync-workspace apiGroup: rbac.authorization.k8s.io {{- end }} diff --git a/values.yaml b/values.yaml index 3d199ba..03ca852 100644 --- a/values.yaml +++ b/values.yaml @@ -35,6 +35,10 @@ syncWorkspace: # to the release namespace k8WatchNamespace: null + # If true watchAllNamespaces will configure the operator to watch for workspace + # changes across all kubernetes namespaces. + watchAllNamespaces: false + # terraformVersion describes the version of Terraform to use for each workspace. # If this is not set then it will default to the latest version of Terraform # compiled with the operator.