import unittest import json from policy_sentry.shared.database import connect_db from policy_sentry.writing.sid_group import SidGroup from policy_sentry.querying.actions import get_action_data from policy_sentry.shared.constants import DATABASE_FILE_PATH db_session = connect_db(DATABASE_FILE_PATH) class SidGroupActionsTestCase(unittest.TestCase): def test_actions_test_case(self): cfg = { "mode": "actions", "name": "RoleNameWithCRUD", "description": "Why I need these privs", "role_arn": "arn:aws:iam::123456789012:role/RiskyEC2", "actions": [ "kms:CreateGrant", "kms:CreateCustomKeyStore", "ec2:AuthorizeSecurityGroupEgress", "ec2:AuthorizeSecurityGroupIngress", ], } sid_group = SidGroup() output = sid_group.process_template(db_session, cfg) print(json.dumps(output, indent=4))
#!/usr/bin/env python from policy_sentry.shared.database import connect_db from policy_sentry.querying.conditions import get_condition_keys_for_service import json if __name__ == '__main__': db_session = connect_db('bundled') output = get_condition_keys_for_service(db_session, "cloud9") print(json.dumps(output, indent=4)) """ Output: [ 'cloud9:EnvironmentId', 'cloud9:EnvironmentName', 'cloud9:InstanceType', 'cloud9:Permissions', 'cloud9:SubnetId', 'cloud9:UserArn' ] """
import unittest from pathlib import Path from policy_sentry.shared.arns import does_arn_match from policy_sentry.shared.database import connect_db home = str(Path.home()) config_directory = '/.policy_sentry/' database_file_name = 'aws.sqlite3' database_path = home + config_directory + database_file_name db_session = connect_db(database_path) # "Does Arn Match" tests # See docs for this list: # https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#genref-arns # Case 1: arn:partition:service:region:account-id:resource # Case 2: arn:partition:service:region:account-id:resourcetype/resource # Case 3: arn:partition:service:region:account-id:resourcetype/resource/qualifier # Case 4: arn:partition:service:region:account-id:resourcetype/resource:qualifier # Case 5: arn:partition:service:region:account-id:resourcetype:resource # Case 6: arn:partition:service:region:account-id:resourcetype:resource:qualifier class ArnsTestCase(unittest.TestCase): def test_does_arn_match_case_bucket(self): # Case 1: arn:partition:service:region:account-id:resource arn_to_test = "arn:aws:s3:::bucket_name" arn_in_database = "arn:aws:s3:::${BucketName}" self.assertTrue(does_arn_match(arn_to_test, arn_in_database)) def test_does_arn_match_case_1(self): # Case 1: arn:partition:service:region:account-id:resource
def write_policy_dir(input_dir, output_dir, crud, minimize): """ write_policy, but this time with an input directory of YML/YAML files, and an output directory for all the JSON files """ db_session = connect_db(DATABASE_FILE_PATH) input_dir = os.path.abspath(input_dir) output_dir = os.path.abspath(output_dir) if not crud: print( "Warning: If you are using ARNs from Terraform to generate your policies, " "try using the CRUD functionality instead of the default actions-based policy writing functionality." ) if not minimize: print( "Warning: --minimize option is not set. If the policy is too large, " "it can hit the AWS IAM Policy character limit. " "We'll execute as-is, but try using `--minimize 0` functionality " "for production to optimize policy size.\n") # Construct the path # Get the list of files # Write a list of the names if not check_valid_file_path(input_dir): print("Input directory is invalid") sys.exit() if not check_valid_file_path(output_dir): print("Output directory is invalid") sys.exit() input_files = glob.glob(str(input_dir + '/*.yml'), recursive=False) if not input_files: print( "Directory is empty or does not have files with *.yml extension. " "Please check the folder contents and/or extension spelling.") print("Writing the policy JSON files from " + input_dir + " to " + output_dir + "...\n") for yaml_file in input_files: # Get the name of the file, and strip the extension. This is what the # policy name will be base_name = os.path.basename(yaml_file) base_name_no_extension = os.path.splitext( os.path.basename(yaml_file))[0] cfg = read_yaml_file(yaml_file) # User supplies file containing resource-specific access levels if crud: policy = write_policy_with_access_levels(cfg, db_session, minimize) # User supplies file containing a list of IAM actions else: policy = write_policy_with_actions(cfg, db_session, minimize) print("Writing policy for " + base_name + '\n') target_file = str(output_dir + '/' + base_name_no_extension + '.json') if os.path.exists(target_file): print( "Target file for " + base_name_no_extension + '.json' + " exists in the target directory. Removing it and writing a new file.\n" ) os.remove(target_file) write_json_file(target_file, policy) print("Finished")
def action_table(name, service, access_level, condition, wildcard_only, fmt, log_level): """Query the Action Table from the Policy Sentry database""" set_log_level(logger, log_level) db_session = connect_db(DATABASE_FILE_PATH) # Actions on all services if service == "all": all_services = get_all_service_prefixes(db_session) if access_level: level = transform_access_level_text(access_level) print(f"{access_level} actions across ALL services:\n") results = [] for serv in all_services: output = get_actions_with_access_level(db_session, serv, level) results.extend(output) print(yaml.dump(results)) if fmt == "yaml" else [ print(result) for result in results ] # Get a list of all services in the database else: print("All services in the database:\n") print(yaml.dump(all_services)) if fmt == "yaml" else [ print(item) for item in all_services ] elif name is None and access_level and not wildcard_only: print( f"All IAM actions under the {service} service that have the access level {access_level}:" ) level = transform_access_level_text(access_level) output = get_actions_with_access_level(db_session, service, level) print(yaml.dump(output)) if fmt == "yaml" else [ print(json.dumps(output, indent=4)) ] elif name is None and access_level and wildcard_only: print( f"{service} {access_level.upper()} actions that must use wildcards in the resources block:" ) output = get_actions_at_access_level_that_support_wildcard_arns_only( db_session, service, access_level ) print(yaml.dump(output)) if fmt == "yaml" else [ print(json.dumps(output, indent=4)) ] # Get a list of all IAM actions under the service that support the specified condition key. elif condition: print( f"IAM actions under {service} service that support the {condition} condition only:" ) output = get_actions_matching_condition_key(db_session, service, condition) print(yaml.dump(output)) if fmt == "yaml" else [ print(json.dumps(output, indent=4)) ] # Get a list of IAM Actions under the service that only support resources = "*" # (i.e., you cannot restrict it according to ARN) elif wildcard_only: print( f"IAM actions under {service} service that support wildcard resource values only:" ) output = get_actions_that_support_wildcard_arns_only(db_session, service) print(yaml.dump(output)) if fmt == "yaml" else [ print(json.dumps(output, indent=4)) ] elif name and access_level is None: output = get_action_data(db_session, service, name) print(yaml.dump(output)) if fmt == "yaml" else [ print(json.dumps(output, indent=4)) ] else: # Get a list of all IAM Actions available to the service action_list = get_actions_for_service(db_session, service) print(f"ALL {service} actions:") print(yaml.dump(action_list)) if fmt == "yaml" else [ print(item) for item in action_list ]