Security

STS AssumeRole AccessDenied: Cross-Account-Trust-Policies korrekt konfigurieren

2026-05-17 · 8 Min. Lesezeit

Sie richten gerade Cross-Account-Zugriff für Ihre CI/CD-Pipeline ein. Die Deploy-Rolle existiert im Zielkonto, Ihre Pipeline hat den richtigen Rollen-ARN, und trotzdem schlägt jedes Deployment mit dieser Meldung fehl:

An error occurred (AccessDenied) when calling the AssumeRole operation:
User: arn:aws:iam::111111111111:role/pipeline-role is not authorized to perform:
sts:AssumeRole on resource: arn:aws:iam::222222222222:role/deploy-role

Oder manchmal erhalten Sie diese leicht abweichende Variante:

An error occurred (AccessDenied) when calling the AssumeRole operation:
User: arn:aws:sts::111111111111:assumed-role/pipeline-role/session-name is not
authorized to perform: sts:AssumeRole on resource:
arn:aws:iam::222222222222:role/deploy-role with an explicit deny in a
resource-based policy

Der STS-AssumeRole-Fehler ist einer der frustrierendsten in AWS, weil er an der Schnittstelle zweier IAM-Policies in zwei verschiedenen Konten liegt. Beide Seiten müssen übereinstimmen, und die Fehlermeldung verrät nicht, welche Seite die Anfrage ablehnt. Nach meiner Erfahrung in der Beratung von Teams bei Cross-Account-Architekturen verursacht dieser Fehler etwa ein Drittel aller Eskalationen beim erstmaligen Multi-Account-Setup.

So gehen Sie systematisch bei der Diagnose und Behebung vor.

Schritt 1: Identität bestätigen

Bevor Sie irgendetwas anderes tun, überprüfen Sie, wer der Aufrufer tatsächlich ist. Probleme in der Credential-Kette verursachen mehr AssumeRole-Fehler als die meisten vermuten.

aws sts get-caller-identity
{
    "UserId": "AROAEXAMPLEID:session-name",
    "Account": "111111111111",
    "Arn": "arn:aws:sts::111111111111:assumed-role/pipeline-role/session-name"
}

Wenn die Kontonummer oder der ARN nicht dem entspricht, was Sie erwartet haben, verwenden Sie die falschen Anmeldedaten. Prüfen Sie auf veraltete Umgebungsvariablen oder ein falsch konfiguriertes Profil:

aws configure list
env | grep AWS_

Ein abgelaufenes AWS_SESSION_TOKEN in Ihrer Umgebung überschreibt Ihr Profil und verursacht verwirrende Fehler. Entfernen Sie es mit unset AWS_SESSION_TOKEN falls nötig.

Schritt 2: Den AssumeRole-Aufruf testen

Führen Sie den assume-role-Aufruf explizit über die CLI aus, damit Sie den genauen Fehler sehen:

aws sts assume-role \
  --role-arn arn:aws:iam::222222222222:role/deploy-role \
  --role-session-name test-session \
  --duration-seconds 900

Wenn eine External ID erforderlich ist, fügen Sie sie hinzu:

aws sts assume-role \
  --role-arn arn:aws:iam::222222222222:role/deploy-role \
  --role-session-name test-session \
  --external-id my-external-id-123 \
  --duration-seconds 900

Wenn der Aufruf erfolgreich ist, liegt das Problem in Ihrem Anwendungscode oder der Pipeline-Konfiguration. Wenn er fehlschlägt, fahren Sie mit der Diagnose fort.

Ursache 1: Trust Policy erlaubt den aufrufenden Principal nicht

Dies ist die häufigste Ursache. Die Trust Policy der Zielrolle muss den aufrufenden Principal explizit aufführen. Hier ein typischer Fehler — die Trust Policy erlaubt einen bestimmten IAM-Benutzer, aber der Aufrufer ist tatsächlich eine IAM-Rolle:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:user/deploy-user"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Wenn Ihr Aufrufer arn:aws:iam::111111111111:role/pipeline-role ist, wird diese Trust Policy die Anfrage ablehnen. Korrigieren Sie es, indem Sie den richtigen Principal angeben:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:role/pipeline-role"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Um die aktuelle Trust Policy einzusehen:

aws iam get-role \
  --role-name deploy-role \
  --query 'Role.AssumeRolePolicyDocument' \
  --output json \
  --profile target-account

Sie können auch dem gesamten Konto erlauben, die Rolle anzunehmen, und den Zugriff dann auf der Aufruferseite kontrollieren:

{
  "Version": "2012-10-17",
  "Principal": {
    "AWS": "arn:aws:iam::111111111111:root"
  },
  "Action": "sts:AssumeRole"
}

Dies ist ein valider Ansatz, bedeutet aber, dass jeder Principal in Konto 111111111111 mit sts:AssumeRole-Berechtigung diese Rolle annehmen kann. Verwenden Sie dies, wenn Sie die Kontrolle zentral im Quellkonto verwalten möchten.

