How to Create Custom Platform Role

1. Overview

This document explains the core concepts of custom roles and how to configure a RoleTemplate.

2. Core Concepts

  • RoleTemplate: Custom role template. It defines role semantics and permission sets, and is converted by the controller into ClusterRoles.
  • FunctionResource: An abstraction of K8s resources used by product features; referenced by functionResourceRef in RoleTemplate.
  • ClusterRole: RBAC rule set; can be aggregated into system roles via labels.
  • UserBinding: Binding between users and roles/scopes; the controller generates RoleBinding/ClusterRoleBinding based on UserBinding for final authorization.
NOTE
  • The value of functionResourceRef comes from FunctionResource metadata.name.
  • Display names are typically in metadata.annotations, which you can use to map to UI modules.

3. Technical Changes

Starting from ACP v4.3, feature permissions are gradually migrated from FunctionResource to native K8s ClusterRole management. RoleTemplate module permissions will be aggregated into system roles via ClusterRole labels. FunctionResource-based management will be retired in v4.5.

4. Supported Configuration Methods

  • FunctionResource method: Select permissions by product modules and control verbs at fine granularity.
  • ClusterRole aggregation method (aggregationRules): Centralized aggregation via ClusterRole labels; recommended for v4.2+.
  • customRules: Configure permissions using native K8s RBAC syntax; same rule format as ClusterRole rules.

5. Configuration

5.1 RoleTemplate YAML

FunctionResource method (supported until v4.5)

apiVersion: auth.alauda.io/v1beta1
kind: RoleTemplate
metadata:
  name: demo-funcrole
  annotations:
    cpaas.io/display-name: Example Function Role
    cpaas.io/description: FunctionResource example
  labels:
    auth.cpaas.io/roletemplate.level: namespace
spec:
  rules:
    - functionResourceRef: acp-app
      verbs: [get, list, watch]

FunctionResource example:

apiVersion: auth.alauda.io/v1beta1
kind: FunctionResource
metadata:
  name: acp-app
  annotations:
    cpaas.io/functionresource.module.display-name: Container Platform
    cpaas.io/functionresource.function.display-name: Application
  labels:
    auth.cpaas.io/functionresource.module: acp
    auth.cpaas.io/functionresource.function: app
    auth.cpaas.io/product: console-acp
spec:
  rules:
    - apiGroup: app.k8s.io
      resources: ["*"]
      bindScope: namespace
      bindCluster: unlimit
      bindNamespacePart: common

ClusterRole aggregation method (v4.2+)

apiVersion: auth.alauda.io/v1beta1
kind: RoleTemplate
metadata:
  name: demo-aggrole
  annotations:
    cpaas.io/display-name: Example Aggregation Role
    cpaas.io/description: ClusterRole aggregation example
  labels:
    auth.cpaas.io/roletemplate.level: namespace
spec:
  aggregationRules:
    - clusterRoleSelectors:
        - matchLabels:
            rbac.cpaas.io/aggregate-to-namespace-developer: "true"
            rbac.cpaas.io/aggregate-to-scope-business-ns: "true"
      scope: business-ns
  rules: []

ClusterRole with aggregation labels:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cpaas:demo:business-ns:view
  labels:
    rbac.cpaas.io/aggregate-to-namespace-developer: "true"
    rbac.cpaas.io/aggregate-to-scope-business-ns: "true"
rules:
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list", "watch"]

customRules method

apiVersion: auth.alauda.io/v1beta1
kind: RoleTemplate
metadata:
  name: demo-customrules
  annotations:
    cpaas.io/display-name: Example Custom Rules Role
    cpaas.io/description: customRules example
  labels:
    auth.cpaas.io/roletemplate.level: namespace
spec:
  customRules:
    - apiGroups: [""]
      resources: ["configmaps"]
      verbs: ["get", "list", "watch"]

RoleTemplate field reference (with ranges):

FieldDescriptionValues/Range
metadata.nameRole nameCustom string
metadata.labels.auth.cpaas.io/roletemplate.levelRole levelplatform / cluster / project / namespace
metadata.annotations.cpaas.io/(display-name/description)Display name and descriptionCustom string
spec.rules[].functionResourceRefFunctionResource referenceSee index (FunctionResource metadata.name)
spec.rules[].verbsVerbsget / list / watch / create / update / patch / delete / deletecollection
spec.aggregationRules[].scopeAggregation scopecluster / project-ns / business-ns / system-ns / kube-public
spec.aggregationRules[].clusterRoleSelectorsLabel selectorsmatchLabels / matchExpressions
spec.aggregationRules[].clusterRoleSelectors.matchLabelsLabel key/valuekey: value
spec.aggregationRules[].clusterRoleSelectors.matchExpressionsExpressionskey + operator + values (operator: In / NotIn / Exists / DoesNotExist)
spec.customRules[].apiGroupsAPI groups"" core group, "*" all
spec.customRules[].resourcesResources"*" all
spec.customRules[].verbsVerbssame as above
spec.customRules[].resourceNamesResource namesOptional
spec.customRules[].nonResourceURLsNon-resource URLsOptional (typically for ClusterRole)
NOTE

