Identity and Access Management (IAM) offers several types of policies to help you control which resources principals can access. This guide describes how to use access policies to control access when publishing event messages to an Eventarc Advanced bus.
IAM access policies can both allow and deny access to resources. However, unlike IAM allow and deny policies, access policies can grant or deny access based on specific event context attributes, such as the event message priority.
Each access policy is a set of rules that lets you identify principals and define conditions which determine the applicability of a rule, and that lets you enable fine-grained access control. For example, depending on the evaluation of a Common Expression Language (CEL) expression applied to an event context attribute, you can allow or deny the permission to publish a subset of event messages to an Eventarc Advanced bus.
This guide explains how to create and apply an access policy by first creating an access policy, and then creating a policy binding to connect that policy to a Google Cloud project.
Before you begin
Before creating and applying an access policy, you should have already created an Eventarc Advanced bus to which event messages can be published.
Make sure that you take into consideration the following:
Access policies must be applied or bound to a Google Cloud project. Each access policy can be attached to up to 5 projects; each project can have up to 5 access policies attached to it. You can create one bus per Google Cloud project per supported region. An access policy that is attached to a project controls the publishing access to any Eventarc Advanced bus in that project.
You can use access policies to control publishing access to an Eventarc Advanced bus, but not to control access to the subscription of messages from a particular bus. The supported permission is
eventarc.messageBuses.publish.Access control can be based only on event context attributes and not on the event payload content.
Event messages that are published from Google sources and that are denied are dropped. If the principal directly publishes an event message, an
Event published successfullylog message indicates this. However, if the event message is denied by the condition in the access policy, an error similar to the following occurs:ERROR: (gcloud.beta.eventarc.message-buses.publish) PERMISSION_DENIED: Permission 'eventarc.googleapis.com/messageBuses.publish' denied on resource due to an IAM Access Policy. This command is authenticated as user@example.com which is the active account specified by the [core/account] property. '@type': type.googleapis.com/google.rpc.ErrorInfo domain: iam.googleapis.com metadata: permission: eventarc.googleapis.com/messageBuses.publish reason: IAM_PERMISSION_DENIED
If you haven't already, enable the Eventarc and IAM APIs:
gcloud services enable eventarc.googleapis.com \ eventarcpublishing.googleapis.com \ iam.googleapis.com
Set up authentication:
gcloud
In the Google Cloud console, activate Cloud Shell.
At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.
REST API
To use the REST API samples on this page in a local development environment, you use the credentials you provide to the gcloud CLI.
Install the Google Cloud CLI. After installation, initialize the Google Cloud CLI by running the following command:
gcloud initIf you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.
For more information, see Authenticate for using REST in the Google Cloud authentication documentation.
Required roles
An IAM role contains a set of permissions that lets you perform specific actions on Google Cloud resources.
To get the permissions that you need to control publishing access, ask your administrator to grant you the following IAM roles on your project:
-
Create access policies:
Access Policy Admin (
roles/iam.accessPolicyAdmin) -
Apply access policies:
Project IAM Admin (
roles/resourcemanager.projectIamAdmin)
For more information about granting roles, see Manage access to projects, folders, and organizations.
These predefined roles contain the permissions required to control publishing access. To see the exact permissions that are required, expand the Required permissions section:
Required permissions
The following permissions are required to control publishing access:
-
Create access policies:
iam.accessPolicies.create -
Apply access policies:
-
iam.accessPolicies.bind -
resourcemanager.projects.createPolicyBinding
-
You might also be able to get these permissions with custom roles or other predefined roles.
Create an access policy
Create an access policy to control access when publishing to an Eventarc Advanced bus in your project.
You can create an access policy by using the Google Cloud CLI or by making a direct request to the IAM v3 API.
gcloud
You can create an access policy by running the gcloud beta iam access-policies create command.
gcloud beta iam access-policies create POLICY_ID \ --project=POLICY_PROJECT_ID \ --location=global \ --details-rules=description="POLICY_DESCRIPTION",effect=EFFECT, \ principals=[PRINCIPALS],excludedPrincipals=[EXCLUDED_PRINCIPALS], \ permissions=[eventarc.googleapis.com/messageBuses.publish], \ activationConditions={eventarc.googleapis.com={celCondition={expression="CEL_EXPRESSION"}}}
Replace the following:
POLICY_ID: a unique name for the access policy—for example,my-access-policy.POLICY_PROJECT_ID: the Google Cloud project ID of the project where the policy will be created.POLICY_DESCRIPTION: an optional description of the policy (256 characters maximum).EFFECT: the effect of the rule (ALLOWorDENY).PRINCIPALS: the identities to which this rule applies. The format of the identifier depends on the type of principal you want to refer to. For more information, see Principal types for access policies.EXCLUDED_PRINCIPALS: the identities that are excluded from the rule application, even if listed inprincipals. For example, you can add a Google group toprincipalsand then exclude specific users who belong to that group.CEL_EXPRESSION: the CEL expression that will be evaluated to determine the rule applicability—for example,message.version != \"v1\". For more information, see Use Common Expression Language.
Note the following:
- The
--locationflag specifies the location of the access policy and must beglobal. The
--details-rulesflag can specify the path to the access policy file which can be written in either JSON or YAML—for example,--details-rules=path_to_file.json.The flag can also be repeated when configuring multiple rules. Each rule is evaluated independently.
An access policy uses the following format:
{ "displayName": "POLICY_DISPLAY_NAME", "details": { "rules": [ { "description": "POLICY_DESCRIPTION", "effect": "EFFECT", "principals": [ "PRINCIPALS" ], "excludedPrincipals": [ "EXCLUDED_PRINCIPALS" ], "permissions": [ "eventarc.googleapis.com/messageBuses.publish" ], "activationConditions": { "eventarc.googleapis.com": { "celCondition": { "expression": "CEL_EXPRESSION" } } } } ] } }
The response contains a long-running operation representing your request. To learn how to get the status of a long-running operation, in this document, see Check the status of a long-running operation.
Example
The following command creates an access policy that allows the principal specified to publish event messages to a bus but denies publishing where the data media type is JSON.
gcloud beta iam access-policies create my-access-policy \ --project=my-project-id \ --location=global \ --details-rules=description="Allow publishing to bus",effect=ALLOW,principals=[principal://goog/subject/user@example.com],permissions=[eventarc.googleapis.com/messageBuses.publish] \ --details-rules=description="Deny publishing to bus if media type is JSON",effect=DENY,principals=[principal://goog/subject/user@example.com],permissions=[eventarc.googleapis.com/messageBuses.publish],activationConditions={eventarc.googleapis.com={celCondition={expression="message.datacontenttype=='application/json'"}}}
REST API
You can create an access policy by using the
projects.locations.accessPolicies.create method.
Before using any of the request data, make the following replacements:
POLICY_DISPLAY_NAME: optional. A human-readable name for the access policy—for example, "Example policy". The display name can be a maximum of 63 characters.POLICY_DESCRIPTION: optional. A human-readable description of the access policy—for example, "Example description". The description can be a maximum of 256 characters.EFFECT: the effect of the rule, eitherALLOWorDENY.PRINCIPALS: the identities to which this rule applies. The format of the identifier depends on the type of principal you want to refer to. For more information, see Principal types for access policies.EXCLUDED_PRINCIPALS: the identities that are excluded from the rule application, even if listed inprincipals. For example, you can add a Google group toprincipalsand then exclude specific users who belong to that group.CEL_EXPRESSION: the CEL expression that will be evaluated to determine the rule applicability. For more information, see Use Common Expression Language.POLICY_PROJECT_ID: the Google Cloud project ID of the project where the policy will be created.POLICY_ID: a unique name for the access policy—for example,my-access-policy.
Multiple rules can be listed. Each rule is evaluated independently. If a rule doesn't apply; other rules might.
Request JSON body:
{
"displayName": "POLICY_DISPLAY_NAME",
"details": {
"rules": [
{
"description": "POLICY_DESCRIPTION",
"effect": "EFFECT",
"principals": [
"PRINCIPALS"
],
"excludedPrincipals": [
"EXCLUDED_PRINCIPALS"
],
"permissions": [
"eventarc.googleapis.com/messageBuses.publish"
],
"activationConditions": {
"eventarc.googleapis.com": {
"celCondition": {
"expression": "CEL_EXPRESSION"
}
}
}
}
]
}
}
To send your request, expand one of these options:
The response contains a long-running operation representing your request. To learn how to get the status of a long-running operation, in this document, see Check the status of a long-running operation on this page.
{
"name": "projects/POLICY_PROJECT_ID/locations/global/operations/OPERATION_ID",
"metadata": {
"@type": "type.googleapis.com/google.iam.v3.OperationMetadata",
"createTime": "2025-01-25T17:17:45.782370139Z",
"target": "projects/POLICY_PROJECT_ID/locations/global/accessPolicies/POLICY_ID",
"verb": "create",
"requestedCancellation": false,
"apiVersion": "v3"
},
"done": false
}
Example
The following access policy allows the principal specified to publish event
messages to a bus but denies publishing where the message priority is
HIGH.
cat > request.json << 'EOF' { "displayName": "Eventarc Advanced access policy", "details": { "rules": [ { "description": "Allow publishing to bus", "effect": "ALLOW", "principals": [ "principal://goog/subject/user@example.com" ], "permissions": [ "eventarc.googleapis.com/messageBuses.publish" ] }, { "description": "Deny publishing to bus if message priority is HIGH", "effect": "DENY", "principals": [ "principal://goog/subject/user@example.com" ], "permissions": [ "eventarc.googleapis.com/messageBuses.publish" ], "activationConditions": { "eventarc.googleapis.com": { "celCondition": { "expression": "message.priority == \"HIGH\"" } } } } ] } } EOF curl -X POST \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ -H "Content-Type: application/json; charset=utf-8" \ -d @request.json \ "https://iam.googleapis.com/v3/projects/POLICY_PROJECT_ID/locations/global/accessPolicies?access_policy_id=POLICY_ID"
Apply an access policy
Create a policy binding to apply your access policy to a Google Cloud project. Each policy binding binds one access policy to one resource.
You can apply an access policy by using the Google Cloud CLI or by making a direct request to the IAM v3 API.
gcloud
You can create a policy binding and apply your access policy by running the gcloud beta iam policy-bindings create command.
gcloud beta iam policy-bindings create BINDING_ID \ --project=BINDING_PROJECT_ID \ --location=global \ --policy=projects/POLICY_PROJECT_ID/locations/global/accessPolicies/POLICY_ID \ --target-resource=//cloudresourcemanager.googleapis.com/projects/BINDING_PROJECT_ID
Replace the following:
BINDING_ID: a unique name for the policy binding—for example,my-access-policy-binding.BINDING_PROJECT_ID: the Google Cloud project ID of the project where the binding will be created. This should be the same as the ID of the project where the Eventarc Advanced bus is created, and indicates the target of the binding.
The --location flag specifies the location of the policy binding and must
be global.
The response contains a long-running operation representing your request. To learn how to get the status of a long-running operation, in this document, see Check the status of a long-running operation.
Example
The following command creates a policy binding that applies the specified access policy to a Google Cloud project:
gcloud beta iam policy-bindings create my-access-policy-binding \ --project=my-project-id \ --location=global \ --policy=projects/my-project-id/locations/global/accessPolicies/my-access-policy \ --target-resource=//cloudresourcemanager.googleapis.com/projects/my-project-id
REST API
You can create a policy binding and apply your access policy by using the
projects.locations.policyBindings.create method.
Before using any of the request data, make the following replacements:
BINDING_DISPLAY_NAME: optional. A human-readable name for the policy binding—for example, "Example binding". The display name can be a maximum of 63 characters.BINDING_PROJECT_ID: the Google Cloud project ID of the project where the binding will be created. This should be the same as the ID of the project where the Eventarc Advanced bus is created, and indicates the target of the binding.POLICY_PROJECT_ID: the Google Cloud project ID of the project where the policy is created.POLICY_ID: the name of the access policy to bind—for example,my-access-policy.
Request JSON body:
{
"display_name": "BINDING_DISPLAY_NAME",
"target": {"resource": "//cloudresourcemanager.googleapis.com/projects/BINDING_PROJECT_ID"},
"policy_kind": "ACCESS",
"policy": "projects/POLICY_PROJECT_ID/locations/global/accessPolicies/POLICY_ID"
}
To send your request, expand one of these options:
The response contains a long-running operation representing your request. To learn how to get the status of a long-running operation, in this document, see Check the status of a long-running operation on this page.
{
"name": "projects/BINDING_PROJECT_ID/locations/global/operations/OPERATION_ID",
"metadata": {
"@type": "type.googleapis.com/google.iam.v3.OperationMetadata",
"createTime": "2025-01-25T17:17:45.782370139Z",
"target": "projects/BINDING_PROJECT_ID/locations/global/policyBindings/POLICY_ID-binding",
"verb": "create",
"requestedCancellation": false,
"apiVersion": "v3"
},
"done": false
}
Check the status of a long-running operation
When you use the IAM REST API, any method that changes an access policy or binding returns a long-running operation (LRO). The long-running operation tracks the status of the request and indicates whether the change to the policy or binding is complete.
The
operations.get
method returns the status of a long-running operation.
Before using any of the request data, make the following replacements:
OPERATION_NAME: the full name of the operation. You receive this name in the response to your original request.The operation name has the following format:
projects/PROJECT_ID/locations/global/operations/OPERATION_ID
PROJECT_ID: the Google Cloud project ID of the project where the operation is returned.
To send your request, expand one of these options:
You should receive a JSON response similar to the following:
{
"name": "projects/PROJECT_ID/locations/global/operations/OPERATION_ID",
"metadata": {
"@type": "type.googleapis.com/google.iam.v3.OperationMetadata",
"createTime": "2025-01-28T00:05:12.006289686Z",
"endTime": "2025-01-28T00:05:12.192141801Z",
"target": "projects/PROJECT_ID/locations/global/accessPolicies/POLICY_ID",
"verb": "create",
"requestedCancellation": false,
"apiVersion": "v3"
},
"done": true,
"response": {
ACCESS_POLICY
}
}
If the operation's donefield is not present, continue to monitor its status by
getting the operation repeatedly. Use
truncated exponential backoff to introduce
a delay between each request. When the done field is set to true, the
operation is complete, and you can stop getting the operation.