Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(helm): Automatically create role & bindings for namespace containing platform secret #1935

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
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
Loading