Approve or deny grants with Privileged Access Manager

After an entitlement has been created, select principals can request a grant against that entitlement. If that entitlement has an approval workflow specified, select principals set up as approvers can then approve or deny grant requests for that entitlement.

Keep the following in mind when approving or denying a grant request against an entitlement:

  • You can't approve your own request.

  • If a request isn't approved or denied in 24 hours, the grant status is changed to expired. After this, a principal must make a new grant request if privilege elevation is still required.

Approve or deny grants using the Google Cloud console

To approve or deny a grant request that has been made against an entitlement, complete the following instructions:

  1. Go to the Privileged Access Manager page.

    Go to Privileged Access Manager

  2. Click the Approve grants tab, followed by the Pending approval tab.

  3. In the row related to the request you want to approve or deny, click Approve/deny.

  4. If a justification is required, enter it in the Comment field.

  5. Click either Approve or Deny.

You can view your approval history in the My approval history tab. Approval history is available for 30 days after an approval action has been taken.

Approve or deny grants programmatically

To approve or deny grants, you need to complete the following actions:

  1. Search for entitlements you're an approver on.

  2. With the relevant entitlement ID, search for grant requests you can approve or deny.

  3. Approve or deny the grant requests.

Search for entitlements you're an approver on

gcloud

The gcloud beta pam entitlements search command with the grant-approver caller access type searches for entitlements on which you are an approver.

Before using any of the command data below, make the following replacements:

  • RESOURCE_TYPE: Optional. The resource type that the entitlement belongs to. Use the value organization, folder, or project.
  • RESOURCE_ID: Used with RESOURCE_TYPE. The ID of the Google Cloud project, folder, or organization that you want to manage entitlements for. Project IDs are alphanumeric strings, like my-project. Folder and organization IDs are numeric, like 123456789012.

Execute the following command:

Linux, macOS, or Cloud Shell

gcloud beta pam entitlements search \
    --caller-access-type=grant-approver \
    --location=global \
    --RESOURCE_TYPE=RESOURCE_ID

Windows (PowerShell)

