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-testAs mention by Shai Katz in previous answer according to documentation: Using RBAC Authorization - Referring to resources
You cannot restrict
createordeletecollectionrequests 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
yesHowever, 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" configmapb)
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
EOFThis 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
noTo 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/