def normalise(self, meta, val): if "use" in val: template = val["use"] if template not in meta.everything["templates"]: available = list(meta.everything["templates"].keys()) raise BadTemplate("Template doesn't exist!", wanted=template, available=available, meta=meta) val = MergedOptions.using(meta.everything["templates"][template], val) formatted_string = sb.formatted( sb.string_or_int_as_string_spec(), MergedOptionStringFormatter, expected_type=six.string_types ) key_name = meta.key_names()["_key_name_0"] key = sb.create_spec( EncryptionKey, name=sb.overridden(key_name), location=sb.required(formatted_string), description=formatted_string, grant=sb.listof(grant_statement_spec("key", key_name)), admin_users=sb.listof(sb.any_spec()), ).normalise(meta, val) statements = [{"principal": {"iam": "root"}, "action": "kms:*", "resource": "*", "Sid": ""}] if key.admin_users: for admin_user in key.admin_users: statements.append( {"principal": admin_user, "action": "kms:*", "resource": {"kms": "__self__"}, "Sid": ""} ) key.policy = sb.container_spec(Document, sb.listof(resource_policy_statement_spec("key", key_name))).normalise( meta.at("admin_users"), statements ) return key
def normalise(self, meta, val): if 'use' in val: template = val['use'] if template not in meta.everything['templates']: available = list(meta.everything['templates'].keys()) raise BadTemplate("Template doesn't exist!", wanted=template, available=available, meta=meta) val = MergedOptions.using(meta.everything['templates'][template], val) formatted_string = sb.formatted(sb.string_or_int_as_string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) function_name = meta.key_names()['_key_name_0'] val = sb.create_spec(Lambda , name = sb.overridden(function_name) , role = sb.required(only_one_spec(resource_spec("lambda", function_name, only=["iam"]))) , code = sb.required(function_code_spec()) , handler = function_handler_spec() , timeout = sb.integer_spec() , runtime = sb.required(formatted_string) , location = sb.required(formatted_string) , description = formatted_string , sample_event = sb.defaulted(sb.or_spec(formatted_dictionary(), sb.string_spec()), "") , desired_output_for_test = sb.defaulted(sb.or_spec(formatted_dictionary(), sb.string_spec()), "") , memory_size = sb.defaulted(divisible_by_spec(64), 128) ).normalise(meta, val) # Hack to make sample_event and desired_output_for_test not appear as a MergedOptions for key in ('sample_event', 'desired_output_for_test'): if isinstance(val[key], MergedOptions): v = val[key].as_dict() class Arbritrary(dictobj): fields = list(v.keys()) val[key] = Arbritrary(**v) return val
def normalise(self, meta, val): if 'use' in val: template = val['use'] if template not in meta.everything['templates']: available = list(meta.everything['templates'].keys()) raise BadTemplate("Template doesn't exist!", wanted=template, available=available, meta=meta) val = MergedOptions.using(meta.everything['templates'][template], val) formatted_string = sb.formatted(sb.string_or_int_as_string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) key_name = meta.key_names()['_key_name_0'] key = sb.create_spec(EncryptionKey , name = sb.overridden(key_name) , location = sb.required(formatted_string) , description = formatted_string , grant = sb.listof(grant_statement_spec('key', key_name)) , admin_users = sb.listof(sb.any_spec()) , permission = sb.listof(sb.dictionary_spec()) , no_root_access = sb.defaulted(sb.boolean(), False) ).normalise(meta, val) statements = key.permission if not key.no_root_access: statements.append({"principal": {"iam": "root"}, "action": "kms:*", "resource": "*", "Sid": ""}) if key.admin_users: for admin_user in key.admin_users: statements.append({"principal": admin_user, "action": "kms:*", "resource": { "kms": "__self__" }, "Sid": ""}) key.policy = sb.container_spec(Document, sb.listof(resource_policy_statement_spec('key', key_name))).normalise(meta.at("admin_users"), statements) return key
def normalise(self, meta, val): if 'use' in val: template = val['use'] if template not in meta.everything['templates']: available = list(meta.everything['templates'].keys()) raise BadTemplate("Template doesn't exist!", wanted=template, available=available, meta=meta) val = MergedOptions.using(meta.everything['templates'][template], val) formatted_string = sb.formatted(sb.string_or_int_as_string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) bucket_name = meta.key_names()['_key_name_0'] original_permission = sb.listof(resource_policy_dict()).normalise(meta.at("permission"), NotSpecified if "permission" not in val else val["permission"]) deny_permission = sb.listof(resource_policy_dict(effect='Deny')).normalise(meta.at("deny_permission"), NotSpecified if "deny_permission" not in val else val["deny_permission"]) allow_permission = sb.listof(resource_policy_dict(effect='Allow')).normalise(meta.at("allow_permission"), NotSpecified if "allow_permission" not in val else val["allow_permission"]) # require_mfa_to_delete is an alias for this permission if val.get("require_mfa_to_delete") is True: delete_policy = {"action": "s3:DeleteBucket", "resource": { "s3": "__self__" }, "Condition": { "Bool": { "aws:MultiFactorAuthPresent": True } } } normalised_delete_policy = resource_policy_dict(effect='Allow').normalise(meta.at("require_mfa_to_delete"), delete_policy) allow_permission.append(normalised_delete_policy) val = val.wrapped() val['permission'] = original_permission + deny_permission + allow_permission return sb.create_spec(Bucket , acl = sb.defaulted(sb.match_spec((six.string_types, canned_acl_spec()), (dict, acl_statement_spec('acl', 'acl'))), None) , name = sb.overridden(bucket_name) , location = sb.defaulted(formatted_string, None) , permission = sb.container_spec(Document, sb.listof(resource_policy_statement_spec('bucket', bucket_name))) , tags = sb.dictof(sb.string_spec(), formatted_string) , website = sb.defaulted(website_statement_spec("website", "website"), None) , logging = sb.defaulted(logging_statement_spec("logging", "logging"), None) , lifecycle = sb.defaulted(sb.listof(lifecycle_statement_spec("lifecycle", "lifecycle")), None) ).normalise(meta, val)
def validate(self, meta, val): """Validate an account_id""" val = string_or_int_as_string_spec().normalise(meta, val) if not regexes['amazon_account_id'].match(val): raise BadOption("Account id must match a particular regex", got=val, should_match=regexes['amazon_account_id'].pattern) return val
class var_spec(many_item_formatted_spec): value_name = "Variable" specs = [ sb.or_spec(sb.string_or_int_as_string_spec(), sb.listof(sb.string_or_int_as_string_spec())) ] optional_specs = [sb.string_or_int_as_string_spec()] formatter = MergedOptionStringFormatter seperators = "|" def create_result(self, variable, variable_value, meta, val, dividers): if variable_value is NotSpecified: return StaticVariable(variable) else: stack = variable return DynamicVariable(stack, variable_value, meta.everything["bespin"])
def setup(self, **kwargs): kwargs = sb.set_options( app_id = sb.required(sb.string_or_int_as_string_spec()) , itunes_country_code = sb.required(sb.string_choice_spec(["au"])) ).normalise(Meta({}, []), kwargs) for key, val in kwargs.items(): setattr(self, key, val)
class port_spec(many_item_formatted_spec): value_name = "Ports" specs = [sb.string_or_int_as_string_spec()] optional_specs = [ sb.string_or_int_as_string_spec(), sb.string_or_int_as_string_spec() ] formatter = MergedOptionStringFormatter def create_result(self, ip, host_port, container_port, meta, val, dividers): """ The format is the same as the default docker cli client:: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort """ if host_port in ('', NotSpecified) and container_port in ('', NotSpecified): container_port = ip ip = NotSpecified host_port = NotSpecified elif container_port in ('', NotSpecified): container_port = host_port host_port = ip ip = NotSpecified elif host_port in ('', NotSpecified): host_port = NotSpecified if host_port == '': host_port = NotSpecified if container_port == '': container_port = NotSpecified if host_port is not NotSpecified: host_port = sb.integer_spec().normalise( meta.indexed_at('host_port'), host_port) container_port = sb.required(container_port_spec()).normalise( meta.indexed_at('container_port'), container_port) return Port(ip, host_port, container_port)
def normalise(self, meta, val): if 'use' in val: template = val['use'] if template not in meta.everything['templates']: available = list(meta.everything['templates'].keys()) raise BadTemplate("Template doesn't exist!", wanted=template, available=available, meta=meta) val = MergedOptions.using(meta.everything['templates'][template], val) formatted_string = sb.formatted(sb.string_or_int_as_string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) function_name = meta.key_names()['_key_name_0'] val = sb.create_spec(Lambda, name=sb.overridden(function_name), role=sb.required( only_one_spec( resource_spec("lambda", function_name, only=["iam"]))), code=sb.required(function_code_spec()), handler=function_handler_spec(), timeout=sb.integer_spec(), runtime=sb.required(formatted_string), location=sb.required(formatted_string), description=formatted_string, sample_event=sb.defaulted( sb.or_spec(formatted_dictionary(), sb.string_spec()), ""), desired_output_for_test=sb.defaulted( sb.or_spec(formatted_dictionary(), sb.string_spec()), ""), memory_size=sb.defaulted(divisible_by_spec(64), 128)).normalise( meta, val) # Hack to make sample_event and desired_output_for_test not appear as a MergedOptions for key in ('sample_event', 'desired_output_for_test'): if isinstance(val[key], MergedOptions): v = val[key].as_dict() class Arbritrary(dictobj): fields = list(v.keys()) val[key] = Arbritrary(**v) return val
def normalise(self, meta, val): if 'use' in val: template = val['use'] if template not in meta.everything['templates']: available = list(meta.everything['templates'].keys()) raise BadTemplate("Template doesn't exist!", wanted=template, available=available, meta=meta) val = MergedOptions.using(meta.everything['templates'][template], val) formatted_string = sb.formatted(sb.string_or_int_as_string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) bucket_name = meta.key_names()['_key_name_0'] original_permission = sb.listof(resource_policy_dict()).normalise( meta.at("permission"), NotSpecified if "permission" not in val else val["permission"]) deny_permission = sb.listof( resource_policy_dict(effect='Deny')).normalise( meta.at("deny_permission"), NotSpecified if "deny_permission" not in val else val["deny_permission"]) allow_permission = sb.listof( resource_policy_dict(effect='Allow')).normalise( meta.at("allow_permission"), NotSpecified if "allow_permission" not in val else val["allow_permission"]) val = val.wrapped() val['permission'] = original_permission + deny_permission + allow_permission return sb.create_spec( Bucket, name=sb.overridden(bucket_name), location=sb.required(formatted_string), permission=sb.container_spec( Document, sb.listof(resource_policy_statement_spec( 'bucket', bucket_name))), tags=sb.dictof(sb.string_spec(), formatted_string)).normalise(meta, val)
class env_spec(many_item_formatted_spec): value_name = "Environment Variable" seperators = [':', '='] specs = [sb.string_spec()] optional_specs = [sb.string_or_int_as_string_spec()] formatter = MergedOptionStringFormatter def create_result(self, env_name, other_val, meta, val, dividers): """Set default_val and set_val depending on the seperator""" args = [env_name] if other_val is NotSpecified: other_val = None if not dividers: args.extend([None, None]) elif dividers[0] == ':': args.extend([other_val, None]) elif dividers[0] == '=': args.extend([None, other_val]) return Environment(*args)
def normalise(self, meta, val): if 'use' in val: template = val['use'] if template not in meta.everything['templates']: available = list(meta.everything['templates'].keys()) raise BadTemplate("Template doesn't exist!", wanted=template, available=available, meta=meta) val = MergedOptions.using(meta.everything['templates'][template], val) formatted_string = sb.formatted(sb.string_or_int_as_string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) bucket_name = meta.key_names()['_key_name_0'] original_permission = sb.listof(resource_policy_dict()).normalise(meta.at("permission"), NotSpecified if "permission" not in val else val["permission"]) deny_permission = sb.listof(resource_policy_dict(effect='Deny')).normalise(meta.at("deny_permission"), NotSpecified if "deny_permission" not in val else val["deny_permission"]) allow_permission = sb.listof(resource_policy_dict(effect='Allow')).normalise(meta.at("allow_permission"), NotSpecified if "allow_permission" not in val else val["allow_permission"]) val = val.wrapped() val['permission'] = original_permission + deny_permission + allow_permission return sb.create_spec(Bucket , name = sb.overridden(bucket_name) , location = sb.required(formatted_string) , permission = sb.container_spec(Document, sb.listof(resource_policy_statement_spec('bucket', bucket_name))) , tags = sb.dictof(sb.string_spec(), formatted_string) ).normalise(meta, val)
def normalise(self, meta, val): if 'use' in val: template = val['use'] if template not in meta.everything['templates']: available = list(meta.everything['templates'].keys()) raise BadTemplate("Template doesn't exist!", wanted=template, available=available, meta=meta) val = MergedOptions.using(meta.everything['templates'][template], val) formatted_string = sb.formatted(sb.string_or_int_as_string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) function_name = meta.key_names()['_key_name_0'] return sb.create_spec(Lambda , name = sb.overridden(function_name) , role = sb.required(only_one_spec(resource_spec("lambda", function_name, only=["iam"]))) , code = sb.required(function_code_spec()) , handler = function_handler_spec() , timeout = sb.integer_spec() , runtime = sb.required(formatted_string) , location = sb.required(formatted_string) , description = formatted_string , sample_event = sb.defaulted(sb.or_spec(sb.dictionary_spec(), sb.string_spec()), "") , memory_size = sb.defaulted(divisible_by_spec(64), 128) ).normalise(meta, val)
ArtifactCommand, copy=sb.listof(artifact_path_spec()), modify=sb.dictof(sb.string_spec(), sb.set_options(append=sb.listof(formatted_string))), command=sb.listof(formatted_string), timeout=sb.defaulted(sb.integer_spec(), 600), temp_dir=sb.defaulted(formatted_string, None), add_into_tar=sb.listof(artifact_path_spec())) params_json_spec = lambda: sb.listof( sb.set_options(ParameterKey=sb.required(sb.any_spec()), ParameterValue=sb.required(sb.any_spec()))) params_yaml_spec = lambda: sb.dictof( sb.string_spec(), sb.formatted(sb.string_or_int_as_string_spec(), formatter=MergedOptionStringFormatter)) stack_json_spec = lambda: sb.set_options(Resources=sb.required( sb.dictof( sb.string_spec(), sb.set_options(Type=sb.required(sb.string_spec()), Properties=sb.optional_spec(sb.dictionary_spec())))), Parameters=sb.optional_spec( sb.dictof(sb.string_spec(), sb.dictionary_spec())), Outputs=sb.optional_spec( sb.dictof(sb.string_spec(), sb.dictionary_spec())))
def normalise(self, meta, val): if 'use' in val: template = val['use'] if template not in meta.everything['templates']: available = list(meta.everything['templates'].keys()) raise BadTemplate("Template doesn't exist!", wanted=template, available=available, meta=meta) val = MergedOptions.using(meta.everything['templates'][template], val) formatted_string = sb.formatted(sb.string_or_int_as_string_spec(), MergedOptionStringFormatter, expected_type=six.string_types) bucket_name = meta.key_names()['_key_name_0'] original_permission = sb.listof(resource_policy_dict()).normalise( meta.at("permission"), NotSpecified if "permission" not in val else val["permission"]) deny_permission = sb.listof( resource_policy_dict(effect='Deny')).normalise( meta.at("deny_permission"), NotSpecified if "deny_permission" not in val else val["deny_permission"]) allow_permission = sb.listof( resource_policy_dict(effect='Allow')).normalise( meta.at("allow_permission"), NotSpecified if "allow_permission" not in val else val["allow_permission"]) # require_mfa_to_delete is an alias for this permission if val.get("require_mfa_to_delete") is True: delete_policy = { "action": "s3:DeleteBucket", "resource": { "s3": "__self__" }, "Condition": { "Bool": { "aws:MultiFactorAuthPresent": True } } } normalised_delete_policy = resource_policy_dict( effect='Allow').normalise(meta.at("require_mfa_to_delete"), delete_policy) allow_permission.append(normalised_delete_policy) val = val.wrapped() val['permission'] = original_permission + deny_permission + allow_permission return sb.create_spec( Bucket, acl=sb.defaulted( sb.match_spec((six.string_types, canned_acl_spec()), (dict, acl_statement_spec('acl', 'acl'))), None), name=sb.overridden(bucket_name), location=sb.defaulted(formatted_string, None), permission=sb.container_spec( Document, sb.listof(resource_policy_statement_spec( 'bucket', bucket_name))), tags=sb.dictof(sb.string_spec(), formatted_string), website=sb.defaulted(website_statement_spec("website", "website"), None), logging=sb.defaulted(logging_statement_spec("logging", "logging"), None), lifecycle=sb.defaulted( sb.listof(lifecycle_statement_spec("lifecycle", "lifecycle")), None)).normalise(meta, val)
from input_algorithms.errors import BadSpecValue from input_algorithms import spec_base as sb from input_algorithms.spec_base import Spec from input_algorithms.dictobj import dictobj from option_merge import MergedOptions from textwrap import dedent import logging import base64 import json import sys import six log = logging.getLogger("aws_syncr.option_spec.apigateway") formatted_string = lambda: sb.formatted(sb.string_or_int_as_string_spec(), MergedOptionStringFormatter) api_key_spec = lambda: sb.create_spec( ApiKey, name=formatted_string(), stages=sb.listof(formatted_string())) class formatted_dictionary(sb.Spec): def normalise(self, meta, val): val = sb.dictionary_spec().normalise(meta, val) return self.formatted_dict(meta, val) def formatted_dict(self, meta, val, chain=None): result = {} for key, val in val.items(): if type(val) is dict:
from input_algorithms.spec_base import NotSpecified from input_algorithms.validators import Validator from input_algorithms.errors import BadSpecValue from input_algorithms import spec_base as sb from input_algorithms.spec_base import Spec from input_algorithms.dictobj import dictobj from option_merge import MergedOptions import logging import base64 import six log = logging.getLogger("aws_syncr.option_spec.apigateway") formatted_string = lambda: sb.formatted(sb.string_or_int_as_string_spec(), MergedOptionStringFormatter) api_key_spec = lambda: sb.create_spec(ApiKey , name = formatted_string() , stages = sb.listof(formatted_string()) ) class valid_secret(Validator): def validate(self, meta, val): val = sb.dictionary_spec().normalise(meta, val) if 'plain' in val and 'kms' in val: raise BadSpecValue("Please only specify plain or kms", got=list(val.keys()), meta=meta) if 'plain' not in val and 'kms' not in val: raise BadSpecValue("Please specify plain or kms", got=list(val.keys()), meta=meta)