GitHub ActionsAWSOIDCCI/CDSecurityIAMTerraformSAM

Von GitHub Actions mit OIDC-Authentifizierung auf AWS deployen

Sloth255
Sloth255
·3 min read·675 words

Einführung

Beim Deployen auf AWS-Ressourcen von GitHub Actions war der traditionelle Ansatz das Speichern von IAM-Benutzer-Zugriffsschlüsseln in GitHub Secrets. Diese Methode hat jedoch mehrere Herausforderungen:

  • Risiko des Zugriffsschlüssel-Lecks
  • Regelmäßige Rotationsarbeiten erforderlich
  • Zunahme zu verwaltender Secrets

OIDC (OpenID Connect)-Authentifizierung löst diese Herausforderungen. Dieser Artikel erklärt detailliert, wie die OIDC-Integration zwischen GitHub Actions und AWS eingerichtet wird.

Was ist OIDC?

OIDC ist ein Authentifizierungsprotokoll basierend auf OAuth 2.0. GitHub Actions gibt ein Token aus, das „Ich bin ein Workflow aus diesem Repository" gegenüber AWS beweisen kann, und AWS verifiziert es und stellt temporäre Credentials bereit.

Vorteile von OIDC

  • Keine Secrets erforderlich: Keine Notwendigkeit, Zugriffsschlüssel in GitHub zu speichern
  • Verbesserte Sicherheit: Verwendet nur temporäre Credentials
  • Feinkörnige Berechtigungskontrolle: Berechtigungen können nach Repository oder Branch eingeschränkt werden
  • Reduzierte Verwaltungskosten: Keine Schlüsselrotation erforderlich

AWS-Konfiguration

1. IAM Identity Provider erstellen

Erstellen Sie zunächst einen IAM Identity Provider in der AWS Management Console.

  1. IAM-Konsole öffnen
  2. „Identity providers" → „Add provider" klicken
  3. Folgende Informationen eingeben:
Provider type: OpenID Connect
Provider URL: https://token.actions.githubusercontent.com
Audience: sts.amazonaws.com

Beispiel mit Terraform

resource "aws_iam_openid_connect_provider" "github_actions" {
  url = "https://token.actions.githubusercontent.com"

  client_id_list = [
    "sts.amazonaws.com",
  ]

  thumbprint_list = [
    "6938fd4d98bab03faadb97b34396831e3780aea1"
  ]
}

Beispiel mit AWS SAM

template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: GitHub Actions OIDC Provider

Resources:
  GitHubOIDCProvider:
    Type: AWS::IAM::OIDCProvider
    Properties:
      Url: https://token.actions.githubusercontent.com
      ClientIdList:
        - sts.amazonaws.com
      ThumbprintList:
        - 6938fd4d98bab03faadb97b34396831e3780aea1

2. IAM-Rolle erstellen

Erstellen Sie als nächstes eine IAM-Rolle, die GitHub Actions übernehmen wird.

Trust Policy konfigurieren

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::123456789012: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:your-org/your-repo:*"
        }
      }
    }
  ]
}

Bedingungsdetails

Der Zugriff kann mit dem Wert token.actions.githubusercontent.com:sub eingeschränkt werden.

# Gesamtes spezifisches Repository
repo:your-org/your-repo:*

# Nur spezifischer Branch
repo:your-org/your-repo:ref:refs/heads/main

# Nur spezifische Umgebung
repo:your-org/your-repo:environment:production

# Nur Pull Requests
repo:your-org/your-repo:pull_request

Beispiel mit Terraform

data "aws_iam_policy_document" "github_actions_assume_role" {
  statement {
    actions = ["sts:AssumeRoleWithWebIdentity"]

    principals {
      type        = "Federated"
      identifiers = [aws_iam_openid_connect_provider.github_actions.arn]
    }

    condition {
      test     = "StringEquals"
      variable = "token.actions.githubusercontent.com:aud"
      values   = ["sts.amazonaws.com"]
    }

    condition {
      test     = "StringLike"
      variable = "token.actions.githubusercontent.com:sub"
      values   = ["repo:your-org/your-repo:*"]
    }
  }
}

resource "aws_iam_role" "github_actions" {
  name               = "github-actions-deploy-role"
  assume_role_policy = data.aws_iam_policy_document.github_actions_assume_role.json
}

# Erforderliche Berechtigungsrichtlinien anhängen
resource "aws_iam_role_policy_attachment" "deploy_policy" {
  role       = aws_iam_role.github_actions.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonECS_FullAccess"
}

Beispiel mit AWS SAM

template.yaml
Resources:
  GitHubActionsRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: github-actions-deploy-role
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Federated: !GetAtt GitHubOIDCProvider.Arn
            Action: sts:AssumeRoleWithWebIdentity
            Condition:
              StringEquals:
                token.actions.githubusercontent.com:aud: sts.amazonaws.com
              StringLike:
                token.actions.githubusercontent.com:sub: repo:your-org/your-repo:*
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonECS_FullAccess

Outputs:
  GitHubActionsRoleArn:
    Description: ARN der GitHub Actions IAM-Rolle
    Value: !GetAtt GitHubActionsRole.Arn
    Export:
      Name: GitHubActionsRoleArn

Mit SAM deployen:

sam build
sam deploy --guided

Nach dem ersten Deployment die ausgegebene Rollen-ARN in GitHub Secrets als AWS_ROLE_ARN registrieren.

3. Berechtigungsrichtlinien anhängen

Hängen Sie die für das Deployment notwendigen Berechtigungen an die Rolle an. Zum Beispiel:

  • Für S3-Deployment: AmazonS3FullAccess
  • Für ECS-Deployment: AmazonECS_FullAccess
  • Für Lambda: AWSLambda_FullAccess

