In large organizations, it can be helpful to let teams independently manage the allow policies for their resources. However, letting a principal grant or revoke all IAM roles can greatly increase your security risk.
You can set limits on the roles that a principal can grant and revoke with
Identity and Access Management (IAM) Conditions and the
iam.googleapis.com/modifiedGrantsByRole
API attribute. These limits let you
create limited IAM admins who can manage their own team's allow
policies, but only within the boundaries that you have set.
Before you begin
Enable the Resource Manager API.
Be familiar with the structure of allow policies.
Understand IAM Conditions.
Required permissions
To get the permissions that you need to create limited IAM admins for a project, folder, or organization, ask your administrator to grant you the following IAM roles on the resource that you want to create a limited IAM admin for (project, folder, or organization):
-
To create a limited IAM admin for a project:
Project IAM Admin (
roles/resourcemanager.projectIamAdmin
) -
To create a limited IAM admin for a folder:
Folder Admin (
roles/resourcemanager.folderAdmin
) -
To create a limited IAM admin for a project, folder, or organization:
Organization Admin (
roles/resourcemanager.organizationAdmin
)
For more information about granting roles, see Manage access to projects, folders, and organizations.
These predefined roles contain the permissions required to create limited IAM admins for a project, folder, or organization. To see the exact permissions that are required, expand the Required permissions section:
Required permissions
The following permissions are required to create limited IAM admins for a project, folder, or organization:
-
To create a limited IAM admin for a project:
-
resourcemanager.projects.getIamPolicy
-
resourcemanager.projects.setIamPolicy
-
-
To create a limited IAM admin for a folder:
-
resourcemanager.folders.getIamPolicy
-
resourcemanager.folders.setIamPolicy
-
-
To create a limited IAM admin for an organization:
-
resourcemanager.organizations.getIamPolicy
-
resourcemanager.organizations.setIamPolicy
-
You might also be able to get these permissions with custom roles or other predefined roles.
Common use cases
The following sections describe how you can use limited role granting to enable self-service management of allow policies.
Create limited IAM admins
Consider a scenario where you want to let a user, Finn (finn@example.com
), act
as a limited IAM admin for your project. You want Finn to be able
to grant and revoke only the App Engine Admin (roles/appengine.appAdmin
) and
App Engine Viewer (roles/appengine.appViewer
) roles for your project.
To grant this limited ability, you conditionally grant Finn the Project IAM
Admin role (roles/resourcemanager.projectIamAdmin
). The Project IAM Admin role
allows Finn to grant and revoke IAM roles, and the condition
limits which roles Finn can grant and revoke:
{ "version": 3, "etag": "BwWKmjvelug=", "bindings": [ { "members": [ "user:owner@example.com" ], "role": "roles/owner" }, { "members": [ "finn@example.com" ], "role": "roles/resourcemanager.projectIamAdmin", "condition": { "title": "only_appengine_admin_viewer_roles", "description": "Only allows changes to role bindings with the App Engine Admin or Viewer roles", "expression": "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly(['roles/appengine.appAdmin', 'roles/appengine.appViewer'])" } } ] }
This conditional role binding lets Finn do the following:
- Grant the App Engine Admin and App Engine Viewer roles for the project.
- Revoke the App Engine Admin and App Engine Viewer roles for the project.
- Add, remove, or modify conditions for project-level role bindings that grant the App Engine Admin and App Engine Viewer roles.
- Perform other actions allowed by the Project IAM Admin role that don't
modify the project's allow policy. For example, Finn could use the
projects.getIamPolicy
method to get the project's allow policy.
This conditional role binding does not let Finn do any of the following:
- Modify allow policies for resources other than the project.
- Grant roles other than the App Engine Admin or App Engine Viewer roles.
- Revoke roles other than the App Engine Admin or App Engine Viewer roles.
- Add, remove, or modify conditions for role bindings that don't grant the App Engine Admin or App Engine Viewer roles.
Allow users to manage limited IAM admins
Consider a scenario where you want to make a user, Lila, a limited
IAM admin for her team. You want Lila to be able to grant and
revoke only the Compute Admin role (roles/compute.admin
) for her project.
However, you also want to let Lila select other users to act as limited
IAM admins. In other words, you want to let Lila allow other
users to grant and revoke only the Compute Admin role.
You might think that the solution is to grant Lila the Project IAM Admin role
(roles/resourcemanager.projectIamAdmin
), and then give her the ability to
grant or revoke that role for others. However, if you grant Lila the Project IAM
Admin role, she could remove the condition from her own role and give herself
the ability to grant or revoke any IAM role.
To help prevent this privilege escalation, you instead
create a Google group, iam-compute-admins@example.com
, for
the project's limited IAM admins. Then, you
add Lila to the group and
make her a group manager.
After you create the group, you conditionally grant the group the Project IAM
Admin role (roles/resourcemanager.projectIamAdmin
). The Project IAM Admin role
allows group members to grant and revoke IAM roles, and the
condition limits which roles they can grant and revoke:
{ "version": 3, "etag": "BwWKmjvelug=", "bindings": [ { "members": [ "user:owner@example.com" ], "role": "roles/owner" }, { "members": [ "iam-compute-admins@example.com" ], "role": "roles/resourcemanager.projectIamAdmin", "condition": { "title": "only_compute_admin_role", "description": "Only allows changes to role bindings for the Compute Admin role", "expression": "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly(['roles/compute.admin'])" } } ] }
As a member of the iam-compute-admins@example.com
group, Lila can do the
following:
- Grant the Compute Admin role for the project by adding a new binding for the role, or by adding a principal to an existing binding for the role.
- Revoke the Compute Admin role by removing an existing binding for the role, or by removing a principal from an existing binding for the role.
- Modify grants for the Compute Admin role by adding, removing, or modifying conditions attached to bindings for the role.
- Perform other actions allowed by the Project IAM Admin role that don't modify
the project's allow policy. For example, she could use the
projects.getIamPolicy
method to get the project's allow policy.
As a manager of the iam-compute-admins@example.com
group, Lila can allow
other users to grant or revoke the Compute Admin role by adding them to the
iam-compute-admins@example.com
group.
Lila cannot do the following:
- Give herself the ability to grant or revoke other roles.
- Modify allow policies for resources other than the project.
- Grant roles other than the Compute Admin role.
- Revoke roles other than the Compute Admin role.
- Add, remove, or modify conditions for role bindings that don't grant the Compute Admin role.
Limit role granting
The following sections explain how to let principals grant or revoke only certain roles.
Write a condition expression to limit role granting
To limit a principal's ability to grant roles, write a condition expression that specifies the roles a principal can grant or revoke.
Use the following format for your condition expression:
api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly(roles)
This expression does the following:
Gets the API attribute
iam.googleapis.com/modifiedGrantsByRole
using theapi.getAttribute()
function.For a request to set the allow policy of a resource, this attribute contains the role names from the bindings that the request modifies. For other types of requests, the attribute is not defined. In these cases, the function returns the default value (
[]
).Uses the
hasOnly()
Common Expression Language (CEL) function to define and enforce the roles that the principal is allowed to grant or revoke.The input for the
hasOnly()
function is a list of the roles that the principal is allowed to grant or revoke. If the roles in theiam.googleapis.com/modifiedGrantsByRole
attribute are included in this list, the function returnstrue
. If they are not, the function returnsfalse
.If the
iam.googleapis.com/modifiedGrantsByRole
attribute contains the default value ([]
), the function returnstrue
, because[]
does not contain any roles not included in the list.
To customize this expression, replace roles
with a list
of the roles that the principal is allowed to grant or revoke. For example, to
let the principal grant or revoke only the Pub/Sub Editor
(roles/pubsub.editor
) and Pub/Sub Publisher (roles/pubsub.publisher
) roles,
use the value ['roles/pubsub.editor', 'roles/pubsub.publisher']
.
You can include up to 10 values in the list of allowed roles. All of these values must be string constants.
Logical operators for hasOnly()
statements
Don't use the &&
or ||
operators to join multiple hasOnly()
statements in
a single condition. If you do, then requests that grant or revoke multiple roles
might fail, even if the principal can grant or revoke those roles individually.
For example, consider the following condition:
api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []) .hasOnly(['roles/pubsub.editor']) || api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []) .hasOnly(['roles/pubsub.publisher'])
This condition evaluates to true
if a request grants either the
roles/pubsub.editor
role or the roles/pubsub.publisher
role, but it
evaluates to false
if a request grants both the roles/pubsub.editor
role
and the roles/pubsub.publisher
role.
Limit role granting with conditional role bindings
To allow a principal to grant or revoke only certain roles, use the condition expression from the preceding section to create a conditional role binding. Then, add the conditional role binding to a resource's allow policy.
Select a resource that represents the scope that you want to let a principal grant and revoke roles for:
- If you want to let a principal grant and revoke certain roles for all resources within an organization, select an organization.
- If you want to let a principal grant and revoke certain roles for all resources within an folder, select a folder.
- If you want to let a principal grant and revoke certain roles for all resources within a project, select a project.
Select a role that allows a principal to set the allow policy for the resource type you selected (project, folder, or organization). To follow the principle of least privilege, choose one of the following predefined roles:
- Projects: Project IAM Admin (
roles/resourcemanager.projectIamAdmin
) - Folders: Folder IAM Admin (
roles/resourcemanager.folderIamAdmin
) Organizations: Organization Admin (
roles/resourcemanager.organizationAdmin
).
Alternatively, choose a custom role that includes the
resourcemanager.resource-type.setIamPolicy
andresourcemanager.resource-type.getIamPolicy
permissions, whereresource-type
isproject
,folder
, ororganization
.- Projects: Project IAM Admin (
Conditionally grant a principal your chosen role on the project, folder, or organization you selected.
The new allow policy is applied, and your principal can modify bindings for only the roles you have allowed.
Console
In the Google Cloud console, go to the IAM page.
Make sure the name of your project, folder, or organization appears in the resource selector at the top of the page. The resource selector tells you what project, folder, or organization you are currently working in.
If you don't see the name of your resource, click the resource selector, then select your resource.
In the list of principals, locate the principal that will grant and revoke roles, and click the
button.In the Edit permissions panel, select the role you chose previously. Then under IAM condition (optional), click Add IAM condition.
In the Edit condition panel, enter a title and optional description for the condition.
Click the Condition editor tab and enter the expression you wrote in Writing a condition expression to limit role granting. This expression limits which roles the principal can grant or revoke.
For example, the following condition expression limits the principal to granting and revoking the Pub/Sub Editor (
roles/pubsub.editor
) and Pub/Sub Publisher (roles/pubsub.publisher
) roles:api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly(['roles/pubsub.editor', 'roles/pubsub.publisher'])
Warning: Don't include the following types of roles in the list of allowed roles:
-
Roles with permissions to grant and revoke IAM roles (that
is, roles with permission names that end in
setIamPolicy
). -
Custom roles that the limited IAM admin can modify. For
example, if the limited IAM admin also has the Role
Administrator role (
roles/iam.roleAdmin
) on a project, don't allow them to grant or revoke project-level custom roles.
Limited IAM admins who can grant and revoke these types of roles can give themselves permission to grant and revoke all IAM roles. See Writing a condition expression to limit role granting for more information.
-
Roles with permissions to grant and revoke IAM roles (that
is, roles with permission names that end in
Click Save to apply the condition.
After the Edit condition panel is closed, click Save in the Edit permissions panel to update your allow policy.
gcloud
Allow policies are set using the read-modify-write pattern.
First, read the allow policy for the resource:
Execute the
get-iam-policy
command. This command gets the current allow policy for the resource.Command:
gcloud resource-type get-iam-policy resource-id --format=json > path
Replace the following values:
resource-type
: The resource type that you want to let a principal grant or revoke roles for. Use one of the following:projects
,resource-manager folders
, ororganizations
.resource-id
: Your Google Cloud project, folder, or organization ID.path
: The path of the file to download the allow policy to.
The allow policy is saved in JSON format, for example:
{ "bindings": [ { "members": [ "user:project-owner@example.com" ], "role": "roles/owner" } ], "etag": "BwWKmjvelug=", "version": 1 }
Next, modify the allow policy.
To let a principal only modify bindings for certain roles, add the highlighted conditional role binding:
{ "bindings": [ { "members": [ "user:owner@example.com" ], "role": "roles/owner" }, { "members": [ "principal" ], "role": "role", "condition": { "title": "title", "description": "description", "expression": "expression" } } ], "etag": "BwWKmjvelug=", "version": 3 }
Replace the following values:
principal
: The principal that will grant or revoke certain roles. For example,user:my-user@example.com
. To see the formats of each principal type, see theBinding
reference.role
: The role you chose in the preceding steps. This role must include thesetIamPolicy
permission for the resource type you chose.title
: A string briefly describing the condition. For example,only_pubsub_roles
.description
: Optional. An additional description for the condition. For example,Only allows granting/revoking the Pub/Sub editor and publisher roles
.expression
: The expression you wrote in Writing a condition expression to limit role granting. This expression limits which roles that the principal can grant or revoke.For example, the following condition expression limits the principal to granting and revoking the Pub/Sub Editor (
roles/pubsub.editor
) and Pub/Sub Publisher (roles/pubsub.publisher
) roles:api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly(['roles/pubsub.editor', 'roles/pubsub.publisher'])
Warning: Don't include the following types of roles in the list of allowed roles:
-
Roles with permissions to grant and revoke IAM roles (that
is, roles with permission names that end in
setIamPolicy
). -
Custom roles that the limited IAM admin can modify. For
example, if the limited IAM admin also has the Role
Administrator role (
roles/iam.roleAdmin
) on a project, don't allow them to grant or revoke project-level custom roles.
Limited IAM admins who can grant and revoke these types of roles can give themselves permission to grant and revoke all IAM roles. See Writing a condition expression to limit role granting for more information.
-
Roles with permissions to grant and revoke IAM roles (that
is, roles with permission names that end in
Finally, write the updated allow policy:
Set the new allow policy by executing the
set-iam-policy
command for the resource:gcloud resource-type set-iam-policy resource-id path
Replace the following values:
resource-type
: The resource type that you want to let a principal grant or revoke roles for. Use one of the following:projects
,resource-manager folders
, ororganizations
.resource-id
: Your Google Cloud project, folder, or organization ID.path
: A path to the file containing the updated allow policy.
The new allow policy is applied, and the principal will be able to modify bindings for only the roles you have allowed.
REST
Allow policies are set using the read-modify-write pattern.
First, read the allow policy for the resource:
The Resource Manager API's
getIamPolicy
method gets a project's, folder's, or organization's allow policy.Before using any of the request data, make the following replacements:
API_VERSION
: The API version to use. For projects and organizations, usev1
. For folders, usev2
.RESOURCE_TYPE
: The resource type whose policy you want to manage. Use the valueprojects
,folders
, ororganizations
.RESOURCE_ID
: Your Google Cloud project, organization, or folder ID. Project IDs are alphanumeric strings, likemy-project
. Folder and organization IDs are numeric, like123456789012
.POLICY_VERSION
: The policy version to be returned. Requests should specify the most recent policy version, which is policy version 3. See Specifying a policy version when getting a policy for details.
HTTP method and URL:
POST https://cloudresourcemanager.googleapis.com/API_VERSION/RESOURCE_TYPE/RESOURCE_ID:getIamPolicy
Request JSON body:
{ "options": { "requestedPolicyVersion": POLICY_VERSION } }
To send your request, expand one of these options:
The response contains the resource's allow policy. For example:
{ "version": 1, "etag": "BwWKmjvelug=", "bindings": [ { "role": "roles/owner", "members": [ "user:owner@example.com" ] } ] }
Next, modify the allow policy.
Add a conditional role binding that lets a principal grant and revoke only certain roles. Make sure to change the
version
field to the value3
:{ "version": 3, "etag": "BwWKmjvelug=", "bindings": [ { "members": [ "user:owner@example.com" ], "role": "roles/owner" }, { "members": [ "PRINCIPAL" ], "role": "ROLE", "condition": { "title": "TITLE", "description": "DESCRIPTION", "expression": "EXPRESSION" } } ] }
PRINCIPAL
: The principal that will grant or revoke certain roles. For example,user:my-user@example.com
. To see the formats of each principal type, see theBinding
reference.ROLE
: The role you chose in the preceding steps. This role must include thesetIamPolicy
permission for the resource type you chose.TITLE
: A string briefly describing the condition. For example,only_pubsub_roles
.DESCRIPTION
: Optional. An additional description for the condition. For example,Only allows granting/revoking the Pub/Sub editor and publisher roles
.EXPRESSION
: The expression you wrote in Writing a condition expression to limit role granting. This expression limits which roles that the principal can grant or revoke.For example, the following condition expression limits the principal to granting and revoking the Pub/Sub Editor (
roles/pubsub.editor
) and Pub/Sub Publisher (roles/pubsub.publisher
) roles:api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly(['roles/pubsub.editor', 'roles/pubsub.publisher'])
Warning: Don't include the following types of roles in the list of allowed roles:
-
Roles with permissions to grant and revoke IAM roles (that
is, roles with permission names that end in
setIamPolicy
). -
Custom roles that the limited IAM admin can modify. For
example, if the limited IAM admin also has the Role
Administrator role (
roles/iam.roleAdmin
) on a project, don't allow them to grant or revoke project-level custom roles.
Limited IAM admins who can grant and revoke these types of roles can give themselves permission to grant and revoke all IAM roles. See Writing a condition expression to limit role granting for more information.
-
Roles with permissions to grant and revoke IAM roles (that
is, roles with permission names that end in
Finally, write the updated allow policy:
The Resource Manager API's
setIamPolicy
method sets the allow policy in the request as the new allow policy for the project, folder, or organization.Before using any of the request data, make the following replacements:
API_VERSION
: The API version to use. For projects and organizations, usev1
. For folders, usev2
.RESOURCE_TYPE
: The resource type whose policy you want to manage. Use the valueprojects
,folders
, ororganizations
.RESOURCE_ID
: Your Google Cloud project, organization, or folder ID. Project IDs are alphanumeric strings, likemy-project
. Folder and organization IDs are numeric, like123456789012
.-
POLICY
: A JSON representation of the policy that you want to set. For more information about the format of a policy, see the Policy reference.For example, to set the policy shown in the previous step, replace
POLICY
with the following:{ "version": 3, "etag": "BwWKmjvelug=", "bindings": [ { "members": [ "user:owner@example.com" ], "role": "roles/owner" }, { "members": [ "principal" ], "role": "role", "condition": { "title": "title", "description": "description", "expression": "expression" } } ] }
HTTP method and URL:
POST https://cloudresourcemanager.googleapis.com/API_VERSION/RESOURCE_TYPE/RESOURCE_ID:setIamPolicy
Request JSON body:
{ "policy": POLICY }
To send your request, expand one of these options:
The response contains the updated allow policy.
What's next
- Enforce the principle of least privilege with role recommendations.
- Learn how to use IAM Conditions to configure temporary access and configure resource-based access.