def test_allows_specific_actions(self): test_policy = { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": [ "iam:PassRole", "ssm:GetParameter", "s3:GetObject", "ssm:GetParameter", "ssm:GetParameters", "ssm:GetParametersByPath", "secretsmanager:GetSecretValue" ], "Resource": "*" }] } policy_document = PolicyDocument(test_policy) results = policy_document.allows_specific_actions_without_constraints( ["iam:PassRole"]) self.assertListEqual(results, ["iam:PassRole"]) # Input should be case insensitive, but give the pretty CamelCase action name result results = policy_document.allows_specific_actions_without_constraints( ["iam:passrole"]) self.assertListEqual(results, ["iam:PassRole"]) # Verify that it will find the high priority read-only actions that we care about high_priority_read_only_actions = [ "s3:GetObject", "ssm:GetParameter", "ssm:GetParameters", "ssm:GetParametersByPath", "secretsmanager:GetSecretValue" ] results = policy_document.allows_specific_actions_without_constraints( high_priority_read_only_actions) self.assertListEqual(results, high_priority_read_only_actions)
def test_condition_is_a_restricted_action(self): test_policy = { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": "cloudwatch:PutMetricData", "Resource": "*", "Condition": { "StringEquals": { "cloudwatch:namespace": "Namespace" } } }] } policy_document = PolicyDocument(test_policy) self.assertListEqual( policy_document.all_allowed_unrestrictable_actions, []) test_policy_without_condition = { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": "cloudwatch:PutMetricData", "Resource": "*", }] } policy_document_without_condition = PolicyDocument( test_policy_without_condition) self.assertListEqual( policy_document_without_condition. all_allowed_unrestrictable_actions, ["cloudwatch:PutMetricData"])
def test_gh_254_flag_risky_actions_with_resource_constraints_privilege_escalation( self): # Privilege Escalation: https://cloudsplaining.readthedocs.io/en/latest/glossary/privilege-escalation/#updating-an-assumerole-policy test_policy = { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": ["iam:UpdateAssumeRolePolicy", "sts:AssumeRole"], "Resource": "arn:aws:iam::111122223333:role/MyRole" }] } policy_document = PolicyDocument(test_policy, flag_resource_arn_statements=True) expected_result = [{ 'type': 'UpdateRolePolicyToAssumeIt', 'actions': ['iam:updateassumerolepolicy', 'sts:assumerole'] }] self.assertDictEqual(policy_document.allows_privilege_escalation[0], expected_result[0]) policy_document = PolicyDocument(test_policy, flag_resource_arn_statements=False) self.assertListEqual(policy_document.allows_privilege_escalation, [])
def test_gh_106_excluded_actions_should_not_show_in_results(self): """test_gh_106_excluded_actions_should_not_show_in_results: Make sure that autoscaling:SetDesiredCapacity does not show in results when it is excluded""" test_policy = { "Version": "2012-10-17", "Statement": [{ "Sid": "Something", "Effect": "Allow", "Action": [ "autoscaling:SetDesiredCapacity", "autoscaling:TerminateInstanceInAutoScalingGroup", "autoscaling:UpdateAutoScalingGroup" ], "Resource": "*", }] } exclusions_cfg = { "policies": ["aws-service-role*"], "roles": ["aws-service-role*"], "users": [""], "include-actions": ["s3:GetObject"], "exclude-actions": [ "autoscaling:SetDesiredCapacity", "autoscaling:TerminateInstanceInAutoScalingGroup", "autoscaling:UpdateAutoScalingGroup" ] } exclusions = Exclusions(exclusions_cfg) policy_document = PolicyDocument(test_policy, exclusions) print(policy_document.infrastructure_modification) self.assertEqual(policy_document.infrastructure_modification, []) exclusions_cfg_2 = { "policies": ["aws-service-role*"], "roles": ["aws-service-role*"], "users": [""], "include-actions": ["s3:GetObject"], "exclude-actions": [ "autoscaling:SetDesiredCapacity", "autoscaling:TerminateInstanceInAutoScalingGroup", ] } exclusions_2 = Exclusions(exclusions_cfg_2) policy_document_2 = PolicyDocument(test_policy, exclusions_2) # Should still include one result print(policy_document_2.infrastructure_modification) self.assertEqual(policy_document_2.infrastructure_modification, ["autoscaling:UpdateAutoScalingGroup"])
def scan_resource_conf(self, conf): if 'Properties' in conf.keys(): props_conf = conf['Properties'] policies_key = 'Policies' # Obtain a list of 1 or more policies regardless of resource schema if policies_key in props_conf.keys(): policy_conf = props_conf[policies_key] else: policy_conf = [props_conf] # Scan all policies for policy in policy_conf: policy_doc_key = 'PolicyDocument' if isinstance(policy, dict) and policy_doc_key in policy.keys(): # When using unresolved Cfn functions, policy is an str policy_doc = policy[policy_doc_key] try: converted_policy_doc = convert_cloudformation_conf_to_iam_policy(policy_doc) statement_key = 'Statement' if statement_key in converted_policy_doc: policy_statement = PolicyDocument(converted_policy_doc) violations = self.cloudsplaining_analysis(policy_statement) if violations: logging.debug("detailed cloudsplainging finding: {}",json.dumps(violations)) return CheckResult.FAILED except Exception as e: # this might occur with templated iam policies where ARN is not in place or similar logging.debug("could not run cloudsplaining analysis on policy {}", conf) return CheckResult.UNKNOWN return CheckResult.PASSED
def scan_resource_conf(self, conf): if 'Properties' in conf.keys(): props_conf = conf['Properties'] key = 'PolicyDocument' if key in props_conf.keys(): converted_conf = props_conf[key] try: converted_conf = convert_cloudformation_conf_to_iam_policy( converted_conf) key = 'Statement' if key in converted_conf: policy = PolicyDocument(converted_conf) violations = self.cloudsplaining_analysis(policy) if violations: logging.debug( "detailed cloudsplainging finding: {}", json.dumps(violations)) return CheckResult.FAILED except Exception as e: # this might occur with templated iam policies where ARN is not in place or similar logging.debug( "could not run cloudsplaining analysis on policy {}", conf) return CheckResult.UNKNOWN return CheckResult.PASSED
def _policy_document(self): """Return the policy document object""" policy_document = {} for policy_version in self.policy_version_list: if policy_version.get("IsDefaultVersion") is True: policy_document = PolicyDocument(policy_version.get("Document"), exclusions=self.exclusions) return policy_document
def test_finding_actions_excluded(self): test_policy = { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": ["s3:GetObject", "logs:CreateLogStream", "logs:PutLogEvents"], "Resource": "*" }] } policy_document = PolicyDocument(test_policy) # (1) EXCLUDE actions exclusions_cfg = { "users": ["obama"], "groups": ["admin"], "roles": ["MyRole"], "policies": ["someOtherName"], "exclude-actions": ["logs:CreateLogStream", "logs:PutLogEvents"] } exclusions = Exclusions(exclusions_cfg) finding = Finding( policy_name="MyPolicy", arn="arn:aws:iam::123456789012:group/SNSNotifications", actions=["s3:GetObject"], policy_document=policy_document, exclusions=exclusions) # print(finding.actions) self.assertListEqual(finding.actions, ["s3:GetObject"])
def test_group_membership_finding(self): test_policy = { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": "*" }] } policy_document = PolicyDocument(test_policy) exclusions_cfg = dict(users=["obama"], groups=["admin"], roles=["MyRole"], policies=["AWSLambdaFullAccess"]) exclusions = Exclusions(exclusions_cfg) group_finding = GroupFinding( policy_name="MyPolicy", arn="arn:aws:iam::123456789012:group/GroupShouldBeEmpty", actions=["s3:GetObject"], policy_document=policy_document, exclusions=exclusions, members=["obama"]) result = group_finding.is_excluded(exclusions) self.assertListEqual(result, []) group_finding = GroupFinding( policy_name="MyPolicy", arn="arn:aws:iam::123456789012:group/GroupShouldBeEmpty", actions=["s3:GetObject"], policy_document=policy_document, exclusions=exclusions, members=["yolo"]) self.assertFalse(group_finding.is_excluded(exclusions))
def test_actions_without_constraints_deny(self): test_policy = { "Version": "2012-10-17", "Statement": [{ "Effect": "Deny", "Action": [ "iam:UpdateUser", "iam:TagRole", "iam:UntagRole", "s3:PutBucketAcl", "s3:GetObject", "s3:PutObject", "s3:CreateBucket" ], "Resource": "*" }] } policy_document = PolicyDocument(test_policy) results = policy_document.permissions_management_without_constraints self.assertListEqual(results, []) results = policy_document.write_actions_without_constraints self.assertListEqual(results, []) results = policy_document.tagging_actions_without_constraints self.assertListEqual(results, [])
def __init__( self, policy_detail: Dict[str, Any], exclusions: Exclusions = DEFAULT_EXCLUSIONS, flag_conditional_statements: bool = False, flag_resource_arn_statements: bool = False, ) -> None: """ Initialize the InlinePolicy object. :param policy_detail: The JSON containing the PolicyName and PolicyDocument """ if not isinstance(exclusions, Exclusions): raise Exception( "The exclusions provided is not an Exclusions type object. " "Please supply an Exclusions object and try again.") # Fix Issue #254 - Allow flagging risky actions even when there are resource constraints self.flag_conditional_statements = flag_conditional_statements self.flag_resource_arn_statements = flag_resource_arn_statements self.policy_name = policy_detail.get("PolicyName", "") self.policy_document = PolicyDocument( cast(Dict[str, Any], policy_detail.get("PolicyDocument")), exclusions=exclusions, flag_conditional_statements=flag_conditional_statements, flag_resource_arn_statements=flag_resource_arn_statements) # Generating the provider ID based on a string representation of the Policy Document, # to avoid collisions where there are inline policies with the same name but different contents # self.policy_id = get_non_provider_id(self.policy_name) self.policy_id = get_non_provider_id( json.dumps(self.policy_document.json)) self.exclusions = exclusions self.is_excluded = self._is_excluded(exclusions)
def test_policy_document_not_action_deny_gh_23(self): test_policy = { "Version": "2012-10-17", "Statement": [{ "Sid": "DenyAllUsersNotUsingMFA", "Effect": "Deny", "NotAction": "iam:*", "Resource": "*", "Condition": { "BoolIfExists": { "aws:MultiFactorAuthPresent": "false" } } }] } policy_document = PolicyDocument(test_policy) allowed_actions = [] for statement in policy_document.statements: if not statement.has_resource_constraints: if statement.expanded_actions: allowed_actions.extend( statement.expanded_actions) # pragma: no cover self.assertListEqual(allowed_actions, []) self.assertListEqual(policy_document.all_allowed_unrestricted_actions, []) # print(json.dumps(policy_document.contains_statement_using_not_action, indent=4)) self.assertListEqual( policy_document.contains_statement_using_not_action, test_policy["Statement"])
def test_gh_193_AmazonEC2ContainerRegistryReadOnly(self): # https://docs.aws.amazon.com/AmazonECR/latest/userguide/ecr_managed_policies.html#AmazonEC2ContainerRegistryReadOnly test_policy = { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": [ "ecr:GetAuthorizationToken", "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:GetRepositoryPolicy", "ecr:DescribeRepositories", "ecr:ListImages", "ecr:DescribeImages", "ecr:BatchGetImage", "ecr:GetLifecyclePolicy", "ecr:GetLifecyclePolicyPreview", "ecr:ListTagsForResource", "ecr:DescribeImageScanFindings" ], "Resource": "*" }] } policy_document = PolicyDocument(test_policy) self.assertTrue("ecr:GetAuthorizationToken" not in policy_document.all_allowed_unrestricted_actions) self.assertListEqual(policy_document.write_actions_without_constraints, []) self.assertListEqual(policy_document.credentials_exposure, ['ecr:GetAuthorizationToken'])
def test_findings_excluded(self): test_policy = { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "*" } ] } policy_document = PolicyDocument(test_policy) always_exclude_actions = [ "logs:CreateLogStream", "logs:PutLogEvents" ] finding = Finding( policy_name="MyPolicy", arn="arn:aws:iam::123456789012:group/SNSNotifications", actions=["s3:GetObject"], policy_document=policy_document, always_exclude_actions=always_exclude_actions ) print(finding.actions) self.assertListEqual(finding.actions, ["s3:GetObject"])
def __init__(self, group_detail, policy_details): """ Initialize the GroupDetail object. :param group_detail: Details about a particular group :param policy_details: The PolicyDetails object - i.e., details about all managed policies in the account so the group can inherit those attributes """ self.create_date = group_detail.get("CreateDate") self.arn = group_detail.get("Arn") self.path = group_detail.get("Path") self.group_id = group_detail.get("GroupId") self.group_name = group_detail.get("GroupName") # Inline Policies self.inline_policies = {} if group_detail.get("GroupPolicyList"): for inline_policy in group_detail.get("GroupPolicyList"): non_provider_id = get_non_provider_id( inline_policy.get("PolicyName")) self.inline_policies[non_provider_id] = dict( PolicyName=inline_policy.get("PolicyName"), PolicyDocument=PolicyDocument( inline_policy.get("PolicyDocument")), ) # Managed Policies (either AWS-managed or Customer managed) self.attached_managed_policies = [] if group_detail.get("AttachedManagedPolicies"): self._attached_managed_policies_details( group_detail.get("AttachedManagedPolicies"), policy_details) else: self.attached_managed_policies = []
def test_findings_add_list(self): """output.findings.findings.add: Make sure the add function works with adding it as a list""" test_policy = { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": "*" }] } policy_document = PolicyDocument(test_policy) finding_1 = Finding( policy_name="MyPolicy", arn="arn:aws:iam::123456789012:group/SNSNotifications", actions=["s3:GetObject"], policy_document=policy_document) finding_2 = Finding(policy_name="MyPolicy", arn="arn:aws:iam::aws:policy/BadAWSManagedPolicy", actions=["s3:GetObject"], policy_document=policy_document) findings = Findings() findings.add([finding_1, finding_2]) result = findings.json self.assertTrue(len(result) == 2)
def test_policy_document_all_allowed_actions(self): """scan.policy_document.all_allowed_actions""" test_policy = { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ssm:GetParameters", "ecr:PutImage" ], "Resource": "*" }, { "Sid": "AllowManageOwnAccessKeys", "Effect": "Allow", "Action": [ "iam:CreateAccessKey" ], "Resource": "arn:aws:iam::*:user/${aws:username}" } ] } policy_document = PolicyDocument(test_policy) result = policy_document.all_allowed_actions expected_result = [ "ecr:PutImage", "ssm:GetParameters", "iam:CreateAccessKey" ] self.assertListEqual(result, expected_result)
def test_policy_document_return_json(self): test_policy = { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ecr:PutImage" ], "Resource": "*" }, { "Sid": "AllowManageOwnAccessKeys", "Effect": "Allow", "Action": [ "iam:CreateAccessKey" ], "Resource": "arn:aws:iam::*:user/${aws:username}" } ] } policy_document = PolicyDocument(test_policy) result = policy_document.json # That function returns the Policy as JSON self.assertEqual(result, test_policy)
def test_policy_document_contains_statement_using_not_action(self): test_policy = { "Version": "2012-10-17", "Statement": [ { "Sid": "Something", "Effect": "Allow", "NotAction": "iam:*", "Resource": "*", } ] } policy_document = PolicyDocument(test_policy) results = policy_document.contains_statement_using_not_action expected_results = [ { "Sid": "Something", "Effect": "Allow", "NotAction": "iam:*", "Resource": "*" } ] # print(json.dumps(results, indent=4)) self.assertListEqual(results, expected_results)
def test_policy_finding_for_resource_exposure(self): test_policy = { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObjectAcl" ], "Resource": "*" } ] } policy_document = PolicyDocument(test_policy) exclusions_cfg = dict() exclusions = Exclusions(exclusions_cfg) policy_finding = PolicyFinding(policy_document, exclusions) results = policy_finding.results expected_results = { "ServicesAffected": ["s3"], "PrivilegeEscalation": [], "ResourceExposure": ["s3:PutObjectAcl"], "DataExfiltration": [], "ServiceWildcard": [], "CredentialsExposure": [], "InfrastructureModification": ["s3:PutObjectAcl"], } # print(json.dumps(results, indent=4)) self.assertDictEqual(results, expected_results)
def _policy_document(self) -> PolicyDocument: """Return the policy document object""" for policy_version in self.policy_version_list: if policy_version.get("IsDefaultVersion") is True: return PolicyDocument(policy_version.get("Document"), exclusions=self.exclusions) raise Exception( "Managed Policy ARN %s has no default Policy Document version", self.arn)
def __init__(self, policy_detail): """ Initialize the InlinePolicy object. :param policy_detail: The JSON containing the PolicyName and PolicyDocument """ self.policy_name = policy_detail.get("PolicyName") self.policy_document = PolicyDocument( policy_detail.get("PolicyDocument")) self.policy_id = get_non_provider_id(self.policy_name)
def test_principal_findings(self): """output.new_findings.UserFinding""" test_policy = { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": "*" }] } policy_document = PolicyDocument(test_policy) # (1) If the user is a member of an excluded group, return True exclusions_cfg = dict(users=["obama"], groups=["admin"], roles=["MyRole"], policies=["AWSLambdaFullAccess"]) exclusions = Exclusions(exclusions_cfg) user_finding = UserFinding( policy_name="MyPolicy", arn="arn:aws:iam::123456789012:user/SomeUser", actions=["s3:GetObject"], policy_document=policy_document, group_membership=["admin"], exclusions=exclusions) result = user_finding.is_excluded(exclusions) expected_result = ["admin"] self.assertListEqual(result, expected_result) # (2) If the user is explicitly excluded, return True exclusions = Exclusions(exclusions_cfg) user_finding = UserFinding( policy_name="MyPolicy", arn="arn:aws:iam::123456789012:user/obama", # Obama is excluded actions=["s3:GetObject"], policy_document=policy_document, group_membership=["not-excluded-group"], exclusions=exclusions) result = user_finding.is_excluded(exclusions) expected_result = ["obama"] self.assertListEqual(result, expected_result) # (3) If the policy attached is excluded user_finding = UserFinding( policy_name="AWSLambdaFullAccess", arn= "arn:aws:iam::123456789012:user/not-excluded-user", # Obama is excluded actions=["s3:GetObject"], policy_document=policy_document, group_membership=["not-excluded-group"], exclusions=exclusions) result = user_finding.is_excluded(exclusions) expected_result = ["AWSLambdaFullAccess"] self.assertListEqual(result, expected_result)
def scan_data_conf(self, conf): key = 'statement' if key in conf.keys(): converted_conf = convert_terraform_conf_to_iam_policy(conf) policy = PolicyDocument(converted_conf) violations = self.cloudsplaining_analysis(policy) if violations: logging.debug("detailed cloudsplainging finding: {}", json.dumps(violations)) return CheckResult.FAILED return CheckResult.PASSED
def scan_policy(policy_json, exclusions_config=DEFAULT_EXCLUSIONS_CONFIG): """ Scan a policy document for missing resource constraints. :param policy_json: Dictionary containing the IAM policy. :param exclusions_config: Exclusions configuration. If none, just send an empty dictionary. Defaults to the contents of cloudsplaining.shared.default-exclusions.yml :return: """ policy_document = PolicyDocument(policy_json) exclusions = Exclusions(exclusions_config) policy_finding = PolicyFinding(policy_document, exclusions) return policy_finding.results
def test_gh_254_flag_risky_actions_with_resource_constraints_credentials_exposure( self): # Credentials Exposure: https://cloudsplaining.readthedocs.io/en/latest/glossary/credentials-exposure/ test_policy = { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": [ "iam:UpdateAccessKey", ], "Resource": "arn:aws:iam::111122223333:user/MyUser" }] } policy_document = PolicyDocument(test_policy, flag_resource_arn_statements=True) self.assertListEqual(policy_document.credentials_exposure, ['iam:UpdateAccessKey']) policy_document = PolicyDocument(test_policy, flag_resource_arn_statements=False) self.assertListEqual(policy_document.credentials_exposure, [])
def test_finding_attributes(self): """scan.findings.new_finding""" test_policy = { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": "*" }] } policy_document = PolicyDocument(test_policy) finding = Finding( policy_name="MyPolicy", arn="arn:aws:iam::123456789012:group/SNSNotifications", actions=["s3:GetObject"], policy_document=policy_document) self.assertEqual(finding.account_id, "123456789012") self.assertEqual(finding.managed_by, "Customer") self.assertEqual(len(finding.services_affected), 1) self.assertEqual(len(finding.actions), 1) self.assertDictEqual(finding.policy_document.json, policy_document.json) expected_finding_json = { "AccountID": "123456789012", "ManagedBy": "Customer", "Name": "SNSNotifications", "PolicyName": "MyPolicy", "Type": "Group", "Arn": "arn:aws:iam::123456789012:group/SNSNotifications", "ActionsCount": 1, "ServicesCount": 1, "Services": ["s3"], "Actions": ["s3:GetObject"], "PolicyDocument": { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": "*" }] }, "AssumableByComputeService": [], "AssumeRolePolicyDocument": None, "PrivilegeEscalation": [], "DataExfiltrationActions": ["s3:GetObject"], "PermissionsManagementActions": [], } # print(json.dumps(finding.json, indent=4)) self.maxDiff = None self.assertDictEqual(finding.json, expected_finding_json)
def scan_policy(policy_json, policy_name, exclusions_cfg=DEFAULT_EXCLUSIONS_CONFIG): """ Scan a policy document for missing resource constraints. :param policy_json: The AWS IAM policy document. :param exclusions_cfg: Defaults to the embedded exclusions file, which has no effect here. :param policy_name: The name of the IAM policy. Defaults to the filename when used from command line. :return: """ policy_document = PolicyDocument(policy_json) actions_missing_resource_constraints = [] # EXCLUDED ACTIONS - actions to exclude if they are false positives excluded_actions = exclusions_cfg.get("exclude-actions", None) if excluded_actions == [""]: excluded_actions = None # convert to lowercase for comparison purposes # some weird if/else logic to reduce loops and improve performance slightly if excluded_actions: excluded_actions = [x.lower() for x in excluded_actions] always_include_actions = exclusions_cfg.get("include-actions") findings = Findings() for statement in policy_document.statements: if statement.effect == "Allow": actions_missing_resource_constraints.extend( statement.missing_resource_constraints_for_modify_actions( always_include_actions ) ) if actions_missing_resource_constraints: results_placeholder = [] for action in actions_missing_resource_constraints: if excluded_actions: if not is_name_excluded(action.lower(), excluded_actions): results_placeholder.append(action) # pragma: no cover else: results_placeholder.append(action) actions_missing_resource_constraints = list( dict.fromkeys(results_placeholder) ) # remove duplicates actions_missing_resource_constraints.sort() finding = Finding( policy_name=policy_name, arn=policy_name, actions=actions_missing_resource_constraints, policy_document=policy_document, ) findings.add(finding) return findings.json
def test_all_allowed_unrestriced_deny(self): """scan.policy_document.all_allowed_unrestricted_actions""" test_policy = { "Version": "2012-10-17", "Statement": [{ "Effect": "Deny", "Action": "*", "Resource": "*", }] } policy_document = PolicyDocument(test_policy) result = policy_document.all_allowed_unrestricted_actions self.assertEquals([], result)
def test_gh_254_flag_risky_actions_with_resource_constraints_data_exfiltration( self): # Data Exfiltration: https://cloudsplaining.readthedocs.io/en/latest/glossary/data-exfiltration/ test_policy = { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": [ "s3:GetObject", ], "Resource": "arn:aws:s3:::mybucket/*" }] } policy_document = PolicyDocument(test_policy, flag_resource_arn_statements=True) self.assertListEqual(policy_document.allows_data_exfiltration_actions, ['s3:GetObject']) policy_document = PolicyDocument(test_policy, flag_resource_arn_statements=False) self.assertListEqual(policy_document.allows_data_exfiltration_actions, [])