Manage lateral movement insights

In addition to providing recommendations, Recommender uses machine learning (ML) to provide detailed insights. Insights are findings that highlight notable patterns in resource usage. For example, you can collect additional information about permission usage in your project, or identify unused service accounts. Some insights also link to recommendations, because the insights provide evidence for the recommendations.

IAM offers several different types of insights. This page shows how to manage lateral movement insights (google.iam.policy.LateralMovementInsight), which identify roles that allow a service account in one project to impersonate a service account in another project. For more information about lateral movement insights, see How lateral movement insights are generated.

Before you begin

Required permissions

The required permissions for using lateral movement insights vary depending on what you want to do.

Permissions to view insights

To view lateral movement insights, you need a role that includes the following permissions:

  • recommender.iamPolicyLateralMovementInsights.get
  • recommender.iamPolicyLateralMovementInsights.list

To gain these permissions while following the principle of least privilege, ask your administrator to grant you one of the following roles:

  • IAM Recommender Viewer (roles/recommender.iamViewer)
  • IAM Security Reviewer (roles/iam.securityReviewer)

Alternatively, your administrator can grant you a different role with the required permissions, such as a custom role or a more permissive predefined role.

Permissions to modify insights

To modify lateral movement insights, you need a role that includes the following permissions:

  • recommender.iamPolicyLateralMovementInsights.get
  • recommender.iamPolicyLateralMovementInsights.list
  • recommender.iamPolicyLateralMovementInsights.update

To gain these permissions while following the principle of least privilege, ask your administrator to grant you the IAM Recommender Admin role (roles/recommender.iamAdmin).

Alternatively, your administrator can grant you a different role with the required permissions, such as a custom role or a more permissive predefined role.

List lateral movement insights

To list all lateral movement insights for your project, use one of the following methods:

gcloud

Use the gcloud recommender insights list command to view all lateral movement 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. This list also includes lateral movement insights for service account-level role bindings within your project.
gcloud recommender insights list --insight-type=google.iam.policy.LateralMovementInsight \
    --project=PROJECT_ID \
    --location=global

The output lists all of the lateral movement insights for your project. For example:

INSIGHT_ID                            LOCATION  INSIGHT_TYPE                              CATEGORY  INSIGHT_STATE  LAST_REFRESH_TIME
0bd428af-d16c-4ac0-83eb-826dbce8c9bb  global    google.iam.policy.LateralMovementInsight  SECURITY  ACTIVE         2021-03-13T08:00:00Z
13088eec-9573-415f-81a7-46e1a260e860  global    google.iam.policy.LateralMovementInsight  SECURITY  ACTIVE         2021-03-13T08:00:00Z
1343077a-c1fe-409f-a7d5-3d01349e7651  global    google.iam.policy.LateralMovementInsight  SECURITY  ACTIVE         2021-03-13T08:00:00Z
31cc14c0-8c9d-4713-a6e5-de6976b0d778  global    google.iam.policy.LateralMovementInsight  SECURITY  ACTIVE         2021-03-13T08:00:00Z
4f0fd42b-5637-47af-9200-e0e55adbf321  global    google.iam.policy.LateralMovementInsight  SECURITY  ACTIVE         2021-03-13T08:00:00Z

REST

The Recommender API's insights.list method lists all lateral movement 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.

HTTP method and URL:

GET https://recommender.googleapis.com/v1/projects/PROJECT_ID/locations/global/insightTypes/google.iam.policy.LateralMovementInsight/insights

To send your request, expand one of these options:

The response lists all of the lateral movement insights in your project. For example:

