Exemplo n.º 1
0
def dynamodb_sfn_handler(event, context):
    """
    Lambda function that is called by the DynamoDB Step Function state machine.
    It attempts to tag the resource specified in the incoming event.

    :param event: The incoming state machine event object.

    :param context: This object provides methods and properties that provide information
    about the invocation, function, and execution environment.
    See https://docs.aws.amazon.com/lambda/latest/dg/python-context-object.html

    @return: The event to the state machine. TagStatus and Attempts can be changed.
    When the resource is tagged, TagStatus is set to "completed". Attempts increment
    each time this Lambda is called.
    """

    if event['MaxAttempts'] <= event['Attempts']:
        event['TagStatus'] = 'max attempts reached'
        return event

    event['Attempts'] = event['Attempts'] + 1
    logging.info('Tag attempt for event: %s', event)

    if event['EventName'] == 'CreateTable':
        try:
            dynamodb = Boto3Wrapper.get_client('dynamodb')
            dynamodb.tag_resource(
                ResourceArn=event['ResourceArn'],
                Tags=[load_creator_tag(event['Creator'])]
            )
            logging.info('Table has been tagged.')
        except ClientError as error:  # fails when resource not ready
            logger.warning(error)
            return event
    elif event['EventName'] == 'CreateCluster':
        try:
            dax = Boto3Wrapper.get_client('dax')
            dax.tag_resource(
                ResourceName=event['ResourceArn'],
                Tags=[load_creator_tag(event['Creator'])]
            )
            logging.info('Cluster has been tagged')
        except ClientError as error:  # fails when resource not ready
            logger.warning(error)
            return event
    else:
        event['TagStatus'] = 'unsupported event'
        return event

    event['TagStatus'] = 'complete'
    return event
Exemplo n.º 2
0
def dynamodb_cloudwatch_handler(event, context):
    """
    Lambda function that responds to DynamoDB create table and create cluster
    CloudWatch events via EventBridge triggers. The event is processed,
    summarized and becomes input to the DynamoDB Step Function state machine
    that is started to manage the resource tagging.

    :param event: The incoming CloudWatch event object.

    :param context: This object provides methods and properties that provide information
    about the invocation, function, and execution environment.
    See https://docs.aws.amazon.com/lambda/latest/dg/python-context-object.html

    @return: True if the state machine execution started or False if the
    event represents an error.
    """
    logger.debug('event: %s', event)

    detail = event['detail']
    event_name = detail['eventName']
    creator = get_creator(event)

    logger.info('Event type: %s', event_name)

    if is_err_detail(logger, detail):
        return False

    sfn_event = {
        "EventName": event_name,
        "Creator": creator,
        "ResourceArn": "",
        "TagStatus": "pending",
        "MaxAttempts": int(os.environ['SFN_MAX_ATTEMPTS']),
        "Attempts": 0
    }

    if event_name == 'CreateTable':
        sfn_event['ResourceArn'] = detail['responseElements'][
            'tableDescription']['tableArn']
        logger.info('Table [ %s ] requires tag Creator [ %s ]',
                    sfn_event['ResourceArn'], creator)
    elif event_name == 'CreateCluster':
        sfn_event['ResourceArn'] = detail['responseElements']['cluster'][
            'clusterArn']
        logger.info('Cluster [ %s ] requires tag Creator [ %s ]',
                    sfn_event['ResourceArn'], creator)
    else:
        logger.warning('Event [ %s ] is not supported', event_name)
        return False

    sfn = Boto3Wrapper.get_client('stepfunctions')
    response = sfn.start_execution(stateMachineArn=os.environ['SFN_ARN'],
                                   name=creator + '-' + event_name + '-' +
                                   detail['eventID'],
                                   input=json.dumps(sfn_event))

    logger.info('Step Functions start execution: %s', response)

    return True
