google-github-actions / auth

A GitHub Action for authenticating to Google Cloud.

Home Page:https://cloud.google.com/iam

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Interaction between 'delegates' and Workload Identity Federation

Tutuchan opened this issue · comments

Hello,

I'm having a hard time understanding how to create a delegation chain to impersonate a service account using this Github Action.

Here is my workflow.

In GCP project MY_PROJECT, I have 2 service accounts:

  • MY_SA@MY_PROJECT.iam.gserviceaccount.com: main service account with large permissions
  • MY_SA-CICD@MY_PROJECT.iam.gserviceaccount.com: only has the roles/iam.serviceAccountTokenCreator on MY_SA.

Meanwhile, WIF is configured so that the principalSet corresponding to a specific repository has roles/iam.workloadIdentityUser and roles/iam.serviceAccountTokenCreator on MY_SA-CICD. I am trying to authenticate to MY_SA with a single auth Github Action.

Here is a simplified version of the Github workflow:

jobs:
  test_workflow:
    permissions:
      contents: read
      id-token: write
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v3
      - id: "auth"
        uses: "google-github-actions/auth@v1"
        with:
          workload_identity_provider: projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/MY_POOL/providers/MY_PROVIDER
          service_account: MY_SA@MY_PROJECT.iam.gserviceaccount.com
          delegates: MY_SA-CICD@MY_PROJECT.iam.gserviceaccount.com
          token_format: "access_token"
          access_token_lifetime: 3600s
      - id: "setup-gcloud"
        uses: "google-github-actions/setup-gcloud@v1"
      - run: |
          gcloud auth list
          gcloud artifacts repositories list

gcloud auth list returns

ACTIVE  ACCOUNT
*       MY_SA@MY_PROJECT.iam.gserviceaccount.com

but gcloud artifacts repositories list fails with

There was a problem refreshing your current auth tokens: ('Unable to acquire impersonated credentials', '{\n  "error": {\n    "code": 403,\n    "message": "Permission \'iam.serviceAccounts.getAccessToken\' denied on resource (or it may not exist).",\n    "status": "PERMISSION_DENIED",\n    "details": [\n      {\n        "@type": "type.googleapis.com/google.rpc.ErrorInfo",\n        "reason": "IAM_PERMISSION_DENIED",\n        "domain": "iam.googleapis.com",\n        "metadata": {\n          "permission": "iam.serviceAccounts.getAccessToken"\n        }\n      }\n    ]\n  }\n}\n')

If I don't use delegates and use --impersonate-service-account in subsequent gcloud calls, it's working fine, e.g.

jobs:
  test_workflow:
    permissions:
      contents: read
      id-token: write
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v3
      - id: "auth"
        uses: "google-github-actions/auth@v1"
        with:
          workload_identity_provider: projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/MY_POOL/providers/MY_PROVIDER
          service_account: MY_SA-CICD@MY_PROJECT.iam.gserviceaccount.com
          access_token_lifetime: 3600s
      - id: "setup-gcloud"
        uses: "google-github-actions/setup-gcloud@v1"
      - run: |
          gcloud auth list

> ACTIVE  ACCOUNT
> *       MY_SA-CICD@MY_PROJECT.iam.gserviceaccount.com

          gcloud artifacts repositories list
> WARNING: This command is using service account impersonation. All API calls will be executed as [MY_SA@MY_PROJECT.iam.gserviceaccount.com].
> [list of artifact registry repositories]

In the audit logs, for the 1st case, I'm under the impression that the delegation chain is ignored when doing the gcloud call – based on the authenticationInfo and request keys in the protoPayload field. See

{
  "protoPayload": {
    "@type": "type.googleapis.com/google.cloud.audit.AuditLog",
    "status": {
      "code": 7,
      "message": "Permission 'iam.serviceAccounts.getAccessToken' denied on resource (or it may not exist)."
    },
    "authenticationInfo": {
      "serviceAccountDelegationInfo": [
        {}
      ],
      "principalSubject": "principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/MY_POOL/subject/repo:MY_ORG/MY_REPO:pull_request"
    },
    "requestMetadata": {
      "callerIp": "20.172.43.82",
      "callerSuppliedUserAgent": "google-cloud-sdk gcloud/450.0.0 command/gcloud.artifacts.repositories.list invocation-id/81b3609092eb4031a7d5c03adcd1fe79 environment/github-actions-setup-gcloud environment-version/1.1.1 client-os/LINUX client-os-ver/6.2.0 client-pltf-arch/x86_64 interactive/False from-script/False python/3.9.16 term/ (Linux 6.2.0-1012-azure),gzip(gfe)",
      "requestAttributes": {
        "time": "2023-10-12T11:56:55.782785497Z",
        "auth": {}
      },
      "destinationAttributes": {}
    },
    "serviceName": "iamcredentials.googleapis.com",
    "methodName": "GenerateAccessToken",
    "authorizationInfo": [
      {
        "permission": "iam.serviceAccounts.getAccessToken",
        "resourceAttributes": {}
      }
    ],
    "resourceName": "projects/-/serviceAccounts/ID",
    "request": {
      "@type": "type.googleapis.com/google.iam.credentials.v1.GenerateAccessTokenRequest",
      "name": "projects/-/serviceAccounts/MY_SA@MY_PROJECT.iam.gserviceaccount.com"
    },
    "metadata": {
      "identityDelegationChain": [
        "projects/-/serviceAccounts/MY_SA@MY_PROJECT.iam.gserviceaccount.com"
      ]
    }
  },
  "insertId": "1mk7zroe50hgl",
  "resource": {
    "type": "service_account",
    "labels": {
      "unique_id": "101851263050728808135",
      "email_id": "MY_SA@MY_PROJECT.iam.gserviceaccount.com",
      "project_id": "MY_PROJECT"
    }
  },
  "timestamp": "2023-10-12T11:56:55.771815158Z",
  "severity": "ERROR",
  "logName": "projects/MY_PROJECT/logs/cloudaudit.googleapis.com%2Fdata_access",
  "operation": {
    "id": "10658336329565734952",
    "producer": "iamcredentials.googleapis.com",
    "first": true,
    "last": true
  },
  "receiveTimestamp": "2023-10-12T11:56:56.845099618Z"
}

Please let me know if I'm missing anything and thanks in advance for your time.

Best,
Pierre

Hi there @Tutuchan 👋!

Thank you for opening an issue. Our team will triage this as soon as we can. Please take a moment to review the troubleshooting steps which lists common error messages and their resolution steps.

Hi @Tutuchan - thank you for opening an issue. The delegates option is listing the delegation chain for generating an ID token and/or signing a JWT. It's specifically for doing the auth handshake. If you want to repeatedly impersonate a service account for all future calls, you need to pass in the gcloud flag or API parameter. Delegation is not a persistent option.

Hi @sethvargo , thanks for clarifying that, that makes a lot more sense now.

I'll close this issue, thank you !