{
  "insights": [
    {
      "name": "projects/123456789012/locations/global/insightTypes/google.iam.policy.LateralMovementInsight/insights/13088eec-9573-415f-81a7-46e1a260e860",
      "description": "Service account service-account@another-project.iam.gserviceaccount.com from another project can impersonate 2 service account(s) under this project.",
      "content": {
        "impersonator": {
          "serviceAccount": "service-account@another-project.iam.gserviceaccount.com",
          "serviceAccountOwner": "//cloudresourcemanager.googleapis.com/projects/987654321098",
          "isGoogleManaged": false
        },
        "targetServiceAccounts": [
          "target-service-account-1@this-project.iam.gserviceaccount.com",
          "target-service-account-2@this-project.iam.gserviceaccount.com"
        ],
        "impersonationPolicy": {
          "resource": "//cloudresourcemanager.googleapis.com/projects/123456789012",
          "role": "roles/editor",
          "member": "serviceAccount:service-account@another-project.iam.gserviceaccount.com",
          "condition": {
            "expression": "",
            "title": "",
            "description": "",
            "location": ""
          }
        },
        "impersonationPermissionUsage": [
          {
            "permission": "iam.serviceAccounts.actAs"
            "used": false
          }
        ],
        "hasPermissionUsageData": true
      },
      "lastRefreshTime": "2021-03-13T08:00:00Z",
      "observationPeriod": "7776000s",
      "stateInfo": {
        "state": "ACTIVE"
      },
      "category": "SECURITY",
      "associatedRecommendations": [
        {
          "recommendation": "projects/123456789012/locations/global/recommenders/google.iam.policy.Recommender/recommendations/03f3dc20-f9e7-4502-95ab-bf7d3164846f"
        }
      ],
      "targetResources": [
        "//cloudresourcemanager.googleapis.com/projects/123456789012"
      ],
      "insightSubtype": "CROSS_PROJECT_IMPERSONATION",
      "etag": "\"f48fa6a1b15c7741\""
    }
  ]
}

To learn more about the components of an insight, see Review lateral movement insights on this page.

Get a single lateral movement 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:

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.
gcloud recommender insights describe INSIGHT_ID \
    --insight-type=google.iam.policy.LateralMovementInsight \
    --project=PROJECT_ID \
    --location=global

The output shows the insight in detail. For example, the following insight indicates that the IAM policy on project 123456789012 allows service-account@another-project.iam.gserviceaccount.com to impersonate target-service-account-1@this-project.iam.gserviceaccount.com and target-service-account-2@this-project.iam.gserviceaccount.com.

associatedRecommendations:
- recommendation: projects/123456789012/locations/global/recommenders/google.iam.policy.Recommender/recommendations/03f3dc20-f9e7-4502-95ab-bf7d3164846f
category: SECURITY
content:
  hasPermissionUsageData: true
  impersonationPermissionUsage:
  - permission: iam.serviceAccounts.actAs
    used: false
  impersonationPolicy:
    condition:
      description: ''
      expression: ''
      location: ''
      title: ''
    member: serviceAccount:service-account@another-project.iam.gserviceaccount.com
    resource: //cloudresourcemanager.googleapis.com/projects/123456789012
    role: roles/editor
  impersonator:
    isGoogleManaged: false
    serviceAccount: service-account@another-project.iam.gserviceaccount.com
    serviceAccountOwner: //cloudresourcemanager.googleapis.com/projects/987654321098
  targetServiceAccounts:
  - target-service-account-1@this-project.iam.gserviceaccount.com
  - target-service-account-2@this-project.iam.gserviceaccount.com
description: Service account service-account@another-project.iam.gserviceaccount.com from another project can impersonate 2 service account(s) under this project.
etag: '"f48fa6a1b15c7741"'
insightSubtype: CROSS_PROJECT_IMPERSONATION
lastRefreshTime: '2021-03-13T08:00:00Z'
name: projects/123456789012/locations/global/insightTypes/google.iam.policy.LateralMovementInsight/insights/13088eec-9573-415f-81a7-46e1a260e860
observationPeriod: 7776000s
stateInfo:
  state: ACTIVE
targetResources:
- //cloudresourcemanager.googleapis.com/projects/123456789012