Exemplo n.º 3
0
def attach_local_aws_response(path, mode='playback'):
    """
    Provide a mock AWS response. Steps:
    1) Create or re-create a session.
    2) Bind the session to the mock API.
    3) Play the mock data.
    :param path: The location of the mock data.
    :param mode: Placebo runtime mode, playback(default) or record.
    """
    session = Boto3Wrapper.get_session()
    pill = placebo.attach(session, data_path=path)
    Boto3Wrapper.SESSION_CREATE_HOOK = session
    if mode == 'playback':
        pill.playback()
    else:
        pill.record()
Exemplo n.º 4
0
def redshift_lambda_handler(event, context):
    """
    Fires on Redshift cluster creation, parses the event, starts and passes event summary to
    the Step Function state machine that will arrange for the Creator tag to be added.

    :param event: The CloudWatch event.
    :param context: Provides information about the invocation, function, and execution environment.
    :return: True if the input event is not describing an error.
    """
    logging.debug('event: %s', event)

    detail = event['detail']
    event_name = detail['eventName']
    creator = get_creator(event)

    logger.info('Event type: %s', event_name)

    if is_err_detail(logger, detail):
        return False

    if event_name == 'CreateCluster':
        logger.debug('%s is creating cluster: %s', creator,
                     detail['requestParameters']['clusterIdentifier'])

        # https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html
        cluster_arn = 'arn:aws:redshift:' + detail['awsRegion'] + ':'\
                      + detail['userIdentity']['accountId'] + ':cluster:'\
                      + detail['requestParameters']['clusterIdentifier']
        short_msg = {
            "EventName": event_name,
            "Creator": creator,
            "ResourceArn": cluster_arn,
            "TagStatus": "pending",
            "MaxRetries": int(os.environ['SFN_MAX_RETRIES']),
            "Retries": 0
        }

        sfn = Boto3Wrapper.get_client('stepfunctions')
        response = sfn.start_execution(stateMachineArn=os.environ['SFN_ARN'],
                                       name=creator + '-' + event_name + '-' +
                                       detail['eventID'],
                                       input=json.dumps(short_msg))

        logger.info('Step Functions start execution: %s', response)

    return True
Exemplo n.º 5
0
def ec2_lambda_handler(event, context):
    """
    Assign owner tag to new EC2 resources.
    :param event: The incoming CloudTrail event object.
    :param context: This object provides methods and properties that provide information
    about the invocation, function, and execution environment.
    :return: True for non-error response events.
    """
    # print('event:', event)

    ids = []
    detail = event['detail']
    event_name = detail['eventName']
    creator = get_creator(event)

    ec2 = Boto3Wrapper.get_resource('ec2')

    if is_err_detail(logger, detail):
        return False

    if event_name == 'CreateVolume':
        ids.append(detail['responseElements']['volumeId'])
        logger.info(ids)
    elif event_name in ('RunInstances', 'StartInstances', 'RebootInstances'):
        ids = _load_instance_ids(detail, ec2, event_name)
        logger.info(ids)
        logger.info('number of instances: %d', len(ids))
    elif event_name == 'CreateImage':
        ids.append(detail['responseElements']['imageId'])
        logger.info(ids)
    elif event_name == 'CreateSnapshot':
        ids.append(detail['responseElements']['snapshotId'])
        logger.info(ids)
    else:
        logger.warning('Not supported action')

    if ids:
        for resource_id in ids:
            logger.info('resource id: %s', resource_id)
            ec2.create_tags(Resources=ids, Tags=[load_creator_tag(creator)])

    return True