Ursache 2: Aufrufer hat keine sts:AssumeRole-Berechtigung

Beide Seiten müssen übereinstimmen. Selbst wenn die Trust Policy Ihren Principal erlaubt, braucht der Aufrufer zusätzlich eine IAM-Policy, die sts:AssumeRole auf den Zielrollen-ARN gewährt. Prüfen Sie die Policies des Aufrufers:

aws iam list-attached-role-policies --role-name pipeline-role
aws iam list-role-policies --role-name pipeline-role

Dann inspizieren Sie jede Policy:

aws iam get-role-policy \
  --role-name pipeline-role \
  --policy-name AssumeRolePolicy

Der Aufrufer benötigt mindestens:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "arn:aws:iam::222222222222:role/deploy-role"
    }
  ]
}

Ein häufiger Fehler ist die Einschränkung der Resource auf den falschen ARN oder die Verwendung eines Wildcards, der nicht passt. Wenn Sie arn:aws:iam::222222222222:role/deploy-* verwenden, stellen Sie sicher, dass der Rollenname tatsächlich mit deploy- beginnt.

Ursache 3: ExternalId-Mismatch

Wenn eine Trust Policy eine External ID voraussetzt, führt das Weglassen oder die Angabe des falschen Werts zu AccessDenied. Dies ist der Mechanismus zur Vermeidung des Confused-Deputy-Problems und wird hauptsächlich beim Zugriff durch Drittanbieter verwendet.

Die Trust Policy sieht so aus:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "unique-external-id-abc123"
        }
      }
    }
  ]
}

Wenn Sie --external-id unique-external-id-abc123 nicht in Ihrem AssumeRole-Aufruf angeben, schlägt er fehl. Die Fehlermeldung gibt keinen Hinweis darauf, dass eine External ID erwartet wurde — es steht einfach nur AccessDenied.

Um zu prüfen, ob die Trust Policy eine External ID erfordert:

aws iam get-role \
  --role-name deploy-role \
  --query 'Role.AssumeRolePolicyDocument.Statement[*].Condition' \
  --profile target-account

Ursache 4: MFA erforderlich, aber nicht bereitgestellt

Trust Policies können MFA für zusätzliche Sicherheit verlangen. Dies ist üblich bei sensiblen Rollen wie Produktions-Admin-Zugang:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:user/admin-user"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "true"
        }
      }
    }
  ]
}

Um eine Rolle mit MFA anzunehmen, müssen Sie die MFA-Seriennummer und einen aktuellen Token-Code angeben:

aws sts assume-role \
  --role-arn arn:aws:iam::222222222222:role/admin-role \
  --role-session-name admin-session \
  --serial-number arn:aws:iam::111111111111:mfa/admin-user \
  --token-code 123456

Beachten Sie, dass Service-Rollen, Lambda-Ausführungsrollen und EC2-Instance-Profile keine MFA-Bedingungen erfüllen können. Wenn Ihre Trust Policy MFA erfordert, aber der Aufrufer ein Service ist, schlägt der Aufruf immer fehl.

Ursache 5: Dauer-Limit bei Role Chaining

Wenn Sie Rolle A annehmen und dann diese Credentials verwenden, um Rolle B anzunehmen, ist das Role Chaining. AWS erzwingt ein hartes Limit von einer Stunde für verkettete Rollensitzungen, unabhängig von den angeforderten --duration-seconds.

# Erste Annahme: funktioniert mit bis zu 12 Stunden
aws sts assume-role \
  --role-arn arn:aws:iam::222222222222:role/intermediate-role \
  --role-session-name hop1 \
  --duration-seconds 3600

# Zweite Annahme mit hop1-Credentials: maximal 1 Stunde
aws sts assume-role \
  --role-arn arn:aws:iam::333333333333:role/final-role \
  --role-session-name hop2 \
  --duration-seconds 3600

Wenn Sie bei einer verketteten Sitzung eine Dauer über 3600 Sekunden anfordern, schlägt der Aufruf fehl. Die Lösung ist entweder, Verkettung zu vermeiden oder sicherzustellen, dass die angeforderte Dauer innerhalb der Grenzen liegt.

Prüfen Sie auch die maximale Sitzungsdauer der Rolle:

aws iam get-role \
  --role-name deploy-role \
  --query 'Role.MaxSessionDuration'

Wenn Sie 3600 Sekunden anfordern, aber das Maximum der Rolle auf 900 Sekunden eingestellt ist, schlägt der Aufruf fehl. Aktualisieren Sie es bei Bedarf:

aws iam update-role \
  --role-name deploy-role \
  --max-session-duration 3600

Ursache 6: Restriktive Condition Keys in der Trust Policy

