|
| 1 | +# Mints a short-lived nuget.org key and returns it to the release pipeline through Secrets Manager. |
| 2 | +# Canonical copy; scripts/enroll-repo.sh copies it into each library repo. |
| 3 | +name: Mint NuGet key |
| 4 | +# The build id lets the release step find its own run. A correlation aid, not a trust signal. |
| 5 | +run-name: Mint NuGet key ${{ inputs.build_id }} |
| 6 | + |
| 7 | +on: |
| 8 | + workflow_dispatch: |
| 9 | + inputs: |
| 10 | + secret_id: |
| 11 | + description: Secrets Manager secret to write the key into |
| 12 | + type: string |
| 13 | + required: true |
| 14 | + build_id: |
| 15 | + description: CODEBUILD_BUILD_ID of the requesting release |
| 16 | + type: string |
| 17 | + required: true |
| 18 | + region: |
| 19 | + description: Region of the secret to write into |
| 20 | + type: string |
| 21 | + required: true |
| 22 | + |
| 23 | +# No contents: read — the job never checks out. |
| 24 | +permissions: |
| 25 | + id-token: write |
| 26 | + |
| 27 | +jobs: |
| 28 | + mint: |
| 29 | + runs-on: ubuntu-latest |
| 30 | + # Pinned by the nuget.org policy and the role trust policy. Its deployment branch policy is the |
| 31 | + # only branch control, so do not change this name. |
| 32 | + environment: nuget-key-mint |
| 33 | + steps: |
| 34 | + # First, because a later step's group header prints its env map. Read from the event payload so no |
| 35 | + # expression puts the value in this step's own header. |
| 36 | + - name: Mask the target secret name |
| 37 | + run: | |
| 38 | + secret_id=$(jq -r '.inputs.secret_id // empty' "$GITHUB_EVENT_PATH") |
| 39 | + if [ -n "$secret_id" ]; then echo "::add-mask::$secret_id"; fi |
| 40 | +
|
| 41 | + # Before NuGet/login: an empty user fails on something unrelated, and an empty input would strand a |
| 42 | + # minted key, which cannot be returned or revoked from here. |
| 43 | + - name: Require everything the mint needs |
| 44 | + env: |
| 45 | + NUGET_USER: ${{ secrets.NUGET_USER }} |
| 46 | + SECRET_ID: ${{ inputs.secret_id }} |
| 47 | + BUILD_ID: ${{ inputs.build_id }} |
| 48 | + run: | |
| 49 | + test -n "$NUGET_USER" || { echo "::error::the NUGET_USER environment secret is not set"; exit 1; } |
| 50 | + test -n "$SECRET_ID" || { echo "::error::no secret_id"; exit 1; } |
| 51 | + test -n "$BUILD_ID" || { echo "::error::no build_id"; exit 1; } |
| 52 | +
|
| 53 | + # v1.2.0 |
| 54 | + - uses: NuGet/login@8d196754b4036150537f80ac539e15c2f1028841 |
| 55 | + id: login |
| 56 | + with: |
| 57 | + user: ${{ secrets.NUGET_USER }} |
| 58 | + |
| 59 | + # v6.3.0 |
| 60 | + - uses: aws-actions/configure-aws-credentials@e1253824e5c10ff9df46874f81ed3ec929e19cfd |
| 61 | + with: |
| 62 | + role-to-assume: ${{ secrets.NUGET_KEY_WRITER_ROLE_ARN }} |
| 63 | + aws-region: ${{ inputs.region }} |
| 64 | + role-session-name: mint-${{ github.run_id }} |
| 65 | + |
| 66 | + - name: Write key to Secrets Manager |
| 67 | + env: |
| 68 | + NUGET_API_KEY: ${{ steps.login.outputs.NUGET_API_KEY }} |
| 69 | + SECRET_ID: ${{ inputs.secret_id }} |
| 70 | + BUILD_ID: ${{ inputs.build_id }} |
| 71 | + run: | |
| 72 | + # Must be first: masking is not retroactive. |
| 73 | + echo "::add-mask::$NUGET_API_KEY" |
| 74 | + test -n "$NUGET_API_KEY" || { echo "::error::no key minted"; exit 1; } |
| 75 | + test -n "$SECRET_ID" || { echo "::error::no secret_id"; exit 1; } |
| 76 | + test -n "$BUILD_ID" || { echo "::error::no build_id"; exit 1; } |
| 77 | + jq -nc --arg k "$NUGET_API_KEY" --arg r "$BUILD_ID" \ |
| 78 | + '{key:$k, codeBuildBuildId:$r, mintedAt:(now|todate)}' \ |
| 79 | + | aws secretsmanager put-secret-value \ |
| 80 | + --secret-id "$SECRET_ID" --secret-string file:///dev/stdin > /dev/null |
| 81 | +
|
| 82 | +# No concurrency block: concurrent releases each mint their own key into their own secret. |
0 commit comments