Esempio n. 1
0
File: aws.py Progetto: ua-ants/peerd
        return None

    # In this block we use the account credentials we got above, to create and cache a client
    # connection to an AWS service.
    try:
        client =  boto3.client(
            service,
            region_name=region,
            aws_access_key_id=credentials['AccessKeyId'],
            aws_secret_access_key=credentials['SecretAccessKey'],
            aws_session_token=credentials['SessionToken'],
            config=Config(retries=dict(max_attempts=10)))
        LOGGER.debug('Obtained fresh client connection.')
        return client
    except BaseException:
        LOGGER.error(f'Unexpected error: {sys.exc_info()[1]}', exc_info=True)


def tag_resource(client: Any, resource: str, tags: Mapping, dryrun: bool = False) -> None:
    """
    Tags an AWS resource with the provided tags.

    Example Usage:
    ```
    ec2_client = aws_client(account_id, 'ec2', region)
    tags = {'peerd_support': '*****@*****.**',
            'peerd_datetime': str(datetime.now())}
    tag_resource(ec2_client, peerding_id, tags)
    ```
    :param client: An AWS boto3 client connection to an AWS resource
    :type client: boto3 client
Esempio n. 2
0
File: core.py Progetto: intfrr/peerd
            }
            for key, value in local_tags.items():
                tags[key] = value
            for key, value in remote_tags.items():
                tags[key] = value
            tag_resource(ec2_client, peering_id, tags, dryrun=dryrun)

            # Add the peering to the list of peerings that we will need to accept
            peering_descriptor_copy = deepcopy(peering_descriptor)
            peering_descriptor_copy[1]['peering_id'] = peering_id
            peering_descriptor_copy[1]['tags'] = tags
            pending_acceptance_peerings.append(peering_descriptor_copy)

        except BaseException:
            LOGGER.error("Unexpected error: %s",
                         sys.exc_info()[1],
                         exc_info=True)
            continue

        LOGGER.info(
            f"Successfully created peering request {peering_id} between {account_id} {vpc_id} "
            f"{region} and {remote_account_id} {remote_vpc_id} {remote_region}"
        )

    # Return the list of peerings that need to be accepted.
    return pending_acceptance_peerings


def accept_vpc_peerings(target_peerings: list, metadata: dict, dryrun: bool):
    """
    Loops through a list of peerings, with existing peering id, to accept them.
Esempio n. 3
0
File: core.py Progetto: intfrr/peerd
def accept_vpc_peerings(target_peerings: list, metadata: dict, dryrun: bool):
    """
    Loops through a list of peerings, with existing peering id, to accept them.
    Requests, accepts and tags them.
    Repairs any half open peerings.

    Example target_peerings:
    ```
    [
        [
        {
            "account_id": "415432961280",
            "peering_id": "pcx-41u5h345h2",
            "vpc_id": "vpc-e08fb484",
            "region": "ap-southeast-2",
            "cidr_overrides": [
                "10.53.101.0/27"
            ],
            "peering_tags": [
                {
                "peerd_az_affinity": "0"
                }
            ]
        },
        {
            "account_id": 415432961280,
            "peering_id": "pcx-41u5h345h2",
            "vpc_id": "vpc-7a83b81e",
            "region": "ap-southeast-2"
        }
        ]
    ]
    ```

    :param target_peerings: A list of lists representing the requester and accepter for each peering.
    :type target_peerings: list
    :param metadata: A dictionary with the environment, owner, etc for tagging
    :type metadata: list
    """
    for peering_descriptor in target_peerings:

        # Unpack some common variables
        account_id = peering_descriptor[0]['account_id']
        vpc_id = peering_descriptor[0]['vpc_id']
        region = peering_descriptor[0]['region']
        local_tags = peering_descriptor[0].get('peering_tags', {})

        remote_account_id = peering_descriptor[1]['account_id']
        remote_vpc_id = peering_descriptor[1]['vpc_id']
        remote_region = peering_descriptor[1]['region']
        remote_tags = peering_descriptor[1].get('peering_tags', {})
        peering_id = peering_descriptor[1]['peering_id']
        tags = peering_descriptor[1]['tags']

        try:
            # Accept the VPC Peering
            LOGGER.info(
                f"Accepting peering request {peering_id} between {account_id} {vpc_id} {region} and "
                f"{remote_account_id} {remote_vpc_id} {remote_region}")
            ec2_client = aws_client(remote_account_id, 'ec2', remote_region)
            # Wait until the peering exists
            # The AWS API is eventually consistent and we need to wait.
            LOGGER.info(f'Waiting for peering to exist...')
            ec2_client.get_waiter('vpc_peering_connection_exists').wait(
                VpcPeeringConnectionIds=[peering_id],
                WaiterConfig={'Delay': 5})
            # Tag the VPC Peering
            tags['Name'] = f'peerd peering to {account_id} {vpc_id} {region}'
            tags['peerd_role'] = 'accepter'
            tag_resource(ec2_client, peering_id, tags, dryrun=dryrun)
            # Accept the peering
            try:
                ec2_client.accept_vpc_peering_connection(
                    VpcPeeringConnectionId=peering_id, DryRun=dryrun)
            except ClientError as err:
                if err.response['Error']['Code'] == 'DryRunOperation':
                    continue
                raise
        except BaseException:
            LOGGER.error("Unexpected error: %s",
                         sys.exc_info()[1],
                         exc_info=True)
            continue

        LOGGER.info(
            f"Successfully accepted peering {peering_id} between {account_id} {vpc_id} "
            f"{region} and {remote_account_id} {remote_vpc_id} {remote_region}"
        )
Esempio n. 4
0
            # We must wait for active state to install routes, otherwise the peering will be ignored.
            # Note, usually this step takes a few seconds, but can sometimes take up to a minute or two in rare cases.
            while not ec2_client.describe_vpc_peering_connections(
                    Filters=[{
                        'Name': 'status-code',
                        'Values': ['active']
                    }, {
                        'Name': 'vpc-peering-connection-id',
                        'Values': [peerding_id]
                    }])['VpcPeeringConnections']:
                LOGGER.info(
                    f'Waiting for peering {peerding_id} to become active...')
                sleep(5)
        except BaseException:
            LOGGER.error("Unexpected error: %s",
                         sys.exc_info()[1],
                         exc_info=True)
            continue

        LOGGER.info(
            f"Successfully created peering {peerding_id} between {account_id} {vpc_id} "
            f"{region} and {remote_account_id} {remote_vpc_id} {remote_region}"
        )


def update_route_tables(target_peerings: list, metadata: dict, dryrun: bool):
    """
    Loops through a list of peerings and updates the route tables on each side.

    Example target_peerings:
    ```