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
def invoke(): session_number, guid = aws_services.get_session_from_dynamo(sessions_table_lock_client) return session_number, guid
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))
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