Exemplo n.º 6
0
def rds_lambda_handler(event, context):
    """
    Assign owner tag to new RDS resources
    :param event: The incoming CloudTrail event object.
    :param context: This object provides methods and properties that provide information
    about the invocation, function, and execution environment.
    :return: True for non-error response events.
    """
    resource_arn = None
    detail = event['detail']
    event_name = detail['eventName']
    creator = get_creator(event)

    rds = Boto3Wrapper.get_client('rds')

    if is_err_detail(logger, detail):
        return False

    if event_name == 'CreateDBInstance':
        resource_arn = detail['responseElements']['dBInstanceArn']
    elif event_name == 'CreateDBSnapshot':
        resource_arn = detail['responseElements']['dBSnapshotArn']
    elif event_name == 'CreateDBClusterSnapshot':
        resource_arn = detail['responseElements']['dBClusterSnapshotArn']
    elif event_name == 'CreateDBParameterGroup':
        resource_arn = detail['responseElements']['dBParameterGroupArn']
    elif event_name == 'CreateDBSubnetGroup':
        resource_arn = detail['responseElements']['dBSubnetGroupArn']
    elif event_name == 'CreateOptionGroup':
        resource_arn = detail['responseElements']['optionGroupArn']
    else:
        logger.warning('Not supported action')

    if resource_arn:
        rds.add_tags_to_resource(
            ResourceName=resource_arn, Tags=[load_creator_tag(creator)]
        )

    return True
Exemplo n.º 7
0
def redshift_sfn_lambda_handler(event, context):
    """
    Assigns Creator tag to a new Redshift cluster, if the resource has completed creation.

    @param event: The input event from the Step Function state machine.
    @param context: Provides information about the invocation, function, and execution environment.
    @return: The event with possible update to 'Retries' and 'TagStatus'.
    'TagStatus' of "complete" or "max retries reached" cause the state machine to exit.
    """

    if event['MaxRetries'] <= event['Retries']:
        event['TagStatus'] = 'max retries reached'
        return event

    event['Retries'] = event['Retries'] + 1
    logging.info('Tag attempt for event: %s', event)

    redshift = Boto3Wrapper.get_client('redshift')

    try:
        redshift.create_tags(
            ResourceName=event['ResourceArn'],
            Tags=[
                {
                    'Key': 'Creator',
                    'Value': event['Creator']
                }
            ]
        )
        logging.info('Cluster has been tagged with Creator: %s', event['Creator'])
    except ClientError as error:  # fails when resource not ready
        logger.warning(error)
        return event

    event['TagStatus'] = 'complete'
    return event
Exemplo n.º 8
0
def s3_lambda_handler(event, context):
    """
    Assign owner tag to new buckets and objects added to buckets. Object creation event
    notification is added to new buckets.

    :param event: The incoming CloudTrail event object.

    :param context: This object provides methods and properties that provide information
    about the invocation, function, and execution environment.
    See https://docs.aws.amazon.com/lambda/latest/dg/python-context-object.html

    :return: True for non-error response events.
    """
    # print('event:', event)

    detail = event['detail']
    event_name = detail['eventName']
    bucket_name = detail['requestParameters']['bucketName']
    creator = get_creator(event)

    logger.info('email: %s', creator)
    logger.info('bucket name: %s', bucket_name)

    # gets an S3.Client object
    s3 = Boto3Wrapper.get_client('s3')

    if is_err_detail(logger, detail, expect_resp_elems=False):
        return False

    tag_set = {
        'TagSet': [load_creator_tag(creator)]
    }

    if event_name in BUCKET_EVENTS:
        logger.info('adding bucket Creator tag: [ %s ] to bucket [ %s ]',
                    creator, bucket_name)
        try:
            logger.info('tagging bucket')
            s3.put_bucket_tagging(
                Bucket=bucket_name,
                Tagging=tag_set
            )
        except ClientError as error:
            logger.error(error)
            return False
    elif event_name in OBJECT_EVENTS:
        object_key = detail['requestParameters']['key']
        logger.info('adding object Creator tag: [ %s ] to bucket [ %s ] object [ %s ]',
                    creator, bucket_name, object_key)
        try:
            s3.put_object_tagging(
                Bucket=bucket_name,
                Key=object_key,
                Tagging=tag_set
            )
        except ClientError as error:
            logger.error(error)
            return False
    else:
        logger.warning('Not supported action: %s', event_name)
        return False

    return True