id: gcloud-service-account-admin-restriction

info:
  name: Restrict Administrator Access for Service Accounts
  author: princechaddha
  severity: medium
  description: |
    Ensure that your Google Cloud user-managed service accounts are not using privileged (administrator) roles, in order to implement the principle of least privilege and prevent any accidental or intentional modifications that may lead to data leaks and/or data loss. A user-managed service account is an identity that a virtual machine (VM) instance or an application can use to run API requests on your behalf. GCP service accounts can create, modify, or delete resources only if you grant the necessary IAM permissions, at the project or resource level.
  impact: |
    Using service accounts with administrative privileges can lead to potential over-privileged scenarios, increasing the risk of security breaches and unauthorized access.
  remediation: |
    Review and minimize the roles assigned to service accounts, ensuring no administrative privileges are granted unless absolutely necessary.
  reference:
    - https://cloud.google.com/iam/docs/understanding-roles
  tags: cloud,devops,gcp,gcloud,google-cloud-iam,gcp-cloud-config

flow: |
  code(1)
  for(let projectId of iterate(template.projectIds)){
    set("projectId", projectId)
    code(2)
    for(let binding of iterate(template.bindings)){
      set("binding", binding)
      javascript(1)
    }
  }

self-contained: true

code:
  - engine:
      - sh
      - bash
    source: |
      gcloud projects list --format="json(projectId)"
    extractors:
      - type: json
        name: projectIds
        internal: true
        json:
          - '.[].projectId'

  - engine:
      - sh
      - bash
    source: |
      gcloud projects get-iam-policy $projectId --format=json
    extractors:
      - type: json
        name: bindings
        internal: true
        json:
          - '.bindings[]'

javascript:
  - code: |
        let binding = JSON.parse(template.binding);
        let isAdminRole = ["roles/editor", "roles/owner"].includes(binding.role) || /admin/i.test(binding.role);
        let projectId = template.projectId;
        if (isAdminRole) {
          Export("Service Account with Admin Privileges " + binding.members.join(", ") + " in project " + projectId);
        }

    extractors:
      - type: dsl
        dsl:
          - response
# digest: 4b0a00483046022100bfc245889da67838def2368e3e06788c9285c886515c9d34d515b83781cf3f72022100d26ed6c27389bcb8450fb7d84e98ee490b9d084a29d8e3e5bce619f8fe2a7375:922c64590222798bb761d5b6d8e72950