Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
policy = analyze_policy_string(
"""{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "s3:listbucket",
"Resource": "arn:aws:s3:::bucket-name",
"Condition": {
"DateGreaterThan" :{"aws:CurrentTime" : "bad"},
"StringEquals": {"s3:prefix":["home/${aws:username}/*"]}
} }}"""
)
assert_false(len(policy.findings) == 0, "First condition is bad")
# Second bad
policy = analyze_policy_string(
"""{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "s3:listbucket",
"Resource": "arn:aws:s3:::bucket-name",
"Condition": {
"DateGreaterThan" :{"aws:CurrentTime" : "2019-07-16T12:00:00Z"},
"StringEquals": {"s3:x":["home/${aws:username}/*"]}
} }}"""
)
assert_false(len(policy.findings) == 0, "Second condition is bad")
def test_analyze_policy_string_no_statement(self):
policy = analyze_policy_string(
"""{
"Version": "2012-10-17" }"""
)
assert_false(len(policy.findings) == 0, "Policy has no Statement")
def test_analyze_policy_string_opposites(self):
# Policy contains Action and NotAction
policy = analyze_policy_string(
"""{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "s3:listallmybuckets",
"NotAction": "s3:listallmybuckets",
"Resource": "*"}}"""
)
assert_false(len(policy.findings) == 0, "Policy contains Action and NotAction")
def test_resource_policy_privilege_escalation_at_bucket_level(self):
policy = analyze_policy_string(
"""{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutBucketPolicy"],
"Resource": ["arn:aws:s3:::bucket", "arn:aws:s3:::bucket/*"]
}}"""
)
assert_false(
len(policy.findings) == 0,
"Resource policy privilege escalation",
)
policy = analyze_policy_string(
"""{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["s3:*Bucket*", "s3:*Object*"],
"Resource": ["arn:aws:s3:::bucket1", "arn:aws:s3:::bucket1/*"]
},
{
"Effect": "Allow",
"Action": ["s3:*Object"],
"Resource": ["arn:aws:s3:::bucket2/*"]
}]}"""
)
print(policy.findings)
# There is one finding for "No resources match for s3:ListAllMyBuckets which requires a resource format of *"
def test_analyze_policy_string_correct_multiple_statements_and_actions(self):
policy = analyze_policy_string(
"""{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "s3:listallmybuckets",
"Resource": "*"},
{
"Effect": "Allow",
"Action": "iam:listusers",
"Resource": "*"}]}"""
)
assert_equal(len(policy.findings), 0)
def test_condition_action_specific(self):
policy = analyze_policy_string(
"""{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "s3:listbucket",
"Resource": "arn:aws:s3:::bucket-name",
"Condition": {"StringEquals": {"s3:prefix":["home/${aws:username}/*"]}} }}"""
)
assert_equal(len(policy.findings), 0)
# The key s3:x-amz-storage-class is not allowed for ListBucket,
# but is for other S3 actions
policy = analyze_policy_string(
"""{
"Version": "2012-10-17",
"Statement": {
"Statement":[
{
"Effect":"Allow",
"Principal":{"AWS":"000000000000"},
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::examplebucket/*"]
}
]
}"""
)
assert_true(
len(policy.findings) == 0,
"S3 bucket policy with one account granted access via ID",
)
policy = analyze_policy_string(
"""{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Principal": { "AWS": "arn:aws:iam::000000000000:user/alice" },
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::examplebucket/*"]
}
]
}"""
)
assert_true(len(policy.findings) == 0, "S3 bucket policy with ARN of user")
policy = analyze_policy_string(
"""{
def test_condition(self):
policy = analyze_policy_string(
"""{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "s3:listbucket",
"Resource": "arn:aws:s3:::bucket-name",
"Condition": {"DateGreaterThan" :{"aws:CurrentTime" : "2019-07-16T12:00:00Z"}} }}"""
)
assert_equal(len(policy.findings), 0)
def test_arn_match(self):
assert_true(is_arn_match("object", "arn:*:s3:::*/*", "arn:*:s3:::*/*"))
assert_true(is_arn_match("object", "*", "arn:*:s3:::*/*"))
assert_true(is_arn_match("object", "arn:*:s3:::*/*", "*"))
assert_true(is_arn_match("object", "arn:*:s3:::*/*", "arn:aws:s3:::*personalize*"))
assert_true(is_arn_match("bucket", "arn:*:s3:::mybucket", "arn:*:s3:::mybucket"))
assert_false(
is_arn_match("bucket", "arn:*:s3:::mybucket", "arn:*:s3:::mybucket/*"),
"Bucket and object types should not match",
)
assert_false(
is_arn_match("object", "arn:*:s3:::*/*", "arn:aws:s3:::examplebucket"),
"Object and bucket types should not match",
)
assert_true(is_arn_match("bucket", "arn:*:s3:::mybucket*", "arn:*:s3:::mybucket2"))
assert_true(is_arn_match("bucket", "arn:*:s3:::*", "arn:*:s3:::mybucket2"))
assert_false(
is_arn_match("object", "arn:*:s3:::*/*", "arn:aws:logs:*:*:/aws/cloudfront/*")
)
assert_false(
is_arn_match("object", "arn:aws:s3:::*/*", "arn:aws:logs:*:*:/aws/cloudfront/*")
)
assert_true(
is_arn_match("cloudfront",
def test_arn_match(self):
assert_true(is_arn_match("object", "arn:*:s3:::*/*", "arn:*:s3:::*/*"))
assert_true(is_arn_match("object", "*", "arn:*:s3:::*/*"))
assert_true(is_arn_match("object", "arn:*:s3:::*/*", "*"))
assert_true(is_arn_match("object", "arn:*:s3:::*/*", "arn:aws:s3:::*personalize*"))
assert_true(is_arn_match("bucket", "arn:*:s3:::mybucket", "arn:*:s3:::mybucket"))
assert_false(
is_arn_match("bucket", "arn:*:s3:::mybucket", "arn:*:s3:::mybucket/*"),
"Bucket and object types should not match",
)
assert_false(
is_arn_match("object", "arn:*:s3:::*/*", "arn:aws:s3:::examplebucket"),
"Object and bucket types should not match",
)
assert_true(is_arn_match("bucket", "arn:*:s3:::mybucket*", "arn:*:s3:::mybucket2"))
assert_true(is_arn_match("bucket", "arn:*:s3:::*", "arn:*:s3:::mybucket2"))
assert_false(
is_arn_match("object", "arn:*:s3:::*/*", "arn:aws:logs:*:*:/aws/cloudfront/*")
)
assert_false(
is_arn_match("object", "arn:aws:s3:::*/*", "arn:aws:logs:*:*:/aws/cloudfront/*")
)
assert_true(
is_arn_match("cloudfront",
"arn:aws:logs:*:*:/aws/cloudfront/*",
"arn:aws:logs:us-east-1:000000000000:/aws/cloudfront/test",
)