spec.rules and spec.aggregationRules are mutually exclusive.

System labels for matchLabels

System role aggregation labels:

  • rbac.cpaas.io/aggregate-to-platform-admin: "true"
  • rbac.cpaas.io/aggregate-to-platform-auditor: "true"
  • rbac.cpaas.io/aggregate-to-cluster-admin: "true"
  • rbac.cpaas.io/aggregate-to-project-admin: "true"
  • rbac.cpaas.io/aggregate-to-namespace-admin: "true"
  • rbac.cpaas.io/aggregate-to-namespace-developer: "true"
  • rbac.cpaas.io/aggregate-to-basic-user: "true"

Scope aggregation labels:

  • rbac.cpaas.io/aggregate-to-scope-cluster: "true"
  • rbac.cpaas.io/aggregate-to-scope-project-ns: "true"
  • rbac.cpaas.io/aggregate-to-scope-business-ns: "true"
  • rbac.cpaas.io/aggregate-to-scope-system-ns: "true"
  • rbac.cpaas.io/aggregate-to-scope-kube-public: "true"
NOTE

Custom labels are also supported for aggregation.

FunctionResource field reference:

FieldDescription
metadata.nameFunctionResource identifier (for functionResourceRef)
metadata.annotationsDisplay names (for UI mapping)
metadata.labelsModule/function metadata (for indexing)
spec.rules[].apiGroupAPI group ("" for core)
spec.rules[].resourcesResource types
spec.rules[].bindScopeScope (cluster / namespace)
spec.rules[].bindClusterCluster scope (global / unlimit / business)
spec.rules[].bindNamespacePartNamespace part (common / system / kube-public / project_ns / cluster / "")
NOTE

acp-namespace-resource-manage is not allowed in custom roles.

5.2 Get ClusterRoles generated from a RoleTemplate

Query ClusterRoles generated by a RoleTemplate using labels:

kubectl get clusterrole -l auth.cpaas.io/role.relative=<roletemplate-name>

6. Copy & Trim (Examples)

For custom roles, it is recommended to copy a built-in system template and trim it to avoid missing module permissions.

6.1 Trim a system RoleTemplate YAML

Steps:

  • Keep the required FunctionResources.
  • Reduce verbs to read-only (get/list/watch).
  • Remove unused modules.

Role example: developer auditor without secret permissions

NOTE
  • In custom roles, do not configure Namespace Resource Management (FunctionResource: acp-namespace-resource-manage).
  • Remove User Secret Dictionary (FunctionResource: acp-user-secret).
  • Set all verbs to get/list/watch.

Example YAML:

apiVersion: auth.alauda.io/v1beta1
kind: RoleTemplate
metadata:
  annotations:
    cpaas.io/description: Responsible for development, deployment, and maintenance within the namespace.
    cpaas.io/display-name: Developer Copy
  labels:
    auth.cpaas.io/roletemplate.level: namespace
  name: namespace-developer-system-copy
spec:
  rules:
    - functionResourceRef: views-acp-userview
      verbs:
        - get
        - list
        - watch
    - functionResourceRef: infrastructure-clusters
      verbs:
        - get
        - list
        - watch
    - functionResourceRef: infrastructure-nodesmanage
      verbs:
        - get
        - list
        - watch
    - functionResourceRef: infrastructure-domains
      verbs:
        - get
        - list
        - watch
    - functionResourceRef: acp-subnet
      verbs:
        - get
        - list
        - watch
    - functionResourceRef: acp-networkpolicies
      verbs:
        - get
        - list
        - watch
    - functionResourceRef: infrastructure-storageclasses
      verbs:
        - get
        - list
        - watch
    - functionResourceRef: infrastructure-persistentvolumes
      verbs:
        - get
        - list
        - watch
    - functionResourceRef: acp-virtualmachineimagetemplates
      verbs:
        - get
        - list
        - watch

6.2 Trim namespace-developer-system into an auditor role

Approach:

  • Keep the scope structure (cluster / project-ns / business-ns / system-ns / kube-public).
  • Replace aggregation labels with auditor labels (requires labeled ClusterRoles).

Example (excerpt):

apiVersion: auth.alauda.io/v1beta1
kind: RoleTemplate
metadata:
  name: namespace-auditor
  annotations:
    cpaas.io/display-name: Namespace Auditor
    cpaas.io/description: Read-only audit
  labels:
    auth.cpaas.io/roletemplate.level: namespace
spec:
  aggregationRules:
    - clusterRoleSelectors:
        - matchLabels:
            rbac.cpaas.io/aggregate-to-namespace-auditor: "true"
            rbac.cpaas.io/aggregate-to-scope-business-ns: "true"
      scope: business-ns
  rules: []
NOTE

aggregate-to-namespace-auditor must match labels on existing ClusterRoles. If not, create a read-only ClusterRole and add the label first.