Advice on specifying more granular permissions with Google Cloud IAM

Katie McLaughlin - May 12 '20 - - Dev Community

If you've worked through any number of tutorial regarding more complex examples of multiple Google Cloud products connecting together, where you define a service account to take actions on services, you may have seen this:

If you are developing a production app, specify more granular permissions than "Project > Owner". For more information, see granting roles to service accounts.

That page details how to grant roles to service accounts, sure. But how do you determine what roles to grant?

This post deals specifically with Google Cloud IAM. Cloud Storage and Kubernetes have their own access control mechanisms and are outside of the scope of this post.

Over-granted permissions

There are tools integrated into Google Cloud to help you with this. Those little lightbulb icons in IAM & Admin > IAM? They are recommendations for changes that you should make. These recommendations are over a period of time, with some machine learning used as well, so for some of your older projects, you may already have recommendations waiting for you.

Overgranted permissions icon
An example of over-granted permissions with recommendations from https://console.cloud.google.com/iam-admin/iam

If your project has recommendations that you can enact today, go do that! Just remember to read and understand what those recommendations are, and don't be afraid to revert if something breaks.

If you're in a new project, though, there won't be any recommendations. Read on to understand what you can do today to help reduce your permissions footprint.

Understanding Roles and Permissions

Google Cloud defines a number of Roles as groups of permissions. The entire list of pre-defined roles is available in IAM & Admin > Roles. You can create your own roles, but for now we'll stick to the predefined ones.

Roles have a title and an ID, and can be referred to by either, depending on the context. They are sometimes referred to with their grouping. For example, "Project > Owner" from earlier. The ID form is often the one used in gcloud calls, and the Name can be used in the search dialogs. For the purposes of this post, I'll use the form "Title (ID)". For example, "Owner (roles/owner)".

Select role dialog
A "Select a role" dialog

Speaking of Owner, just what permissions does Owner grant? Checking the role details for roles/owner, there are 2751 assigned permissions at time of writing. This number will change as Google Cloud changes, but that's still a very long list of permissions, and probably not what permissions you want your random service account to have.

Each permission can be thought of as an 'action', normally named in a triple of values "service.resource.verb", and that permission is probably required to perform that action. Roles can group permissions from different products for more logical collections.

For example, the "Cloud Functions Viewer (roles/cloudfunctions.viewer)" role grants a number of permissions to cloudfunctions -- like cloudfunctions.functions.get and cloudfunctions.functions.list -- but also permissions across resourcemanager and serviceusage. If you intend to view a Cloud Function, these are the permissions you'll need.

The Understanding Roles doc describes some of the base concepts (including how Owner existed before Cloud IAM!), but also lists all the predefined rolls. Skip down to Product-specific Cloud IAM documentation and see if the product you're most interested in has more detailed information.

Which role is right for your use case?

When working out which roles to assign, using the Roles list and choosing something that "sounds" right as a first step is not a bad starting point. For instance, that Cloud Functions Viewer role sounds like it would be the right role if you wanted only view access on a Function.

Some of these roles are automatically associated with the dynamically created service accounts when you enable certain products. Removing any of the roles these service accounts use is a really bad idea, as functionality will probably break throughout your project.

Instead, if you need to make changes to the role, create a new service account using the default service account's base roles as a starting point, then make changes.

What if you need a role that doesn't exist?

That's when custom roles come into play. You can define your own role that has custom permissions, thus ensuring you can enforce the Principle of least privilege. There are some limitations that the Understanding Custom IAM Roles docs goes into more detail for, and some general recommendations.

Debugging permissions from first principles

Whether you create a new service account with predefined or custom roles, which permissions you need is the question.

No two projects are going to be the same, so the answer to the question "what is the minimum set of permissions I need for my project" is going to be different for every project. But there are a number of things you can do to work out what you need for yourself.

Important note: you should probably do your debugging outside of your production project. Just saying ✨

Start from nothing

First, create a new service account. Then use that service account for your action. If you've set it up right, it should fail because the service account has zero permissions. If you're still able to perform your action, confirm you are actually using the new service account identity.

Work through the errors

Logging and error outputs will be your friend here. Turn on DEBUG for your code, or verbose output where you can, and look for instances of those permissions triples if you get explicit "Permission Denied" errors. Calling gcloud commands with --verbosity=debug is extremely helpful here. As are checking not only your local error logs, but also checking Cloud Logging for output against all your services.

Hitting the edge cases

Making sure your site loads is one thing, but performing actions that exercise all the complex use cases is another. If possible, get someone that's not you to try out the new deployment and see if they get any issues trying to use some of the more complex actions. A fresh set of eyes is extremely helpful in this sort of complex tasking.

Better yet, if your use case is an application that can be set up in a new project, get them to set up a new project using your instructions for minimal permissions. Defaults in your setup will become abundantly visible.

Eventual consistency

One of the biggest gotchas in all of this is that even when you make your changes, they may not be immediately available. It can take some time for IAM changes to propagate, so if you think a change didn't have any effect, wait a minute and try again.

Conditional access

If even permanent access is too much for your situation, you can define conditional access, such as temporary access (access for a limited time), or resource-based access (access to a limited set of resources). Resource-based access limitations are only available for a subset of Google Cloud products, but consider if these sort of limitations will help with your setup.

This isn't easy

The amount of work this process requires makes it clear why "just use roles/owner" is a timesaver in the short term, but a solid and situationally appropriate permission overview can do wonders for the security of your deployment, and your understanding of the ecosystem in which your deployment lives. Try some of these tricks on your next project, and check if there are any recommendations for your existing projects ✨

In the next post, we'll work through an example of how to apply some of these concepts in an example deployment.

Updated May 18 2020 with a link to part two

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .