Review policy insights for Cloud Storage buckets

This page shows how to manage bucket-level policy insights, which are machine learning-based findings about permission usage for your Cloud Storage buckets. Policy insights can help you identify which principals have permissions that they don't need.

This page focuses on policy insights for buckets. Recommender also offers policy insights for the following resource types:

Bucket-level policy insights are sometimes linked to role recommendations. Role recommendations suggest actions that you can take to remediate the issues identified by bucket-level policy insights.

Before you begin

Required roles

To get the permissions that you need to manage bucket-level policy insights, ask your administrator to grant you the following IAM roles on your project:

  • Storage Admin (roles/storage.admin)
  • Manage bucket-level policy insights with the gcloud CLI or REST API: Service Usage Consumer (`roles/serviceusage.serviceUsageConsumer`)

For more information about granting roles, see Manage access to projects, folders, and organizations.

These predefined roles contain the permissions required to manage bucket-level policy insights. To see the exact permissions that are required, expand the Required permissions section:

Required permissions

The following permissions are required to manage bucket-level policy insights:

  • To view bucket-level policy insights:
    • recommender.iamPolicyInsights.get
    • recommender.iamPolicyInsights.list
  • To modify bucket-level policy insights: recommender.iamPolicyInsights.update
  • To manage bucket-level policy insights in the Google Cloud console:
    • resourcemanager.projects.get
    • storage.buckets.list
  • Manage bucket-level policy insights with the gcloud CLI or REST API: serviceusage.services.use

You might also be able to get these permissions with custom roles or other predefined roles.

List bucket-level policy insights

To list all bucket-level policy insights for your project, use one of the following methods:

Console

  1. In the Google Cloud console, go to the Buckets page.

    Go to Buckets

  2. Find the Security insights column in the table. If the Security insights column is not visible, click  Column display options and select Security insights.

    This column shows a summary of all policy insights for the bucket. Each summary indicates the total number of excess permissions for all roles granted on that bucket.

  3. Find the bucket whose insights you want to view and click the policy insights summary in that row. This action opens the Security recommendations pane, which lists all principals who have a role on the bucket, their roles, and any policy insights associated with those roles.

    In this table, policy insights have the form EXCESS/TOTAL excess permissions, where EXCESS is the number of permissions in the role that the principal does not need and TOTAL is the total number of permissions in the role.

gcloud

Use the gcloud recommender insights list command to view all bucket-level policy insights for your project.

Before you run the command, replace the following values:

  • PROJECT_ID: The ID of the project that you want to list insights for.
  • LOCATION: The location of the buckets whose insights you want to list.
gcloud recommender insights list --insight-type=google.iam.policy.Insight \
    --project=PROJECT_ID \
    --location=LOCATION\
    --filter="insightSubtype:PERMISSIONS_USAGE_STORAGE_BUCKET"

The output lists all of the bucket-level policy insights for your project in the specified location. For example:

INSIGHT_ID                            CATEGORY  INSIGHT_STATE  LAST_REFRESH_TIME     SEVERITY  INSIGHT_SUBTYPE                   DESCRIPTION
00dd7eb5-15c2-4fb3-a9b2-1a85f842462b  SECURITY  ACTIVE         2022-05-24T07:00:00Z  CRITICAL  PERMISSIONS_USAGE_STORAGE_BUCKET  2 of the permissions in this role binding were used in the past 90 days.
04307297-f57c-416d-9323-38abac450db0  SECURITY  ACTIVE         2022-05-24T07:00:00Z  LOW       PERMISSIONS_USAGE_STORAGE_BUCKET  2 of the permissions in this role binding were used in the past 90 days.
04845da5-74ba-46b4-a0f3-47d83095c261  SECURITY  ACTIVE         2022-05-24T07:00:00Z  CRITICAL  PERMISSIONS_USAGE_STORAGE_BUCKET  1 of the permissions in this role binding were used in the past 90 days.
0a39f643-d7a8-4c11-b490-fecd74290fb5  SECURITY  ACTIVE         2022-05-24T07:00:00Z  LOW       PERMISSIONS_USAGE_STORAGE_BUCKET  2 of the permissions in this role binding were used in the past 90 days.
0a4cee48-777b-4dea-a2b0-702b70da4b6f  SECURITY  ACTIVE         2022-05-24T07:00:00Z  CRITICAL  PERMISSIONS_USAGE_STORAGE_BUCKET  0 of the permissions in this role binding were used in the past 90 days.
0b2d147c-b26e-4afe-8fab-449c6e793750  SECURITY  ACTIVE         2022-05-24T07:00:00Z  LOW       PERMISSIONS_USAGE_STORAGE_BUCKET  0 of the permissions in this role binding were used in the past 90 days.
0b5eacc5-ba9a-45f6-aea2-bcdc33ce2a2d  SECURITY  ACTIVE         2022-05-24T07:00:00Z  LOW       PERMISSIONS_USAGE_STORAGE_BUCKET  1 of the permissions in this role binding were used in the past 90 days.
0bb3032d-721c-44e8-b464-5293f235281c  SECURITY  ACTIVE         2022-05-24T07:00:00Z  LOW       PERMISSIONS_USAGE_STORAGE_BUCKET  3 of the permissions in this role binding were used in the past 90 days.

REST

The Recommender API's insights.list method lists all bucket-level policy insights for your project.

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

  • PROJECT_ID: The ID of the project that you want to list insights for.
  • LOCATION: The location of the buckets whose insights you want to list.

HTTP method and URL:

GET https://recommender.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/insightTypes/google.iam.policy.Insight/insights?filter=insightSubtype%20%3D%20PERMISSIONS_USAGE_STORAGE_BUCKET

To send your request, expand one of these options:

The response lists all of the bucket-level policy insights for your project in the specified location. For example:

{
  "insights": [
    {
      "name": "projects/123456789012/locations/us/insightTypes/google.iam.policy.Insight/insights/00dd7eb5-15c2-4fb3-a9b2-1a85f842462b",
      "description": "2 of the permissions in this role binding were used in the past 90 days.",
      "content": {
        "role": "roles/storage.legacyBucketReader",
        "member": "allUsers",
        "condition": {
          "expression": "",
          "title": "",
          "description": "",
          "location": ""
        },
        "exercisedPermissions": [
          {
            "permission": "storage.buckets.get"
          },
          {
            "permission": "storage.objects.list"
          }
        ],
        "inferredPermissions": [],
        "currentTotalPermissionsCount": "3"
      },
      "lastRefreshTime": "2022-05-24T07:00:00Z",
      "observationPeriod": "7772400s",
      "stateInfo": {
        "state": "ACTIVE"
      },
      "category": "SECURITY",
      "associatedRecommendations": [
        {
          "recommendation": "projects/123456789012/locations/us/recommenders/google.iam.policy.Recommender/recommendations/4a31a9d4-5132-4616-8a1f-fb07fad01883"
        }
      ],
      "targetResources": [
        "//storage.googleapis.com/bucket-1"
      ],
      "insightSubtype": "PERMISSIONS_USAGE_STORAGE_BUCKET",
      "etag": "\"2a8784e529b80aea\"",
      "severity": "CRITICAL"
    },
    {
      "name": "projects/123456789012/locations/us/insightTypes/google.iam.policy.Insight/insights/04307297-f57c-416d-9323-38abac450db0",
      "description": "2 of the permissions in this role binding were used in the past 90 days.",
      "content": {
        "role": "roles/storage.legacyBucketReader",
        "member": "projectViewer:my-project",
        "condition": {
          "expression": "",
          "title": "",
          "description": "",
          "location": ""
        },
        "exercisedPermissions": [
          {
            "permission": "storage.buckets.get"
          },
          {
            "permission": "storage.objects.list"
          }
        ],
        "inferredPermissions": [],
        "currentTotalPermissionsCount": "3"
      },
      "lastRefreshTime": "2022-05-24T07:00:00Z",
      "observationPeriod": "7772400s",
      "stateInfo": {
        "state": "ACTIVE"
      },
      "category": "SECURITY",
      "associatedRecommendations": [
        {
          "recommendation": "projects/123456789012/locations/us/recommenders/google.iam.policy.Recommender/recommendations/f3198e63-7f76-462e-a980-8e6370ff32d6"
        }
      ],
      "targetResources": [
        "//storage.googleapis.com/bucket-2"
      ],
      "insightSubtype": "PERMISSIONS_USAGE_STORAGE_BUCKET",
      "etag": "\"5b60b935f27caf2c\"",
      "severity": "LOW"
    }
  ]
}

To learn more about the components of an insight, see Review bucket-level policy insights on this page.

Get a single bucket-level policy insight

To get more information about a single insight, including the insight's description, status, and any recommendations it's associated with, use one of the following methods:

Console

  1. In the Google Cloud console, go to the Buckets page.

    Go to Buckets

  2. Ensure that the Security insights column is visible.
  3. Find the Security insights column in the table. This column shows a summary of all policy insights for the bucket. Each summary indicates the total number of excess permissions for all roles granted on that bucket.

    If the Security insights column is not visible, click  Column display options and select Security insights. Then, find the column in the table.

  4. Find the bucket whose insights you want to view and click the policy insights summary in that row. This opens a pane that lists all principals who have a role on the bucket, their roles, and any policy insights associated with those roles.
  5. In the Security insights column, click a policy insight. Policy insights have the form EXCESS/TOTAL excess permissions, where EXCESS is the number of permissions in the role that the principal does not need and TOTAL is the total number of permissions in the role.

The Google Cloud console opens a pane showing the details of the insight.

gcloud

Use the gcloud recommender insights describe command with your insight ID to view information about a single insight.

  • INSIGHT_ID: The ID of the insight that you want to view. To find the ID, list the insights for your project.
  • PROJECT_ID: The ID of the project that you want to manage insights for.
  • LOCATION: The location of the bucket whose insight you want to get.
gcloud recommender insights describe INSIGHT_ID \
    --insight-type=google.iam.policy.Insight \
    --project=PROJECT_ID \
    --location=LOCATION

The output shows the insight in detail. For example, the following insight indicates that all users (allUsers) have the Storage Legacy Bucket Reader role (roles/storage.legacyBucketReader) on the bucket bucket-1, but that only two permissions in that role were used in the past 90 days:

associatedRecommendations:
- recommendation: projects/123456789012/locations/us/recommenders/google.iam.policy.Recommender/recommendations/4a31a9d4-5132-4616-8a1f-fb07fad01883
category: SECURITY
content:
  condition:
    description: ''
    expression: ''
    location: ''
    title: ''
  currentTotalPermissionsCount: '3'
  exercisedPermissions:
  - permission: storage.buckets.get
  - permission: storage.objects.list
  inferredPermissions: []
  member: allUsers
  role: roles/storage.legacyBucketReader
description: 2 of the permissions in this role binding were used in the past 90 days.
etag: '"2a8784e529b80aea"'
insightSubtype: PERMISSIONS_USAGE_STORAGE_BUCKET
lastRefreshTime: '2022-05-24T07:00:00Z'
name: projects/123456789012/locations/us/insightTypes/google.iam.policy.Insight/insights/00dd7eb5-15c2-4fb3-a9b2-1a85f842462b
observationPeriod: 7772400s
severity: CRITICAL
stateInfo:
  state: ACTIVE
targetResources:
- //storage.googleapis.com/bucket-1

To learn more about the components of an insight, see Review bucket-level policy insights on this page.

REST

The Recommender API's insights.get method gets a single insight.

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

  • PROJECT_ID: The ID of the project that you want to manage insights for.
  • LOCATION: The location of the bucket whose insight you want to get.
  • INSIGHT_ID: The ID of the insight that you want to view. If you don't know the insight ID, you can find it by listing the insights in your project. The ID of an insight is everything after insights/ in the name field for the insight.

HTTP method and URL:

GET https://recommender.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/insightTypes/google.iam.policy.Insight/insights/INSIGHT_ID

To send your request, expand one of these options:

