Although the GCP console provides a nice interface for displaying which user/service account is in which IAM security role (IAM & Admin > IAM), it can be difficult to analyze using gcloud get-iam-policy because of the inner array of ‘members’ returned.
However, if you use the flattening ability of gcloud, it becomes much easier to parse. Here an example of pulling all the roles for a specific user or service account.
# get list of project id gcloud projects list --format='value(project_id)' # show roles for user gcloud projects get-iam-policy <projectId> --flatten="bindings[].members" --filter="bindings.members=user:<userEmailId>" --format="value(bindings.role)" # list all service accounts gcloud iam service-accounts --project <projectId> list # show roles for single service account gcloud projects get-iam-policy <projectId> --flatten="bindings[].members" --filter="bindings.members=serviceAccount:<serviceAccountId>" --format="value(bindings.role)"
Here is another example, this time coming from the opposite perspective and listing all entities in the “logging.logWriter” role.
# given a role, show all entities bound to policy gcloud projects get-iam-policy <projectId> --flatten="bindings[].members" --filter="bindings.role=roles/logging.logWriter" --format="value(bindings.members)"
If you find the gcloud flattening/filter/format combination too limiting, you could have get-iam-policy output all the json and instead use the jq utility to transform and filter it.
Here is an example of using jq to perform the same operation as the first gcloud example, where given a user/serviceAccount Id, you get a list of roles.
# grab all the IAM results for project alljson=$(mktemp alljson-XXXXXXXX.json) gcloud projects get-iam-policy <projectId> --format=json > $alljson # choose one: either looking for user or service account objectId="user:<userEmailId>" objectId="serviceAccount:<serviceAccountId>" # for single user/service account, find all roles it is a member of cat $alljson | jq -r ".bindings[] | select ( .members | index(\"$objectId\") ) | .role"
We could make this selection even more flexible by using a regex to match the user or service account name. With a regex like ‘myService1’, we do not have to specify the standard ‘serviceAccount:’ prefix, or the standard suffix ‘<projectName>.iam.gserviceaccount.com’.
# regex match myentity="myService1" cat $alljson | jq -r ".bindings[] | select ( .members[] | test(\"$myentity\") ) | .role"
Just beware that if your regex is wide ‘myService’, it could pull in more than one account, and pull the roles for both a ‘myService1’ and ‘myService2’ (which depending on the scenario may be what you want).
If you want to see the second gcloud example written using jq, showing all the entities in a certain role, see below.
# exact match myregexrole="roles/logging.logWriter" jq ".bindings[] | select ( .role | test(\"$myregexrole\") )" # regex match for all compute based roles myregexrole="roles/compute" jq ".bindings[] | select ( .role | test(\"$myregexrole\") )"
REFERENCES
google, service-accounts list reference
stackoverflow, using jq to filter on inner arrays
statckoverflow, flattening bindings for better viewing
github Kielan, gcloud cheat sheet
stackexchange, using search-all-iam-policies to query roles
ncona.com, using gcloud to add/remove policy bindings