Create a custom IAM role by using YAML and flags in GCP

To create a custom role, a caller must possess iam.roles.create permission. By default, the owner of a project or an organization has this permission and can create and manage custom roles.

Users who are not owners, including organization admins, must be assigned either the Organization Role Administrator role, or the IAM Role Administrator role.

Use the gcloud iam roles create command to create new custom roles. You can use this command in two ways:

  • By providing a YAML file that contains the role definition
  • By using flags to specify the role definition When creating a custom role, you must specify whether it applies to the organization level or project level by using the --organization [ORGANIZATION_ID] or --project [PROJECT_ID] flags. Each example below creates a custom role at the project level.

To create a custom role using a YAML file

Create a YAML file that contains the definition for your custom role. The file must be structured in the following way:

title: [ROLE_TITLE]
description: [ROLE_DESCRIPTION]
stage: [LAUNCH_STAGE]
includedPermissions:
- [PERMISSION_1]
- [PERMISSION_2]

Each of the placeholder values is described below:

  • [ROLE_TITLE] is a friendly title for the role, such as Role Viewer.
  • [ROLE_DESCRIPTION] is a short description about the role, such as My custom role description.
  • [LAUNCH_STAGE] indicates the stage of a role in the launch lifecycle, such as ALPHA, BETA, or GA.
  • includedPermissions specifies the list of one or more permissions to include in the custom role, such as iam.roles.get.

Time to get started! Create your role definition YAML file by running:

nano role-definition.yaml

Add this custom role definition to the YAML file:

title: "Role Editor"
description: "Edit access for App Versions"
stage: "ALPHA"
includedPermissions:
- appengine.versions.create
- appengine.versions.delete

Then save and close the file.

Execute the following gcloud command:

gcloud iam roles create editor --project $DEVSHELL_PROJECT_ID \
--file role-definition.yaml

If the role was created successfully, the following response is returned:

Created role [editor].
description: Edit access for App Versions
etag: BwVs4O4E3e4=
includedPermissions:
- appengine.versions.create
- appengine.versions.delete
name: projects/[PROJECT_ID]/roles/editor
stage: ALPHA
title: Role Editor

Create a custom role using flags

Now you’ll use the flag method to create a new custom role. The flags take a similar form to the YAML file, so you’ll recognize how the command is being built.

Execute the following gcloud command to create a new role using flags:

gcloud iam roles create viewer --project $DEVSHELL_PROJECT_ID \
--title "Role Viewer" --description "Custom role description." \
--permissions compute.instances.get,compute.instances.list --stage ALPHA

sample output:

Created role [viewer].
description: Custom role description.
etag: BwVs4PYHqYI=
includedPermissions:
- compute.instances.get
- compute.instances.list
name: projects/[PROJECT_ID]/roles/viewer
stage: ALPHA
title: Role Viewer

Listing the custom roles

Execute the following gcloud command to list custom roles, specifying either project-level or organization-level custom roles:

gcloud iam roles list --project $DEVSHELL_PROJECT_ID

Example Output:

---
description: Edit access for App Versions
etag: BwVxLgrnawQ=
name: projects/[PROJECT_ID]/roles/editor
title: Role Editor
---
description: Custom role description.
etag: BwVxLg18IQg=
name: projects/[PROJECT_ID]/roles/viewer
title: Role Viewer

To list deleted roles, you can also specify the --show-deleted flag.

Execute the following gcloud command to list predefined roles:

gcloud iam roles list

Editing an existing custom role

A common pattern for updating a resource’s metadata, such as a custom role, is to read its current state, update the data locally, and then send the modified data for writing. This pattern could cause a conflict if two or more independent processes attempt the sequence simultaneously.

For example, if two owners for a project try to make conflicting changes to a role at the same time, some changes could fail.

Cloud IAM solves this problem using an etag property in custom roles. This property is used to verify if the custom role has changed since the last request. When you make a request to Cloud IAM with an etag value, Cloud IAM compares the etag value in the request with the existing etag value associated with the custom role. It writes the change only if the etag values match.

Use the gcloud iam roles update command to update custom roles. You can use this command in two ways:

  • By providing a YAML file that contains the updated role definition
  • By using flags to specify the updated role definition

When updating a custom role, you must specify whether it applies to the organization level or project level by using the --organization [ORGANIZATION_ID] or --project [PROJECT_ID] flags. Each example below creates a custom role at the project level.

The describe command returns the role’s definition and includes an etag value that uniquely identifies the current version of the role. The etag value should be provided in the updated role definition to ensure that any concurrent role changes are not overwritten.