The response contains the insight. For example, the following insight indicates that all users (allUsers) have the Storage Legacy Bucket Reader role (roles/storage.legacyBucketReader) on the bucket bucket-1, but that only two permissions in that role were used in the past 90 days:

{
  "name": "projects/123456789012/locations/us/insightTypes/google.iam.policy.Insight/insights/00dd7eb5-15c2-4fb3-a9b2-1a85f842462b",
  "description": "2 of the permissions in this role binding were used in the past 90 days.",
  "content": {
    "role": "roles/storage.legacyBucketReader",
    "member": "allUsers",
    "condition": {
      "expression": "",
      "title": "",
      "description": "",
      "location": ""
    },
    "exercisedPermissions": [
      {
        "permission": "storage.buckets.get"
      },
      {
        "permission": "storage.objects.list"
      }
    ],
    "inferredPermissions": [],
    "currentTotalPermissionsCount": "3"
  },
  "lastRefreshTime": "2022-05-24T07:00:00Z",
  "observationPeriod": "7772400s",
  "stateInfo": {
    "state": "ACTIVE"
  },
  "category": "SECURITY",
  "associatedRecommendations": [
    {
      "recommendation": "projects/123456789012/locations/us/recommenders/google.iam.policy.Recommender/recommendations/4a31a9d4-5132-4616-8a1f-fb07fad01883"
    }
  ],
  "targetResources": [
    "//storage.googleapis.com/bucket-1"
  ],
  "insightSubtype": "PERMISSIONS_USAGE_STORAGE_BUCKET",
  "etag": "\"2a8784e529b80aea\"",
  "severity": "CRITICAL"
}

To learn more about the components of an insight, see Review bucket-level policy insights on this page.

Review bucket-level policy insights

After you get a single insight, you can review its contents to understand the pattern of resource usage that it highlights.

Console

When you click a policy insight in the Google Cloud console, the Google Cloud console opens a pane showing the details of the insight. The appearance of these details depends on whether the insight is associated with a recommendation.

If the insight is associated with a recommendation, the pane shows the details of the recommendation.

If the insight is not associated with a recommendation, the pane shows a list of all permissions in the role. The permissions that the principal used appear at the top of the list, followed by the excess permissions.

gcloud

An insight's content is determined by its subtypes. Bucket-level policy insights (google.iam.policy.Insight) insights have the PERMISSIONS_USAGE_STORAGE_BUCKET subtype.

PERMISSIONS_USAGE_STORAGE_BUCKET insights have the following components, not necessarily in this order:

  • associatedRecommendations: The identifiers for any recommendations associated with the insight. If there are no recommendations associated with the insight, this field is empty.
  • category: The category for IAM insights is always SECURITY.
  • content: Reports a principal's permission usage for a specific role. This field contains the following components:

    • condition: Any conditions attached to the binding that grants the principal the role. If there are no conditions, this field contains an empty condition.
    • exercisedPermissions: The permissions in the role that the principal used during the observation period.
    • inferredPermissions: The permissions in the role that Recommender has determined, through ML, that the principal is likely to need based on their exercised permissions.
    • member: The principal whose permission usage was analyzed.
    • role: The role for which the permission usage was analyzed.
  • description: A human-readable summary of the insight.
  • etag: A unique identifier for the current state of an insight. Each time the insight changes, a new etag value is assigned.

    To change the state of an insight, you must provide the etag of the existing insight. Using the etag helps ensure that any operations are performed only if the insight has not changed since you last retrieved it.

  • insightSubtype: The insight subtype.
  • lastRefreshTime: The date when the insight was last refreshed, which indicates the freshness of the data used to generate the insight.
  • name: The name of the insight, in the following format:

    projects/PROJECT_ID/locations/LOCATION/insightTypes/google.iam.policy.Insight/insights/INSIGHT_ID

    The placeholders have the following values:

    • PROJECT_ID: The ID of the project where the insight was generated.
    • LOCATION: The location of the bucket that the insight is for.
    • INSIGHT_ID: A unique ID for the insight.
  • observationPeriod: The time period leading up to the insight. The source data used to generate the insight ends at lastRefreshTime and begins at lastRefreshTime minus observationPeriod.
  • stateInfo: Insights go through multiple state transitions after they are proposed:

    • ACTIVE: The insight has been generated, but either no actions have been taken, or an action was taken without updating the insight's state. Active insights are updated when the underlying data changes.
    • ACCEPTED: Some action has been taken based on the insight. Insights become accepted when an associated recommendation was marked CLAIMED, SUCCEEDED, or FAILED, or the insight was accepted directly. When an insight is in the ACCEPTED state, the content of the insight cannot change. Accepted insights are retained for 90 days after they are accepted.
  • targetResources: The full resource name of the bucket that the insight is for. For example, //storage.googleapis.com/my-bucket.

