Working without RBAC Manager

This document is for an unreleased version of Crossplane.

This document applies to the Crossplane master branch and not to the latest release v1.18.

RBAC Manager is responsible for establishing appropriate roles structure to components.

In cases, where administrators are not allowing permissive cluster wide-permissions,you can turn off RBAC Manager with argument --set rbacManager.deploy=false in helm chart during installation.

1rbacManager:
2  enabled: false

Once done, you need to configure Roles on your own for each provider and Composition Resource Definitions (XRDs). Below guides will instruct you step by step the additional work needed for each provider and XRD to be able to successfully deploy a provider and an XRD.

The guide only establishes minimal number of resources to fulfill the guide’s goal, RBAC Manager creates more resources and if you want to read more, the Crossplane RBAC Manager design document has more information on the installed ClusterRoles.

Note: The guide doesn’t address any cluster-wide permissions that are used in Core Crossplane service.

Provider RBAC

Note: Please keep in mind this guide doesn’t show manual steps for installing providers. If you want to control Crossplane Core pod permissions even further, you can manually install the provider service.

For the prpose of this guide, let’s assume you want to deploy a provider-kubernetes to the cluster and control its permissions. You create a resource provider as usual

1apiVersion: pkg.crossplane.io/v1
2kind: Provider
3metadata:
4  name: provider-kubernetes
5spec:
6  package: xpkg.upbound.io/crossplane-contrib/provider-kubernetes:v0.15.1

Once installed, save provider service account name

1SA=$(kubectl -n crossplane-system get sa -o name | grep provider-kubernetes | sed -e 's|serviceaccount\/||g')

Provider ClusterRole

Then, create a ClusterRole, that will have necessary rules for resources that are to be managed by a provider:

 1apiVersion: rbac.authorization.k8s.io/v1
 2kind: ClusterRole
 3metadata:
 4  name: provider-kubernetes-aggregate
 5rules:
 6- apiGroups:
 7  - kubernetes.crossplane.io
 8  resources:
 9  - objects
10  - objects/status
11  - observedobjectcollections
12  - observedobjectcollections/status
13  - providerconfigs
14  - providerconfigs/status
15  - providerconfigusages
16  - providerconfigusages/status
17  verbs:
18  - get
19  - list
20  - watch
21  - update
22  - patch
23  - create
24- apiGroups:
25  - kubernetes.crossplane.io
26  resources:
27  - '*/finalizers'
28  verbs:
29  - update
30- apiGroups:
31  - ""
32  - coordination.k8s.io
33  resources:
34  - secrets
35  - configmaps
36  - events
37  - leases
38  verbs:
39  - '*'

With the role, now create a binding to the service account:

Note: make sure that the SA environment variable that was defined earlier is still set correctly.

 1apiVersion: rbac.authorization.k8s.io/v1
 2kind: ClusterRoleBinding
 3metadata:
 4  name: provider-kubernetes-binding
 5roleRef:
 6  apiGroup: rbac.authorization.k8s.io
 7  kind: ClusterRole
 8  name: provider-kubernetes-aggregate
 9subjects:
10- kind: ServiceAccount
11  name: ${SA}
12  namespace: crossplane-system

Core Crossplane ClusterRole

Now, create a new ClusterRole, for core Crossplane service

 1apiVersion: rbac.authorization.k8s.io/v1
 2kind: ClusterRole
 3metadata:
 4  name: provider-kubernetes-aggregate
 5rules:
 6- apiGroups:
 7  - kubernetes.crossplane.io
 8  resources:
 9  - objects
10  - objects/status
11  - observedobjectcollections
12  - observedobjectcollections/status
13  - providerconfigs
14  - providerconfigs/status
15  - providerconfigusages
16  - providerconfigusages/status
17  verbs:
18  - '*'

With the cluster role in place, create a binding to the core Crossplane service:

 1apiVersion: rbac.authorization.k8s.io/v1
 2kind: ClusterRoleBinding
 3metadata:
 4  name: crossplane-provider-kubernetes-binding
 5roleRef:
 6  apiGroup: rbac.authorization.k8s.io
 7  kind: ClusterRole
 8  name: crossplane-aggregate-provider-access
 9subjects:
10- kind: ServiceAccount
11  name: crossplane
12  namespace: crossplane-system

Verification

With the previous steps applied, you can now verify the configuration by adding a provider config:

1apiVersion: kubernetes.crossplane.io/v1alpha1
2kind: ProviderConfig
3metadata:
4  name: kubernetes-provider-config
5spec:
6  credentials:
7    source: InjectedIdentity