To learn more about the components of an insight, see Review lateral movement 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.
  • 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/global/insightTypes/google.iam.policy.LateralMovementInsight/insights/INSIGHT_ID

To send your request, expand one of these options:

The response contains the insight. For example, the following insight indicates that the IAM policy on project 123456789012 allows service-account@another-project.iam.gserviceaccount.com to impersonate target-service-account-1@this-project.iam.gserviceaccount.com and target-service-account-2@this-project.iam.gserviceaccount.com.

{
  "name": "projects/123456789012/locations/global/insightTypes/google.iam.policy.LateralMovementInsight/insights/13088eec-9573-415f-81a7-46e1a260e860",
  "description": "Service account service-account@another-project.iam.gserviceaccount.com from another project can impersonate 2 service account(s) under this project.",
  "content": {
    "impersonator": {
      "serviceAccount": "service-account@another-project.iam.gserviceaccount.com",
      "serviceAccountOwner": "//cloudresourcemanager.googleapis.com/projects/987654321098",
      "isGoogleManaged": false
    },
    "targetServiceAccounts": [
      "target-service-account-1@this-project.iam.gserviceaccount.com",
      "target-service-account-2@this-project.iam.gserviceaccount.com"
    ],
    "impersonationPolicy": {
      "resource": "//cloudresourcemanager.googleapis.com/projects/123456789012",
      "role": "roles/editor",
      "member": "serviceAccount:service-account@another-project.iam.gserviceaccount.com",
      "condition": {
        "expression": "",
        "title": "",
        "description": "",
        "location": ""
      }
    },
    "impersonationPermissionUsage": [
      {
        "permission": "iam.serviceAccounts.actAs"
        "used": false
      }
    ],
    "hasPermissionUsageData": true
  },
  "lastRefreshTime": "2021-03-13T08:00:00Z",
  "observationPeriod": "7776000s",
  "stateInfo": {
    "state": "ACTIVE"
  },
  "category": "SECURITY",
  "associatedRecommendations": [
    {
      "recommendation": "projects/123456789012/locations/global/recommenders/google.iam.policy.Recommender/recommendations/03f3dc20-f9e7-4502-95ab-bf7d3164846f"
    }
  ],
  "targetResources": [
    "//cloudresourcemanager.googleapis.com/projects/123456789012"
  ],
  "insightSubtype": "CROSS_PROJECT_IMPERSONATION",
  "etag": "\"f48fa6a1b15c7741\""
}

To learn more about the components of an insight, see Review lateral movement insights on this page.

Review lateral movement insights

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

An insight's content is determined by its subtypes. Lateral movement insights (google.iam.policy.LateralMovementInsight) support insights with the CROSS_PROJECT_IMPERSONATION subtype.

CROSS_PROJECT_IMPERSONATION 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 the details of the service account's ability to impersonate service accounts in other projects. This field contains the following components:

    • hasPermissionUsageData: A boolean value indicating whether there is permission usage data for this role binding. Permission usage data indicates whether the permissions in the role binding have been used. This data is not available for conditional role bindings.
    • impersonationPermissionUsage: A list of impersonation permissions and their usage information. If hasPermissionUsageData is false, this field is empty.
    • impersonationPolicy: Information about the role binding that gives the service account impersonation permissions.
    • impersonator: The service account that has permission to impersonate service accounts in your project
    • targetServiceAccounts: A list of the service accounts that the service account in the impersonator field has permission to impersonate. If the impersonator can impersonate more than 1500 service accounts, the list is empty. To learn how many service accounts the impersonator can impersonate, see the description field.
  • 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/global/insightTypes/google.iam.policy.LateralMovementInsight/insights/INSIGHT_ID

    The placeholders have the following values:

    • PROJECT_ID: The ID of the project where the insight was generated.
    • 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.
  • severity: The severity of the insight. All lateral movement insights have a severity of LOW.
  • 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 project or service account that the insight is for. For example, //cloudresourcemanager.googleapis.com/projects/1234567890.

