From f8d4aca49999fb52246dbc102857796e62be0b76 Mon Sep 17 00:00:00 2001 From: Somefive Date: Wed, 29 Jun 2022 14:22:35 +0800 Subject: [PATCH] Feat: enhance ServiceAccount trait to support privileges Signed-off-by: Somefive --- .../defwithtemplate/service-account.yaml | 104 +++++++++++++++++ .../defwithtemplate/service-account.yaml | 104 +++++++++++++++++ .../internal/trait/service-account.cue | 105 ++++++++++++++++++ 3 files changed, 313 insertions(+) diff --git a/charts/vela-core/templates/defwithtemplate/service-account.yaml b/charts/vela-core/templates/defwithtemplate/service-account.yaml index 23ffc6e4c..d03fe6b69 100644 --- a/charts/vela-core/templates/defwithtemplate/service-account.yaml +++ b/charts/vela-core/templates/defwithtemplate/service-account.yaml @@ -14,10 +14,114 @@ spec: schematic: cue: template: | + #Privileges: { + // +usage=Specify the verbs to be allowed for the resource + verbs: [...string] + // +usage=Specify the apiGroups of the resource + apiGroups?: [...string] + // +usage=Specify the resources to be allowed + resources?: [...string] + // +usage=Specify the resourceNames to be allowed + resourceNames?: [...string] + // +usage=Specify the resource url to be allowed + nonResourceURLs?: [...string] + // +usage=Specify the scope of the privileges, default to be namespace scope + scope: *"namespace" | "cluster" + } parameter: { // +usage=Specify the name of ServiceAccount name: string + // +usage=Specify whether to create new ServiceAccount or not + create: *false | bool + // +usage=Specify the privileges of the ServiceAccount, if not empty, RoleBindings(ClusterRoleBindings) will be created + privileges?: [...#Privileges] } // +patchStrategy=retainKeys patch: spec: template: spec: serviceAccountName: parameter.name + _clusterPrivileges: [ for p in parameter.privileges if p.scope == "cluster" {p}] + _namespacePrivileges: [ for p in parameter.privileges if p.scope == "namespace" {p}] + outputs: { + if parameter.create { + "service-account": { + apiVersion: "v1" + kind: "ServiceAccount" + metadata: name: parameter.name + } + } + if parameter.privileges != _|_ { + if len(_clusterPrivileges) > 0 { + "cluster-role": { + apiVersion: "rbac.authorization.k8s.io/v1" + kind: "ClusterRole" + metadata: name: "\(context.namespace):\(parameter.name)" + rules: [ for p in _clusterPrivileges { + verbs: p.verbs + if p.apiGroups != _|_ { + apiGroups: p.apiGroups + } + if p.resources != _|_ { + resources: p.resources + } + if p.resourceNames != _|_ { + resources: p.resourceNames + } + if p.nonResourceURLs != _|_ { + nonResourceURLs: p.nonResourceURLs + } + }] + } + "cluster-role-binding": { + apiVersion: "rbac.authorization.k8s.io/v1" + kind: "ClusterRoleBinding" + metadata: name: "\(context.namespace):\(parameter.name)" + roleRef: { + apiGroup: "rbac.authorization.k8s.io" + kind: "ClusterRole" + name: "\(context.namespace):\(parameter.name)" + } + subjects: [{ + kind: "ServiceAccount" + name: parameter.name + namespace: "\(context.namespace)" + }] + } + } + if len(_namespacePrivileges) > 0 { + role: { + apiVersion: "rbac.authorization.k8s.io/v1" + kind: "Role" + metadata: name: parameter.name + rules: [ for p in _namespacePrivileges { + verbs: p.verbs + if p.apiGroups != _|_ { + apiGroups: p.apiGroups + } + if p.resources != _|_ { + resources: p.resources + } + if p.resourceNames != _|_ { + resources: p.resourceNames + } + if p.nonResourceURLs != _|_ { + nonResourceURLs: p.nonResourceURLs + } + }] + } + "role-binding": { + apiVersion: "rbac.authorization.k8s.io/v1" + kind: "RoleBinding" + metadata: name: parameter.name + roleRef: { + apiGroup: "rbac.authorization.k8s.io" + kind: "Role" + name: parameter.name + } + subjects: [{ + kind: "ServiceAccount" + name: parameter.name + }] + } + } + } + } diff --git a/charts/vela-minimal/templates/defwithtemplate/service-account.yaml b/charts/vela-minimal/templates/defwithtemplate/service-account.yaml index 23ffc6e4c..d03fe6b69 100644 --- a/charts/vela-minimal/templates/defwithtemplate/service-account.yaml +++ b/charts/vela-minimal/templates/defwithtemplate/service-account.yaml @@ -14,10 +14,114 @@ spec: schematic: cue: template: | + #Privileges: { + // +usage=Specify the verbs to be allowed for the resource + verbs: [...string] + // +usage=Specify the apiGroups of the resource + apiGroups?: [...string] + // +usage=Specify the resources to be allowed + resources?: [...string] + // +usage=Specify the resourceNames to be allowed + resourceNames?: [...string] + // +usage=Specify the resource url to be allowed + nonResourceURLs?: [...string] + // +usage=Specify the scope of the privileges, default to be namespace scope + scope: *"namespace" | "cluster" + } parameter: { // +usage=Specify the name of ServiceAccount name: string + // +usage=Specify whether to create new ServiceAccount or not + create: *false | bool + // +usage=Specify the privileges of the ServiceAccount, if not empty, RoleBindings(ClusterRoleBindings) will be created + privileges?: [...#Privileges] } // +patchStrategy=retainKeys patch: spec: template: spec: serviceAccountName: parameter.name + _clusterPrivileges: [ for p in parameter.privileges if p.scope == "cluster" {p}] + _namespacePrivileges: [ for p in parameter.privileges if p.scope == "namespace" {p}] + outputs: { + if parameter.create { + "service-account": { + apiVersion: "v1" + kind: "ServiceAccount" + metadata: name: parameter.name + } + } + if parameter.privileges != _|_ { + if len(_clusterPrivileges) > 0 { + "cluster-role": { + apiVersion: "rbac.authorization.k8s.io/v1" + kind: "ClusterRole" + metadata: name: "\(context.namespace):\(parameter.name)" + rules: [ for p in _clusterPrivileges { + verbs: p.verbs + if p.apiGroups != _|_ { + apiGroups: p.apiGroups + } + if p.resources != _|_ { + resources: p.resources + } + if p.resourceNames != _|_ { + resources: p.resourceNames + } + if p.nonResourceURLs != _|_ { + nonResourceURLs: p.nonResourceURLs + } + }] + } + "cluster-role-binding": { + apiVersion: "rbac.authorization.k8s.io/v1" + kind: "ClusterRoleBinding" + metadata: name: "\(context.namespace):\(parameter.name)" + roleRef: { + apiGroup: "rbac.authorization.k8s.io" + kind: "ClusterRole" + name: "\(context.namespace):\(parameter.name)" + } + subjects: [{ + kind: "ServiceAccount" + name: parameter.name + namespace: "\(context.namespace)" + }] + } + } + if len(_namespacePrivileges) > 0 { + role: { + apiVersion: "rbac.authorization.k8s.io/v1" + kind: "Role" + metadata: name: parameter.name + rules: [ for p in _namespacePrivileges { + verbs: p.verbs + if p.apiGroups != _|_ { + apiGroups: p.apiGroups + } + if p.resources != _|_ { + resources: p.resources + } + if p.resourceNames != _|_ { + resources: p.resourceNames + } + if p.nonResourceURLs != _|_ { + nonResourceURLs: p.nonResourceURLs + } + }] + } + "role-binding": { + apiVersion: "rbac.authorization.k8s.io/v1" + kind: "RoleBinding" + metadata: name: parameter.name + roleRef: { + apiGroup: "rbac.authorization.k8s.io" + kind: "Role" + name: parameter.name + } + subjects: [{ + kind: "ServiceAccount" + name: parameter.name + }] + } + } + } + } diff --git a/vela-templates/definitions/internal/trait/service-account.cue b/vela-templates/definitions/internal/trait/service-account.cue index 70eedac65..1ad97f791 100644 --- a/vela-templates/definitions/internal/trait/service-account.cue +++ b/vela-templates/definitions/internal/trait/service-account.cue @@ -9,10 +9,115 @@ } } template: { + #Privileges: { + // +usage=Specify the verbs to be allowed for the resource + verbs: [...string] + // +usage=Specify the apiGroups of the resource + apiGroups?: [...string] + // +usage=Specify the resources to be allowed + resources?: [...string] + // +usage=Specify the resourceNames to be allowed + resourceNames?: [...string] + // +usage=Specify the resource url to be allowed + nonResourceURLs?: [...string] + // +usage=Specify the scope of the privileges, default to be namespace scope + scope: *"namespace" | "cluster" + } parameter: { // +usage=Specify the name of ServiceAccount name: string + // +usage=Specify whether to create new ServiceAccount or not + create: *false | bool + // +usage=Specify the privileges of the ServiceAccount, if not empty, RoleBindings(ClusterRoleBindings) will be created + privileges?: [...#Privileges] } // +patchStrategy=retainKeys patch: spec: template: spec: serviceAccountName: parameter.name + + _clusterPrivileges: [ for p in parameter.privileges if p.scope == "cluster" {p}] + _namespacePrivileges: [ for p in parameter.privileges if p.scope == "namespace" {p}] + outputs: { + if parameter.create { + "service-account": { + apiVersion: "v1" + kind: "ServiceAccount" + metadata: name: parameter.name + } + } + if parameter.privileges != _|_ { + if len(_clusterPrivileges) > 0 { + "cluster-role": { + apiVersion: "rbac.authorization.k8s.io/v1" + kind: "ClusterRole" + metadata: name: "\(context.namespace):\(parameter.name)" + rules: [ for p in _clusterPrivileges { + verbs: p.verbs + if p.apiGroups != _|_ { + apiGroups: p.apiGroups + } + if p.resources != _|_ { + resources: p.resources + } + if p.resourceNames != _|_ { + resources: p.resourceNames + } + if p.nonResourceURLs != _|_ { + nonResourceURLs: p.nonResourceURLs + } + }] + } + "cluster-role-binding": { + apiVersion: "rbac.authorization.k8s.io/v1" + kind: "ClusterRoleBinding" + metadata: name: "\(context.namespace):\(parameter.name)" + roleRef: { + apiGroup: "rbac.authorization.k8s.io" + kind: "ClusterRole" + name: "\(context.namespace):\(parameter.name)" + } + subjects: [{ + kind: "ServiceAccount" + name: parameter.name + namespace: "\(context.namespace)" + }] + } + } + if len(_namespacePrivileges) > 0 { + "role": { + apiVersion: "rbac.authorization.k8s.io/v1" + kind: "Role" + metadata: name: parameter.name + rules: [ for p in _namespacePrivileges { + verbs: p.verbs + if p.apiGroups != _|_ { + apiGroups: p.apiGroups + } + if p.resources != _|_ { + resources: p.resources + } + if p.resourceNames != _|_ { + resources: p.resourceNames + } + if p.nonResourceURLs != _|_ { + nonResourceURLs: p.nonResourceURLs + } + }] + } + "role-binding": { + apiVersion: "rbac.authorization.k8s.io/v1" + kind: "RoleBinding" + metadata: name: parameter.name + roleRef: { + apiGroup: "rbac.authorization.k8s.io" + kind: "Role" + name: parameter.name + } + subjects: [{ + kind: "ServiceAccount" + name: parameter.name + }] + } + } + } + } }