Skip to content

Commit 5e0ec0b

Browse files
author
tim.yates1
committed
final tweaks
1 parent 7f2bb64 commit 5e0ec0b

File tree

1 file changed

+13
-7
lines changed

1 file changed

+13
-7
lines changed

_posts/2025-04-03-automated-iam-policy-simulator-testing.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ summary: A quick guide to implementing a test framework for IAM permissions usin
1111
image: tyates/assets/awsiam.png
1212
---
1313

14-
On Scott Logic's DWP Analytics DataOps team, we're sharing a monorepo with another Scott Logic team, and exposing data in S3 for various other teams throughout DWP Analytics in both our and other AWS accounts. There are a lot of moving parts and shared Terraform modules, so we wanted a way to detect and highlight changes in our role and bucket policies (either deliberate or inadvertent) to ensure data access is allowed or denied correctly, and all permission sets are as least-privilege as possible.
14+
On Scott Logic's DWP Analytics DataOps team, we're sharing a monorepo with another Scott Logic team, and exposing data in S3 for various other teams throughout DWP Analytics in both our and other AWS accounts. There are a lot of moving parts and permissions derived from shared Terraform modules, so we wanted a way to detect and highlight changes in our role and bucket policies (either deliberate or inadvertent) to ensure data access is allowed or denied correctly, and all permission sets are as least-privilege as possible.
1515

1616
The AWS IAM policy simulator allows theoretical evaluation of policies to determine if an action will be allowed or denied. It can be useful for ad-hoc testing of a user or role's access to resources such as S3 buckets and objects, but the console UI is clunky (if not downright infuriating) and the API imposes limitations when testing more complex, real-world situations involving both principal and resource policies. With only a small amount of shenanigans, it's possible to leverage the simulator API for more useful testing.
1717

@@ -21,6 +21,10 @@ In the majority of cases where I've used the policy simulator console UI, I've b
2121

2222
Policy simulator API methods are available via the AWS CLI and implementations such as the `boto3` Python package, but there are some limitations. The `simulate principal policy` method seems like it should do what we need by finding the policies of a user or role for us, but it doesn't work with resource policies unless you're testing a user entity as the principal, which I am not.
2323

24+
~~~
25+
An error occurred (InvalidInput) when calling the SimulatePrincipalPolicy operation: Invalid caller - Caller must be an IAM user in this context.
26+
~~~
27+
2428
There are other solutions around providing a friendly implementation for the policy simulator API, but I don't believe any provide the ability to test a role with a resource policy.
2529

2630
## So...
@@ -74,7 +78,7 @@ To start off, I've created a bucket and role with the following basic policies.
7478
],
7579
"Condition": {
7680
"ArnLike": {
77-
"aws:PrincipalArn": "arn:aws:iam:::role/tims-test-role"
81+
"aws:PrincipalArn": "arn:aws:iam::<ACCOUNT ID>:role/tims-test-role"
7882
}
7983
}
8084
}
@@ -165,7 +169,7 @@ class S3PolicyTest:
165169

166170
policies.append(policy["PolicyVersion"]["Document"])
167171

168-
return [json.dumps(policy) for policy in policies]
172+
return policies
169173

170174
def _get_bucket_policy(self) -> list[str]:
171175
"""Get JSON format S3 bucket policy"""
@@ -244,7 +248,7 @@ Slightly truncating the output for clarity, we get:
244248
"SourcePolicyId": "ResourcePolicy",
245249
"SourcePolicyType": "Resource Policy",
246250
"StartPosition": { "Line": 1, "Column": 248 },
247-
"EndPosition": { "Line": 1, "Column": 448 }
251+
"EndPosition": { "Line": 1, "Column": 470 }
248252
},
249253
{
250254
"SourcePolicyId": "PolicyInputList.1",
@@ -257,9 +261,9 @@ Slightly truncating the output for clarity, we get:
257261
]
258262
~~~
259263

260-
We can see that `GetObject` is allowed, and the start and end characters of the statement in the role policy json string that awards the allow are indicated; as we've fetched the policy we can use this information to show the relevant sections to aid in debugging (as you get in the simulator console). `PutObject` is an implicit deny, so there are no matching statements to show here as neither allow or deny policy statements are in effect. `DeleteObject` is explicitly denied, and the matched statements indicate both the deny in the resource policy and the allow in the role policy.
264+
We can see that `GetObject` is allowed, and the start and end characters of the statement in the role policy json string that awards the allow are indicated; as we've fetched the policy we can use this information to show the relevant sections to aid in debugging (as you get in the simulator console). `PutObject` is an implicit deny as neither the role nor bucket policy grant it, so there are no `MatchedStatements` to show as no statements are in effect. `DeleteObject` is explicitly denied, and the matched statements indicate both the `DenyTimDelete` statement in the resource policy, and the allow in the role policy.
261265

262-
If we change the `aws:SecureTransport` context value to `false`, then the `DenyInsecureTransport` section of the bucket policy kicks in and `GetObject` is also now explicitly denied.
266+
If we change the `aws:SecureTransport` context value to `false`, then the `DenyInsecureTransport` statement of the bucket policy kicks in and `GetObject` is now explicitly denied, with the character indexes of this statement indicated.
263267

264268
~~~json
265269
{
@@ -269,7 +273,9 @@ If we change the `aws:SecureTransport` context value to `false`, then the `DenyI
269273
"MatchedStatements": [
270274
{
271275
"SourcePolicyId": "ResourcePolicy",
272-
"SourcePolicyType": "Resource Policy"
276+
"SourcePolicyType": "Resource Policy",
277+
"StartPosition": {"Line": 1, "Column": 38},
278+
"EndPosition": {"Line": 1, "Column": 248}
273279
}
274280
]
275281
}

0 commit comments

Comments
 (0)