gcloud beta pam entitlements search `
    --caller-access-type=grant-approver `
    --location=global `
    --RESOURCE_TYPE=RESOURCE_ID

Windows (cmd.exe)

gcloud beta pam entitlements search ^
    --caller-access-type=grant-approver ^
    --location=global ^
    --RESOURCE_TYPE=RESOURCE_ID

You should receive a response similar to the following:

additionalNotificationTargets: {}
approvalWorkflow:
  manualApprovals:
    requireApproverJustification: true
    steps:
    - approvalsNeeded: 1
      approvers:
      - principals:
        - user:alex@example.com
createTime: '22024-03-26T11:07:37.009498890Z'
etag: 00000000000000000000000000000000000000000000000000000000000=
maxRequestDuration: 3600s
name: projects/my-project/locations/global/entitlements/ENTITLEMENT_ID
privilegedAccess:
  gcpIamAccess:
    resource: //cloudresourcemanager.googleapis.com/projects/my-project
    resourceType: cloudresourcemanager.googleapis.com/Project
    roleBindings:
    - role: roles/storage.admin
requesterJustificationConfig:
  notMandatory: {}
state: AVAILABLE
updateTime: '2024-03-26T11:07:40.056780645Z'

REST

The Privileged Access Manager API's searchEntitlements method with the GRANT_APPROVER caller access type searches for entitlements on which you are an approver.

Before using any of the request data, make the following replacements:

  • SCOPE: The organization, folder, or project that the entitlement is in, in the format of organizations/ORGANIZATION_ID, folders/FOLDER_ID, or projects/PROJECT_ID. Project IDs are alphanumeric strings, like my-project. Folder and organization IDs are numeric, like 123456789012.
  • FILTER: Optional. Returns entitlements whose field values match an AIP-160 expression.
  • PAGE_SIZE: Optional. The number of items to return in a response.
  • PAGE_TOKEN: Optional. Which page to start the response from, using a page token returned in a previous response.

HTTP method and URL:

GET https://privilegedaccessmanager.googleapis.com/v1beta/SCOPE/locations/global/entitlements:search?callerAccessType=GRANT_APPROVER&filter=FILTER&pageSize=PAGE_SIZE&pageToken=PAGE_TOKEN

To send your request, expand one of these options:

You should receive a JSON response similar to the following:

[
  {
    "name": "projects/my-project/locations/global/entitlements/ENTITLEMENT_ID",
    "createTime": "2023-11-21T17:28:39.962144708Z",
    "updateTime": "2023-11-21T17:28:43.160309410Z",
    "eligibleUsers": [
      {
        "principals": [
          "user:alex@example.com"
        ]
      }
    ],
    "approvalWorkflow": {
      "manualApprovals": {
        "steps": [
          {
            "approvers": [
              {
                "principals": [
                  "user:bola@example.com"
                ]
              }
            ],
            "approvalsNeeded": 1
          }
        ]
      }
    },
    "privilegedAccess": {
      "gcpIamAccess": {
        "resourceType": "cloudresourcemanager.googleapis.com/Project",
        "resource": "//cloudresourcemanager.googleapis.com/projects/my-project",
        "roleBindings": [
          {
            "role": "roles/storage.admin"
          }
        ]
      }
    },
    "maxRequestDuration": "14400s",
    "state": "AVAILABLE",
    "requesterJustificationConfig": {
      "unstructured": {}
    },
    "additionalNotificationTargets": {
      "adminEmailRecipients": [
        "alex@example.com"
      ]
    },
    "etag": "00000000000000000000000000000000000000000000000000000000000="
  }
]

Search for grant requests you can approve or deny

gcloud

The gcloud beta pam grants search command searches for a grant you can approve or deny, or have already approved or denied. This method doesn't require specific Privileged Access Manager permissions to use.

Before using any of the command data below, make the following replacements:

  • ENTITLEMENT_ID: The ID of the entitlement that the grant belongs to. You can retrieve the ID by searching for entitlements you're an approver on.
  • CALLER_RELATIONSHIP_TYPE: Use one of the following values:

    • had-approved: Returns grants the caller has approved or denied.
    • can-approve: Returns grants the caller can approve or deny.
  • RESOURCE_TYPE: Optional. The resource type that the entitlement belongs to. Use the value organization, folder, or project.
  • RESOURCE_ID: Used with RESOURCE_TYPE. The ID of the Google Cloud project, folder, or organization that you want to manage entitlements for. Project IDs are alphanumeric strings, like my-project. Folder and organization IDs are numeric, like 123456789012.

Execute the following command:

Linux, macOS, or Cloud Shell

gcloud beta pam grants search \
    --entitlement=ENTITLEMENT_ID \
    --caller-relationship=CALLER_RELATIONSHIP_TYPE \
    --location=global \
    --RESOURCE_TYPE=RESOURCE_ID

Windows (PowerShell)

gcloud beta pam grants search `
    --entitlement=ENTITLEMENT_ID `
    --caller-relationship=CALLER_RELATIONSHIP_TYPE `
    --location=global `
    --RESOURCE_TYPE=RESOURCE_ID

Windows (cmd.exe)

gcloud beta pam grants search ^
    --entitlement=ENTITLEMENT_ID ^
    --caller-relationship=CALLER_RELATIONSHIP_TYPE ^
    --location=global ^
    --RESOURCE_TYPE=RESOURCE_ID

You should receive a response similar to the following:

additionalEmailRecipients:
- bola@example.com
createTime: '2024-03-07T00:34:32.557017289Z'
justification:
  unstructuredJustification: Renaming a file to mitigate issue #312
name: projects/my-project/locations/global/entitlements/ENTITLEMENT_ID/grants/GRANT_ID
privilegedAccess:
  gcpIamAccess:
    resource: //cloudresourcemanager.googleapis.com/projects/my-project
    resourceType: cloudresourcemanager.googleapis.com/Project
    roleBindings:
    - role: roles/storage.admin
requestedDuration: 3600s
requester: cruz@example.com
state: DENIED
timeline:
  events:
  - eventTime: '2024-03-07T00:34:32.793769042Z'
    requested:
      expireTime: '2024-03-08T00:34:32.793769042Z'
  - denied:
      actor: alex@example.com
      reason: Issue has already been resolved
    eventTime: '2024-03-07T00:36:08.309116203Z'
updateTime: '2024-03-07T00:34:32.926967128Z'

REST

The Privileged Access Manager API's searchGrants method searches for a grant you can approve or deny, or have already approved or denied. This method doesn't require specific Privileged Access Manager permissions to use.

Before using any of the request data, make the following replacements:

  • SCOPE: The organization, folder, or project that the entitlement is in, in the format of organizations/ORGANIZATION_ID, folders/FOLDER_ID, or projects/PROJECT_ID. Project IDs are alphanumeric strings, like my-project. Folder and organization IDs are numeric, like 123456789012.
  • ENTITLEMENT_ID: The ID of the entitlement that the grant belongs to. You can retrieve the ID by searching for entitlements you're an approver on.
  • RELATIONSHIP_TYPE: Valid values are:
    • HAD_APPROVED: Returns grants the caller has previously approved or denied.
    • CAN_APPROVE: Returns grants the caller can approve or deny.
  • FILTER: Optional. Returns grants whose field values match an AIP-160 expression.
  • PAGE_SIZE: Optional. The number of items to return in a response.
  • PAGE_TOKEN: Optional. Which page to start the response from, using a page token returned in a previous response.

HTTP method and URL:

GET https://privilegedaccessmanager.googleapis.com/v1beta/SCOPE/locations/global/entitlements/ENTITLEMENT_ID/grants:search?callerRelationship=RELATIONSHIP_TYPE&filter=FILTER&pageSize=PAGE_SIZE&pageToken=PAGE_TOKEN

To send your request, expand one of these options:

You should receive a JSON response similar to the following:

{
  "grants": [
    {
      "name": "projects/my-project/locations/global/entitlements/ENTITLEMENT_ID/grants/GRANT_ID",
      "createTime": "2024-03-06T03:08:49.330577625Z",
      "updateTime": "2024-03-06T03:08:49.625874598Z",
      "requester": "alex@example.com",
      "requestedDuration": "3600s",
      "justification": {
        "unstructuredJustification": "Emergency service for outage"
      },
      "state": "APPROVAL_AWAITED",
      "timeline": {
        "events": [
          {
            "eventTime": "2024-03-06T03:08:49.462765846Z",
            "requested": {
              "expireTime": "2024-03-07T03:08:49.462765846Z"
            }
          }
        ]
      },
      "privilegedAccess": {
        "gcpIamAccess": {
          "resourceType": "cloudresourcemanager.googleapis.com/Project",
          "resource": "//cloudresourcemanager.googleapis.com/projects/my-project",
          "roleBindings": [
            {
              "role": "roles/storage.admin"
            }
          ]
        }
      },
      "additionalEmailRecipients": [
        "bola@google.com"
      ]
    }
  ]
}

Approve grants programmatically

gcloud

The gcloud beta pam grants describe command approves a specific grant request.

Before using any of the command data below, make the following replacements:

  • GRANT_ID: The ID of the grant you're approving. You can retrieve the ID by searching for grant requests you can approve or deny.
  • ENTITLEMENT_ID: The ID of the entitlement that the grant belongs to.
  • APPROVAL_REASON: Why the grant has been approved.
  • RESOURCE_TYPE: Optional. The resource type that the entitlement belongs to. Use the value organization, folder, or project.
  • RESOURCE_ID: Used with RESOURCE_TYPE. The ID of the Google Cloud project, folder, or organization that you want to manage entitlements for. Project IDs are alphanumeric strings, like my-project. Folder and organization IDs are numeric, like 123456789012.

Execute the following command:

Linux, macOS, or Cloud Shell

gcloud beta pam grants approve \
    GRANT_ID \
    --entitlement=ENTITLEMENT_ID \
    --reason="APPROVAL_REASON" \
    --location=global \
    --RESOURCE_TYPE=RESOURCE_ID

Windows (PowerShell)

gcloud beta pam grants approve `
    GRANT_ID `
    --entitlement=ENTITLEMENT_ID `
    --reason="APPROVAL_REASON" `
    --location=global `
    --RESOURCE_TYPE=RESOURCE_ID

