4

I'm trying to publish a npm package on GAR (Google Artifact Registry) through github using google-github-actions/auth@v0 and google-artifactregistry-auth

For the authentication to google from github here is what I did to use the Federation Workload Identity:

export PROJECT_ID="my-project-id"

gcloud iam service-accounts create "gh-deploy-service-account" --project "${PROJECT_ID}"

gcloud iam workload-identity-pools create "github-pool" --project="${PROJECT_ID}" --location="global" --display-name="Github pool"

gcloud iam workload-identity-pools describe github-pool" --project="${PROJECT_ID}" --location="global" --format="value(name)"

export WORKLOAD_IDENTITY_POOL_ID=projects/my-custom-id-number/locations/global/workloadIdentityPools/github-pool

gcloud iam workload-identity-pools providers create-oidc "github-provider" \
  --project="${PROJECT_ID}" \
  --location="global" \
  --workload-identity-pool="github-pool" \
  --display-name="Github provider" \
  --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository" \
  --issuer-uri="https://token.actions.githubusercontent.com"

export REPO="@example/my-package"

gcloud iam service-accounts add-iam-policy-binding "gh-deploy-service-account@${PROJECT_ID}.iam.gserviceaccount.com" \
  --project="${PROJECT_ID}" \
  --role="roles/iam.workloadIdentityUser" \
  --member="principalSet://iam.googleapis.com/${WORKLOAD_IDENTITY_POOL_ID}/attribute.repository/${REPO}"

Then I created my artifact repository on google :

gcloud artifacts repositories create npm-repository --repository-format=npm --location=asia-east2

Here is my github workflows :

name: Publish Package
on:
  push:
    branches:
      - main

jobs:
  publish:
    timeout-minutes: 10
    runs-on: ubuntu-latest
    permissions:
      contents: "read"
      id-token: "write"
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - uses: actions/setup-node@v2
        with:
          node-version: 16

      - name: Install
        run: npm ci

      - id: "auth"
        name: "Authenticate to Google Cloud"
        uses: "google-github-actions/auth@v0"
        with:
          workload_identity_provider: ${{ secrets.WORKLOAD_IDENTITY_PROVIDER }}
          service_account: ${{ secrets.SERVICE_ACCOUNT }}
          create_credentials_file: true

      - name: "Set up Cloud SDK"
        uses: "google-github-actions/setup-gcloud@v0"

      - name: Create .npmrc
        run: |
          cat << EOF > .npmrc
            @example:registry=https://asia-east2-npm.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/npm-repository/
            //asia-east2-npm.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/npm-repository/:_authToken=""
            //asia-east2-npm.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/npm-repository/:always-auth=true
          EOF

      - name: Artifact login
        run: |
          #export GOOGLE_APPLICATION_CREDENTIALS=${{ steps.auth.outputs.credentials_file_path }}
          npx google-artifactregistry-auth@v3 --repo-config=[./.npmrc] --credential-config=[./.npmrc]

But on this workflow, I got an error on the step Artifact login. Telling me :

npm WARN exec The following package was not found and will be installed: google-artifactregistry-auth
Retrieving application default credentials...
Retrieving credentials from gcloud...
Error: Fail to get credentials. Please run: 
`gcloud auth application-default login`, `gcloud auth login`, or 
`export GOOGLE_APPLICATION_CREDENTIALS=<path/to/service/account/key>`
    at Object.getCreds (/home/runner/.npm/_npx/64aef35f3ba01c7c/node_modules/google-artifactregistry-auth/src/auth.js:40:9)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async main (/home/runner/.npm/_npx/64aef35f3ba01c7c/node_modules/google-artifactregistry-auth/src/main.js:66:19)
Error: Process completed with exit code 1.

The full workflow is available here I don't know where is my mistake here. Does my service account need more right ? or is it an issue on the google-artifactregistry-auth ? I really don't know :/

Thx in advance for you help !

EDIT 1 : I tried to follow this documentation and I added to my service account some right :

