def elasticity_function(instance_id, action_type, event_account_id,
                        event_region, solution_account_id, log_name):
    try:
        ec2_object = aws_services.get_account_details(solution_account_id,
                                                      event_account_id,
                                                      event_region)
        instance_details = aws_services.get_ec2_details(
            instance_id, ec2_object, event_account_id)
        instance_data = aws_services.get_instance_data_from_dynamo_table(
            instance_id)
        if action_type == 'terminated':
            if not instance_data:
                logger.info(f"Item {instance_id} does not exist on DB")
                return None
            instance_status = instance_data["Status"]["S"]
            if instance_status == OnBoardStatus.on_boarded_failed:
                logger.error(
                    f"Item {instance_id} is in status OnBoard failed, removing from DynamoDB table"
                )
                aws_services.remove_instance_from_dynamo_table(instance_id)
                return None
        elif action_type == 'running':
            if not instance_details[
                    "address"]:  # In case querying AWS return empty address
                logger.error("Retrieving Instance Address from AWS failed.")
                return None
            if instance_data:
                instance_status = instance_data["Status"]["S"]
                if instance_status == OnBoardStatus.on_boarded:
                    logger.info(
                        f"Item {instance_id} already exists on DB, no need to add it to Vault"
                    )
                    return None
                elif instance_status == OnBoardStatus.on_boarded_failed:
                    logger.error(
                        f"Item {instance_id} exists with status 'OnBoard failed', adding to Vault"
                    )
                else:
                    logger.info(
                        f"Item {instance_id} does not exist on DB, adding to Vault"
                    )
        else:
            logger.info('Unknown instance state')
            return

        store_parameters_class = aws_services.get_params_from_param_store()
        if not store_parameters_class:
            return
        if store_parameters_class.aob_mode == 'Production':
            # Save PVWA Verification key in /tmp folder
            logger.info('Saving verification key')
            crt = open("/tmp/server.crt", "w+")
            crt.write(store_parameters_class.pvwa_verification_key)
            crt.close()
        pvwa_connection_number, session_guid = aws_services.get_session_from_dynamo(
        )
        if not pvwa_connection_number:
            return
        session_token = pvwa_integration_class.logon_pvwa(
            store_parameters_class.vault_username,
            store_parameters_class.vault_password,
            store_parameters_class.pvwa_url, pvwa_connection_number)
        if not session_token:
            return
        disconnect = False
        if action_type == 'terminated':
            logger.info(f'Detected termination of {instance_id}')
            instance_processing.delete_instance(instance_id, session_token,
                                                store_parameters_class,
                                                instance_data,
                                                instance_details)
        elif action_type == 'running':
            # get key pair
            logger.info('Retrieving account id where the key-pair is stored')
            # Retrieving the account id of the account where the instance keyPair is stored
            # AWS.<AWS Account>.<Event Region name>.<key pair name>
            key_pair_value_on_safe = f'AWS.{instance_details["aws_account_id"]}.{event_region}.{instance_details["key_name"]}'
            key_pair_account_id = pvwa_api_calls.check_if_kp_exists(
                session_token, key_pair_value_on_safe,
                store_parameters_class.key_pair_safe_name, instance_id,
                store_parameters_class.pvwa_url)
            if not key_pair_account_id:
                logger.error(f"Key Pair {key_pair_value_on_safe} does not exist in Safe " \
                             f"{store_parameters_class.key_pair_safe_name}")
                return
            instance_account_password = pvwa_api_calls.get_account_value(
                session_token, key_pair_account_id, instance_id,
                store_parameters_class.pvwa_url)
            if instance_account_password is False:
                return
            pvwa_integration_class.logoff_pvwa(store_parameters_class.pvwa_url,
                                               session_token)
            aws_services.release_session_on_dynamo(pvwa_connection_number,
                                                   session_guid)
            disconnect = True
            instance_processing.create_instance(instance_id, instance_details,
                                                store_parameters_class,
                                                log_name, solution_account_id,
                                                event_region, event_account_id,
                                                instance_account_password)
        else:
            logger.error('Unknown instance state')
            return

        if not disconnect:
            pvwa_integration_class.logoff_pvwa(store_parameters_class.pvwa_url,
                                               session_token)
            aws_services.release_session_on_dynamo(pvwa_connection_number,
                                                   session_guid)

    except Exception as e:
        logger.error(f"Unknown error occurred: {e}")
        if action_type == 'terminated':
            # put_instance_to_dynamo_table(instance_id, instance_details["address"]\
            # , OnBoardStatus.delete_failed, str(e), log_name)
            aws_services.update_instances_table_status(
                instance_id, OnBoardStatus.delete_failed, str(e))
        elif action_type == 'running':
            aws_services.put_instance_to_dynamo_table(
                instance_id, instance_details["address"],
                OnBoardStatus.on_boarded_failed, str(e), log_name)


