Просмотр исходного кода

Use OIDC for AWS credentials in integration workflow

The AWS integration job previously authenticated with long-lived access
keys stored as the AWS_ACCESS_KEY / AWS_SECRET_KEY repo secrets. Switch
to GitHub Actions OIDC so the job assumes a per-run role via STS
WebIdentity, eliminating standing keys in the repo and shortening
credential lifetime to the job duration.

Workflow changes:

* Grant `id-token: write` on the integration job so it can mint an OIDC
  token; `contents: read` is set explicitly to keep the rest of the
  default GITHUB_TOKEN scope minimal.
* Add an `aws-actions/configure-aws-credentials@v4` step gated on
  `matrix.cloud-provider == 'aws'`, reading the role ARN from a new
  `AWS_OIDC_ROLE_ARN` secret and pinning the region to us-east-1.
* Drop the AWS_ACCESS_KEY / AWS_SECRET_KEY env vars from the tox step.
  cloudbridge's AWS provider passes `None` to boto3 when its own
  `aws_access_key` / `aws_secret_key` config is unset, which lets
  boto3's default credential chain pick up the AWS_ACCESS_KEY_ID,
  AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN env vars that
  configure-aws-credentials writes.

IAM artifacts under .github/aws/:

* trust-policy.json restricts AssumeRoleWithWebIdentity to this repo
  via the `sub` claim, allowing only `refs/heads/main` and
  `pull_request` contexts.
* permissions-policy.json grants the API surface cloudbridge exercises
  (ec2:* scoped to us-east-1 via ec2:Region, s3:*, route53:*). EC2's
  region condition uses StringEqualsIfExists so global EC2 calls like
  DescribeRegions aren't denied.
* setup.sh registers the GitHub OIDC provider, renders the trust
  policy with the caller's account id, creates/updates the role and
  attaches the inline policy. Idempotent.
Nuwan Goonasekera 2 дней назад
Родитель
Сommit
29b87a6a48
4 измененных файлов с 126 добавлено и 3 удалено
  1. 32 0
      .github/aws/permissions-policy.json
  2. 59 0
      .github/aws/setup.sh
  3. 24 0
      .github/aws/trust-policy.json
  4. 11 3
      .github/workflows/integration.yaml

+ 32 - 0
.github/aws/permissions-policy.json

@@ -0,0 +1,32 @@
+{
+  "Version": "2012-10-17",
+  "Statement": [
+    {
+      "Sid": "EC2FullAccessUsEast1",
+      "Effect": "Allow",
+      "Action": "ec2:*",
+      "Resource": "*",
+      "Condition": {
+        "StringEqualsIfExists": {
+          "ec2:Region": "us-east-1"
+        }
+      }
+    },
+    {
+      "Sid": "S3FullAccess",
+      "Effect": "Allow",
+      "Action": "s3:*",
+      "Resource": "*"
+    },
+    {
+      "Sid": "Route53FullAccess",
+      "Effect": "Allow",
+      "Action": [
+        "route53:*",
+        "route53domains:List*",
+        "route53domains:Get*"
+      ],
+      "Resource": "*"
+    }
+  ]
+}

+ 59 - 0
.github/aws/setup.sh