gcloud artifacts repositories add-iam-policy-binding npm-repository \
--location asia-east2 --member=serviceAccount:my-service-account --role=roles/artifactregistry.writer
  • I do not think **google-artifactregistry-auth** picks up Workload Identity Federation credentials. The line before sets up the ADC environment variable which **google-artifactregistry-auth** supports. Why do you have that line commented out? **#export GOOGLE_APPLICATION_CREDENTIALS=${{ steps.auth.outputs.credentials_file_path }}** – John Hanley Feb 11 '22 at 08:49
  • It's something i tried myself but even using this line it didn't work. I can try to push it again ! – magento2-users Feb 11 '22 at 09:14
  • as you can see [here](https://github.com/cybernadinou/google-actions-gar-npm/runs/5153877703?check_suite_focus=true) even by trying to force the export CREDENTIALS I got the same error :/ – magento2-users Feb 11 '22 at 09:27
  • Try creating a new workflow and specify a normal service account json file. Then setup **GOOGLE_APPLICATION_CREDENTIALS** and verify that *8npx google-artifactregistry-auth@v3 ...** now works. I am trying to split the problem into smaller parts to debug. Another item,, verify that **gha-creds-c43dbb9eded07964.json** actually contains a service account JSON file - print the contents so that you can see that in the Actions log. – John Hanley Feb 11 '22 at 09:32
  • 1/ it does work with service-account and account service key.json : [You can see here](https://github.com/cybernadinou/google-actions-gar-npm/tree/main-json) but I'd like to use the Workload Identity Federation. Google recommand to use this instead of the key. I also wanna try something else by giving also this role to my previous service account : `roles/iam.serviceAccountTokenCreator` . 2/ so the **gha-creds-c43dbb9eded07964.json** does return something. ( I ran it on private repo instead of the public one I shared ) . – magento2-users Feb 11 '22 at 10:17
  • my question now is : is there any way to use workload identity token and **not use** `google-artifactregistry-auth` . Do you know any alternative ? Thx for your help :) – magento2-users Feb 11 '22 at 10:42
  • The json file provided through Workload Identity Federation is : `not a valid format.` whith this cmd :`gcloud auth activate-service-account ${{ secrets.SERVICE_ACCOUNT }} --key-file=${{ steps.auth.outputs.credentials_file_path }}` – magento2-users Feb 11 '22 at 11:19

1 Answers1

5

I finally find out !!! BUT I'm not sure in term of security if there is any risk or not so if anyone can advice I'll edit the answer !

What is changing but I'm not sure in term of security is here :

gcloud iam service-accounts add-iam-policy-binding "gh-deploy-service-account@${PROJECT_ID}.iam.gserviceaccount.com" \
  --project="${PROJECT_ID}" \
  --role="roles/iam.serviceAccountTokenCreator" \
  --member="principalSet://iam.googleapis.com/projects/MY_PROJECT_NUMBER/locations/global/workloadIdentityPools/github-pool-2/*"


gcloud iam service-accounts add-iam-policy-binding "gh-deploy-service-account@${PROJECT_ID}.iam.gserviceaccount.com" \
  --project="${PROJECT_ID}" \
  --role="roles/iam.workloadIdentityUser" \
  --member="principalSet://iam.googleapis.com/projects/MY_PROJECT_NUMBER/locations/global/workloadIdentityPools/github-pool-2/*"

I think I don't really get the principalSet option and all the attribute possible so if anyone can advice also on this, I'll be grateful !

Then don't forget to bind your repo to your service account :

gcloud artifacts repositories add-iam-policy-binding npm-repository \
--location asia-east2 --member=serviceAccount:gh-deploy-service-account@${PROJECT_ID}.iam.gserviceaccount.com --role=roles/artifactregistry.writer

And for the github workflow I remove the google-artifactregistry-auth and i use the access_token in the .npmrc file.

Here is the full workflow :

name: Publish Package
on:
  push:
    branches:
      - main

jobs:
  publish:
    timeout-minutes: 10
    runs-on: ubuntu-latest
    permissions:
      contents: "read"
      id-token: "write"
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - uses: actions/setup-node@v2
        with:
          node-version: 16

      - name: Install
        run: npm ci

      - id: "auth"
        name: "Authenticate to Google Cloud"
        uses: "google-github-actions/auth@v0"
        with:
          workload_identity_provider: ${{ secrets.WORKLOAD_IDENTITY_PROVIDER }}
          service_account: ${{ secrets.SERVICE_ACCOUNT }}
          token_format: 'access_token'

      - name: "Set up Cloud SDK"
        uses: "google-github-actions/setup-gcloud@v0"

      - name: Create .npmrc
        run: |
          cat << EOF > .npmrc
            @example:registry=https://asia-east2-npm.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/npm-repository/
            //asia-east2-npm.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/npm-repository/:_authToken="${{ steps.auth.outputs.access_token }}"
            //asia-east2-npm.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/npm-repository/:always-auth=true
          EOF

      - name: Artifact login
        run: |
          npm publish