def test_click_crud_case_4(self): """write_policy: using 4-wildcard-only-bulk-selection.yml""" template_file = os.path.join(test_file_directory, "crud-cases", "4-wildcard-only-bulk-selection.yml") result = self.runner.invoke(write_policy, ["--input-file", template_file]) result_json = json.loads(result.output) self.assertListEqual(get_sid_names_from_policy(result_json), ["MultMultNone"]) self.assertTrue(result.exit_code == 0)
def test_click_crud_case_2(self): """write_policy: using 2-skip-resource-constraints.yml""" template_file = os.path.join(test_file_directory, "crud-cases", "2-skip-resource-constraints.yml") result = self.runner.invoke(write_policy, ["--input-file", template_file]) result_json = json.loads(result.output) self.assertListEqual(get_sid_names_from_policy(result_json), ["SkipResourceConstraints"]) self.assertTrue(result.exit_code == 0)
def test_click_crud_case_1(self): """write_policy: using 1-ssm-read.yml""" template_file = os.path.join(test_file_directory, "crud-cases", "1-ssm-read.yml") result = self.runner.invoke(write_policy, ["--input-file", template_file]) result_json = json.loads(result.output) self.assertListEqual(get_sid_names_from_policy(result_json), ["SsmReadParameter"]) self.assertTrue(result.exit_code == 0)
def test_minimize_rw_same(self): cfg = { "mode": "crud", "name": "", "read": [ "arn:aws:ssm:us-east-1:123456789012:parameter/myparameter", "arn:aws:ssm:us-east-1:123456789012:parameter/myparameter2" ], "write": [ "arn:aws:ssm:us-east-1:123456789012:parameter/myparameter", "arn:aws:ssm:us-east-1:123456789012:parameter/myparameter2" ] } sid_grp = SidGroup() write_format = sid_grp.process_template(cfg, minimize=1) # print(json.dumps(write_format, indent=4)) """ the output will look like: { "Version": "2012-10-17", "Statement": [ { "Sid": "SsmParameterMyparameter", "Effect": "Allow", "Action": [ "ssm:getpar*", "ssm:deletepar*", "ssm:la*", "ssm:putp*" ], "Resource": [ "arn:aws:ssm:us-east-1:123456789012:parameter/myparameter", "arn:aws:ssm:us-east-1:123456789012:parameter/myparameter2" ] } ] } """ # To future-proof this unit test... # (1) check that there is only one SID so it was combined during minimization sid_names = get_sid_names_from_policy(write_format) self.assertEqual(len(sid_names), 1, "More than one statement returned, expected 1") # (2) Check for the presence of certain actions that we know will be there expected_action = [ 'ssm:getpar*', 'ssm:deletepar*', 'ssm:la*', 'ssm:putp*' ] self.assertEqual(write_format['Statement'][0]['Action'], expected_action, "extra actions are returned") self.assertEqual(write_format['Statement'][0]['Resource'], cfg['read'], "Wrong resources were returned")
def test_minimize_arn_case_7(self): """minimization test with ARN types from test_does_arn_match_case_1""" cfg = { "mode": "crud", "read": ["arn:aws:greengrass:${Region}:${Account}:/greengrass/definition/devices/1234567/versions/1"], "write": ["arn:aws:greengrass:${Region}:${Account}:/greengrass/definition/devices/1234567/versions/1"] } sid_group = SidGroup() results = sid_group.process_template(cfg, minimize=0) sid_names = get_sid_names_from_policy(results) self.assertEqual(len(sid_names), 1, "More than one statement returned, expected 1")
def test_minimize_arn_case_6(self): """minimization test with ARN types from test_does_arn_match_case_1""" cfg = { "mode": "crud", "read": ["arn:aws:states:region:account-id:execution:stateMachineName:executionName"], "write": ["arn:aws:states:region:account-id:execution:stateMachineName:executionName"] } sid_group = SidGroup() results = sid_group.process_template(cfg, minimize=0) sid_names = get_sid_names_from_policy(results) self.assertEqual(len(sid_names), 1, "More than one statement returned, expected 1")
def test_minimize_arn_case_3(self): """minimization test with ARN types from test_does_arn_match_case_1""" cfg = { "mode": "crud", "read": ["arn:aws:kinesis:us-east-1:account-id:firehose/myfirehose/consumer/someconsumer:${ConsumerCreationTimpstamp}"], "write": ["arn:aws:kinesis:us-east-1:account-id:firehose/myfirehose/consumer/someconsumer:${ConsumerCreationTimpstamp}"] } sid_group = SidGroup() results = sid_group.process_template(cfg, minimize=0) sid_names = get_sid_names_from_policy(results) self.assertEqual(len(sid_names), 1, "More than one statement returned, expected 1")
def test_minimize_arn_case_1(self): """minimization test with ARN types from test_does_arn_match_case_1""" cfg = { "mode": "crud", "read": ["arn:aws:codecommit:us-east-1:123456789012:MyDemoRepo"], "write": ["arn:aws:codecommit:us-east-1:123456789012:MyDemoRepo"] } sid_group = SidGroup() results = sid_group.process_template(cfg, minimize=0) sid_names = get_sid_names_from_policy(results) self.assertEqual(len(sid_names), 1, "More than one statement returned, expected 1")
def test_write_iam_policy(self): payload = { "name": "test", "actions_for_resources_at_access_level": { "read": ["arn:aws:s3:::mybucket/*"] } } response = client.post("/write-iam-policy", json.dumps(payload)) print(response.json()) self.assertTrue(response.status_code == 200) results = response.json() self.assertListEqual(get_sid_names_from_policy(results), ["S3ReadObject"])
def test_minimize_arn_case_bucket(self): cfg = { "mode": "crud", "read": ["arn:aws:s3:::bucket_name"], "write": ["arn:aws:s3:::bucket_name"] } sid_group = SidGroup() results = sid_group.process_template(cfg, minimize=0) # print(json.dumps(results, indent=4)) # To future-proof this unit test... # (1) check that there is only one SID so it was combined during minimization sid_names = get_sid_names_from_policy(results) # For S3, it does require iam:PassRole lol because of s3:PutReplicationConfiguration requiring it as an action self.assertEqual(len(sid_names), 2, "More than 2 statements returned, expected 2")
def test_minimize_rw_same_one(self): cfg = { "mode": "crud", "name": "", "read": [ "arn:aws:ssm:us-east-1:123456789012:parameter/myparameter", ], "write": [ "arn:aws:ssm:us-east-1:123456789012:parameter/myparameter", ] } sid_grp = SidGroup() write_format = sid_grp.process_template(cfg, minimize=0) """ Expected result: { "Version": "2012-10-17", "Statement": [ { "Sid": "SsmMultParametermyparameter", "Effect": "Allow", "Action": [ "ssm:getpar*", "ssm:deletepar*", "ssm:la*", "ssm:putp*" ], "Resource": [ "arn:aws:ssm:us-east-1:123456789012:parameter/myparameter" ] } ] } """ # To future-proof this unit test... # (1) check that there is only one SID so it was combined during minimization sid_names = get_sid_names_from_policy(write_format) self.assertEqual(len(sid_names), 1, "More than one statement returned, expected 1")
def test_get_sid_names_from_policy(self): """util.policy_files.get_sid_names_from_policy""" policy_json = { "Version": "2012-10-17", "Statement": [ { "Sid": "MultMultNone", "Effect": "Allow", "Action": [ "ram:EnableSharingWithAwsOrganization", "ram:GetResourcePolicies", "ecr:GetAuthorizationToken", "s3:GetAccessPoint", "s3:GetAccountPublicAccessBlock", "s3:ListAccessPoints" ], "Resource": [ "*" ] }, { "Sid": "S3PermissionsmanagementBucket", "Effect": "Allow", "Action": [ "s3:DeleteBucketPolicy", "s3:PutBucketAcl", "s3:PutBucketPolicy", "s3:PutBucketPublicAccessBlock" ], "Resource": [ "arn:aws:s3:::example-org-s3-access-logs" ] } ] } expected_result = ["MultMultNone", "S3PermissionsmanagementBucket"] result = get_sid_names_from_policy(policy_json) self.assertListEqual(result, expected_result)
def test_add_wildcard_only_actions_matching_services_and_access_level(self): """test_add_wildcard_only_actions_matching_services_and_access_level: We'd never write a policy like this IRL but doing this as a quality check against how it handles the database """ policy_file_path = os.path.abspath( os.path.join( os.path.dirname(__file__), os.path.pardir, os.path.pardir, "examples", "yml", "crud-with-wildcard-service-level.yml", ) ) cfg = read_yaml_file(policy_file_path) results = write_policy_with_template(cfg) # The Policy *should* look like this. # desired_output = { # "Version": "2012-10-17", # "Statement": [ # { # "Sid": "MultMultNone", # "Effect": "Allow", # "Action": [ # "ram:EnableSharingWithAwsOrganization", # "ram:GetResourcePolicies", # "ecr:GetAuthorizationToken", # "s3:GetAccessPoint", # "s3:GetAccountPublicAccessBlock", # "s3:ListAccessPoints", # "s3:ListJobs" # ], # "Resource": [ # "*" # ] # }, # { # "Sid": "S3PermissionsmanagementBucket", # "Effect": "Allow", # "Action": [ # "s3:DeleteBucketPolicy", # "s3:PutBucketAcl", # "s3:PutBucketPolicy", # "s3:PutBucketPublicAccessBlock" # ], # "Resource": [ # "arn:aws:s3:::example-org-s3-access-logs" # ] # } # ] # } print(json.dumps(results, indent=4)) self.maxDiff = None # To future-proof this unit test... # (1) check the Sid names sid_names = get_sid_names_from_policy(results) self.assertIn("MultMultNone", sid_names, "Sid is not in the list of expected Statement Ids") self.assertIn("S3PermissionsmanagementBucket", sid_names, "Sid is not in the list of expected Statement Ids") # (2) Check for the presence of certain actions that we know will be there statement_1 = get_statement_from_policy_using_sid(results, "MultMultNone") self.assertIn("ram:EnableSharingWithAwsOrganization", statement_1.get("Action")) self.assertIn("s3:GetAccountPublicAccessBlock", statement_1.get("Action")) statement_2 = get_statement_from_policy_using_sid(results, "S3PermissionsmanagementBucket") self.assertIn("s3:DeleteBucketPolicy", statement_2.get("Action")) self.assertIn("s3:PutBucketPolicy", statement_2.get("Action")) # (3) Check that the length of the list is at least the length that it is right now, # since we expect it to grow eventually self.assertTrue(len(statement_1.get("Action")) > 5) # Size is 6 at time of writing self.assertTrue(len(statement_2.get("Action")) > 3) # Size is 4 at time of writing
def test_write_policy_input_schema(self): actions_for_resources_at_access_level = { "read": [], "write": [], "list": [], "tagging": [], "permissions-management": [], } actions_for_services_without_resource_constraint_support = { "single-actions": [], "read": [], "write": [], "list": [], "tagging": [], "permissions-management": [], } wildcard_only_section = ActionsForServicesWithoutResourceConstraintSupport( read=[], write=[], list_access=[], permissions_management=[], tagging=[], single_actions=["s3:ListAllMyBuckets"]) actions_for_resources_at_access_level = ActionsForResourcesAtAccessLevel( read=["arn:aws:s3:::mybucket/*"], write=[], list_access=[], permissions_management=[], tagging=[], ) write_policy_input = WritePolicyInput( name="test", actions_for_resources_at_access_level= actions_for_resources_at_access_level, actions_for_services_without_resource_constraint_support= wildcard_only_section, skip_resource_constraints=["s3:PutObject"], exclude_actions=["kms:Delete*"]) template = WritePolicyTemplate(write_policy_input) results = write_policy_with_template(template.json) print(json.dumps(results, indent=4)) expected_results = { "Version": "2012-10-17", "Statement": [{ "Sid": "MultMultNone", "Effect": "Allow", "Action": ["s3:ListAllMyBuckets"], "Resource": ["*"] }, { "Sid": "S3ReadObject", "Effect": "Allow", "Action": [ "s3:GetObject", "s3:GetObjectAcl", "s3:GetObjectLegalHold", "s3:GetObjectRetention", "s3:GetObjectTagging", "s3:GetObjectTorrent", "s3:GetObjectVersion", "s3:GetObjectVersionAcl", "s3:GetObjectVersionForReplication", "s3:GetObjectVersionTagging", "s3:GetObjectVersionTorrent" ], "Resource": ["arn:aws:s3:::mybucket/*"] }, { "Sid": "SkipResourceConstraints", "Effect": "Allow", "Action": ["s3:PutObject"], "Resource": ["*"] }] } self.assertListEqual(get_sid_names_from_policy(results), get_sid_names_from_policy(expected_results))