Mark a lateral movement 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.

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.
  • 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.LateralMovementInsight \
    --project=PROJECT_ID \
    --location=global \
    --etag=ETAG

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

associatedRecommendations:
- recommendation: projects/123456789012/locations/global/recommenders/google.iam.policy.Recommender/recommendations/03f3dc20-f9e7-4502-95ab-bf7d3164846f
category: SECURITY
content:
  hasPermissionUsageData: true
  impersonationPermissionUsage:
  - permission: iam.serviceAccounts.actAs
    used: false
  impersonationPolicy:
    condition:
      description: ''
      expression: ''
      location: ''
      title: ''
    member: serviceAccount:service-account@another-project.iam.gserviceaccount.com
    resource: //cloudresourcemanager.googleapis.com/projects/123456789012
    role: roles/editor
  impersonator:
    isGoogleManaged: false
    serviceAccount: service-account@another-project.iam.gserviceaccount.com
    serviceAccountOwner: //cloudresourcemanager.googleapis.com/projects/987654321098
  targetServiceAccounts:
  - target-service-account-1@this-project.iam.gserviceaccount.com
  - target-service-account-2@this-project.iam.gserviceaccount.com
description: Service account service-account@another-project.iam.gserviceaccount.com from another project can impersonate 2 service account(s) under this project.
etag: '"f48fa6a1b15c7741"'
insightSubtype: CROSS_PROJECT_IMPERSONATION
lastRefreshTime: '2021-03-13T08:00:00Z'
name: projects/123456789012/locations/global/insightTypes/google.iam.policy.LateralMovementInsight/insights/13088eec-9573-415f-81a7-46e1a260e860
observationPeriod: 7776000s
stateInfo:
  state: ACCEPTED
targetResources:
- //cloudresourcemanager.googleapis.com/projects/123456789012

To learn more about the state info of an insight, see Review lateral movement 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.
  • 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/global/insightTypes/google.iam.policy.LateralMovementInsight/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/global/insightTypes/google.iam.policy.LateralMovementInsight/insights/13088eec-9573-415f-81a7-46e1a260e860",
  "description": "Service account service-account@another-project.iam.gserviceaccount.com from another project can impersonate 2 service account(s) under this project.",
  "content": {
    "impersonator": {
      "serviceAccount": "service-account@another-project.iam.gserviceaccount.com",
      "serviceAccountOwner": "//cloudresourcemanager.googleapis.com/projects/987654321098",
      "isGoogleManaged": false
    },
    "targetServiceAccounts": [
      "target-service-account-1@this-project.iam.gserviceaccount.com",
      "target-service-account-2@this-project.iam.gserviceaccount.com"
    ],
    "impersonationPolicy": {
      "resource": "//cloudresourcemanager.googleapis.com/projects/123456789012",
      "role": "roles/editor",
      "member": "serviceAccount:service-account@another-project.iam.gserviceaccount.com",
      "condition": {
        "expression": "",
        "title": "",
        "description": "",
        "location": ""
      }
    },
    "impersonationPermissionUsage": [
      {
        "permission": "iam.serviceAccounts.actAs"
        "used": false
      }
    ],
    "hasPermissionUsageData": true
  },
  "lastRefreshTime": "2021-03-13T08:00:00Z",
  "observationPeriod": "7776000s",
  "stateInfo": {
    "state": "ACCEPTED"
  },
  "category": "SECURITY",
  "associatedRecommendations": [
    {
      "recommendation": "projects/123456789012/locations/global/recommenders/google.iam.policy.Recommender/recommendations/03f3dc20-f9e7-4502-95ab-bf7d3164846f"
    }
  ],
  "targetResources": [
    "//cloudresourcemanager.googleapis.com/projects/123456789012"
  ],
  "insightSubtype": "CROSS_PROJECT_IMPERSONATION",
  "etag": "\"f48fa6a1b15c7741\""
}

To learn more about the state info of an insight, see Review lateral movement insights on this page.

What's next