Skip to content

Commit

Permalink
Merge pull request #1935 from loft-sh/thomaskosiewski/eng-4148-vclust…
Browse files Browse the repository at this point in the history
…er-helm-chart-auto-create-role-and-rolebinding-if

feat(helm): Automatically create role & bindings for namespace containing platform secret
  • Loading branch information
FabianKramm authored Jul 16, 2024
2 parents a902b90 + cc0c731 commit d5475d4
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 1 deletion.
1 change: 1 addition & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ generate-vcluster-images version="0.0.0":
generate-cli-docs:
go run -mod vendor -tags pro ./hack/docs/main.go

# Generate the vcluster.yaml config schema
generate-config-schema:
go run -mod vendor ./hack/schema/main.go

Expand Down
33 changes: 33 additions & 0 deletions chart/templates/_rbac.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,36 @@
{{- end }}
{{- end }}
{{- end -}}

{{/*
Whether to create a role and role binding to access the platform API key secret
*/}}
{{- define "vcluster.rbac.createPlatformSecretRole" -}}
{{- $createRBAC := dig "platform" "apiKey" "createRBAC" true .Values.external -}}
{{- if and $createRBAC (ne (include "vcluster.rbac.platformSecretNamespace" .) .Release.Namespace) }}
{{- true -}}
{{- end }}
{{- end -}}

{{/*
Namespace containing the vCluster platform secret
*/}}
{{- define "vcluster.rbac.platformSecretNamespace" -}}
{{- dig "platform" "apiKey" "namespace" .Release.Namespace .Values.external | default .Release.Namespace -}}
{{- end -}}

{{/*
Name specifies the secret name containing the vCluster platform licenses and tokens
*/}}
{{- define "vcluster.rbac.platformSecretName" -}}
{{- dig "platform" "apiKey" "secretName" "vcluster-platform-api-key" .Values.external | quote -}}
{{- end -}}

{{- define "vcluster.rbac.platformRoleName" -}}
{{- printf "vc-%s-v-%s-platform-role" .Release.Name .Release.Namespace | trunc 63 | trimSuffix "-" -}}
{{- end -}}


{{- define "vcluster.rbac.platformRoleBindingName" -}}
{{- printf "vc-%s-v-%s-platform-role-binding" .Release.Name .Release.Namespace | trunc 63 | trimSuffix "-" -}}
{{- end -}}
31 changes: 31 additions & 0 deletions chart/templates/platform-rbac.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{{- if include "vcluster.rbac.createPlatformSecretRole" . }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "vcluster.rbac.platformRoleName" . }}
namespace: {{ include "vcluster.rbac.platformSecretNamespace" .}}
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
resourceNames:
- {{ include "vcluster.rbac.platformSecretName" . }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "vcluster.rbac.platformRoleBindingName" . }}
namespace: {{ include "vcluster.rbac.platformSecretNamespace" .}}
subjects:
- kind: ServiceAccount
{{- if .Values.controlPlane.advanced.serviceAccount.name }}
name: {{ .Values.controlPlane.advanced.serviceAccount.name }}
{{- else }}
name: vc-{{ .Release.Name }}
{{- end }}
namespace: {{ include "vcluster.rbac.platformSecretNamespace" .}}
roleRef:
kind: Role
name: {{ include "vcluster.rbac.platformRoleName" . }}
apiGroup: rbac.authorization.k8s.io
{{- end }}
114 changes: 114 additions & 0 deletions chart/tests/platform-secret-role_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
suite: Platform Secret Role
templates:
- platform-rbac.yaml

tests:
- it: check explicitly disabled
set:
external:
platform:
apiKey:
namespace: "some-other-namespace"
createRBAC: false
asserts:
- hasDocuments:
count: 0

- it: check disabled on empty namespace
set:
external:
platform:
apiKey:
namespace: ""
asserts:
- hasDocuments:
count: 0

- it: check disabled on implicit same namespace
set:
external:
platform:
apiKey:
secretName: "some-other-secret"
asserts:
- hasDocuments:
count: 0

- it: automatically create role for specific secret for reading & patching
set:
external:
platform:
apiKey:
secretName: "my-secret-name"
namespace: "some-other-namespace"
asserts:
- hasDocuments:
count: 2
- documentIndex: 0
lengthEqual:
path: rules
count: 1
- documentIndex: 0
equal:
path: metadata.name
value: "vc-RELEASE-NAME-v-NAMESPACE-platform-role"
- documentIndex: 1
equal:
path: metadata.name
value: "vc-RELEASE-NAME-v-NAMESPACE-platform-role-binding"
- documentIndex: 0
contains:
path: rules
count: 1
content:
apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
resourceNames: ["my-secret-name"]
- documentIndex: 1
contains:
path: subjects
count: 1
content:
kind: ServiceAccount
name: vc-RELEASE-NAME
namespace: some-other-namespace

- it: automatically create role for default secret for reading & patching
set:
external:
platform:
apiKey:
namespace: "some-other-namespace"
asserts:
- hasDocuments:
count: 2
- documentIndex: 0
lengthEqual:
path: rules
count: 1
- documentIndex: 0
equal:
path: metadata.name
value: "vc-RELEASE-NAME-v-NAMESPACE-platform-role"
- documentIndex: 1
equal:
path: metadata.name
value: "vc-RELEASE-NAME-v-NAMESPACE-platform-role-binding"
- documentIndex: 0
contains:
path: rules
count: 1
content:
apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
resourceNames: ["vcluster-platform-api-key"]
- documentIndex: 1
contains:
path: subjects
count: 1
content:
kind: ServiceAccount
name: vc-RELEASE-NAME
namespace: some-other-namespace
6 changes: 5 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -1795,7 +1795,6 @@ type ExperimentalDeployHelmChart struct {

type PlatformConfig struct {
// APIKey defines where to find the platform access key and host. By default, vCluster will search in the following locations in this precedence:
// * platform.api.accessKey
// * environment variable called LICENSE
// * secret specified under external.platform.apiKey.secretName
// * secret called "vcluster-platform-api-key" in the vCluster namespace
Expand All @@ -1810,6 +1809,11 @@ type PlatformAPIKey struct {
// Namespace defines the namespace where the access key secret should be retrieved from. If this is not equal to the namespace
// where the vCluster instance is deployed, you need to make sure vCluster has access to this other namespace.
Namespace string `json:"namespace,omitempty"`

// CreateRBAC will automatically create the necessary RBAC roles and role bindings to allow vCluster to read the secret specified
// in the above namespace, if specified.
// This defaults to true.
CreateRBAC *bool `json:"createRBAC,omitempty"`
}

type ExperimentalGenericSync struct {
Expand Down

0 comments on commit d5475d4

Please sign in to comment.