Custom Roles: You’ve Got a Friend in IAM
By Drew Rothstein, President
Google’s Cloud Platform offers a Custom Roles feature which enables you to create a role to be used by a project or organization. This in turn allows you to grant said role to a principal (such as a Service Account). This feature is powerful, especially at the organizational level for security & auditing tooling. If you have tens or hundreds of GCP Projects and want to perform some type of operation on them, having a custom role that is assigned an appropriate principal is a great solution.
A similar concept exists in Amazon Web Services with Cross-Account Roles and utilizing AssumeRole.
A similarity between Public Cloud Providers is that properly configuring roles + principals to perform the action you desire as expected can be extremely difficult. If you add Configuration Management (e.g. Terraform) into the mix, building out what you are seeking can take a lot of trial and error to achieve.
It is quite fascinating how proper configuration with configuration management of something that is incredibly useful is also incredibly complex and not well documented by either Public Cloud Provider with clear examples and use cases.
This post attempts to demystify the usage and configuration of a Custom Role on GCP with a practical example. If this is helpful to you and you might be interested in some of the challenges like this, feel free to check out our jobs link or reach out to us from your favorite media platform.
Custom Roles: The Basics
What is a Custom Role?
Great question because this isn’t actually clearly documented in the Google Cloud Platform documentation. A Custom Role is a defined set of user-configured allowable permissions that can be used to assign principals and utilize those permissions. There is a limited set of permissions that a Custom Role can utilize which are documented. A Custom Role can be created at a Project or Organization level in GCP.
Does creation of a Custom Role grant any permissions?
No, it does not. Until a principal is assigned (such as a User, Service Account, or Group), the permissions are just a construct.
How do I use a Custom Role?
Assuming you have created a Custom Role at the required scope (Project or Organization), you simply apply a principal to it in IAM. Once assigned, you may perform some action as that principal and you will inherit the permissions granted to your Custom Role.
Custom Roles: An Example
You are Buzz Lightyear and while trying to keep an eye on all the toys (GCP Projects) you have decided it would be cool to send out a team to check on them! They are all in locked rooms. But, you have the key to each room. That key is similar to a Custom Role. It doesn’t really do much of anything on its own and without knowing what house, what room, and without gaining access to the premises, etc. Giving the key to the team and helping them gain access to the premises is similar to assigning a principal to a Custom Role. Performing the actual check on the toys in each room is actually using the principal to assume the permissions of the Custom Role.
How can I codify (IaaS) a Custom Role with Terraform?
This is pretty simple and requires you to define a couple items including, most importantly, deciding what permissions are required for what you are trying to accomplish.
resource "google_organization_iam_custom_role" "buzz-associates" {
role_id = "BuzzRole"
org_id = data.google_project.org.org_id
title = "Buzz’s Associates"
permissions = [
"compute.instances.getGuestAttributes",
"compute.instances.list",
"compute.projects.get",
"iam.serviceAccounts.actAs",
"resourcemanager.projects.list",
...
]
}
How do I configure a principal to utilize a Custom Role?
Assuming that a Service Account will be the configured principal, first you will want one of those.
resource "google_service_account" "buzz-associates" {
account_id = "buzz-associates-sa"
project = "buzz-force-1234"
display_name = "buzz-associates-service-account"
}
Then assign this principal:
binding {
members = [
"serviceAccount:${google_service_account.buzz-associates.email}",
]
role = google_organization_iam_custom_role.buzz-associates.id
}
How do I configure a service to utilize the principal-associated Custom Role?
This is the last step in the process. This is highly dependent on what type of service you are running so there isn’t a single example that will make complete sense for your particular application- Cloud Functions, Cloud Run, a service on a VM, etc.
A simple Cloud Run service may look something like:
resource "google_cloud_run_service" "service" {
...
template {
spec {
service_account_name = google_service_account.buzz-associates.email
...
}
}
Full Example
A more complete example combining all of the pieces together may look something like:
terraform {
backend "gcs" {
bucket = "<state-bucket>"
}
}
provider "google" {
project = "buzz-org-root.com"
region = "us-west2"
}
resource "google_organization_iam_custom_role" "buzz-associates" {
role_id = "BuzzRole"
org_id = data.google_project.org.org_id
title = "Buzz’s Associates"
permissions = [
"compute.instances.getGuestAttributes",
"compute.instances.list",
"compute.projects.get",
"iam.serviceAccounts.actAs",
"resourcemanager.projects.list",
...
]
}
resource "google_service_account" "buzz-associates" {
account_id = "buzz-associates-sa"
project = "buzz-force-1234"
display_name = "buzz-associates-service-account"
}
binding {
members = [
"serviceAccount:${google_service_account.buzz-associates.email}",
]
role = google_organization_iam_custom_role.buzz-associates.id
}
resource "google_cloud_run_service" "service" {
name = "example"
location = "us-west2"
project = "buzz-org-root.com"
template {
spec {
service_account_name = google_service_account.buzz-associates.email
containers {
image = "gcr.io/cloudrun/hello"
}
}
}
}
Conclusion
Utilizing Custom Roles to define policy across projects and organizations can be incredibly powerful and more importantly, useful! This is true, whether you are Buzz Lightyear running Buzz’s Associates or simply looking to run a security or auditing service across various projects.
Configuring a Custom Role through Configuration Management (e.g. Terraform) is actually fairly reasonable once you have all of the pieces well understood. Public Cloud Providers could make this a lot easier through better documentation and examples.
We are currently hiring for multiple positions in various locations and remote.