Für Produktionsumgebungen empfehlen wir die Erstellung benutzerdefinierter Richtlinien nach dem Prinzip der geringsten Berechtigung.

GitHub Actions-Konfiguration

Workflow-Datei erstellen

.github/workflows/deploy.yml erstellen.

name: Deploy to AWS

on:
  push:
    branches:
      - main

# Berechtigungseinstellungen zum Abrufen des OIDC-Tokens (Wichtig!)
permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/github-actions-deploy-role
          aws-region: ap-northeast-1

      - name: Deploy to S3
        run: |
          aws s3 sync ./dist s3://your-bucket-name --delete

      - name: Verify deployment
        run: |
          aws s3 ls s3://your-bucket-name

Wichtige Punkte

1. permissions-Konfiguration

permissions:
  id-token: write  # Zum Abrufen des OIDC-Tokens erforderlich
  contents: read   # Zum Auschecken des Repositorys erforderlich

Ohne diese Einstellung kann das OIDC-Token nicht abgerufen werden und es tritt ein Fehler auf.

2. configure-aws-credentials-Aktionsversion

Verwenden Sie v4 oder später. Ältere Versionen unterstützen möglicherweise kein OIDC.

uses: aws-actions/configure-aws-credentials@v4

Praktisches Beispiel: SAM-Anwendung deployen

Hier ist ein Beispiel für das Deployen einer serverlosen Anwendung mit AWS SAM.

name: Deploy SAM Application

on:
  push:
    branches:
      - main

permissions:
  id-token: write
  contents: read

env:
  AWS_REGION: ap-northeast-1
  SAM_STACK_NAME: my-sam-app

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Setup SAM CLI
        uses: aws-actions/setup-sam@v2
        with:
          use-installer: true

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
          aws-region: ${{ env.AWS_REGION }}

      - name: SAM Build
        run: sam build --use-container

      - name: SAM Deploy
        run: |
          sam deploy \
            --stack-name ${{ env.SAM_STACK_NAME }} \
            --capabilities CAPABILITY_IAM \
            --resolve-s3 \
            --no-fail-on-empty-changeset \
            --no-confirm-changeset

      - name: Get Stack Outputs
        run: |
          aws cloudformation describe-stacks \
            --stack-name ${{ env.SAM_STACK_NAME }} \
            --query 'Stacks[0].Outputs' \
            --output table

Fehlerbehebung

Fehler: „Not authorized to perform sts:AssumeRoleWithWebIdentity"

Ursache: Trust-Policy-Bedingungen stimmen nicht überein

Lösung:

  1. Den token.actions.githubusercontent.com:sub-Wert in der Trust Policy der IAM-Rolle überprüfen
  2. Repository-Namen und Branch-Namen prüfen
  3. Den tatsächlichen sub-Claim-Wert in den GitHub Actions-Logs prüfen
- name: Debug OIDC token
  run: |
    curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
      "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=sts.amazonaws.com" | \
      jq -R 'split(".") | .[1] | @base64d | fromjson'

Fehler: „Error: Credentials could not be loaded"

Ursache: Fehlende permissions-Konfiguration

Lösung: Folgendes zur Workflow-Datei hinzufügen

permissions:
  id-token: write
  contents: read

Authentifizierung erfolgreich, aber Berechtigungsfehler

Ursache: Erforderliche Berechtigungsrichtlinien sind nicht an die IAM-Rolle angehängt

Lösung: Geeignete Richtlinien an die IAM-Rolle anhängen

aws iam attach-role-policy \
  --role-name github-actions-deploy-role \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess

Sicherheits-Best-Practices

1. Prinzip der geringsten Berechtigung

Nur die minimal notwendigen Berechtigungen gewähren.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::your-specific-bucket",
        "arn:aws:s3:::your-specific-bucket/*"
      ]
    }
  ]
}

2. Nach Branch oder Tag einschränken

Produktions-Deployments auf spezifische Branches beschränken.

{
  "Condition": {
    "StringEquals": {
      "token.actions.githubusercontent.com:sub": "repo:your-org/your-repo:ref:refs/heads/main"
    }
  }
}

3. Rollen nach Umgebung trennen

Unterschiedliche Rollen für Entwicklung, Staging und Produktion verwenden.

- name: Configure AWS credentials (Production)
  if: github.ref == 'refs/heads/main'
  uses: aws-actions/configure-aws-credentials@v4
  with:
    role-to-assume: ${{ secrets.AWS_ROLE_ARN_PROD }}
    aws-region: ap-northeast-1

- name: Configure AWS credentials (Development)
  if: github.ref == 'refs/heads/develop'
  uses: aws-actions/configure-aws-credentials@v4
  with:
    role-to-assume: ${{ secrets.AWS_ROLE_ARN_DEV }}
    aws-region: ap-northeast-1

4. Mit CloudTrail auditieren

Alle API-Aufrufe aufzeichnen und regelmäßig überprüfen.

Fazit

Die OIDC-Integration zwischen GitHub Actions und AWS bietet folgende Vorteile:

  • Sicheres Deployment ohne Zugriffsschlüssel
  • Verwendet nur temporäre Credentials
  • Feinkörnige Berechtigungskontrolle nach Repository oder Branch
  • Reduzierte Verwaltungskosten

Obwohl die anfängliche Einrichtung etwas komplex ist, führt sie nach der Konfiguration zu langfristigen Verbesserungen in Sicherheit und Betriebsfähigkeit. Ich empfehle dringend, ihre Einführung zu erwägen.

Referenzen