Querying Policy Rules in OpenShift using jq

In my last post on the subject, I mentioned that I was able to use kubectl to get the same information as oc describe clusterPolicy. Here are some more details.

To see the whole cluster policy in an openshift deployment, you can run:

kubectl get clusterpolicy

But it produces a lot of data. I want to know what roles to assign to a user in order to get access to a specific API. I’ve come to rely on the jq tool to do this kind of work.

To see the complete list of roles, with all the outside containers removed, run:

kubectl get clusterpolicy -o json | jq '.items[] | .roles[]'

Notice that the roles are in

To get just the role names:

kubectl get clusterpolicy -o json | jq '.items[] | .roles[] | .name'

 

Lets start simple.  Lets see what is defined for a single role:

kubectl get clusterpolicy -o json | jq '.items[] | .roles[] | select (.name == "view")'

 

And that returns a lot of information.  To make sure we have the right general approch, go simpler:

$ kubectl get clusterpolicy -o json | jq '.items[] | .roles[] | select (.name == "view") | .name ' 
"view"

To see the resources:

kubectl get clusterpolicy -o json | jq '.items[] | .roles[] | select (.name == "view") | .role | .rules[] | .resources'

 

Again, a lot of data.  Time to dig deep.  In order to find an element inside a list, we can use the bsearch function.

$ kubectl get clusterpolicy -o json | jq '.items[] | .roles[] | .role | .rules[] | select(.resources | bsearch("buildlogs") > -1 ) '

Which returns

{
 "apiGroups": [
 ""
 ],
 "attributeRestrictions": null,
 "resources": [
 "buildlogs"
 ],
 "verbs": [
 "create",
 "delete",
 "deletecollection",
 "get",
 "list",
 "patch",
 "update",
 "watch"
 ]
}
{
 "apiGroups": [
 ""
 ],
 "attributeRestrictions": null,
 "resources": [
 "buildlogs"
 ],
 "verbs": [
 "get",
 "list",
 "watch"
 ]
}
{
 "apiGroups": [
 ""
 ],
 "attributeRestrictions": null,
 "resources": [
 "buildlogs"
 ],
 "verbs": [
 "create",
 "delete",
 "deletecollection",
 "get",
 "list",
 "patch",
 "update",
 "watch"
 ]
}
{
 "apiGroups": [
 ""
 ],
 "attributeRestrictions": null,
 "resources": [
 "buildlogs"
 ],
 "verbs": [
 "get",
 "list",
 "watch"
 ]
}

Which shows that the specific rule matches.  Of course, it does not have the role names in it as it is one level too low.  If we target one level higher in the structure:

kubectl get clusterpolicy -o json | jq '.items[] | .roles[] | .role | select(.rules[] | .resources | bsearch("buildlogs") > -1 ) '

We see that there is, once again, too much data.  So now we can filter it out:

$ kubectl get clusterpolicy -o json | jq '.items[] | .roles[] | select(.role | .rules[] | .resources | bsearch("buildlogs") > -1 ) | .name' 
"admin"
"cluster-reader"
"edit"
"view"

The general pattern I followed here was to push elements from the chain into the select until I get only the object I wanted, and then append new filter values after the select.

 

I’ll spare you the rest of the trial and error and come to the final solution:

kubectl get clusterpolicy -o json | jq '.items[] | .roles[] |  .role |  select( (.rules[] | select (.verbs | bsearch ("create") > -1) and ( .resources | bsearch ("imagestreams") > -1 )) ) | .metadata | .name  '  
"admin"
"edit"
"registry-admin"
"registry-editor"
"system:image-builder"

 

Leave a Reply

Your email address will not be published. Required fields are marked *