Skip to content
Merged
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
13 changes: 9 additions & 4 deletions charts/kubernetes-agent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,12 @@ The Kubernetes monitor is optionally installed alongside the Kubernetes agent, [
| agent.pollingProxy | object | `{"host":"","password":"","port":80,"username":""}` | The host, port, username and password of the proxy server to use for polling connections |
| agent.preinstall.containers.tentacle.env | list | `[]` | Additional env to apply to the pre-install tentacle container - does not override any other configuration |
| agent.preinstall.containers.tentacle.spec | object | `{}` | Additional container spec to apply to the pre-install tentacle container - does not override any other configuration |
| agent.preinstall.roleRules | list | `[{"apiGroups":[""],"resources":["configmaps","secrets"],"verbs":["get","list","watch","create","update","patch","delete"]}]` | If set to a non-empty list, completely replaces the default Role rules for the pre-install registration role. Note: `[]` (empty list) means "use defaults", not "no rules". |
| agent.preinstall.serviceAccount.annotations | object | `{}` | Annotations to add to the autogenerated pre-install registration service account |
| agent.preinstall.serviceAccount.name | string | Generates a name based on `agent.serviceAccount.name`, appending `-pre` | The name of the service account for the agent pre-install registration pod |
| agent.preinstall.spec | object | `{}` | Additional pod spec to apply to the pre-install pod - does not override any other agent configuration |
| agent.resources | object | `{"requests":{"cpu":"100m","memory":"150Mi"}}` | The resource limits and requests assigned to the agent container |
| agent.roleRules | list | Core API resources (pods, pods/log, configmaps, secrets, events) with full CRUD verbs, plus read-only access to apps/deployments. | If set to a non-empty list, completely replaces the default Role rules for the tentacle role. Note: `[]` (empty list) means "use defaults", not "no rules". CRD rules for `agent.octopus.com/scriptpodtemplates` are appended when `scriptPods.podTemplate.enabled=true` and `scriptPods.podTemplate.crdDisabled` is not `true`. |
| agent.securityContext | object | `{}` | The security context to apply to the agent pod. runAsGroup and fsGroup should be blank or set to `0` |
| agent.serverApiKey | string | `""` | An Octopus Server API key used to authenticate with the target Octopus Server |
| agent.serverApiKeySecretName | string | `""` | The name of an existing Secret that contains a base64-encoded Octopus Server API Key. Value must be set in `data.api-key` in secret. |
Expand Down Expand Up @@ -122,8 +124,9 @@ The Kubernetes monitor is optionally installed alongside the Kubernetes agent, [

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| autoUpgrader.selfNamespaceRoleRules | list | `[{"apiGroups":["*"],"resources":["*"],"verbs":["*"]}]` | Rules for managing the agent in its own namespace when using namespace-scoped roles |
| autoUpgrader.targetNamespaceRoleRules | list | `[{"apiGroups":["rbac.authorization.k8s.io"],"resources":["roles","rolebindings"],"verbs":["create","update","patch","get","list","watch","delete"]},{"apiGroups":["rbac.authorization.k8s.io"],"resources":["roles"],"verbs":["escalate"]}]` | Rules for managing script pod roles in target namespaces when using namespace-scoped roles |
| autoUpgrader.clusterRoleRules | list | `[{"apiGroups":["*"],"resources":["*"],"verbs":["*"]}]` | If set to a non-empty list, completely replaces the default ClusterRole rules for the auto-upgrader. This ClusterRole is only created when `scriptPods.serviceAccount.useNamespacedRoles` is false. Note: `[]` (empty list) means "use defaults", not "no rules". |
| autoUpgrader.selfNamespaceRoleRules | list | `[{"apiGroups":["*"],"resources":["*"],"verbs":["*"]}]` | If set to a non-empty list, completely replaces the default Role rules for managing the agent in its own namespace when using namespace-scoped roles. Note: `[]` (empty list) means "use defaults", not "no rules". |
| autoUpgrader.targetNamespaceRoleRules | list | `[{"apiGroups":["rbac.authorization.k8s.io"],"resources":["roles","rolebindings"],"verbs":["create","update","patch","get","list","watch","delete"]},{"apiGroups":["rbac.authorization.k8s.io"],"resources":["roles"],"verbs":["escalate"]}]` | If set to a non-empty list, completely replaces the default Role rules for managing script pod roles in target namespaces when using namespace-scoped roles. Note: `[]` (empty list) means "use defaults", not "no rules". |

### Globals

Expand Down Expand Up @@ -167,6 +170,7 @@ The Kubernetes monitor is optionally installed alongside the Kubernetes agent, [
| scriptPods.logging.disablePodEventsInTaskLog | bool | `false` | Disables script pod events being written to Octopus Server task log |
| scriptPods.metadata | object | `{"annotations":{},"labels":{}}` | Additional metadata to add to script pods |
| scriptPods.pendingPodsTimeoutMinutes | int | `60` | The number of minutes a script pod remains pending before it is deleted @default 60 |
| scriptPods.podTemplate.crdDisabled | bool | `false` | If true, disables the CRD RBAC rules for scriptpodtemplates in the tentacle role even when podTemplate is enabled |
| scriptPods.podTemplate.enabled | bool | `false` | overrides any other script pod customisation options and requires the `ScriptPodTemplate` CRD to be installed in the cluster |
| scriptPods.podTemplate.podMetadata | object | `{"annotations":{},"labels":{}}` | Pod metadata for the `ScriptPodTemplate` |
| scriptPods.podTemplate.podSpec | object | `{}` | Pod spec for the `ScriptPodTemplate` |
Expand All @@ -178,13 +182,14 @@ The Kubernetes monitor is optionally installed alongside the Kubernetes agent, [
| scriptPods.resources | object | `{"requests":{"cpu":"25m","memory":"100Mi"}}` | The resource limits and requests assigned to script pod containers |
| scriptPods.securityContext | object | `{}` | The security context to apply to the script pods |
| scriptPods.serviceAccount.annotations | object | `{}` | Annotations to add to the service account |
| scriptPods.serviceAccount.clusterRole | object | `[{"apiGroups":["*"],"resources":["*"],"verbs":["*"]},{"nonResourceURLs":["*"],"verbs":["*"]}]` | if defined, overrides the default ClusterRole rules |
| scriptPods.serviceAccount.clusterRole | object | `[{"apiGroups":["*"],"resources":["*"],"verbs":["*"]},{"nonResourceURLs":["*"],"verbs":["*"]}]` | If set to a non-empty list, completely replaces the default ClusterRole rules. Note: `[]` (empty list) means "use defaults", not "no rules". |
| scriptPods.serviceAccount.name | string | `""` | The name of the service account used for executing script pods |
| scriptPods.serviceAccount.roleRules | list | `[{"apiGroups":["*"],"resources":["*"],"verbs":["*"]}]` | if defined, overrides the default Role rules when using namespace-scoped roles |
| scriptPods.serviceAccount.roleRules | list | `[{"apiGroups":["*"],"resources":["*"],"verbs":["*"]}]` | If set to a non-empty list, completely replaces the default Role rules when using namespace-scoped roles. Note: `[]` (empty list) means "use defaults", not "no rules". |
| scriptPods.serviceAccount.targetNamespaces | list | Uses a ClusterRoleBinding to allow the service account to run in any namespace | Specifies that the pod service account should be constrained to target namespaces |
| scriptPods.serviceAccount.useNamespacedRoles | bool | `false` | Use namespace-scoped Roles instead of ClusterRoles |
| scriptPods.tolerations | list | `[]` | The tolerations to apply to script pods |
| scriptPods.worker.image | object | `{"pullPolicy":"IfNotPresent","repository":"octopusdeploy/worker-tools","tag":"ubuntu.22.04"}` | The repository, pullPolicy & tag to use for the script pod image when the agent is a worker |
| scriptPods.workerRoleRules | list | `[{"apiGroups":["*"],"resources":["*"],"verbs":["*"]}]` | If set to a non-empty list, completely replaces the default Role rules for the script pod worker role (only created when `agent.worker.enabled=true`). Note: `[]` (empty list) means "use defaults", not "no rules". |

### Other Values

Expand Down
18 changes: 17 additions & 1 deletion charts/kubernetes-agent/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
{{/*
Validate and render RBAC rule overrides. Accepts a dict with:
- "rules": the value to check (list or empty)
- "name": the values.yaml path name for the error message
Returns the rendered YAML if rules is a non-empty list, or empty string if rules is empty/nil.
Fails with an error if rules is non-nil/non-empty but not a list.
*/}}
{{- define "kubernetes-agent.renderRbacRules" -}}
{{- if .rules -}}
{{- if not (kindIs "slice" .rules) -}}
{{- fail (printf "%s must be a list of RBAC rule objects" .name) -}}
{{- end -}}
{{- .rules | toYaml }}
{{- end -}}
{{- end -}}

{{/*
The name for the agent
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
Expand Down Expand Up @@ -316,4 +332,4 @@ Returns the list as JSON array (use fromJsonArray to deserialize)
{{- else }}
{{- .Values.global.targetNamespaces | toJson }}
{{- end }}
{{- end }}
{{- end }}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ kind: ClusterRole
metadata:
name: {{ include "kubernetes-agent.autoUpgraderClusterRoleName" . }}
rules:
{{- $overrideRules := include "kubernetes-agent.renderRbacRules" (dict "rules" .Values.autoUpgrader.clusterRoleRules "name" "autoUpgrader.clusterRoleRules") }}
{{- if $overrideRules }}
{{ $overrideRules | nindent 2 }}
{{- else }}
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
{{- end }}
{{- end }}
{{- end }}
12 changes: 7 additions & 5 deletions charts/kubernetes-agent/templates/auto-upgrader-roles.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ metadata:
name: {{ $autoUpgraderSelfRoleName }}
namespace: {{ .Release.Namespace | quote }}
rules:
{{- if .Values.autoUpgrader.selfNamespaceRoleRules }}
{{ .Values.autoUpgrader.selfNamespaceRoleRules | toYaml | nindent 2 }}
{{- $overrideRules := include "kubernetes-agent.renderRbacRules" (dict "rules" .Values.autoUpgrader.selfNamespaceRoleRules "name" "autoUpgrader.selfNamespaceRoleRules") }}
{{- if $overrideRules }}
{{ $overrideRules | nindent 2 }}
{{- else }}
- apiGroups: ["*"]
resources: ["*"]
Expand All @@ -21,6 +22,7 @@ rules:

{{- if not (empty $targetNamespaces) }}
# Roles for managing script pod roles/rolebindings in target namespaces
{{- $targetOverrideRules := include "kubernetes-agent.renderRbacRules" (dict "rules" $.Values.autoUpgrader.targetNamespaceRoleRules "name" "autoUpgrader.targetNamespaceRoleRules") }}
{{- range $targetNamespace := $targetNamespaces }}
---
apiVersion: rbac.authorization.k8s.io/v1
Expand All @@ -29,15 +31,15 @@ metadata:
name: {{ $autoUpgraderTargetRoleName }}
namespace: {{ $targetNamespace | quote }}
rules:
{{- if $.Values.autoUpgrader.targetNamespaceRoleRules }}
{{ $.Values.autoUpgrader.targetNamespaceRoleRules | toYaml | nindent 2 }}
{{- if $targetOverrideRules }}
{{ $targetOverrideRules | nindent 2 }}
{{- else }}
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["roles", "rolebindings"]
verbs: ["create", "update", "patch", "get", "list", "watch", "delete"]
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["roles"]
{{/* escalate verb allows us to create roles/rolebindings in this namespace with correct permissions */}}
{{/* escalate verb allows granting permissions in Roles beyond what the auto-upgrader itself holds */}}
verbs: ["escalate"]
{{- end }}
{{- end }}
Expand Down
7 changes: 4 additions & 3 deletions charts/kubernetes-agent/templates/pod-clusterroles.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ kind: ClusterRole
metadata:
name: {{ include "kubernetes-agent.scriptPodClusterRoleName" . }}
rules:
{{- if .Values.scriptPods.serviceAccount.clusterRole.rules}}
{{ .Values.scriptPods.serviceAccount.clusterRole.rules | toYaml| nindent 2 }}
{{- $overrideRules := include "kubernetes-agent.renderRbacRules" (dict "rules" .Values.scriptPods.serviceAccount.clusterRole.rules "name" "scriptPods.serviceAccount.clusterRole.rules") }}
{{- if $overrideRules }}
{{ $overrideRules | nindent 2 }}
{{- else }}
- apiGroups:
- '*'
Expand All @@ -26,7 +27,7 @@ metadata:
name: {{ include "kubernetes-agent.scriptPodDeleterClusterRoleName" . }}
rules:
- apiGroups:
- '*'
- ''
resources:
- 'pods'
verbs:
Expand Down
24 changes: 16 additions & 8 deletions charts/kubernetes-agent/templates/pod-roles.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@ metadata:
name: {{ include "kubernetes-agent.scriptPodWorkerRoleName" . }}
namespace: {{ $.Release.Namespace | quote }}
rules:
{{- $overrideRules := include "kubernetes-agent.renderRbacRules" (dict "rules" .Values.scriptPods.workerRoleRules "name" "scriptPods.workerRoleRules") }}
{{- if $overrideRules }}
{{ $overrideRules | nindent 2 }}
{{- else }}
# Wildcards grant broad namespace-level access; consider scoping to specific resources if worker pods have well-defined permission requirements
- apiGroups:
- '*'
resources:
- '*'
verbs:
- '*'
{{- end }}
{{- end -}}

{{- $podServiceAccountName := include "kubernetes-agent.scriptPodServiceAccountName" . -}}
Expand All @@ -19,6 +25,7 @@ rules:
{{- $targetNamespaces := include "kubernetes-agent.targetNamespaces" . | fromJsonArray -}}

{{- if and .Values.scriptPods.serviceAccount.useNamespacedRoles (not (empty $targetNamespaces)) }}
{{- $roleOverrideRules := include "kubernetes-agent.renderRbacRules" (dict "rules" $.Values.scriptPods.serviceAccount.roleRules "name" "scriptPods.serviceAccount.roleRules") }}
{{- range $targetNamespace := $targetNamespaces }}
---
apiVersion: rbac.authorization.k8s.io/v1
Expand All @@ -27,15 +34,16 @@ metadata:
name: {{ $podRoleName }}
namespace: {{ $targetNamespace | quote }}
rules:
{{- if $.Values.scriptPods.serviceAccount.roleRules }}
{{ $.Values.scriptPods.serviceAccount.roleRules | toYaml | nindent 2 }}
{{- if $roleOverrideRules }}
{{ $roleOverrideRules | nindent 2 }}
{{- else }}
- apiGroups:
- '*'
resources:
- '*'
verbs:
- '*'
# Wildcards are retained because script pods execute arbitrary user scripts and the required permissions are not predictable
- apiGroups:
- '*'
resources:
- '*'
verbs:
- '*'
{{- end }}
{{- end }}
{{- end }}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ metadata:
annotations:
{{- include "kubernetes-agent.hookAnnotationsWithSuccessDelete" . | nindent 4 }}
rules:
- apiGroups: ["*"]
resources: ["configmaps", "secrets"]
verbs: ["*"]
{{- $overrideRules := include "kubernetes-agent.renderRbacRules" (dict "rules" .Values.agent.preinstall.roleRules "name" "agent.preinstall.roleRules") }}
{{- if $overrideRules }}
{{ $overrideRules | nindent 2 }}
{{- else }}
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
{{- end }}
2 changes: 1 addition & 1 deletion charts/kubernetes-agent/templates/script-pdb.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: script-pod-disruption-budget
name: {{ printf "%s-script-pdb" (include "kubernetes-agent.fullName" .) | trunc 63 | trimSuffix "-" }}
namespace: {{ .Release.Namespace }}
spec:
minAvailable: 8888
Expand Down
25 changes: 16 additions & 9 deletions charts/kubernetes-agent/templates/tentacle-role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,19 @@ metadata:
name: {{ printf "%s-role" (include "kubernetes-agent.serviceAccountName" .) }}
namespace: {{ .Release.Namespace | quote }}
rules:
- apiGroups: ["*"]
resources: ["pods", "pods/log", "configmaps", "secrets", "events"]
verbs: ["*"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch"]
- apiGroups: ["agent.octopus.com"]
resources: ["*"]
verbs: ["*"]
{{- $overrideRules := include "kubernetes-agent.renderRbacRules" (dict "rules" .Values.agent.roleRules "name" "agent.roleRules") }}
{{- if $overrideRules }}
{{ $overrideRules | nindent 2 }}
{{- else }}
- apiGroups: [""]
resources: ["pods", "pods/log", "configmaps", "secrets", "events"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if and .Values.scriptPods.podTemplate.enabled (not .Values.scriptPods.podTemplate.crdDisabled) }}
- apiGroups: ["agent.octopus.com"]
resources: ["scriptpodtemplates"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
{{- end }}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ should match snapshot:
name: octopus-agent-scripts-RELEASE-NAME-delete-role
rules:
- apiGroups:
- '*'
- ""
resources:
- pods
verbs:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
should match snapshot:
1: |
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
annotations:
helm.sh/hook: pre-install
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
helm.sh/hook-weight: "-10"
name: octopus-agent-tentacle-pre-role
namespace: NAMESPACE
rules:
- apiGroups:
- ""
resources:
- configmaps
- secrets
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ should match snapshot:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: script-pod-disruption-budget
name: octopus-agent-RELEASE-NAME-script-pdb
namespace: NAMESPACE
spec:
minAvailable: 8888
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,21 @@ should match snapshot:
namespace: NAMESPACE
rules:
- apiGroups:
- '*'
- ""
resources:
- pods
- pods/log
- configmaps
- secrets
- events
verbs:
- '*'
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- apps
resources:
Expand All @@ -24,9 +30,3 @@ should match snapshot:
- get
- list
- watch
- apiGroups:
- agent.octopus.com
resources:
- '*'
verbs:
- '*'
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
suite: "pod permissions"
suite: "auto-upgrader clusterbinding permissions"
templates:
- templates/auto-upgrader-clusterbinding.yaml
tests:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
suite: "pod permissions"
suite: "auto-upgrader clusterrole permissions"
templates:
- templates/auto-upgrader-clusterrole.yaml
tests:
Expand All @@ -14,3 +14,38 @@ tests:
asserts:
- hasDocuments:
count: 0

- it: "should use wildcard default rules when no override is provided"
asserts:
- contains:
path: rules
content:
apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]

- it: "should use custom rules when autoUpgrader.clusterRoleRules is set"
set:
autoUpgrader:
clusterRoleRules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "update"]
asserts:
- contains:
path: rules
content:
apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "update"]
- lengthEqual:
path: rules
count: 1

- it: "should fail when autoUpgrader.clusterRoleRules is not a list"
set:
autoUpgrader:
clusterRoleRules: "not-a-list"
asserts:
- failedTemplate:
errorMessage: "autoUpgrader.clusterRoleRules must be a list of RBAC rule objects"
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,5 @@ tests:
- equal:
path: kind
value: RoleBinding
documentIndex: 1
documentIndex: 1

Loading
Loading