# TODO: Retry mechanism?
        aws_services.release_session_on_dynamo(pvwa_connection_number,
                                               session_guid)
        return
示例#2
0
 def invoke():
     session_number, guid = aws_services.get_session_from_dynamo(sessions_table_lock_client)
     return session_number, guid
示例#3
0
 def invoke2():
     with self.assertRaises(Exception) as context:
         aws_services.get_session_from_dynamo(sessions_table_lock_client)
     self.assertTrue('fake_exc' in str(context.exception))
示例#4
0
def create_instance(instance_id, instance_details, store_parameters_class,
                    log_name, solution_account_id, event_region,
                    event_account_id, instance_account_password):
    logger.trace(instance_id,
                 instance_details,
                 store_parameters_class,
                 log_name,
                 solution_account_id,
                 event_region,
                 event_account_id,
                 caller_name='create_instance')
    logger.info(f'Adding {instance_id} to AOB')
    if instance_details[
            'platform'] == "windows":  # Windows machine return 'windows' all other return 'None'
        logger.info('Windows platform detected')
        kp_processing.save_key_pair(instance_account_password)
        instance_password_data = get_instance_password_data(
            instance_id, solution_account_id, event_region, event_account_id)
        decrypted_password = kp_processing.decrypt_password(
            instance_password_data)
        aws_account_name = f'AWS.{instance_id}.Windows'
        instance_key = decrypted_password
        platform = WINDOWS_PLATFORM
        instance_username = ADMINISTRATOR
        safe_name = store_parameters_class.windows_safe_name
    else:
        logger.info('Linux\\Unix platform detected')
        ppk_key = kp_processing.convert_pem_to_ppk(instance_account_password)
        if not ppk_key:
            raise Exception("Error on key conversion")
        # ppk_key contains \r\n on each row end, adding escape char '\'
        trimmed_ppk_key = str(ppk_key).replace("\n", "\\n")
        instance_key = trimmed_ppk_key.replace("\r", "\\r")
        aws_account_name = f'AWS.{instance_id}.Unix'
        platform = UNIX_PLATFORM
        safe_name = store_parameters_class.unix_safe_name
        instance_username = get_os_distribution_user(
            instance_details['image_description'])

    # Check if account already exist - in case exist - just add it to DynamoDB
    print('pvwa_connection_number')
    pvwa_connection_number, session_guid = aws_services.get_session_from_dynamo(
    )
    if not pvwa_connection_number:
        return False
    session_token = pvwa_integration_class.logon_pvwa(
        store_parameters_class.vault_username,
        store_parameters_class.vault_password, store_parameters_class.pvwa_url,
        pvwa_connection_number)
    print('session_token')
    if not session_token:
        return False

    search_account_pattern = f"{instance_details['address']},{instance_username}"
    print('retrieve_account_id_from_account_name')
    existing_instance_account_id = pvwa_api_calls.retrieve_account_id_from_account_name(
        session_token, search_account_pattern, safe_name, instance_id,
        store_parameters_class.pvwa_url)
    if existing_instance_account_id:  # account already exist and managed on vault, no need to create it again
        logger.info("Account already exists in vault")
        aws_services.put_instance_to_dynamo_table(instance_id,
                                                  instance_details['address'],
                                                  OnBoardStatus.on_boarded,
                                                  "None", log_name)
        return False
    else:
        account_created, error_message = pvwa_api_calls.create_account_on_vault(
            session_token, aws_account_name, instance_key,
            store_parameters_class, platform, instance_details['address'],
            instance_id, instance_username, safe_name)
        if account_created:
            # if account created, rotate the key immediately
            instance_account_id = pvwa_api_calls.retrieve_account_id_from_account_name(
                session_token, search_account_pattern, safe_name, instance_id,
                store_parameters_class.pvwa_url)
            pvwa_api_calls.rotate_credentials_immediately(
                session_token, store_parameters_class.pvwa_url,
                instance_account_id, instance_id)
            aws_services.put_instance_to_dynamo_table(
                instance_id, instance_details['address'],
                OnBoardStatus.on_boarded, "None", log_name)
        else:  # on board failed, add the error to the table
            aws_services.put_instance_to_dynamo_table(
                instance_id, instance_details['address'],
                OnBoardStatus.on_boarded_failed, error_message, log_name)
    pvwa_integration_class.logoff_pvwa(store_parameters_class.pvwa_url,
                                       session_token)
    aws_services.release_session_on_dynamo(pvwa_connection_number,
                                           session_guid)
    return True