Windows (cmd.exe)

gcloud beta pam grants approve ^
    GRANT_ID ^
    --entitlement=ENTITLEMENT_ID ^
    --reason="APPROVAL_REASON" ^
    --location=global ^
    --RESOURCE_TYPE=RESOURCE_ID

You should receive a response similar to the following:

createTime: '2024-04-05T01:17:04.596455403Z'
justification:
  unstructuredJustification: Renaming a file to mitigate issue #312
name: projects/my-project/locations/global/entitlements/ENTITLEMENT_ID/grants/GRANT_ID
privilegedAccess:
  gcpIamAccess:
    resource: //cloudresourcemanager.googleapis.com/projects/my-project
    resourceType: cloudresourcemanager.googleapis.com/Project
    roleBindings:
    - role: roles/storage.admin
requestedDuration: 2700s
requester: cruz@example.com
state: SCHEDULED
timeline:
  events:
  - eventTime: '2024-04-05T01:17:04.732226659Z'
    requested:
      expireTime: '2024-04-06T01:17:04.732226659Z'
  - approved:
      actor: alex@example.com
      reason: Access allowed under existing policy
    eventTime: '2024-04-05T01:21:49.139539732Z'
  - eventTime: '2024-04-05T01:21:49.139463954Z'
    scheduled:
      scheduledActivationTime: '2024-04-05T01:21:49.139463954Z'
