def load_app_in_account_region( parent, account, region, app_name, app_config, project=None, monitor_config=None, read_file_path='not set', ): """ Load an Application from config into an AccountContainer and RegionContainer. Account can be a paco.ref but then the Paco Project must be supplied too. """ account_name = account if is_ref(account): account_name = get_model_obj_from_ref(account, project).name if account_name not in parent: account_cont = AccountContainer(account_name, parent) parent[account_name] = account_cont if region not in parent[account_name]: region_cont = RegionContainer(region, parent[account_name]) parent[account_name][region] = region_cont app = Application(app_name, parent[account_name][region]) parent[account_name][region][app_name] = app if project == None: project = get_parent_by_interface(parent) apply_attributes_from_config( app, app_config, lookup_config=monitor_config, read_file_path=read_file_path, resource_registry=project.resource_registry, ) return app
def add_apigateway_resource(self, resource): resource_logical_id = 'ApiGatewayResource' + self.create_cfn_logical_id(resource.name + md5sum(str_data=resource.paco_ref_parts)) cfn_export_dict = resource.cfn_export_dict parent_resource = resource.__parent__.__parent__ # root resource if schemas.IApiGatewayRestApi.providedBy(parent_resource): cfn_export_dict["ParentId"] = troposphere.GetAtt(self.restapi_resource, "RootResourceId") # child resource else: cfn_export_dict["ParentId"] = troposphere.Ref(parent_resource.resource) cfn_export_dict["RestApiId"] = troposphere.Ref(self.restapi_resource) resource_resource = troposphere.apigateway.Resource.from_dict(resource_logical_id, cfn_export_dict) resource.resource = resource_resource self.template.add_resource(resource_resource) self.create_output( title=self.create_cfn_logical_id(f'ApiGatewayRestApiResource{resource.name}' + md5sum(str_data=resource.paco_ref_parts)), value=troposphere.Ref(resource_resource), ref=resource.paco_ref_parts + '.id', ) # Add an OPTIONS method if CORS is enabled if resource.enable_cors == True: options_config = { 'http_method': 'OPTIONS', 'integration': { 'integration_type': 'MOCK', 'integration_http_method': 'OPTIONS', 'pass_through_behavior': 'WHEN_NO_MATCH', 'request_templates': {'application/json': '{"statusCode": 200}'}, 'integration_responses': [{ 'status_code': '200', 'response_parameters': { 'method.response.header.Access-Control-Allow-Headers': "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'", 'method.response.header.Access-Control-Allow-Methods': "'POST,OPTIONS'", 'method.response.header.Access-Control-Allow-Origin': "'*'", }, 'response_templates': {'application/json': ''}, },], }, 'method_responses': [{ 'status_code': '200', 'response_models': [{ 'content_type': 'application/json', 'model_name': 'emptyjson', }], 'response_parameters': { 'method.response.header.Access-Control-Allow-Headers': False, 'method.response.header.Access-Control-Allow-Methods': False, 'method.response.header.Access-Control-Allow-Origin': False, }, }], } options_config['resource_name'] = resource.nested_name method_name = f'{resource.nested_name}PacoCORS' options_method = ApiGatewayMethod(method_name, self.apigatewayrestapi.methods) apply_attributes_from_config(options_method, options_config) self.apigatewayrestapi.methods[method_name] = options_method return resource_resource
def __init__(self, name, parent, config_dict): super().__init__(name, parent) self.zones_by_account = {} if config_dict == None: return loader.apply_attributes_from_config(self, config_dict) for zone_id in self.hosted_zones.keys(): hosted_zone = self.hosted_zones[zone_id] aws_account_ref = hosted_zone.account ref = Reference(aws_account_ref) account_name = ref.parts[1] if account_name not in self.zones_by_account: self.zones_by_account[account_name] = [] self.zones_by_account[account_name].append(zone_id)
def create_config_bucket(self, account_ctx, accounts): "Create an S3 Bucket for AWS Config" s3_ctl = self.paco_ctx.get_controller('S3') global_buckets = self.paco_ctx.project['resource']['s3'].buckets bucket_config_dict = { 'region': self.config.global_resources_region, 'account': self.config.s3_bucket_logs_account, 'bucket_name': 'config', 'enabled': True, 'deletion_policy': 'delete', 'policy': [{ 'sid': "AWSConfigBucketPermissionsCheck", 'effect': "Allow", 'action': ["s3:GetBucketAcl"], 'principal': { "Service": "config.amazonaws.com" }, }, { 'sid': "AWSConfigBucketExistenceCheck", 'effect': "Allow", 'action': ["s3:ListBucket"], 'principal': { "Service": "config.amazonaws.com" }, }, { 'sid': "AWSConfigBucketDelivery", 'effect': "Allow", 'action': ["s3:PutObject"], 'principal': { "Service": "config.amazonaws.com" }, 'resource_suffix': [ f"/AWSLogs/{account.account_id}/Config/*" for account in accounts ], 'condition': { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control" } }, }] } s3bucket = paco.models.applications.S3Bucket('paco-awsconfig', global_buckets) apply_attributes_from_config( s3bucket, bucket_config_dict, read_file_path= 'dynamically generated in code paco.controllers.ctl_config') global_buckets['paco-awsconfig'] = s3bucket s3bucket.resolve_ref_object = self bucket_account_ctx = self.paco_ctx.get_account_context( account_ref=self.config.s3_bucket_logs_account) try: s3_config_ref = s3bucket.paco_ref_parts s3_ctl.init_context(bucket_account_ctx, self.config.global_resources_region, s3_config_ref, self, None) s3_ctl.add_bucket(s3bucket, config_ref=s3_config_ref) except PacoBucketExists: pass return s3bucket.get_bucket_name()
def add_policy(self, policy_config_dict): policy_config = Policy(self) loader.apply_attributes_from_config(policy_config, policy_config_dict) self.policies.append(policy_config)
def set_assume_role_policy(self, policy_config_dict): policy_config = AssumeRolePolicy(self) loader.apply_attributes_from_config(policy_config, policy_config_dict) self.assume_role_policy = policy_config
def apply_config(self, config_dict): loader.apply_attributes_from_config(self, config_dict)
def add_roles(self, roles_config_dict): roles_dict = {'roles': roles_config_dict} loader.apply_attributes_from_config(self, roles_dict)
def __init__(self, paco_ctx, account_ctx, cloudtrail, controller, accounts, account_default_region): aws_name = account_ctx.get_name() super().__init__(paco_ctx, account_ctx, 'CloudTrail', aws_name, controller) project = self.paco_ctx.project self.cloudtrail = cloudtrail self.account_default_region = account_default_region self.stack_list = [] for trail in cloudtrail.trails.values(): if trail.region: region = trail.region else: region = self.account_default_region # Create an S3 bucket to store the CloudTrail in s3_ctl = self.paco_ctx.get_controller('S3') s3_config_ref = trail.paco_ref + '.s3bucket' # ToDo: StackTags is None s3_ctl.init_context(account_ctx, region, s3_config_ref, self, None) put_suffixes = [] for account in accounts: if trail.s3_key_prefix: put_suffixes.append("/{}/AWSLogs/{}/*".format( trail.s3_key_prefix, account.account_id)) else: put_suffixes.append("/AWSLogs/{}/*".format( account.account_id)) bucket_config_dict = { 'region': region, 'account': account_ctx.gen_ref(), 'bucket_name': 'cloudtrail', 'enabled': True, 'deletion_policy': 'delete', 'policy': [{ 'principal': { "Service": "cloudtrail.amazonaws.com" }, 'effect': 'Allow', 'action': ['s3:GetBucketAcl'], 'resource_suffix': [''] }, { 'principal': { "Service": "cloudtrail.amazonaws.com" }, 'effect': 'Allow', 'action': ['s3:PutObject'], 'resource_suffix': put_suffixes, 'condition': { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control" } } }], } global_buckets = project['resource']['s3'] s3bucket = paco.models.applications.S3Bucket( trail.name, global_buckets) apply_attributes_from_config( s3bucket, bucket_config_dict, read_file_path= 'dynamically generated in code paco.controllers.ctl_cloudtrail' ) global_buckets.buckets[trail.name] = s3bucket s3bucket.resolve_ref_object = self s3bucket.enabled = trail.is_enabled() try: s3_ctl.add_bucket( s3bucket, config_ref=s3_config_ref, ) except PacoBucketExists: # for multiple accounts there is only one bucket needed pass # Create the CloudTrail stack and prepare it cloudtrail_template = paco.cftemplates.CloudTrail( self.paco_ctx, self.account_ctx, region, self, None, #stack_tags trail, s3bucket.get_bucket_name()) self.stack_list.append(cloudtrail_template.stack)
def create_role_from_yaml(yaml): config = load_yaml(yaml) role = RoleDefaultEnabled('role', None) apply_attributes_from_config(role, config) return role
def __init__( self, paco_ctx, account_ctx, cloudtrail, controller, accounts, account_default_region, kms_key_account=False ): aws_name = account_ctx.get_name() super().__init__( paco_ctx, account_ctx, 'CloudTrail', aws_name, controller ) project = self.paco_ctx.project self.cloudtrail = cloudtrail self.account_default_region = account_default_region self.stack_list = [] for trail in cloudtrail.trails.values(): if trail.region: region = trail.region else: region = self.account_default_region # If KMS encryption is enabled then create a KMS Key for the trail if kms_key_account: kms_crypto_principle_list = [] for account in accounts: kms_crypto_principle_list.append( "paco.sub 'arn:aws:iam::${%s}:root'" % (account.paco_ref) ) kms_config_dict = { 'admin_principal': { 'aws': [ "!Sub 'arn:aws:iam::${{AWS::AccountId}}:root'" ] }, 'crypto_principal': { 'aws': kms_crypto_principle_list } } cloudtrail.kms_stack = self.add_new_stack( region, trail, paco.cftemplates.KMS, account_ctx=account_ctx, support_resource_ref_ext='kms', extra_context={'cloudtrail': trail} ) self.stack_list.append(cloudtrail.kms_stack) # Create an S3 bucket to store the CloudTrail in s3_ctl = self.paco_ctx.get_controller('S3') # ToDo: StackTags is None put_suffixes = [] for account in accounts: if trail.s3_key_prefix: put_suffixes.append("/{}/AWSLogs/{}/*".format(trail.s3_key_prefix, account.account_id)) else: put_suffixes.append("/AWSLogs/{}/*".format(account.account_id)) bucket_config_dict = { 'region': region, 'account': account_ctx.paco_ref, 'bucket_name': 'cloudtrail', 'enabled': True, 'deletion_policy': 'delete', 'policy': [ { 'principal': {"Service": "cloudtrail.amazonaws.com"}, 'effect': 'Allow', 'action': ['s3:GetBucketAcl'], 'resource_suffix': [''] }, { 'principal': {"Service": "cloudtrail.amazonaws.com"}, 'effect': 'Allow', 'action': ['s3:PutObject'], 'resource_suffix': put_suffixes, 'condition': {"StringEquals": {"s3:x-amz-acl": "bucket-owner-full-control"}} } ], } global_buckets = project['resource']['s3'].buckets s3bucket = paco.models.applications.S3Bucket(trail.name, global_buckets) apply_attributes_from_config(s3bucket, bucket_config_dict, read_file_path = 'dynamically generated in code paco.controllers.ctl_cloudtrail') global_buckets[trail.name] = s3bucket s3bucket.resolve_ref_object = self s3bucket.enabled = trail.is_enabled() try: s3_config_ref = s3bucket.paco_ref_parts s3_ctl.init_context(account_ctx, region, s3_config_ref, self, None) s3_ctl.add_bucket(s3bucket, config_ref=s3_config_ref) except PacoBucketExists: # for multiple accounts there is only one bucket needed pass # Create the CloudTrail stack and prepare it stack = self.add_new_stack( region, trail, paco.cftemplates.CloudTrail, account_ctx=self.account_ctx, extra_context={'s3_bucket_name': s3bucket.get_bucket_name()} ) self.stack_list.append(stack)