From 03e0357f18ac624e9c187c5ee89406842b6ea553 Mon Sep 17 00:00:00 2001 From: Rachael Sewell Date: Thu, 10 Oct 2024 23:47:06 +0000 Subject: [PATCH] token-based auth for azure container registry (#52356) Co-authored-by: Kevin Heis --- .github/workflows/azure-prod-build-deploy.yml | 34 +++++++----- package.json | 1 + src/workflows/acr-create-token.ts | 54 +++++++++++++++++++ 3 files changed, 77 insertions(+), 12 deletions(-) create mode 100755 src/workflows/acr-create-token.ts diff --git a/.github/workflows/azure-prod-build-deploy.yml b/.github/workflows/azure-prod-build-deploy.yml index 254ca141255b..d84551fb9cae 100644 --- a/.github/workflows/azure-prod-build-deploy.yml +++ b/.github/workflows/azure-prod-build-deploy.yml @@ -34,6 +34,7 @@ jobs: RESOURCE_GROUP_NAME: docs-prod APP_SERVICE_NAME: ghdocs-prod SLOT_NAME: canary + ACR_TOKEN_NAME: acrToken steps: - name: 'Az CLI login' @@ -41,16 +42,6 @@ jobs: with: creds: ${{ secrets.PROD_AZURE_CREDENTIALS }} - - name: 'Docker login' - uses: azure/docker-login@15c4aadf093404726ab2ff205b2cdd33fa6d054c - with: - login-server: ${{ secrets.PROD_REGISTRY_SERVER }} - username: ${{ secrets.PROD_REGISTRY_USERNAME }} - password: ${{ secrets.PROD_REGISTRY_PASSWORD }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db - - name: Check out repo uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: @@ -64,11 +55,30 @@ jobs: node-version-file: 'package.json' cache: npm - # Currently we only need this to run dependencies in - # src/workflows/check-canary-slots.js + # We need this to run a few scripts that were easier to write in JS/TS - name: Install dependencies run: npm install + # Create a temporary token for the Azure Container Registry + # and set it as a GitHub Actions environment variable + # Then clean up by deleting the temp token. + # Created token are viewable in the ACR resource UI + # under Repository permissions > Tokens + - name: 'Create Azure Container Registry Token' + env: + PROD_REGISTRY_SERVER: ${{ secrets.PROD_REGISTRY_SERVER }} + run: npm run create-acr-token + + - name: 'Docker login' + uses: azure/docker-login@15c4aadf093404726ab2ff205b2cdd33fa6d054c + with: + login-server: ${{ secrets.PROD_REGISTRY_SERVER }} + username: ${{ env.ACR_TOKEN_NAME }} + password: ${{ env.ACR_TOKEN_VALUE }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db + - name: Clone docs-early-access uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: diff --git a/package.json b/package.json index 19df82b77946..d9ee1dcd7ebe 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "content-changes-table-comment": "tsx src/workflows/content-changes-table-comment.ts", "copy-fixture-data": "node src/tests/scripts/copy-fixture-data.js", "count-translation-corruptions": "tsx src/languages/scripts/count-translation-corruptions.ts", + "create-acr-token": "tsx src/workflows/acr-create-token.js", "debug": "cross-env NODE_ENV=development ENABLED_LANGUAGES=en nodemon --inspect src/frame/server.ts", "delete-orphan-translation-files": "tsx src/workflows/delete-orphan-translation-files.ts", "deleted-features-pr-comment": "tsx src/data-directory/scripts/deleted-features-pr-comment.ts", diff --git a/src/workflows/acr-create-token.ts b/src/workflows/acr-create-token.ts new file mode 100755 index 000000000000..ba18ebac7fdc --- /dev/null +++ b/src/workflows/acr-create-token.ts @@ -0,0 +1,54 @@ +#!/usr/bin/env node +import { execSync } from 'child_process' +import * as core from '@actions/core' +import dotenv from 'dotenv' + +type IsoDateString = string + +// For local testing set environment variables in the .env file +dotenv.config() + +const acrTokenName = process.env.ACR_TOKEN_NAME +const acrProdRegistryServer = process.env.PROD_REGISTRY_SERVER +const repo = process.env.GITHUB_REPOSITORY + +function main() { + // Get the current time and add 30 minutes to it + // Convert Date format from YYYY-MM-DDTHH:mm:ss.sssZ to + // YYYY-MM-DDTHH:mm:ssZ (remove .sss) + const expirationDate: IsoDateString = + new Date(Date.now() + 30 * 60 * 1000).toISOString().split('.')[0] + 'Z' + + let resp + try { + const cmd = `az acr token create \ + --name ${acrTokenName} \ + --registry ${acrProdRegistryServer} \ + --repository ${repo} \ + content/write \ + content/read \ + --expiration ${expirationDate} \ + --output json` + + console.log('Executing az acr token create command.') + resp = JSON.parse(execSync(cmd, { encoding: 'utf8' })) + } catch (error) { + console.error('An error occurred while creating ACR token with the Azure CLI') + throw error + } + + const acrTokenValue = resp?.credentials?.passwords[0]?.value + if (!acrTokenValue) { + throw new Error( + 'The response from the Azure CLI was not in the expected format: \n' + + JSON.stringify(resp, null, 2), + ) + } + + // Set the ACR_TOKEN_VALUE environment variable so + // that it can be used in the subsequent steps + core.exportVariable('ACR_TOKEN_VALUE', acrTokenValue) + execSync(`echo $ACR_TOKEN_VALUE`) +} + +main()