I am trying to create a Pod that is able to create and update a specific configmap using Role.rules.resourceNames
. I am able to perform a get request for the resource to the API from within the pod, but I'm not able to create the resource, instead getting
$ kubectl logs rbac-test
Error from server (Forbidden): error when creating "/config/aaa.yaml": configmaps is forbidden: User "system:serviceaccount:default:rbac-test" cannot create resource "configmaps" in API group "" in the namespace "default"
If I remove the resourceNames
attribute I am able to create the configmap, but I don't necessarily want this pod to be able to create and update configmaps willy-nilly. How can I restrict the serviceAccount's roles so that this pod can manipulate only the named configmap aaa
?
I got some help in the kubernetes slack (thank you, Alan). RBAC happens at the level of the URL so resourceName-restricted authorization can't happen for create URLs since there is no resource name in the URL!
kind: Pod
apiVersion: v1
metadata:
name: rbac-test
spec:
restartPolicy: Never
serviceAccountName: rbac-test
imagePullSecrets:
- name: docker-hub-creds
containers:
- name: rbac-test
image: bitnami/kubectl
command: [ "kubectl" ]
args: [ "apply", "-f", "/config/aaa.yaml" ]
volumeMounts:
- name: aaa-config
mountPath: /config/
volumes:
- name: aaa-config
configMap:
name: aaa-config
---
kind: ConfigMap
apiVersion: v1
metadata:
name: aaa-config
data:
aaa.yaml: |
kind: ConfigMap
apiVersion: v1
metadata:
name: aaa
data:
value: na
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: rbac-test
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: rbac-test
rules:
- apiGroups: [ "" ]
resources: [ "configmaps" ]
verbs: [ "get", "create", "update" ]
resourceNames: [ "aaa" ]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: rbac-test
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: rbac-test
subjects:
- kind: ServiceAccount
name: rbac-test
As mention by Shai Katz in previous answer according to documentation: Using RBAC Authorization - Referring to resources
You cannot restrict
create
ordeletecollection
requests byresourceName
. For create, this limitation is because the object name is not known at authorization time.
Solution provided in the edit section - still will not work.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: rbac-test
rules:
- apiGroups: [ "" ]
resources: [ "configmaps" ]
verbs: [ "get", "create", "update" ]
resourceNames: [ "aaa" ]
This config allows you to only get and update existing configmap named aaa
while the create operation is pointless as this resource cannot be created..
You can achieve what you want if you will edit your Role
Solution 1
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: rbac-test
rules:
- apiGroups: [ "" ] #this rule will allow to update existing configmap aaa referenced by resourcename
resources: [ "configmaps" ]
verbs: [ "get", "update" ]
resourceNames: [ "aaa" ]
- apiGroups: [ "" ] #this rule will allow you to create configmaps
resources: [ "configmaps" ]
verbs: [ "get", "create" ]
It can be verified by executing commands below:
$ kubectl auth can-i update configmaps/aaa --as=system:serviceaccount:default:rbac-test
yes
$ kubectl auth can-i create configmaps/new-aaa --as=system:serviceaccount:default:rbac-test
yes
However, in this scenario rbac-test pod/sa
can perform update
action by executing kubectl replace
command f.e:
$ kubectl replace -f /config/aaa.yaml
I you are interested with $ kubectl apply
probably you should use verb patch
like in the example below.
- apiGroups: [ "" ]
resources: [ "configmaps" ]
verbs: [ "get", "patch" ]
resourceNames: [ "aaa" ]
Solution 2 - More restrictive approach.
Instead of giving your serviceAccount: rbac-test
permission to create configs in k8s api. Please consider creating two configmaps:
a)
$ kubectl create cm aaa ### an empty "aaa" configmap
b)
kubectl apply -f - <<EOF
kind: ConfigMap
apiVersion: v1
metadata:
name: aaa-config
data:
aaa.yaml: |
kind: ConfigMap
apiVersion: v1
metadata:
name: aaa
data:
value: na
EOF
This configmap
will be populated to the POD
using volumes. Configmap.data
will be stored inside the pods
directory under /config/aaa.yaml
kind: ConfigMap
apiVersion: v1
metadata:
name: aaa
data:
value: na
Configure this RBAC Role
:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: rbac-test
rules:
- apiGroups: [ "" ] #this rule will allow to patch existing empty "aaa" configmap aaa referenced by resourcename
resources: [ "configmaps" ]
verbs: [ "get", "patch" ]
resourceNames: [ "aaa" ]
In this scenario you will have preconfigured aaa
empty configmap
and your pod
with associated rbac-test serviceAccount
will be able to perform patch
request using provided YAML manifest stored in /config/aaa.yaml
inside the Pod
.
$ kubectl auth can-i patch configmaps/aaa --as=system:serviceaccount:default:rbac-test
yes
$ kubectl auth can-i create configmaps/new-aaa --as=system:serviceaccount:default:rbac-test
no
To check which verbs you can use in RBAC
for ConfigMap
execute:
$ kubectl api-resources -o wide | grep configmap
configmaps cm true ConfigMap [create delete deletecollection get list patch update watch]
Note: You cannot restrict create or deletecollection requests by resourceName. For create, this limitation is because the object name is not known at authorization time.
Reference: https://kubernetes.io/docs/reference/access-authn-authz/rbac/