Organisationen fügen Trust Policies oft Condition Keys für erhöhte Sicherheit hinzu. Diese Bedingungen verweigern den Zugriff stillschweigend, wenn sie nicht erfüllt sind:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:PrincipalOrgID": "o-abc123def4"
        },
        "ArnLike": {
          "aws:PrincipalArn": "arn:aws:iam::*:role/pipeline-*"
        }
      }
    }
  ]
}

Diese Trust Policy erlaubt jede Rolle mit dem Muster pipeline-* aus jedem Konto in der Organisation o-abc123def4. Wenn Ihre aufrufende Rolle deploy-role statt pipeline-deploy heißt, wird sie abgelehnt.

Prüfen Sie Ihre Organisations-ID:

aws organizations describe-organization \
  --query 'Organization.Id'

Und verifizieren Sie, dass der ARN des Aufrufers mit allen ArnLike- oder StringLike-Bedingungen übereinstimmt.

Ursache 7: SCPs oder Permission Boundaries blockieren sts:AssumeRole

Service Control Policies (SCPs) auf Organisationsebene können sts:AssumeRole einschränken, selbst wenn die IAM-Policies korrekt sind. Wenn Ihre Organisation eine SCP hat, die Cross-Account-Zugriff außer für genehmigte Rollen verweigert, schlägt der Aufruf mit AccessDenied fehl.

Ebenso gilt: Wenn die aufrufende Rolle eine Permissions Boundary hat, muss diese Boundary ebenfalls sts:AssumeRole erlauben.

Um die Permissions Boundary zu prüfen:

aws iam get-role \
  --role-name pipeline-role \
  --query 'Role.PermissionsBoundary'

SCPs sind ohne Organisations-Admin-Zugriff schwerer einzusehen:

aws organizations list-policies \
  --filter SERVICE_CONTROL_POLICY \
  --profile org-admin

Prävention und Best Practices

Nachdem Sie das unmittelbare Problem behoben haben, setzen Sie diese Praktiken um, um zukünftige AssumeRole-Fehler zu vermeiden:

Verwenden Sie aws:PrincipalOrgID statt Konto-IDs. Dies erlaubt jedem Konto in Ihrer Organisation den Zugriff, ohne eine Liste von Kontonummern pflegen zu müssen:

{
  "Condition": {
    "StringEquals": {
      "aws:PrincipalOrgID": "o-abc123def4"
    }
  }
}

Verwenden Sie immer ExternalId für Drittanbieter-Zugriff. Überspringen Sie diesen Schritt nie, wenn ein Anbieter Sie bittet, eine Cross-Account-Rolle zu erstellen. Es verhindert den Confused-Deputy-Angriff.

Testen Sie Cross-Account-Zugriff in der CI, bevor Sie sich darauf verlassen. Fügen Sie Ihrer Pipeline einen Schritt hinzu, der aws sts assume-role ausführt und das Ergebnis verifiziert, bevor zum Deployment übergegangen wird.

Nutzen Sie IAM Access Analyzer zur Validierung von Trust Policies. Access Analyzer markiert zu permissive Trust Policies und identifiziert externen Zugriff:

aws accessanalyzer list-findings \
  --analyzer-arn arn:aws:access-analyzer:us-east-1:222222222222:analyzer/my-analyzer \
  --filter '{"resourceType": {"eq": ["AWS::IAM::Role"]}}'

Dokumentieren Sie Rollenketten. Wenn Ihre Architektur Role Chaining erfordert (Hub-and-Spoke-Zugriffsmuster), dokumentieren Sie die Kette und stellen Sie sicher, dass kein Hop mehr als eine Stunde benötigt.

Vermeiden Sie Wildcard-Principals in Trust Policies. Die Verwendung von "AWS": "*" im Principal ohne Bedingungen erlaubt jedem AWS-Konto, die Rolle anzunehmen. Kombinieren Sie es immer mit aws:PrincipalOrgID oder einer spezifischen Konto-Bedingung.

Wann Sie Hilfe holen sollten

Wenn Sie alle oben genannten Punkte überprüft haben und der Fehler weiterhin besteht, kann die Ursache eine Race Condition bei der Rollenerstellung sein (Eventual Consistency bedeutet, dass eine neu erstellte Rolle für einige Sekunden möglicherweise nicht annehmbar ist), ein cross-regionaler STS-Endpoint-Fehler oder eine komplexe SCP-Interaktion, die ohne Sichtbarkeit auf Organisationsebene schwer nachzuvollziehen ist.

Wir helfen Teams regelmäßig bei Design und Debugging von Cross-Account-Zugriffsarchitekturen. Wenn Ihr Multi-Account-Setup Deployments blockiert oder Sie eine Sicherheitsüberprüfung Ihrer Trust Policies wünschen, kontaktieren Sie uns für eine kostenlose Beratung. Wir kartieren Ihre Rollen-Trust-Kette und identifizieren jede Lücke.

Brauchen Sie Hilfe mit Ihrer AWS-Infrastruktur?

Buchen Sie ein kostenloses 30-Minuten-Gespräch.