Full Report
Let’s explore some common missteps in securing your AWS OIDC.
Analysis Summary
# Best Practices: Securing AWS IAM Role Trust Policies for OIDC Integrations
## Overview
These practices address the critical security risk of misconfiguring IAM role trust policies when integrating third-party SaaS solutions (like GitHub Actions, Terraform Cloud, Gitlab, etc.) using OpenID Connect (OIDC) with AWS accounts. Misconfigurations can allow unintended external actors to assume sensitive IAM roles.
## Key Recommendations
### Immediate Actions
1. **Audit Existing OIDC Trust Policies:** Immediately inventory all IAM roles configured with an OIDC Trusted Entity. Focus specifically on roles allowing external-provider federation.
2. **Verify Required Conditions Exist:** For every OIDC trust policy, verify the presence and correctness of vendor-specific conditions (e.g., `sub`, `aud`, `sts:RoleSessionName`, specific tags). Do not rely solely on basic setup.
3. **Address Missing Critical Conditions:** For all documented OIDC integrations missing *any* required condition (especially `sub` for CI/CD systems or platform-specific identifiers), update the trust policy immediately to restrict access to the intended resource only.
4. **Check for Unrestricted `sub` Usage:** Review any policy using `StringLike` on the `sub` condition for non-specific patterns (e.g., patterns that allow any repo or branch within an entire organization) and tighten the restriction to the specific path required.
### Short-term Improvements (1-3 months)
1. **Enforce Vendor-Specific Conditions:** Systematically review documentation for every integrated vendor (GitHub, Terraform Cloud, Gitlab, Microsoft Defender, DoIT, Teleport, etc.) and ensure the precise conditions documented for that vendor are enforced in the corresponding IAM trust policy (e.g., enforcing `sts:RoleSessionName` for Microsoft Defender integrations).
2. **Standardize the `aud` Claim Check:** For all OIDC providers, ensure the `Audience` (`aud`) condition is explicitly checked, particularly for EKS OIDC providers, where the documented expectation is `aud` equals `sts.amazonaws.com`.
3. **Retire or Remediate Old Configurations:** Identify and update any legacy OIDC trust policies that predate modern AWS restrictions, as newer policies often enforce necessary conditions automatically.
### Long-term Strategy (3+ months)
1. **Implement IP Restriction where Applicable:** Investigate security guidance from vendors like Bitbucket and Buildkite and apply source IP address restrictions to OIDC trust policies where the vendor supports and recommends it, adding an extra layer of defense.
2. **Establish a Policy Review Cadence:** Integrate the review of OIDC trust policy conditions into the standard security configuration baseline review process, scheduled for at least quarterly review, to catch drift as new configurations or vendors are added.
3. **Automate Validation Check:** Develop automated tooling (e.g., using configuration scanning tools or AWS Config rules) to continuously monitor the IAM trust policies against a known-good standard checklist derived from vendor documentation.
## Implementation Guidance
### For Small Organizations
- **Prioritize Critical Vendors:** Focus initial auditing efforts on external CI/CD tools (GitHub Actions, Gitlab) that grant compute privileges.
- **Consult Official Documentation:** Since dedicated security teams may be absent, rely strictly on the latest vendor-provided configuration documentation when updating policies, noting the exact required conditions (`sub`, `aud`, etc.).
- **Use AWS Managed Policies (if applicable):** When setting up new built-in identity providers (Cognito, Google), start with the structure dictated by the AWS documentation unless specific customizations are necessary.
### For Medium Organizations
- **Central Asset Inventory:** Create a centralized, up-to-date inventory mapping each IAM Role/OIDC Provider relationship to its associated SaaS vendor and the required trust policy conditions.
- **Rollout Remediation via IaC:** If using Infrastructure as Code (IaC) (Terraform, CloudFormation) to manage IAM roles, update the source templates to include all mandatory conditions before deploying replacements or updates.
- **Test Assumptions:** For roles where vendor documentation is unclear, assume the strictest requirements (`sub` and `aud`) unless explicitly known otherwise, and conduct targeted testing to confirm functionality before broad enforcement.
### For Large Enterprises
- **Develop Custom Security Standard:** Formalize an internal security standard for OIDC configurations, detailing required conditions for *every* supported vendor integration, going beyond the basic defaults.
- **Leverage Configuration Management Tools:** Implement continuous scanning tools capable of parsing IAM policy JSON and flagging exceptions against the established internal standard.
- **Phased Policy Update:** Roll out trust policy updates under change control, especially for production roles, using a pilot group of non-critical roles first to validate that hardening the conditions does not break automated deployment pipelines.
## Configuration Examples
The following illustrates a **Secure GitHub Actions Trust Policy Snippet** requiring the `sub` condition to restrict access to a specific repository and branch:
json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/github.com/org/repo-name"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.subject": "repo:ORG_NAME/REPO_NAME:ref:refs/heads/main"
}
// NOTE: The missing or incorrect configuration typically occurs here if the 'sub' attribute is omitted or too broad.
}
}
]
}
*Self-Correction Note: The article implies AWS has made it difficult/impossible to create new unconditioned GitHub OIDC policies, but legacy ones must still be vetted.*
## Compliance Alignment
- **NIST SP 800-53:** References to **AC-2 (Account Management)**, **AC-3 (Access Enforcement)**, and **SC-8 (Transmission Confidentiality and Integrity)** when considering secure federation.
- **ISO 27001/27002:** Aligns with requirements for **A.9.2 (Access to applications and systems)** and **A.14.2 (Secure development policy)**, specifically concerning the secure configuration of system interfaces and access controls.
- **CIS AWS Foundations Benchmark:** Directly supports controls related to least privilege access configuration for federated identity.
## Common Pitfalls to Avoid
- **Assuming `sub` is Universal:** Believing that adding the `sub` condition solves all OIDC trust policy issues; different vendors require different or additional conditions (e.g., `sts:RoleSessionName`, vendor-specific tags).
- **Ignoring Built-in Providers:** Overlooking the unique condition requirements for built-in identity providers like Amazon Cognito, Google, and Facebook, which use keys like `oaud` or `app_id`.
- **Trusting Vendor Defaults on New Roles:** Assuming that the AWS console setup wizard automatically provisions the most secure policy, potentially leading to inclusion of only a basic `aud` check or missing customer-specific identifiers.
- **Using Overly Permissive `StringLike`:** Applying `StringLike` on the `sub` condition that matches an entire organization instead of explicitly restricting to a single repository, folder, or branch path when possible.
## Resources
- **AWS IAM Condition Keys Documentation:** For comprehensive reference on available keys for trust policies (defanged: `https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_iam-condition-keys.html`)
- **EKS OIDC Role Association Documentation:** For EKS-specific best practices involving `aud` and `sub` checks (defanged: `https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html`)