updateTime: '2024-04-05T01:21:49.139463954Z'

REST

The Privileged Access Manager API's approveGrant method approves a specific grant request.

Before using any of the request data, make the following replacements:

  • SCOPE: The organization, folder, or project that the entitlement is in, in the format of organizations/ORGANIZATION_ID, folders/FOLDER_ID, or projects/PROJECT_ID. Project IDs are alphanumeric strings, like my-project. Folder and organization IDs are numeric, like 123456789012.
  • ENTITLEMENT_ID: The ID of the entitlement that the grant belongs to.
  • GRANT_ID: The ID of the grant you are approving. You can retrieve the ID by searching for grant requests you can approve or deny.
  • REASON: The reason the grant request was approved.

HTTP method and URL:

POST https://privilegedaccessmanager.googleapis.com/v1beta/SCOPE/locations/global/entitlements/ENTITLEMENT_ID/grants/GRANT_ID:approve

Request JSON body:

{
    "reason": "REASON"
}

To send your request, expand one of these options:

You should receive a JSON response similar to the following:

{
  "name": "projects/my-project/locations/global/entitlements/ENTITLEMENT_ID/grants/GRANT_ID",
  "createTime": "2024-03-06T03:08:49.330577625Z",
  "updateTime": "2024-03-06T23:01:13.964619844Z",
  "requester": "alex@example.com",
  "requestedDuration": "3600s",
  "justification": {
    "unstructuredJustification": "Emergency service for outage"
  },
  "state": "SCHEDULED",
  "timeline": {
    "events": [
      {
        "eventTime": "2024-03-06T03:08:49.462765846Z",
        "requested": {
          "expireTime": "2024-03-07T03:08:49.462765846Z"
        }
      },
      {
        "eventTime": "2024-03-06T23:01:13.964685709Z",
        "approved": {
          "reason": "Approved escalation",
          "actor": "cruz@example.com"
        }
      },
      {
        "eventTime": "2024-03-06T23:01:13.964619844Z",
        "scheduled": {
          "scheduledActivationTime": "2024-03-06T23:01:13.964619844Z"
        }
      }
    ]
  },
  "privilegedAccess": {
    "gcpIamAccess": {
      "resourceType": "cloudresourcemanager.googleapis.com/Project",
      "resource": "//cloudresourcemanager.googleapis.com/projects/my-project",
      "roleBindings": [
        {
          "role": "roles/storage.admin"
        }
      ]
    }
  },
  "additionalEmailRecipients": [
    "bola@example.com.com"
  ]
}

Deny grants programmatically

gcloud

The gcloud beta pam grants describe command denies a specific grant request.

Before using any of the command data below, make the following replacements:

  • GRANT_ID: The ID of the grant you're denying. You can retrieve the ID by searching for grants you can approve or deny.
  • ENTITLEMENT_ID: The ID of the entitlement that the grant belongs to.
  • DENIAL_REASON: Why the grant has been denied.
  • RESOURCE_TYPE: Optional. The resource type that the entitlement belongs to. Use the value organization, folder, or project.
  • RESOURCE_ID: Used with RESOURCE_TYPE. The ID of the Google Cloud project, folder, or organization that you want to manage entitlements for. Project IDs are alphanumeric strings, like my-project. Folder and organization IDs are numeric, like 123456789012.