And add a binding, so that it’s possible to manage local cluster by a provider:

 1apiVersion: rbac.authorization.k8s.io/v1
 2kind: ClusterRoleBinding
 3metadata:
 4  name: provider-kubernetes-admin-binding
 5roleRef:
 6  apiGroup: rbac.authorization.k8s.io
 7  kind: ClusterRole
 8  name: cluster-admin
 9subjects:
10- kind: ServiceAccount
11  name: ${SA}
12  namespace: crossplane-system

With the configuration in place, you can add a test resource:

 1apiVersion: kubernetes.crossplane.io/v1alpha2
 2kind: Object
 3metadata:
 4  name: test-namespace
 5spec:
 6  forProvider:
 7    manifest:
 8      apiVersion: v1
 9      kind: Namespace
10      metadata:
11        name: test-namespace
12        labels:
13          example: 'true'
14  providerConfigRef:
15    name: kubernetes-provider-config

Composition Resource Definitions RBAC

If you want to add a CompositionResourceDefinition in a system without RBAC Manager, you need to create the necessary XRD definition as well as assign permissions to the defined type to Core Crossplane ServiceAccount.

XRD ClusterRole

For the purpose of the example, let’s create a sample XRD:

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: CompositeResourceDefinition
 3metadata:
 4  name: compositenamespaces.k8s.crossplane.io
 5spec:
 6  group: k8s.crossplane.io
 7  names:
 8    kind: CompositeNamespace
 9    plural: compositenamespaces
10  claimNames:
11    kind: NamespaceClaim
12    plural: namespaceclaims
13  versions:
14    - name: v1alpha1
15      served: true
16      referenceable: true
17      schema:
18        openAPIV3Schema:
19          type: object
20          properties:
21            spec:
22              type: object
23              properties:
24                name:
25                  type: string
26                  description: "The name of the Kubernetes namespace to be created."
27            status:
28              type: object
29              properties:
30                ready:
31                  type: boolean
32                  description: "Indicates if the namespace is ready."

After that, create a ClusterRole:

 1apiVersion: rbac.authorization.k8s.io/v1
 2kind: ClusterRole
 3metadata:
 4  name: compositenamespace:aggregate-to-crossplane
 5  labels:
 6    rbac.crossplane.io/aggregate-to-crossplane: "true"
 7rules:
 8- apiGroups:
 9  - k8s.crossplane.io
10  resources:
11  - compositenamespaces
12  - compositenamespaces/status
13  verbs:
14  - '*'
15- apiGroups:
16  - k8s.crossplane.io
17  resources:
18  - compositenamespaces/finalizers
19  verbs:
20  - update
21- apiGroups:
22  - k8s.crossplane.io
23  resources:
24  - namespaceclaims
25  - namespaceclaims/status
26  verbs:
27  - '*'
28- apiGroups:
29  - k8s.crossplane.io
30  resources:
31  - namespaceclaims/finalizers
32  verbs:
33  - update

If the ServiceAccount for your Core Crossplane service is default crossplane, apply below binding:

 1apiVersion: rbac.authorization.k8s.io/v1
 2kind: ClusterRoleBinding
 3metadata:
 4  name: crossplane-provider-kubernetes-binding-CRD
 5roleRef:
 6  apiGroup: rbac.authorization.k8s.io
 7  kind: ClusterRole
 8  name: compositenamespace:aggregate-to-crossplane
 9subjects:
10- kind: ServiceAccount
11  name: crossplane
12  namespace: crossplane-system

Verification

Once proper permissions are applied, you can create a composition:

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: Composition
 3metadata:
 4  name: compositenamespace.k8s.crossplane.io
 5spec:
 6  compositeTypeRef:
 7    apiVersion: k8s.crossplane.io/v1alpha1
 8    kind: CompositeNamespace
 9  resources:
10    - name: namespace
11      base:
12        apiVersion: kubernetes.crossplane.io/v1alpha2
13        kind: Object
14        spec:
15          providerConfigRef:
16            name: kubernetes-provider-config
17          forProvider:
18            manifest:
19              apiVersion: v1
20              kind: Namespace
21      patches:
22        - fromFieldPath: "spec.name"
23          toFieldPath: "metadata.name"
24          type: FromCompositeFieldPath

Followed by a Claim creation

1apiVersion: k8s.crossplane.io/v1alpha1
2kind: NamespaceClaim
3metadata:
4  name: example-namespace-claim
5spec:
6  name: testing-no-rbac