REST

An insight's content is determined by its subtypes. Bucket-level policy insights (google.iam.policy.Insight) insights have the PERMISSIONS_USAGE_STORAGE_BUCKET subtype.

PERMISSIONS_USAGE_STORAGE_BUCKET insights have the following components, not necessarily in this order:

  • associatedRecommendations: The identifiers for any recommendations associated with the insight. If there are no recommendations associated with the insight, this field is empty.
  • category: The category for IAM insights is always SECURITY.
  • content: Reports a principal's permission usage for a specific role. This field contains the following components:

    • condition: Any conditions attached to the binding that grants the principal the role. If there are no conditions, this field contains an empty condition.
    • exercisedPermissions: The permissions in the role that the principal used during the observation period.
    • inferredPermissions: The permissions in the role that Recommender has determined, through ML, that the principal is likely to need based on their exercised permissions.
    • member: The principal whose permission usage was analyzed.
    • role: The role for which the permission usage was analyzed.
  • description: A human-readable summary of the insight.
  • etag: A unique identifier for the current state of an insight. Each time the insight changes, a new etag value is assigned.

    To change the state of an insight, you must provide the etag of the existing insight. Using the etag helps ensure that any operations are performed only if the insight has not changed since you last retrieved it.

  • insightSubtype: The insight subtype.
  • lastRefreshTime: The date when the insight was last refreshed, which indicates the freshness of the data used to generate the insight.
  • name: The name of the insight, in the following format:

    projects/PROJECT_ID/locations/LOCATION/insightTypes/google.iam.policy.Insight/insights/INSIGHT_ID

    The placeholders have the following values:

    • PROJECT_ID: The ID of the project where the insight was generated.
    • LOCATION: The location of the bucket that the insight is for.
    • INSIGHT_ID: A unique ID for the insight.
  • observationPeriod: The time period leading up to the insight. The source data used to generate the insight ends at lastRefreshTime and begins at lastRefreshTime minus observationPeriod.
  • stateInfo: Insights go through multiple state transitions after they are proposed:

    • ACTIVE: The insight has been generated, but either no actions have been taken, or an action was taken without updating the insight's state. Active insights are updated when the underlying data changes.
    • ACCEPTED: Some action has been taken based on the insight. Insights become accepted when an associated recommendation was marked CLAIMED, SUCCEEDED, or FAILED, or the insight was accepted directly. When an insight is in the ACCEPTED state, the content of the insight cannot change. Accepted insights are retained for 90 days after they are accepted.
  • targetResources: The full resource name of the bucket that the insight is for. For example, //storage.googleapis.com/my-bucket.

Mark a bucket-level policy insight as ACCEPTED

If you take action based on an active insight, you can mark that insight as ACCEPTED. The ACCEPTED state tells the Recommender API that you have taken action based on this insight, which helps refine your recommendations.

Accepted insights are retained for 90 days after they are marked as ACCEPTED.

Console

If an insight is associated with a recommendation, applying the recommendation changes the insight's state to ACCEPTED.

To mark an insight as ACCEPTED without applying a recommendation, use the gcloud CLI or REST API.

gcloud

Use the gcloud recommender insights mark-accepted command with your insight ID to mark an insight as ACCEPTED.

  • INSIGHT_ID: The ID of the insight that you want to view. To find the ID, list the insights for your project.
  • PROJECT_ID: The ID of the project that you want to manage insights for.
  • LOCATION: The location of the bucket whose insight you want to mark as ACCEPTED.
  • ETAG: An identifier for a version of the insight. To get the etag, do the following:

    1. Get the insight using the gcloud recommender insights describe command.
    2. Find and copy the etag value from the output, including the enclosing quotes. For example, "d3cdec23cc712bd0".
