Skip to content

Commit

Permalink
Github Actions OIDC IAM Role Trust Relation
Browse files Browse the repository at this point in the history
  • Loading branch information
bcpenta authored and bcpenta committed Dec 19, 2024
1 parent 188b9bc commit 2d143c0
Show file tree
Hide file tree
Showing 2 changed files with 239 additions and 0 deletions.
37 changes: 37 additions & 0 deletions policies/aws_iam_policies/aws_iam_role_github_actions_trust.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
def policy(resource):
assume_role_policy = resource.get("AssumeRolePolicyDocument", {}).get("Statement", [])

# Iterate through each statement in the trust policy
for statement in assume_role_policy:
# Check if the statement allows sts:AssumeRoleWithWebIdentity
if statement.get("Effect") == "Allow" and "sts:AssumeRoleWithWebIdentity" in statement.get("Action", []):
# Validate the Principal
principal = statement.get("Principal", {}).get("Federated")
if not principal:
return False # Invalid Principal
if principal == "*":
return False # Wildcard in Principal is insecure
if "oidc-provider/token.actions.githubusercontent.com" not in principal:
continue # Skip non-GitHub-related Principals

# Validate the conditions only if the Principal is valid for GitHub Actions
conditions = statement.get("Condition", {})

# Check if the aud is correctly set
audience = conditions.get("StringEquals", {}).get("token.actions.githubusercontent.com:aud")
if audience != "sts.amazonaws.com":
return False

# Check if the sub is properly restricted
subject = conditions.get("StringLike", {}).get("token.actions.githubusercontent.com:sub", "") or \
conditions.get("StringEquals", {}).get("token.actions.githubusercontent.com:sub", "")

if not subject.startswith("repo:"):
return False # Ensure sub references a repository

if "*" in subject and not subject.startswith("repo:org/repo:*"):
return False # Disallow overly permissive wildcards

return True # Valid GitHub Actions config

return False # No valid statements found
202 changes: 202 additions & 0 deletions policies/aws_iam_policies/aws_iam_role_github_actions_trust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
AnalysisType: policy
Filename: aws_iam_role_github_actions_trust.py
PolicyID: "AWS.IAM.Role.GitHubActionsTrust"
DisplayName: "AWS IAM Role Trust Relationship for GitHub Actions"
Enabled: true
ResourceTypes:
- AWS.IAM.Role
Tags:
- AWS
- GitHub Actions
- Identity & Access Management
Severity: High
Description: >
This policy ensures that IAM roles used with GitHub Actions are securely configured to prevent unauthorized access to AWS resources.
It validates trust relationships by checking for proper audience (aud) restrictions, ensuring it is set to sts.amazonaws.com, and subject (sub) conditions,
confirming they are scoped to specific repositories or environments. Misconfigurations, such as overly permissive wildcards or missing conditions,
can allow unauthorized repositories to assume roles, leading to potential data breaches or compliance violations.
By enforcing these checks, the policy mitigates risks of exploitation, enhances security posture, and protects critical AWS resources from external threats.
Runbook: >
To fix roles flagged by this policy:
1. Update the trust relationship of the flagged IAM role in the AWS Management Console or CLI.
2. Add a Condition block with 'StringLike' or 'StringEquals' for 'token.actions.githubusercontent.com:sub'.
3. Ensure the audience is set to 'sts.amazonaws.com'.
4. Avoid overly permissive wildcards in the sub condition.
Reference: >
- https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-idp_oidc.html
- https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-cloud-providers
- https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services
Tests:
- Name: Valid GitHub Actions Trust Relationship
ExpectedResult: true
Resource:
{
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRoleWithWebIdentity",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
},
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:org/repo:*"
}
}
}
]
}
}

- Name: Missing Audience Condition
ExpectedResult: false
Resource:
{
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRoleWithWebIdentity",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
},
"Condition": {
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:org/repo:*"
}
}
}
]
}
}

- Name: Missing Subject Restriction
ExpectedResult: false
Resource:
{
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRoleWithWebIdentity",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
},
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
}
}
}
]
}
}

- Name: Overly Permissive Wildcard in Subject
ExpectedResult: false
Resource:
{
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRoleWithWebIdentity",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
},
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "*"
}
}
}
]
}
}

- Name: Valid Subject Restriction with Specific Environment
ExpectedResult: true
Resource:
{
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRoleWithWebIdentity",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
},
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub": "repo:org/repo:environment:prod"
}
}
}
]
}
}

- Name: Invalid Principal as Wildcard
ExpectedResult: false
Resource:
{
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRoleWithWebIdentity",
"Principal": {
"Federated": "*"
},
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:org/repo:*"
}
}
}
]
}
}

- Name: Non-GitHub OIDC Principal
ExpectedResult: false
Resource:
{
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRoleWithWebIdentity",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/accounts.google.com"
},
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:org/repo:*"
}
}
}
]
}
}

0 comments on commit 2d143c0

Please sign in to comment.