Search code examples
google-cloud-platformgcloudservice-accountsgoogle-iam

Google cloud: How to list all service-accounts from all Projects in GCP


I have requirement to get all the properties of a service account in google cloud. is it possible to list all the properties something like Select *.

otherwise i need the following information:

  • SA account name
  • Email address
  • Iam Role assigned
  • User managed Keys (if any)
  • account creation date
  • last used /authentication time.
  • Project name
  • account status (enable / disable)

I can get all the projects then all the service accounts in it but i dont know how to get all other values.

foreach ($project in gcloud projects list --format="value(projectId)")
{
  Write-Host "ProjectId: $project"
  foreach ($robot in  gcloud iam service-accounts list --project $project --format="value(email)")
  {
     Write-Host "    -> Robot $robot"
   
  }
}

Solution

  • As the commenters have pointed out, this isn't trivial.

    But, I'm always up for some gcloud-bashing ;-)

    Your code sample suggests you want the answer in PowerShell which I don't have and hope you don't mind pointers (what follows is incomplete) in bash:

    Does:

    • Project ID
    • Account name
    • Enabled|Disabled
    • Email
    • Keys
    • Creation (timestamp)

    Doesn't:

    • Role assignments
    • Last used (audit logs?)
    PROJECTS=$(gcloud projects list --format="value(projectId)")
    
    for PROJECT in ${PROJECTS}
    do
      echo "Project: ${PROJECT}"
      # Extracts ACCOUNT_ID, EMAIL (==ACCOUNT_ID@...), DISABLED
      ROBOTS=$(\
        gcloud iam service-accounts list \
        --project=${PROJECT} \
        --format="csv[no-heading](displayName.encode(\"base64\"),email,email.split(\"@\").slice(0),disabled)")
      for ROBOT in ${ROBOTS}
      do
        # Parse results
        IFS=, read ENCODED_NAME EMAIL ACCOUNT_ID DISABLED <<< ${ROBOT}
        NAME=$(echo -e ${ENCODED_NAME} | base64 --decode)
        echo "  Service Account: ${NAME}"
        echo "    Disabled: ${DISABLED}"
        echo "    Email: ${EMAIL}"
        # Keys
        KEYS=$(\
            gcloud iam service-accounts keys list \
            --iam-account=${EMAIL} \
            --project=${PROJECT} \
            --format="value(name.scope(keys))")
        for KEY in ${KEYS}
        do
          echo "    Key: ${KEY}"
        done
        # Creation (Only searches back 30-days!)
        FILTER=""\
    "logName=\"projects/${PROJECT}/logs/cloudaudit.googleapis.com%2Factivity\" "\
    "resource.type=\"service_account\" "\
    "protoPayload.methodName=\"google.iam.admin.v1.CreateServiceAccount\" "\
    "protoPayload.request.account_id=\"${ACCOUNT_ID}\" "
    
        LOG=$(\
            gcloud logging read "${FILTER}" \
            --project=${PROJECT} \
            --format=json \
            --freshness=30d \
            --format="value(timestamp)")
        echo "    Created: ${LOG}"
      done
    done
    

    Notes

    • Service Account creation times -- IIUC -- can only be obtained through audit logs (CreateServiceAccount[Key]). One challenge with this is having to search back through the project's (entire) history to find these.
    • Only user-created Service Accounts are created (during the project's lifetime). Google-maintained account e.g. App Engine will not be found.
    • The script searches the logs for each account. This is inefficient and it would be better to search the logs once for all accounts and then merge the results.
    • Role assignments is difficult because of inheritance. A naive solution would get the IAM policy for each Project but this is insufficient as it doesn't cover Organizational|Folder permissions nor does it include resource-specific bindings.
    • I actually don't know how to grep the logs for last auth times and assume this is available through audit logs
    • Apologies for the gnarly base64 encoding of the account's displayName. This is to avoid over-eager parsing of (the majority of) names that include spaces. There's likely a better approach.