gcloud recommender insights mark-accepted INSIGHT_ID \
    --insight-type=google.iam.policy.Insight \
    --project=PROJECT_ID \
    --location=LOCATION \
    --etag=ETAG

The output shows the insight, now with the state of ACCEPTED:

associatedRecommendations:
- recommendation: projects/123456789012/locations/us/recommenders/google.iam.policy.Recommender/recommendations/4a31a9d4-5132-4616-8a1f-fb07fad01883
category: SECURITY
content:
  condition:
    description: ''
    expression: ''
    location: ''
    title: ''
  currentTotalPermissionsCount: '3'
  exercisedPermissions:
  - permission: storage.buckets.get
  - permission: storage.objects.list
  inferredPermissions: []
  member: allUsers
  role: roles/storage.legacyBucketReader
description: 2 of the permissions in this role binding were used in the past 90 days.
etag: '"0187c0362e4bcea7"'
insightSubtype: PERMISSIONS_USAGE_STORAGE_BUCKET
lastRefreshTime: '2022-05-24T07:00:00Z'
name: projects/123456789012/locations/us/insightTypes/google.iam.policy.Insight/insights/00dd7eb5-15c2-4fb3-a9b2-1a85f842462b
observationPeriod: 7772400s
severity: CRITICAL
stateInfo:
  state: ACCEPTED
targetResources:
- //storage.googleapis.com/bucket-1

To learn more about the state info of an insight, see Review bucket-level policy insights on this page.

REST

The Recommender API's insights.markAccepted method marks an insight as ACCEPTED.

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

  • PROJECT_ID: The ID of the project that you want to manage insights for.
  • LOCATION: The location of the bucket whose insight you want to mark as ACCEPTED.
  • INSIGHT_ID: The ID of the insight that you want to view. If you don't know the insight ID, you can find it by listing the insights in your project. The ID of an insight is everything after insights/ in the name field for the insight.
  • ETAG: An identifier for a version of the insight. To get the etag, do the following:
    1. Get the insight using the insights.get method.
    2. Find and copy the etag value from the response.

HTTP method and URL:

POST https://recommender.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/insightTypes/google.iam.policy.Insight/insights/INSIGHT_ID:markAccepted

Request JSON body:

{
  "etag": "ETAG"
}

To send your request, expand one of these options:

The response contains the insight, now with the state of ACCEPTED:

{
  "name": "projects/123456789012/locations/us/insightTypes/google.iam.policy.Insight/insights/00dd7eb5-15c2-4fb3-a9b2-1a85f842462b",
  "description": "2 of the permissions in this role binding were used in the past 90 days.",
  "content": {
    "role": "roles/storage.legacyBucketReader",
    "member": "allUsers",
    "condition": {
      "expression": "",
      "title": "",
      "description": "",
      "location": ""
    },
    "exercisedPermissions": [
      {
        "permission": "storage.buckets.get"
      },
      {
        "permission": "storage.objects.list"
      }
    ],
    "inferredPermissions": [],
    "currentTotalPermissionsCount": "3"
  },
  "lastRefreshTime": "2022-05-24T07:00:00Z",
  "observationPeriod": "7772400s",
  "stateInfo": {
    "state": "ACCEPTED"
  },
  "category": "SECURITY",
  "associatedRecommendations": [
    {
      "recommendation": "projects/123456789012/locations/us/recommenders/google.iam.policy.Recommender/recommendations/4a31a9d4-5132-4616-8a1f-fb07fad01883"
    }
  ],
  "targetResources": [
    "//storage.googleapis.com/bucket-1"
  ],
  "insightSubtype": "PERMISSIONS_USAGE_STORAGE_BUCKET",
  "etag": "\"9a5485cdc1f05b58\"",
  "severity": "CRITICAL"
}

To learn more about the state info of an insight, see Review bucket-level policy insights on this page.

What's next