Decouple Resource Policies from Their Principals

In attempting to ready all new accounts for provisioning of resources through our CICD pipeline, we needed to create roles that trusted roles in our pipeline account.

However, seeing as my team was creating new accounts before the DevOps team was able to provision the role in the pipeline account that would be assuming into it, we were faced with a common error similar to the one seen here:

If you aren’t familiar with this type of error, it’s due to the creation of a resource policy (a trust policy in this case) that references a principal that doesn’t exist. AWS validates principals before allowing the trust policy to be saved.

To get around this, I moved the principal out of the Principal key entirely. By moving the principal to a Condition, you are able to decouple the resource from the Principal. Another reason this is important is due to a “feature” in AWS whereby the value for the Principal key referenced in the policy is removed and replaced with an Access Key if the resource referenced is deleted. (Similar to the screenshot below.)

Rebuilding the resource referenced in the Principal does not repopulate the policy nor associate itself with the Principal in the policy.

By moving the principal to a Condition value, you further decouple the yet-to-be-created resource from the policy referencing it. The statement below provides a solution to both needing to have the role/resource built prior to the application of the policy, as well as the concern for broken principals when a resource is torn down and rebuilt.

   {
"Sid": "STS",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringLike": {
"aws:PrincipalArn": "arn:aws:iam::*:role/TrustedRole"
}
}
}

By moving to the use of Conditions, you are also able to integrate other AWS Global Condition Keys to gain further flexibility and granularity in these resource policies.

Update:

This approach can be further enhanced to accommodate for multi-account strategies in two distinctly different ways.

The first use case is for a standard named role that exists in multiple accounts that will need to assume into this target entity. Below, the TrustedRole entity exists in accounts 123456789012 and 210987654321 and this policy allows both of them to assume into the entity in which it is attached.

  {
"Sid": "STS",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::123456789012:root",
"arn:aws:iam::210987654321:root"
]
},
"Action": "sts:AssumeRole",
"Condition": {
"StringLike": {
"aws:PrincipalArn": "arn:aws:iam::*:role/TrustedRole"
}
}
}

In the second use case, the assumption of a standard name for the role doesn’t exist, but there is still a need to have multiple principals assume into this target entity. To accomplish this, we can add the set condition operator ForAnyValue in front of the string condition operator StringLike and add the list of accepted roles. Below, TrustedRole and NotSoTrustedRole belonging to different accounts are able to assume into this entity.

   {
"Sid": "STS",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "sts:AssumeRole",
"Condition": {
"ForAnyValue:StringLike": {
"aws:PrincipalArn": [
"arn:aws:iam::123456789012:role/TrustedRole",
"arn:aws:iam::210987654321:role/NotSoTrustedRole",
}
}
}

At the point of saving this policy, AWS will notify you of an Overly Permissive policy. This is a very elementary response from AWS at seeing the wildcard (“*”) in the Principal key. Click Update Anyway.

Again, AWS does its due diligence to protect customers from themselves by displaying a similar message on the Trust Relationship tab of the IAM role.

Keep in mind, this is effectively a false positive — as long as that Condition is in place. I would like to see AWS do a little more analysis before presenting this error, but the potential for actually allowing all entities outweigh the inconvenience of explaining this to uninformed users or auditors. Currently, as long as that wildcard is in the Principal key, this error will present.

Modernizing companies’ AWS security and governance programs at scale.