Execute the following command:

Linux, macOS, or Cloud Shell

gcloud beta pam grants deny \
    GRANT_ID \
    --entitlement=ENTITLEMENT_ID \
    --reason="DENIAL_REASON" \
    --location=global \
    --RESOURCE_TYPE=RESOURCE_ID

Windows (PowerShell)

gcloud beta pam grants deny `
    GRANT_ID `
    --entitlement=ENTITLEMENT_ID `
    --reason="DENIAL_REASON" `
    --location=global `
    --RESOURCE_TYPE=RESOURCE_ID

Windows (cmd.exe)

gcloud beta pam grants deny ^
    GRANT_ID ^
    --entitlement=ENTITLEMENT_ID ^
    --reason="DENIAL_REASON" ^
    --location=global ^
    --RESOURCE_TYPE=RESOURCE_ID

You should receive a response similar to the following:

createTime: '2024-04-05T01:29:13.129192816Z'
justification:
  unstructuredJustification: Renaming a file to mitigate issue #312
name: projects/my-project/locations/global/entitlements/ENTITLEMENT_ID/grants/GRANT_ID
privilegedAccess:
  gcpIamAccess:
    resource: //cloudresourcemanager.googleapis.com/projects/my-project
    resourceType: cloudresourcemanager.googleapis.com/Project
    roleBindings:
    - role: roles/storage.admin
requestedDuration: 2700s
requester: cruz@example.com
state: DENIED
timeline:
  events:
  - eventTime: '2024-04-05T01:29:13.267878626Z'
    requested:
      expireTime: '2024-04-06T01:29:13.267878626Z'
  - denied:
      actor: alex@example.com
      reason: Access denied under existing policy
    eventTime: '2024-04-05T01:29:49.492161363Z'
updateTime: '2024-04-05T01:29:49.492097724Z'

REST

The Privileged Access Manager API's denyGrant method denies a specific grant request.

Before using any of the request data, make the following replacements:

  • SCOPE: The organization, folder, or project that the entitlement is in, in the format of organizations/ORGANIZATION_ID, folders/FOLDER_ID, or projects/PROJECT_ID. Project IDs are alphanumeric strings, like my-project. Folder and organization IDs are numeric, like 123456789012.
  • ENTITLEMENT_ID: The ID of the entitlement that the grant belongs to.
  • GRANT_ID: The ID of the grant you are denying. You can retrieve the ID by searching for grants you can approve or deny.
  • REASON: The reason the grant request was denied.

HTTP method and URL:

POST https://privilegedaccessmanager.googleapis.com/v1beta/SCOPE/locations/global/entitlements/ENTITLEMENT_ID/grants/GRANT_ID:deny

Request JSON body:

{
    "reason": "REASON"
}

To send your request, expand one of these options:

You should receive a JSON response similar to the following:

{
  "name": "projects/my-project/locations/global/entitlements/ENTITLEMENT_ID/grants/GRANT_ID",
  "createTime": "2024-03-07T00:34:32.557017289Z",
  "updateTime": "2024-03-07T00:36:08.309046580Z",
  "requester": "alex@example.com",
  "requestedDuration": "3600s",
  "justification": {
    "unstructuredJustification": "Emergency service for outage"
  },
  "state": "DENIED",
  "timeline": {
    "events": [
      {
        "eventTime": "2024-03-07T00:34:32.793769042Z",
        "requested": {
          "expireTime": "2024-03-08T00:34:32.793769042Z"
        }
      },
      {
        "eventTime": "2024-03-07T00:36:08.309116203Z",
        "denied": {
          "reason": "Outage already resolved",
          "actor": "cruz@example.com"
        }
      }
    ]
  },
  "privilegedAccess": {
    "gcpIamAccess": {
      "resourceType": "cloudresourcemanager.googleapis.com/Project",
      "resource": "//cloudresourcemanager.googleapis.com/projects/my-project",
      "roleBindings": [
        {
          "role": "roles/storage.admin"
        }
      ]
    }
  },
  "additionalEmailRecipients": [
    "bola@example.com"
  ]
}