To update a custom role using a YAML file

Get the current definition for the role by executing the following gcloud command, replacing [ROLE_ID] with editor.

gcloud iam roles describe [ROLE_ID] --project $DEVSHELL_PROJECT_ID

The describe command returns the following output:

description: [ROLE_DESCRIPTION]
etag: [ETAG_VALUE]
includedPermissions:
- [PERMISSION_1]
- [PERMISSION_2]
name: [ROLE_ID]
stage: [LAUNCH_STAGE]
title: [ROLE_TITLE]

You’ll create a new YAML file with the outputted value. Copy the output from this command.

Create a new-role-definition.yaml file with your editor.

nano new-role-definition.yaml

Paste in the outputted value from the last command and add these two permissions under includedPermissions:

- storage.buckets.get
- storage.buckets.list

Your YAML file will look like this when you’re finished:

description: Edit access for App Versions
etag: BwVxIAbRq_I=
includedPermissions:
- appengine.versions.create
- appengine.versions.delete
- storage.buckets.get
- storage.buckets.list
name: projects/[PROJECT_ID]/roles/editor
stage: ALPHA
title: Role Editor

Save and close the file.

Now you’ll use the update command to update the role. Execute the following gcloud command, replacing [ROLE_ID] with editor:

gcloud iam roles update [ROLE_ID] --project $DEVSHELL_PROJECT_ID \
--file new-role-definition.yaml

If the role was updated successfully, the following response is returned:

description: Edit access for App Versions
etag: BwVxIBjfN3M=
includedPermissions:
- appengine.versions.create
- appengine.versions.delete
- storage.buckets.get
- storage.buckets.list
name: projects/[PROJECT_ID]/roles/editor
stage: ALPHA
title: Role Editor

To update a custom role using flags

Each part of a role definition can be updated using a corresponding flag. See the gcloud iam roles update topic for a list of all possible flags.

You can use the following flags to add or remove permissions:

  • --add-permissions: Adds one or more comma-separated permissions to the role.
  • --remove-permissions: Removes one or more comma-separated permissions from the role.

Alternatively, you can simply specify the new permissions using the --permissions [PERMISSIONS] flag and providing a comma-separated list of permissions to replace the existing permissions list.

Execute the following gcloud command to add permissions to the viewer role using flags:

gcloud iam roles update viewer --project $DEVSHELL_PROJECT_ID \
--add-permissions storage.buckets.get,storage.buckets.list

If the role was updated successfully, the following response is returned:

description: Custom role description.
etag: BwVxLi4wTvk=
includedPermissions:
- compute.instances.get
- compute.instances.list
- storage.buckets.get
- storage.buckets.list
name: projects/[PROJECT_ID]/roles/viewer
stage: ALPHA
title: Role Viewer

Disabling a custom role

When a role is disabled, any policy bindings related to the role are inactivated, meaning that the permissions in the role will not be granted, even if you grant the role to a user.

The easiest way to disable an existing custom role is to use the --stage flag and set it to DISABLED.

Execute the following gcloud command to disable the viewer role:

gcloud iam roles update viewer --project $DEVSHELL_PROJECT_ID \
--stage DISABLED

If the role was updated successfully, the following response is returned:

description: Custom role description.
etag: BwVxLkIYHrQ=
includedPermissions:
- compute.instances.get
- compute.instances.list
- storage.buckets.get
- storage.buckets.list
name: projects/[PROJECT_ID]/roles/viewer
stage: DISABLED
title: Role Viewer

Deleting a custom role

Use the gcloud iam roles delete command to delete a custom role. Once deleted the role is inactive and cannot be used to create new IAM policy bindings.

gcloud iam roles delete viewer --project $DEVSHELL_PROJECT_ID

Example Output:

description: Custom role description.
etag: BwVxLkf_epw=
includedPermissions:
- compute.instances.get
- compute.instances.list
- storage.buckets.get
- storage.buckets.list
name: projects/[PROJECT_ID]/roles/viewer
stage: DISABLED
title: Role Viewer

After the role has been deleted, existing bindings remain, but are inactive. The role can be undeleted within 7 days. After 7 days, the role enters a permanent deletion process that lasts 30 days. After 37 days, the Role ID is available to be used again.Note: If a role is being phased out, change its role.stage property to DEPRECATED, and set the deprecation_message to let users know what alternative roles should be used or where to get more information.

Undeleting a custom role

Within the 7 days window you can undelete a role. Deleted roles are in a DISABLEDstate. You can make it available again by updating the --stage flag:

gcloud iam roles undelete viewer --project $DEVSHELL_PROJECT_ID