def handler(event, context): props = properties.load( event, { 'ConfigurationBucket': properties.String(), 'ConfigurationKey': properties.String(), 'DeploymentName': properties.String() }) data = { 'ConfigurationBucket': props.ConfigurationBucket, 'ConfigurationKey': '{}/deployment/{}'.format(props.ConfigurationKey, props.DeploymentName), 'DeploymentTemplateURL': 'https://s3.amazonaws.com/{}/{}/deployment/{}/deployment-template.json' .format(props.ConfigurationBucket, props.ConfigurationKey, props.DeploymentName), 'AccessTemplateURL': 'https://s3.amazonaws.com/{}/{}/deployment-access-template-{}.json'. format(props.ConfigurationBucket, props.ConfigurationKey, props.DeploymentName), 'DeploymentName': props.DeploymentName } physical_resource_id = 'CloudCanvas:DeploymentConfiguration:{}:{}'.format( discovery_utils.get_stack_name_from_stack_arn(event['StackId']), props.DeploymentName) custom_resource_response.succeed(event, context, data, physical_resource_id)
def handler(event, context): props = properties.load(event, { 'ConfigurationBucket': properties.String(), # Currently not used 'ConfigurationKey': properties.String(), # Depend on unique upload id in key to force Cloud Formation to call handler 'FeatureStack': properties.String(default=''), 'DeploymentStack': properties.String(default='')}) if props.FeatureStack is '' and props.DeploymentStack is '': raise ValidationError('A value for the FeatureStack property or the DeploymentStack property must be provided.') if props.FeatureStack is not '' and props.DeploymentStack is not '': raise ValidationError('A value for only the FeatureStack property or the DeploymentStack property can be provided.') data = {} physical_resource_id = 'CloudCanvas:PlayerAccess:{stack_name}'.format( stack_name=discovery_utils.get_stack_name_from_stack_arn(event['StackId'])) if props.FeatureStack is not '': feature_info = discovery_utils.FeatureInfo(props.FeatureStack) # The PlayerAccess resources in feature stacks will be created before # the deployment access stack, and the Player role, is created. In # this case it is OK for us to do nothing and wait for the PlayerAccess # resource defined by the deployment access stack to be created. It # will initialize the role at athat time. role_name = _find_player_role(feature_info.deployment) if role_name is not None: _process_feature_stack(event['RequestType'], feature_info, role_name) else: # DeploymentStack _process_deployment_stack(event['RequestType'], props.DeploymentStack) custom_resource_response.succeed(event, context, data, physical_resource_id)
def handler(event, context): props = properties.load( event, { 'ConfigurationBucket': properties.String(), 'ConfigurationKey': properties.String(), 'ResourceGroupName': properties.String() }) data = { 'ConfigurationBucket': props.ConfigurationBucket, 'ConfigurationKey': '{}/resource-group/{}'.format(props.ConfigurationKey, props.ResourceGroupName), 'TemplateURL': 'https://s3.amazonaws.com/{}/{}/resource-group/{}/resource-template.json' .format(props.ConfigurationBucket, props.ConfigurationKey, props.ResourceGroupName) } physical_resource_id = 'CloudCanvas:LambdaConfiguration:{stack_name}:{resource_group_name}'.format( stack_name=discovery_utils.get_stack_name_from_stack_arn( event['StackId']), resource_group_name=props.ResourceGroupName) custom_resource_response.succeed(event, context, data, physical_resource_id)
def handler(event, context): props = properties.load(event, { 'ConfigurationBucket': properties.String(), 'ConfigurationKey': properties.String(), 'FunctionName': properties.String(), 'Settings': properties.Object( default={}, schema={ '*': properties.String() }), 'Runtime': properties.String() }) request_type = event['RequestType'] if request_type == 'Delete': physical_resource_name = event['PhysicalResourceId'] resource_uuid = physical_resource_name.split(':')[4] _delete_role(resource_uuid) data = {} else: if request_type == 'Create': resource_uuid = uuid4() physical_resource_name = 'CloudCanvas:LambdaConfiguration:{stack_name}:{function_name}:{uuid}'.format( stack_name=discovery_utils.get_stack_name_from_stack_arn(event['StackId']), function_name=props.FunctionName, uuid=resource_uuid) role_arn = _create_role(event['StackId'], props.FunctionName, resource_uuid) else: # Update physical_resource_name = event['PhysicalResourceId'] resource_uuid = physical_resource_name.split(':')[4] role_arn = _update_role(event['StackId'], props.FunctionName, resource_uuid) output_key = '{}/feature-code.zip'.format(props.ConfigurationKey) output_key = _inject_settings(props.Settings.__dict__, props.Runtime, props.ConfigurationBucket, output_key, props.FunctionName) data = { 'ConfigurationBucket': props.ConfigurationBucket, 'ConfigurationKey': output_key, 'Runtime': props.Runtime, 'Role': role_arn } custom_resource_response.succeed(event, context, data, physical_resource_name)
def handler(event, context): resource_properties = event['ResourceProperties'] resource_properties['RoleLogicalId'] = 'Player' resource_properties['PhysicalResourceId'] = 'CloudCanvas:PlayerAccess:{stack_name}'.format( stack_name=discovery_utils.get_stack_name_from_stack_arn(event['StackId'])) resource_properties['MetadataKey'] = 'PlayerAccess' resource_properties['UsePropagationDelay'] = 'false' resource_properties['RequireRoleExists'] = 'false' return AccessResourceHandler.handler(event, context)
def handler(event, context): props = properties.load( event, { 'ConfigurationBucket': properties.String(), # Currently not used 'ConfigurationKey': properties.String( ), # Depend on unique upload id in key to force Cloud Formation to call handler 'FeatureStack': properties.String(default=''), 'DeploymentStack': properties.String(default='') }) if props.FeatureStack is '' and props.DeploymentStack is '': raise ValidationError( 'A value for the FeatureStack property or the DeploymentStack property must be provided.' ) if props.FeatureStack is not '' and props.DeploymentStack is not '': raise ValidationError( 'A value for only the FeatureStack property or the DeploymentStack property can be provided.' ) data = {} physical_resource_id = 'CloudCanvas:PlayerAccess:{stack_name}'.format( stack_name=discovery_utils.get_stack_name_from_stack_arn( event['StackId'])) if props.FeatureStack is not '': feature_info = discovery_utils.FeatureInfo(props.FeatureStack) # The PlayerAccess resources in feature stacks will be created before # the deployment access stack, and the Player role, is created. In # this case it is OK for us to do nothing and wait for the PlayerAccess # resource defined by the deployment access stack to be created. It # will initialize the role at athat time. role_name = _find_player_role(feature_info.deployment) if role_name is not None: _process_feature_stack(event['RequestType'], feature_info, role_name) else: # DeploymentStack _process_deployment_stack(event['RequestType'], props.DeploymentStack) custom_resource_response.succeed(event, context, data, physical_resource_id)
def handler(event, context): # This resource does nothing. It exists so that deployment stacks can be created # before any resource groups have been defined. In such cases the Resources list # would be empty, which CloudFormation doesn't allow, so the lmbr_aws client inserts # this resource into the deployment template when no other resources are defined # by the template. props = properties.load(event, {}) data = {} physical_resource_id = 'CloudCanvas:EmptyDeployment:{}'.format( discovery_utils.get_stack_name_from_stack_arn(event['StackId'])) custom_resource_response.succeed(event, context, data, physical_resource_id)
def handler(event, context): props = properties.load(event, { 'ConfigurationBucket': properties.String(), 'ConfigurationKey': properties.String(), 'DeploymentName': properties.String()}) data = { 'ConfigurationBucket': props.ConfigurationBucket, 'ConfigurationKey': '{}/deployment/{}'.format(props.ConfigurationKey, props.DeploymentName), 'DeploymentTemplateURL': 'https://s3.amazonaws.com/{}/{}/deployment/{}/deployment-template.json'.format(props.ConfigurationBucket, props.ConfigurationKey, props.DeploymentName), 'AccessTemplateURL': 'https://s3.amazonaws.com/{}/{}/deployment-access-template-{}.json'.format(props.ConfigurationBucket, props.ConfigurationKey, props.DeploymentName), 'DeploymentName': props.DeploymentName } physical_resource_id = 'CloudCanvas:DeploymentConfiguration:{}:{}'.format(discovery_utils.get_stack_name_from_stack_arn(event['StackId']), props.DeploymentName) custom_resource_response.succeed(event, context, data, physical_resource_id)
def handler(event, context): props = properties.load(event, { 'ConfigurationBucket': properties.String(), 'ConfigurationKey': properties.String(), 'FeatureName': properties.String()}) data = { 'ConfigurationBucket': props.ConfigurationBucket, 'ConfigurationKey': '{}/feature/{}'.format(props.ConfigurationKey, props.FeatureName), 'TemplateURL': 'https://s3.amazonaws.com/{}/{}/feature/{}/feature-template.json'.format(props.ConfigurationBucket, props.ConfigurationKey, props.FeatureName) } physical_resource_id = 'CloudCanvas:LambdaConfiguration:{stack_name}:{feature_name}'.format( stack_name=discovery_utils.get_stack_name_from_stack_arn(event['StackId']), feature_name=props.FeatureName) custom_resource_response.succeed(event, context, data, physical_resource_id)
def handler(event, context): props = properties.load(event, {'MainBucket': properties.String()}) s3 = boto3.client('s3') if event['RequestType'] == 'Create': for file_name in bucket_data: s3.put_object(Bucket=props.MainBucket, Key=file_name, Body=bucket_data[file_name]) elif event['RequestType'] == 'Delete': for file_name in bucket_data: s3.delete_object(Bucket=props.MainBucket, Key=file_name) physical_id = 'CloudCanvas:PopulateMainBucket:{stack_name}'.format( stack_name=discovery_utils.get_stack_name_from_stack_arn( event['StackId'])) return custom_resource_response.succeed(event, context, {}, physical_id)
def _get_role_name(stack_arn, logical_role_name): # Expecting stack names like: {project-name}-{deployment-name}-{resource-group-name}-{random-stuff}. # We shorten the {project-name}-{deployment-name}-{resource-group-name} part to the point that we # can append {random-stuff} and the role's logical name and end up with a name that meets the max # role name length requirement. stack_name = discovery_utils.get_stack_name_from_stack_arn(stack_arn) if len(stack_name) + len(logical_role_name) + 1 <= MAX_ROLE_NAME_LENGTH: role_name = stack_name + '-' + logical_role_name else: last_dash = stack_name.rfind('-') if last_dash == -1: raise ValidationError( 'Stack name does not have the expected format: {}'.format( stack_name)) root_part = stack_name[:last_dash] random_part = stack_name[last_dash + 1:] root_part_len = MAX_ROLE_NAME_LENGTH - (len(random_part) + len(logical_role_name) + 2) if root_part_len < 0: raise ValidationError( 'The logical role name is too long: {}'.format( logical_role_name)) root_part = root_part[:root_part_len] role_name = root_part + '-' + random_part + '-' + logical_role_name return role_name
def handler(event, context): props = properties.load( event, { 'ConfigurationBucket': properties.String(), 'ConfigurationKey': properties.String( ), ##this is only here to force the resource handler to execute on each update to the deployment 'IdentityPoolName': properties.String(), 'UseAuthSettingsObject': properties.String(), 'AllowUnauthenticatedIdentities': properties.String(), 'Roles': properties.Object(default={}, schema={'*': properties.String()}), }) #give the identity pool a unique name per stack stack_name = discovery_utils.get_stack_name_from_stack_arn( event['StackId']) identity_pool_name = props.IdentityPoolName + stack_name identity_pool_name = identity_pool_name.replace('-', ' ') cognito_client = boto3.client('cognito-identity') found_pool = _find_identity_pool(cognito_client, identity_pool_name) identity_pool_id = None request_type = event['RequestType'] if request_type == 'Delete': if found_pool != None: identity_pool_id = found_pool['IdentityPoolId'] cognito_client.delete_identity_pool( IdentityPoolId=identity_pool_id) data = {} else: use_auth_settings_object = props.UseAuthSettingsObject.lower( ) == 'true' supported_login_providers = {} if use_auth_settings_object == True: #download the auth settings from s3 player_access_key = 'player-access/auth-settings.json' auth_doc = json.loads( _load_doc_from_s3(props.ConfigurationBucket, player_access_key)) #if the doc has entries add them to the supported_login_providers dictionary if len(auth_doc) > 0: for key, value in auth_doc.iteritems(): supported_login_providers[ value['provider_uri']] = value['app_id'] allow_anonymous = props.AllowUnauthenticatedIdentities.lower( ) == 'true' #if the pool exists just update it, otherwise create a new one if found_pool != None: response = cognito_client.update_identity_pool( IdentityPoolId=found_pool['IdentityPoolId'], IdentityPoolName=identity_pool_name, AllowUnauthenticatedIdentities=allow_anonymous, SupportedLoginProviders=supported_login_providers) identity_pool_id = found_pool['IdentityPoolId'] else: response = cognito_client.create_identity_pool( IdentityPoolName=identity_pool_name, AllowUnauthenticatedIdentities=allow_anonymous, SupportedLoginProviders=supported_login_providers) identity_pool_id = response['IdentityPoolId'] #now update the roles for the pool cognito_client.set_identity_pool_roles(IdentityPoolId=identity_pool_id, Roles=props.Roles.__dict__) data = { 'IdentityPoolName': identity_pool_name, 'IdentityPoolId': identity_pool_id } physical_resource_id = identity_pool_id custom_resource_response.succeed(event, context, data, physical_resource_id)
def handler(event, context): props = properties.load( event, { 'ConfigurationBucket': properties.String(), 'ConfigurationKey': properties.String(), 'FunctionName': properties.String(), 'Settings': properties.Object(default={}, schema={'*': properties.String()}), 'Runtime': properties.String() }) request_type = event['RequestType'] stack_arn = event['StackId'] logical_role_name = event['LogicalResourceId'] physical_resource_name = event.get('PhysicalResourceId', None) # None when create request if request_type == 'Delete': role_utils.delete_role(stack_arn, logical_role_name, POLICY_NAME) data = {} else: policy_metadata_filter = lambda entry: _policy_metadata_filter( entry, props.FunctionName) if request_type == 'Create': physical_resource_name = discovery_utils.get_stack_name_from_stack_arn( stack_arn) + '-' + event['LogicalResourceId'] assume_role_service = 'lambda.amazonaws.com' role_arn = role_utils.create_role(stack_arn, logical_role_name, POLICY_NAME, assume_role_service, DEFAULT_POLICY_STATEMENTS, policy_metadata_filter) elif request_type == 'Update': role_arn = role_utils.update_role(stack_arn, logical_role_name, POLICY_NAME, DEFAULT_POLICY_STATEMENTS, policy_metadata_filter) else: raise ValidationError( 'Unexpected request type: {}'.format(request_type)) input_key = '{}/lambda-function-code.zip'.format( props.ConfigurationKey) output_key = _inject_settings(props.Settings.__dict__, props.Runtime, props.ConfigurationBucket, input_key, props.FunctionName) data = { 'ConfigurationBucket': props.ConfigurationBucket, 'ConfigurationKey': output_key, 'Runtime': props.Runtime, 'Role': role_arn } custom_resource_response.succeed(event, context, data, physical_resource_name)
def handler(event, context): props = properties.load(event, { 'ConfigurationBucket': properties.String(), 'ConfigurationKey': properties.String(), ##this is only here to force the resource handler to execute on each update to the deployment 'IdentityPoolName': properties.String(), 'UseAuthSettingsObject': properties.String(), 'AllowUnauthenticatedIdentities': properties.String(), 'Roles': properties.Object( default={}, schema={ '*': properties.String() }), }) #give the identity pool a unique name per stack stack_name = discovery_utils.get_stack_name_from_stack_arn(event['StackId']) identity_pool_name = props.IdentityPoolName + stack_name identity_pool_name = identity_pool_name.replace('-', ' ') cognito_client = boto3.client('cognito-identity') found_pool = _find_identity_pool(cognito_client, identity_pool_name) identity_pool_id = None request_type = event['RequestType'] if request_type == 'Delete': if found_pool != None: identity_pool_id = found_pool['IdentityPoolId'] cognito_client.delete_identity_pool(IdentityPoolId=identity_pool_id) data = {} else: use_auth_settings_object = props.UseAuthSettingsObject.lower() == 'true' supported_login_providers = {} if use_auth_settings_object == True: #download the auth settings from s3 player_access_key = 'player-access/auth-settings.json' auth_doc = json.loads(_load_doc_from_s3(props.ConfigurationBucket, player_access_key)) #if the doc has entries add them to the supported_login_providers dictionary if len(auth_doc) > 0: for key, value in auth_doc.iteritems(): supported_login_providers[value['provider_uri']] = value['app_id'] allow_anonymous = props.AllowUnauthenticatedIdentities.lower() == 'true' #if the pool exists just update it, otherwise create a new one if found_pool != None: response = cognito_client.update_identity_pool(IdentityPoolId=found_pool['IdentityPoolId'], IdentityPoolName=identity_pool_name, AllowUnauthenticatedIdentities=allow_anonymous, SupportedLoginProviders=supported_login_providers) identity_pool_id=found_pool['IdentityPoolId'] else: response = cognito_client.create_identity_pool(IdentityPoolName = identity_pool_name, AllowUnauthenticatedIdentities=allow_anonymous, SupportedLoginProviders=supported_login_providers) identity_pool_id=response['IdentityPoolId'] #now update the roles for the pool cognito_client.set_identity_pool_roles(IdentityPoolId=identity_pool_id, Roles=props.Roles.__dict__) data = { 'IdentityPoolName': identity_pool_name, 'IdentityPoolId': identity_pool_id } physical_resource_id = identity_pool_id custom_resource_response.succeed(event, context, data, physical_resource_id)
def handler(event, context): props = properties.load( event, { 'ConfigurationBucket': properties.String(), 'ConfigurationKey': properties.String(), 'FunctionName': properties.String(), 'Settings': properties.Object(default={}, schema={'*': properties.String()}), 'Runtime': properties.String() }) request_type = event['RequestType'] if request_type == 'Delete': physical_resource_name = event['PhysicalResourceId'] resource_uuid = physical_resource_name.split(':')[4] _delete_role(resource_uuid) data = {} else: if request_type == 'Create': resource_uuid = uuid4() physical_resource_name = 'CloudCanvas:LambdaConfiguration:{stack_name}:{function_name}:{uuid}'.format( stack_name=discovery_utils.get_stack_name_from_stack_arn( event['StackId']), function_name=props.FunctionName, uuid=resource_uuid) role_arn = _create_role(event['StackId'], props.FunctionName, resource_uuid) else: # Update physical_resource_name = event['PhysicalResourceId'] resource_uuid = physical_resource_name.split(':')[4] role_arn = _update_role(event['StackId'], props.FunctionName, resource_uuid) output_key = '{}/feature-code.zip'.format(props.ConfigurationKey) output_key = _inject_settings(props.Settings.__dict__, props.Runtime, props.ConfigurationBucket, output_key, props.FunctionName) data = { 'ConfigurationBucket': props.ConfigurationBucket, 'ConfigurationKey': output_key, 'Runtime': props.Runtime, 'Role': role_arn } custom_resource_response.succeed(event, context, data, physical_resource_name)
def stack_name(self): return discovery_utils.get_stack_name_from_stack_arn(self.stack_arn)