@@ -0,0 +1,59 @@
+#!/usr/bin/env bash
+# One-time setup to enable GitHub Actions OIDC -> AWS access for this repo.
+# Run with credentials that can manage IAM (admin, or a scoped IAM-admin role).
+# Re-running is safe: each step is idempotent or no-ops if already present.
+
+set -euo pipefail
+
+ACCOUNT_ID="$(aws sts get-caller-identity --query Account --output text)"
+ROLE_NAME="cloudbridge-github-actions"
+POLICY_NAME="cloudbridge-github-actions-policy"
+REGION="us-east-1"
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+TRUST_POLICY="${SCRIPT_DIR}/trust-policy.json"
+PERMISSIONS_POLICY="${SCRIPT_DIR}/permissions-policy.json"
+
+# 1. Register GitHub's OIDC provider in IAM (no-op if it already exists).
+if ! aws iam get-open-id-connect-provider \
+      --open-id-connect-provider-arn "arn:aws:iam::${ACCOUNT_ID}:oidc-provider/token.actions.githubusercontent.com" \
+      >/dev/null 2>&1; then
+  aws iam create-open-id-connect-provider \
+    --url "https://token.actions.githubusercontent.com" \
+    --client-id-list "sts.amazonaws.com" \
+    --thumbprint-list "ffffffffffffffffffffffffffffffffffffffff"
+  # Thumbprint above is a placeholder — GitHub OIDC uses a JWKS endpoint and
+  # AWS now validates the JWKS chain server-side, so the thumbprint is no
+  # longer security-critical. Set any 40-char hex value.
+fi
+
+# 2. Render the trust policy with the real account id.
+TRUST_RENDERED="$(mktemp)"
+sed "s/ACCOUNT_ID/${ACCOUNT_ID}/g" "${TRUST_POLICY}" > "${TRUST_RENDERED}"
+
+# 3. Create or update the role.
+if aws iam get-role --role-name "${ROLE_NAME}" >/dev/null 2>&1; then
+  aws iam update-assume-role-policy \
+    --role-name "${ROLE_NAME}" \
+    --policy-document "file://${TRUST_RENDERED}"
+else
+  aws iam create-role \
+    --role-name "${ROLE_NAME}" \
+    --assume-role-policy-document "file://${TRUST_RENDERED}" \
+    --description "Assumed by GitHub Actions to run cloudbridge integration tests in ${REGION}"
+fi
+
+# 4. Attach an inline permissions policy (replaces on each run).
+aws iam put-role-policy \
+  --role-name "${ROLE_NAME}" \
+  --policy-name "${POLICY_NAME}" \
+  --policy-document "file://${PERMISSIONS_POLICY}"
+
+ROLE_ARN="arn:aws:iam::${ACCOUNT_ID}:role/${ROLE_NAME}"
+
+echo
+echo "Role ready: ${ROLE_ARN}"
+echo "Set this as a repo secret named AWS_OIDC_ROLE_ARN at:"
+echo "  https://github.com/CloudVE/cloudbridge/settings/secrets/actions"
+echo
+echo "Then remove the AWS_ACCESS_KEY and AWS_SECRET_KEY repo secrets — they are no longer used."

+ 24 - 0
.github/aws/trust-policy.json

@@ -0,0 +1,24 @@
+{
+  "Version": "2012-10-17",
+  "Statement": [
+    {
+      "Sid": "AllowGitHubActionsOIDC",
+      "Effect": "Allow",
+      "Principal": {
+        "Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com"
+      },
+      "Action": "sts:AssumeRoleWithWebIdentity",
+      "Condition": {
+        "StringEquals": {
+          "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
+        },
+        "StringLike": {
+          "token.actions.githubusercontent.com:sub": [
+            "repo:CloudVE/cloudbridge:ref:refs/heads/main",
+            "repo:CloudVE/cloudbridge:pull_request"
+          ]
+        }
+      }
+    }
+  ]
+}

+ 11 - 3
.github/workflows/integration.yaml

@@ -48,6 +48,9 @@ jobs:
     needs: lint
     needs: lint
     # Set the type of machine to run on
     # Set the type of machine to run on
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
+    permissions:
+      id-token: write   # required for AWS OIDC
+      contents: read
     strategy:
     strategy:
       fail-fast: false
       fail-fast: false
       matrix:
       matrix:
@@ -74,14 +77,19 @@ jobs:
       - name: Install required packages
       - name: Install required packages
         run: pip install tox
         run: pip install tox
 
 
+      - name: Configure AWS credentials via OIDC
+        if: matrix.cloud-provider == 'aws'
+        uses: aws-actions/configure-aws-credentials@v4
+        with:
+          role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
+          aws-region: us-east-1
+
       - name: Run tox
       - name: Run tox
         id: tox
         id: tox
         run: tox -e py${{ matrix.python-version }}-${{ matrix.cloud-provider }}
         run: tox -e py${{ matrix.python-version }}-${{ matrix.cloud-provider }}
         env:
         env:
           PYTHONUNBUFFERED: "True"
           PYTHONUNBUFFERED: "True"
-          # aws
-          AWS_ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY }}
-          AWS_SECRET_KEY: ${{ secrets.AWS_SECRET_KEY }}
+          # aws — credentials provided by configure-aws-credentials step above (OIDC)
           CB_VM_TYPE_AWS: ${{ secrets.CB_VM_TYPE_AWS }}
           CB_VM_TYPE_AWS: ${{ secrets.CB_VM_TYPE_AWS }}
           # azure
           # azure
           AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
           AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}