def generate_security_check_webhook(trace_id, organization_id, project_id, user_id, email): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) # リソース関連性のバリデーションチェックを行います。 try: project = pm_projects.get_projects_by_organization_id( trace_id, project_id, organization_id) except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) if not project: return common_utils.error_common( MsgConst.ERR_AWS_401, HTTPStatus.UNPROCESSABLE_ENTITY, pm_logger) try: webhooks = pm_securityCheckWebhook.query_project_index( trace_id, project_id, user_id) except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) if webhooks: return common_utils.error_common(MsgConst.ERR_302, HTTPStatus.CONFLICT, pm_logger) try: security_check_webhook_id = common_utils.get_uuid4() webhook_path = common_utils.get_uuid4() pm_securityCheckWebhook.create(trace_id, security_check_webhook_id, webhook_path, user_id, email, organization_id, project_id, 3) except PmError as e: return common_utils.error_exception(MsgConst.ERR_DB_403, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) response = common_utils.get_response_by_response_body( HTTPStatus.CREATED, {'webhookPath': webhook_path}) return common_utils.response(response, pm_logger)
def execute_security_check_with_executed_type(trace_id, organization_id, project_id, user_id, email, executed_type): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) # リソース関連性のバリデーションチェックを行います。 try: project = pm_projects.get_projects_by_organization_id( trace_id, project_id, organization_id) except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) if not project: return common_utils.error_common( MsgConst.ERR_AWS_401, HTTPStatus.UNPROCESSABLE_ENTITY, pm_logger) try: check_history_id = common_utils.get_uuid4() executed_date_time = common_utils.get_current_date() pm_checkHistory.create(trace_id, check_history_id, organization_id, project_id, CHECK_SECURITY, CheckStatus.Waiting, None, executed_type, None, executed_date_time, None, user_id) except PmError as e: return common_utils.error_exception(MsgConst.ERR_DB_403, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) try: topic_arn = common_utils.get_environ( CommonConst.SECURITYCHECK_EXECUTE_TOPIC) subject = "USER : {0}".format(user_id) message = { 'CheckHistoryId': check_history_id } # Publish message aws_common.aws_sns(trace_id, subject, json.dumps(message), topic_arn) except PmError as e: common_utils.write_log_pm_error(e, pm_logger, exc_info=True) try: check_history = pm_checkHistory.query_key(trace_id, check_history_id, True) except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # return data response response = common_utils.get_response_by_response_body( HTTPStatus.CREATED, check_history) return common_utils.response(response, pm_logger)
def update_security_check_webhook(trace_id, webhook_path, user_id, data_body): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) has_webhook_path = 'webhookPath' in data_body has_enabled = 'enabled' in data_body webhook = None try: webhooks = pm_securityCheckWebhook.query_webhook_index( trace_id, webhook_path) if webhooks: webhook = webhooks[0] except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) if not webhook: return common_utils.error_common(MsgConst.ERR_301, HTTPStatus.NOT_FOUND, pm_logger) if webhook['UserID'] != user_id: return common_utils.error_common(MsgConst.ERR_301, HTTPStatus.NOT_FOUND, pm_logger) if has_webhook_path: attribute = {'WebhookPath': {"Value": common_utils.get_uuid4()}} elif has_enabled: attribute = {'Enabled': {"Value": data_body['enabled']}} else: return common_utils.error_common(MsgConst.ERR_REQUEST_201, HTTPStatus.BAD_REQUEST, pm_logger) updated_at = webhook['UpdatedAt'] try: pm_securityCheckWebhook.update( trace_id, webhook['SecurityCheckWebhookID'], attribute, updated_at) webhook = pm_securityCheckWebhook.query_key( trace_id, webhook['SecurityCheckWebhookID'], convert_response=True) except PmError as e: return common_utils.error_exception(MsgConst.ERR_DB_404, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) response = common_utils.get_response_by_response_body( HTTPStatus.OK, webhook) return common_utils.response(response, pm_logger)
def execute_check_job_launcher(trace_id): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) # プロジェクト一覧の取得 list_project, segment = pm_projects.get_projects_effective_enable(trace_id) count_submit_job = 0 for project in list_project: # ログID(UUID(v4)) project_id = project['ProjectID'] organization_id = project['OrganizationID'] # チェック履歴テーブルに新規のチェック履歴レコードを作成します。 try: check_history_id = common_utils.get_uuid4() executed_date_time = common_utils.get_current_date() pm_checkHistory.create(trace_id, check_history_id, organization_id, project_id, "CHECK_SECURITY", 0, None, "AUTO", None, executed_date_time, None, CommonConst.SYSTEM) except PmError as e: pm_logger.error("チェック履歴レコード作成に失敗しました。: ProjectID=%s", project_id) pm_logger.error(e) # セキュリティチェック処理ジョブの設定 # セキュリティチェック結果集計処理ジョブの設定 # セキュリティチェック結果レポート出力処理ジョブの設定 LIST_CODE_CHECK_SECURITY = [ 'CHECK_SECURITY_EXEC', 'CHECK_SECURITY_AGGREGATE', 'CHECK_SECURITY_REPORT' ] job_id = [] for code_security in LIST_CODE_CHECK_SECURITY: result, job_id = job_check_security(trace_id, project_id, check_history_id, code_security, job_id) if result is True: count_submit_job += 1 # ジョブサブミット実績をログに出力する。 pm_logger.info("チェック処理ジョブをサブミットしました。: 取得回数=%s、ジョブサブミット件数=%s", segment, count_submit_job) return True
def delete_report(trace_id, email, report_id, organization_id, project_id): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) try: # get report report_item = pm_reports.query_report_filter_organization_project( trace_id, report_id, project_id, organization_id) except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) if (not report_item): return common_utils.error_common(MsgConst.ERR_301, HTTPStatus.NOT_FOUND, pm_logger) try: # delete report pm_reports.delete_reports(trace_id, report_id) except PmError as e: return common_utils.error_exception(MsgConst.ERR_DB_405, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) task_id = common_utils.get_uuid4() try: # create task informaiton request delete in Organization Tasks pm_organizationTasks.create_organizationTask(trace_id, task_id, task_code, report_id, trace_id, email, 0, 0, 3) except PmError as e: return common_utils.error_exception(MsgConst.ERR_DB_403, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # Send message to organization topic task aws_common.sns_organization_topic(trace_id, task_id, task_code) # response if delete success response = common_utils.get_response_by_response_body( HTTPStatus.NO_CONTENT, None) return common_utils.response(response, pm_logger)
def create_session(): aws_account = copy.deepcopy(DataCommon.AWS_ACCOUNT) role_name = copy.deepcopy(DataTestSTS.ROLE_NAME) external_id = copy.deepcopy(DataTestSTS.EXTERNAL_ID) role_arn = 'arn:aws:iam::{0}:role/{1}'.format(aws_account, role_name) session_name = common_utils.get_uuid4() client = boto3.client('sts') credentials = client.assume_role(RoleArn=role_arn, RoleSessionName=session_name, ExternalId=external_id) access_key = credentials['Credentials']['AccessKeyId'] secret_key = credentials['Credentials']['SecretAccessKey'] session_token = credentials['Credentials']['SessionToken'] session = Session(aws_access_key_id=access_key, aws_secret_access_key=secret_key, aws_session_token=session_token) return session
def create_session_client(trace_id, awsaccount, role_name, external_id, is_cw_logger=False): if (is_cw_logger): logger = common_utils.begin_cw_logger(trace_id, __name__, inspect.currentframe()) else: logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) role_arn = 'arn:aws:iam::{0}:role/{1}'.format(awsaccount, role_name) ssession_name = common_utils.get_uuid4() try: client = boto3.client('sts') except ClientError as e: raise common_utils.write_log_exception(e, logger) try: credentials = client.assume_role( RoleArn=role_arn, RoleSessionName=ssession_name, ExternalId=external_id) except ClientError as e: raise common_utils.write_log_exception(e, logger) accesskey = credentials['Credentials']['AccessKeyId'] secretkey = credentials['Credentials']['SecretAccessKey'] session_token = credentials['Credentials']['SessionToken'] try: session = Session( aws_access_key_id=accesskey, aws_secret_access_key=secretkey, aws_session_token=session_token) except ClientError as e: raise common_utils.write_log_exception(e, logger) return session
def test_list_item_settings_handler_success_case_exists_data_exclusion_resource( self): # perpare data test aws_account = copy.deepcopy(DataCommon.AWS_ACCOUNT) mock_pm_affiliation.create(data_pm_affiliation) mock_pm_projects.create(data_pm_projects) mock_pm_awsAccountCoops.create(data_pm_aws_account_coops) for check_item_code in LIST_CHECK_ITEM_CODE_EXCLUDED_RESOURCE: data_pm_exclusion_resources[ 'ExclusionResourceID'] = common_utils.get_uuid4() data_pm_exclusion_resources['CheckItemCode'] = check_item_code data_pm_exclusion_resources['CheckItemRefineCode'] = copy.deepcopy( DataPmExclusionResources.CHECK_ITEM_REFINE_CODE_TEMPLATE. format(organization_id, project_id, aws_account, check_item_code)) data_pm_exclusion_resources['AccountRefineCode'] = copy.deepcopy( DataPmExclusionResources.ACCOUNT_REFINE_CODE_TEMPLATE.format( organization_id, project_id, aws_account)) mock_pm_exclusionResources.create(data_pm_exclusion_resources) # Call function test actual_response = checkitemsettings.list_item_settings_handler( event_mock, {}) # Get data response actual_status_code = actual_response['statusCode'] actual_response_bodys = json.loads(actual_response['body']) # Check data self.assertEqual(HTTPStatus.OK, actual_status_code) for actual_response_body in actual_response_bodys: if actual_response_body[ "checkItemCode"] in LIST_CHECK_ITEM_CODE_EXCLUDED_RESOURCE: self.assertEqual(ExcludedResourceFlag.Enable, actual_response_body["excludedResourceFlag"]) else: self.assertEqual(ExcludedResourceFlag.Other, actual_response_body["excludedResourceFlag"])
def job_check_security(trace_id, project_id, check_history_id, code, job_id): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) try: batch_job_def = pm_batchJobDefs.query_report_job_def_key( trace_id, code) except PmError as e: pm_logger.error("バッチジョブ定義の取得に失敗しました。: %s", code) pm_logger.error(e) return False, None if not batch_job_def: pm_logger.error("ジョブ定義情報が取得できませんでした。:%s", code) return False, None # ログID(UUID(v4)) log_id = common_utils.get_uuid4() # AWS Batch job_name = code + "--" + check_history_id + "--" + log_id job_queue = batch_job_def['JobQueue'] job_definition = batch_job_def['JobDefinition'] check_history_id_param = check_history_id log_id_param = log_id if (code == 'CHECK_SECURITY_REPORT'): check_history_id_param = "--checkHistoryId=" + check_history_id log_id_param = "--logId=" + log_id parameters = { "CheckHistoryID": check_history_id_param, "LogID": log_id_param } container_overrides = {} if (common_utils.check_key('Environment', batch_job_def) and len(batch_job_def['Environment']) > 0): container_overrides = batch_job_def['Environment'] max_retry = batch_job_def['MaxRetry'] try: # submid job job_id, parameter = aws_common.submit_job(trace_id, job_name, job_queue, job_id, job_definition, parameters, container_overrides, max_retry) except PmError as e: pm_logger.error("セキュリティチェック処理ジョブ(%s)の送信に失敗しました。: ProjectID=%s", code, project_id) return False, None # セキュリティチェック結果レポート出力処理ジョブ履歴ファイルを作成し、S3に保存します。 job_id_key = job_id[0]['jobId'] date_now = common_utils.get_current_date() try: check_log = { 'ProjectID': project_id, 'CheckHistoryID': check_history_id, 'LogID': log_id, 'Code': code, 'UserID': 'Check-Job-Launcher', 'MailAddress': 'Check-Job-Launcher', 'JobID': job_id_key, 'Parameter': parameter, 'CreatedAt': date_now, 'UpdatedAt': date_now } s3_file_name = CommonConst.PATH_BATCH_CHECK_LOG.format( check_history_id, log_id + ".json") FileUtils.upload_json(trace_id, "S3_BATCH_LOG_BUCKET", check_log, s3_file_name) except PmError as e: pm_logger.error( "セキュリティチェックジョブ履歴ファイルの作成に失敗しました。: ProjectID=%s, LogID=%s", project_id, log_id) return False, None return True, job_id
import copy from http import HTTPStatus from dotenv import load_dotenv from pathlib import Path from premembers.repository import pm_affiliation, pm_awsAccountCoops from premembers.repository import pm_exclusionitems, pm_assessmentItems from premembers.repository import pm_organizations, pm_projects from premembers.const.msg_const import MsgConst from tests import event_create from premembers.common import common_utils from premembers.check.handler import checkitemsettings from premembers.const.const import CommonConst from premembers.exception.pm_exceptions import PmError trace_id = common_utils.get_uuid4() try: awsAccountCoops = [{ "RoleName": "insightwatch-dev-IAMRole-18TL7SRKGI6PL", "Description": "\u958b\u767a\u74b0\u5883", "AWSAccount": "216054658829", "CreatedAt": "2017-12-05 03:12:53.229", "ExternalID": "4defd5cf-e3d7-49de-932f-b9bdd9276b5f", "ProjectID": "2458d17c-8dff-4983-9a36-e9e964058fd7", "OrganizationID": "3c9381d8-9267-47b8-83b9-4281250f8d96", "AWSAccountName": "IW\u958b\u767a\u74b0\u5883", "CoopID": "e206e0dd-fbc0-47a9-8577-bfa2c656065a", "UpdatedAt": "2018-03-28 05:51:22.533", "Members": 1, "Effective": 1
def job_report(trace_id, email, report_id, code, job_id): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) try: report_job_def = pm_batchJobDefs.query_report_job_def_key( trace_id, code) except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True), None if not report_job_def: pm_logger.error("ジョブ定義情報が取得できませんでした。:" + code) return common_utils.error_common(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, pm_logger), None # ログID(UUID(v4)) log_id = common_utils.get_uuid4() # AWS Batch job_name = code + "-" + log_id job_queue = report_job_def['JobQueue'] job_definition = report_job_def['JobDefinition'] parameters = { "ReportID": "--reportId=" + report_id, "LogID": "--logId=" + log_id } container_overrides = {} if (common_utils.check_key('Environment', report_job_def) and len(report_job_def['Environment']) > 0): container_overrides = report_job_def['Environment'] max_retry = report_job_def['MaxRetry'] try: # submid job job_id, parameter = aws_common.submit_job(trace_id, job_name, job_queue, job_id, job_definition, parameters, container_overrides, max_retry) except PmError as e: return common_utils.error_exception(MsgConst.ERR_AWS_601, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True), None # Create ReportJobLogs user_id = trace_id # 配列内のオブジェクトとして格納されていたので、job_idのみを抽出する(暫定対応) job_id_key = job_id[0]['jobId'] date_now = common_utils.get_current_date() try: report_log = { 'ReportID': report_id, 'LogID': log_id, 'Code': code, 'UserID': user_id, 'MailAddress': email, 'JobID': job_id_key, 'Parameter': parameter, 'CreatedAt': date_now, 'UpdatedAt': date_now } s3_file_name = CommonConst.PATH_REPORT_BATCH.format( report_id, log_id + ".json") FileUtils.upload_json(trace_id, "S3_BATCH_LOG_BUCKET", report_log, s3_file_name) except PmError as e: return common_utils.error_exception(MsgConst.ERR_S3_701, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True), None return common_utils.response(None, pm_logger), job_id
def delete_organization(trace_id, email, organization_id): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) try: organization_item = pm_organizations.get_organization( trace_id, organization_id) except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) if (not organization_item): return common_utils.error_common(MsgConst.ERR_301, HTTPStatus.NOT_FOUND, pm_logger) try: # delete organization pm_organizations.delete_organization(trace_id, organization_id) except PmError as e: return common_utils.error_exception(MsgConst.ERR_DB_405, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) try: # get affiliations get by organization id affiliation_items = pm_affiliation.query_organization_index( trace_id, organization_id) except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) for affiliation in affiliation_items: try: # delete affiliations get by organization id pm_affiliation.delete_affiliation(affiliation["UserID"], organization_id) except PmError as e: return common_utils.error_exception( MsgConst.ERR_DB_405, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # set task informaiton request delete in Organization Tasks task_id = common_utils.get_uuid4() target = CommonConst.TARGET_DELETE_ORG_USER.format( affiliation["UserID"], organization_id) try: # create task informaiton request delete in Organization Tasks pm_organizationTasks.create_organizationTask( trace_id, task_id, CommonConst.TASK_TYPE_CODE_DELETE_ORG_USER, target, trace_id, email, Status.Waiting.value, 0, 3) except PmError as e: return common_utils.error_exception( MsgConst.ERR_DB_403, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) try: # Send message to organization topic task aws_common.sns_organization_topic( trace_id, task_id, CommonConst.TASK_TYPE_CODE_DELETE_ORG_USER) except PmError as e: common_utils.write_log_pm_error(e, pm_logger, exc_info=True) # set task informaiton request delete in Organization Tasks task_id = common_utils.get_uuid4() try: # create task informaiton request delete in Organization Tasks pm_organizationTasks.create_organizationTask( trace_id, task_id, CommonConst.TASK_TYPE_CODE_DELETE_ORG, organization_id, trace_id, email, 0, 0, 3) except PmError as e: return common_utils.error_exception(MsgConst.ERR_DB_403, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # Send message to organization topic task aws_common.sns_organization_topic(trace_id, task_id, CommonConst.TASK_TYPE_CODE_DELETE_ORG, organization_id, trace_id) # response if delete success response = common_utils.get_response_by_response_body( HTTPStatus.NO_CONTENT, None) return common_utils.response(response, pm_logger)
from dotenv import load_dotenv from pathlib import Path from premembers.organizations.handler import awscoops from premembers.repository import pm_affiliation, pm_organizations, pm_projects from premembers.repository import pm_awsAccountCoops from tests import event_create from premembers.const.msg_const import MsgConst from premembers.common import common_utils trace_id = "eb3b5f76-8945-11e7-b15a-8f7e5433dada" mail_address = "test-user{}@example.com" user_id = "eb3b5f76-8945-11e7-b15a-8f7e5433dada{}" organization_id = "awscoops-78ee-11e7-89e6-OrganizationID" project_id = "awscoops-77f1-11e7-adfe-ProjectID" coop_id = "awscoops-77f1-11e7-adfe-CoopID{}" coop_id_members_enable = common_utils.get_uuid4() affiliation_template = { "MailAddress": mail_address.format(str(0)), "UserID": user_id, "Authority": 0, "OrganizationID": organization_id, "InvitationStatus": 1, } organization_template = { "OrganizationID": organization_id, "OrganizationName": "OrganizationName", "Contract": 1, "ContractStatus": 1 }
class DataTestCognitoIdp: FILTER = '*****@*****.**' TRACE_ID = common_utils.get_uuid4() USER_NAME = 'test_user' CURRENT_DATE = datetime.now(timezone('UTC')) DATA_OVERDUE = parse("2009-12-31").replace(tzinfo=timezone('UTC')) LIST_DATA_USER = [{ 'userName': '******', 'user_attributes': { 'Name': 'email', 'Value': '*****@*****.**' } }, { 'userName': '******', 'user_attributes': { 'Name': 'email', 'Value': '*****@*****.**' } }, { 'userName': '******', 'user_attributes': { 'Name': 'email', 'Value': '*****@*****.**' } }] DATA_RESPONSE_SUCCESS = [{ 'Name': 'email', 'Value': '*****@*****.**' }, { 'Name': 'email', 'Value': '*****@*****.**' }, { 'Name': 'email', 'Value': '*****@*****.**' }] USER_ATTRIBUTES_UPDATE = [{ 'Name': 'email', 'Value': '*****@*****.**' }] USER_INFO = { 'User': { 'Username': '******', 'Attributes': [ { 'Name': 'string', 'Value': 'string' }, ], 'UserCreateDate': DATA_OVERDUE, 'UserLastModifiedDate': "datetime", 'Enabled': False, 'UserStatus': 'CONFIRMED', 'MFAOptions': [ { 'DeliveryMedium': 'EMAIL', 'AttributeName': 'string' }, ] } } USER_INFOR_GET_COGNITO_USER_INFO_BY_USER_NAME = { "Enabled": True, "MFAOptions": [{ "AttributeName": "AttributeName", "DeliveryMedium": "DeliveryMedium" }], "PreferredMfaSetting": "PreferredMfaSetting", "UserAttributes": [{ "Name": "email", "Value": copy.deepcopy(DataPmEmailChangeApply.BEFORE_MAIL_ADDRESS) }], "UserCreateDate": DATA_OVERDUE, "UserLastModifiedDate": 2, "UserMFASettingList": ["UserMFASettingList1"], "Username": user_id, "UserStatus": "UserStatus" } LIST_DATA_USER_UNCONFIRMED = [{ 'Username': '******', 'Attributes': { 'Name': 'email', 'Value': '*****@*****.**' }, 'UserCreateDate': CURRENT_DATE, 'UserLastModifiedDate': CURRENT_DATE, 'Enabled': False, 'UserStatus': 'UNCONFIRMED' }, { 'Username': '******', 'Attributes': { 'Name': 'email', 'Value': '*****@*****.**' }, 'UserCreateDate': DATA_OVERDUE, 'UserLastModifiedDate': DATA_OVERDUE, 'Enabled': False, 'UserStatus': 'UNCONFIRMED' }] LIST_DATA_USER_FORCE_CHANGE_PASSWORD = [{ 'Username': '******', 'Attributes': { 'Name': 'email', 'Value': '*****@*****.**' }, 'UserCreateDate': CURRENT_DATE, 'UserLastModifiedDate': CURRENT_DATE, 'Enabled': False, 'UserStatus': 'FORCE_CHANGE_PASSWORD' }, { 'Username': '******', 'Attributes': { 'Name': 'email', 'Value': '*****@*****.**' }, 'UserCreateDate': DATA_OVERDUE, 'UserLastModifiedDate': DATA_OVERDUE, 'Enabled': False, 'UserStatus': 'FORCE_CHANGE_PASSWORD' }] USER_INFO_COGNITO = { 'Username': '******', 'UserAttributes': [{ 'Name': 'sub', 'Value': 'ee9795e8-1d3a-454c-9382-7d0d4b901937' }, { 'Name': 'email_verified', 'Value': 'true' }, { 'Name': 'locale', 'Value': 'ja' }, { 'Name': 'email', 'Value': '*****@*****.**' }], 'UserCreateDate': CURRENT_DATE, 'UserLastModifiedDate': CURRENT_DATE, 'Enabled': True, 'UserStatus': 'CONFIRMED', 'ResponseMetadata': { 'RequestId': '72523c27-ec36-45f8-899c-ff5b51150e73', 'HTTPStatusCode': 200, 'HTTPHeaders': { 'date': 'Thu, 03 Oct 2019 06:30:46 GMT', 'content-type': 'application/x-amz-json-1.1', 'content-length': '369', 'connection': 'keep-alive', 'x-amzn-requestid': '72523c27-ec36-45f8-899c-ff5b51150e73' }, 'RetryAttempts': 0 } } list_data_user = [{ 'userName': '******', 'user_attributes': { 'Name': 'email', 'Value': '*****@*****.**' } }, { 'userName': '******', 'user_attributes': { 'Name': 'email', 'Value': '*****@*****.**' } }, { 'userName': '******', 'user_attributes': { 'Name': 'email', 'Value': '*****@*****.**' } }] data_response_success = [{ 'Name': 'email', 'Value': '*****@*****.**' }, { 'Name': 'email', 'Value': '*****@*****.**' }, { 'Name': 'email', 'Value': '*****@*****.**' }] user_attributes_data = [{ 'Name': 'email', 'Value': '*****@*****.**' }] user_attributes_update = [{ 'Name': 'email', 'Value': '*****@*****.**' }]
import os import json import copy from http import HTTPStatus from dotenv import load_dotenv from pathlib import Path from premembers.repository import pm_affiliation from premembers.repository import pm_orgNotifySlack from premembers.repository import pm_orgNotifyMailDestinations from premembers.const.msg_const import MsgConst from tests import event_create from premembers.common import common_utils from premembers.organizations.handler import notifymail trace_id = common_utils.get_uuid4() notify_code = "CHECK_CIS" webhook_url = "test_webhook_url" mentions = "test_mentions" mail_address = "test-user{}@example.com" user_id = "eb3b5f76-8945-11e7-b15a-8f7e5433dada{}" organization_id = common_utils.get_uuid4() affiliation_template = { "MailAddress": mail_address.format(str(0)), "UserID": user_id, "Authority": 0, "OrganizationID": organization_id, "InvitationStatus": 1, }
def execute_force_invites(trace_id, body_object, organization_id): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) # parse json try: body_object_json = json.loads(body_object) except Exception as e: return common_utils.error_exception(MsgConst.ERR_REQUEST_202, HTTPStatus.BAD_REQUEST, e, pm_logger, True) caller_service_name = common_utils.get_value("callerServiceName", body_object_json, None) mail_lang = common_utils.get_value("mailLang", body_object_json, None) mail_address = common_utils.get_value("mailAddress", body_object_json, None) authority = common_utils.get_value("authority", body_object_json, None) # validate param execute invite unregistered list_error = validate_param_invite_unregistered_user( trace_id, mail_lang, caller_service_name, mail_address, authority) if list_error: return common_utils.error_validate(MsgConst.ERR_REQUEST_201, HTTPStatus.UNPROCESSABLE_ENTITY, list_error, pm_logger) # get list cognito users try: list_users = aws_common.get_cognito_user_pools(trace_id, mail_address) except PmError as e: return common_utils.error_exception(MsgConst.ERR_COGNITO_501, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) if list_users: return common_utils.error_common(MsgConst.ERR_302, HTTPStatus.CONFLICT, pm_logger) # regist Cognito UserPools temporary_password = '' pattern = re.compile(CommonConst.FORMAT_PASSWORD_TEMPORARY) while pattern.match(temporary_password) is None: temporary_password = common_utils.get_password_temporary( CommonConst.NUMBER_CHARACTERS_PASSWORD_TEMPORARY) user_attributes = [{"Name": "email", "Value": mail_address}] user_name = common_utils.get_uuid4() message_action = MessageAction.Suppress try: aws_common.process_admin_create_user_pools(trace_id, user_name, user_attributes, temporary_password, message_action) except PmError as e: return common_utils.error_exception(MsgConst.ERR_COGNITO_501, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # enable confirm email try: user_attributes = [{'Name': 'email_verified', 'Value': 'true'}] aws_common.update_cognito_user_attributes(trace_id, user_name, user_attributes) except PmError as e: return common_utils.error_exception(MsgConst.ERR_COGNITO_501, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # get affiliation try: affiliation = pm_affiliation.get_affiliation(user_name, organization_id) except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) if affiliation and affiliation["InvitationStatus"] != InvitationStatus.Deny: return common_utils.error_common(MsgConst.ERR_302, HTTPStatus.CONFLICT, pm_logger) # get organization try: organization = pm_organizations.get_organization( trace_id, organization_id) except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) if len(organization) == 0: return common_utils.error_common(MsgConst.ERR_301, HTTPStatus.NOT_FOUND, pm_logger) # create affiliation try: pm_affiliation.create_affiliation(trace_id, mail_address, user_name, organization_id, authority, InvitationStatus.Invited) except PmError as e: return common_utils.error_exception(MsgConst.ERR_DB_403, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # Get data affiliation try: affiliation_result = pm_affiliation.get_affiliation( user_name, organization_id, True) except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # Get data user_attribute try: user_attribute = pm_userAttribute.query_key(trace_id) except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # S3から通知メール送信設定ファイルを取得します。 try: config = FileUtils.read_yaml(trace_id, CommonConst.S3_SETTING_BUCKET, CommonConst.NOTIFY_CONFIG_CIS_RESULT_MAIL) except PmError as e: pm_logger.error("メール送信設定ファイルの取得に失敗しました。:s3://{0}/{1}".format( common_utils.get_environ(CommonConst.S3_SETTING_BUCKET), CommonConst.NOTIFY_CONFIG_CIS_RESULT_MAIL)) return common_utils.error_exception(MsgConst.ERR_S3_702, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # メッセージ本文を作成します。 path_file_template = config[ CommonConst.KEY_GET_PATH_FILE_TEMPLATE_USER_INVITE_MAIL.format( language=mail_lang, serviceName=caller_service_name)] try: template_body_mail = FileUtils.read_decode( trace_id, CommonConst.S3_SETTING_BUCKET, path_file_template) except PmError as e: pm_logger.error("招待メール本文テンプレートファイルの取得に失敗しました。:s3://{0}/{1}".format( common_utils.get_environ(CommonConst.S3_SETTING_BUCKET), path_file_template)) return common_utils.error_exception(MsgConst.ERR_S3_702, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # SESで通知メールを送信します。 bcc_addresses = [mail_address] user_name_sign_in = common_utils.get_value("UserName", user_attribute, None) if not user_name_sign_in: try: affiliation_sign_in = pm_affiliation.get_affiliation( trace_id, organization_id) except PmError as e: return common_utils.error_exception( MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) user_name_sign_in = common_utils.get_value("MailAddress", affiliation_sign_in, None) organization_name = common_utils.get_value("OrganizationName", organization, None) time_zone = date_utils.get_time_zone_by_language(mail_lang) time_to_live_date = date_utils.get_current_date() + timedelta(days=6) time_to_live = date_utils.toString(time_to_live_date, date_utils.PATTERN_YYYYMMDD_SLASH, time_zone) template_body_mail = Template(template_body_mail) context = { 'mailAddress': mail_address, 'userName': user_name_sign_in, 'organizationName': organization_name, 'temporaryPassword': temporary_password, 'timeToLive': time_to_live } body_mail = template_body_mail.render(context) mail_subject = config[CommonConst.KEY_MAIL_SUBJECT_USER_INVITE.format( language=mail_lang, serviceName=caller_service_name)] mail_from = config[CommonConst.KEY_INVITE_MAIL_FROM_SERVICE.format( serviceName=caller_service_name)] ses_region = config['ses.region'] try: aws_common.send_email(user_name, ses_region, mail_from, bcc_addresses, mail_subject, body_mail) except PmError as e: pm_logger.error("通知メール送信に失敗しました。") return common_utils.error_exception(MsgConst.ERR_SES_801, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) response = common_utils.get_response_by_response_body( HTTPStatus.CREATED, affiliation_result) # return data response return common_utils.response(response, pm_logger)
import unittest import os import copy from dotenv import load_dotenv from pathlib import Path from premembers.organizations.batch import projects from premembers.repository import pm_reports from premembers.repository import pm_organizationTasks from premembers.repository import pm_organizations, pm_projects from premembers.repository import pm_awsAccountCoops from premembers.common import common_utils from premembers.repository.const import Status trace_id = "eb3b5f76-8945-11e7-b15a-8f7e5433dada" user_id = common_utils.get_uuid4() mail_address = "test-user{}@example.com" organization_id = "reports-78ee-11e7-89e6-OrganizationID" organization_id_error = "reports-78ee-11e7-89e6-OrganizationID-error{}" project_id = "reports-77f1-11e7-adfe-ProjectID" project_id_error = "reports-77f1-11e7-adfe-ProjectID-error{}" report_id = "reports-77f1-11e7-adfe-ReportID{}" coop_id = "awscoops-77f1-11e7-adfe-CoopID{}" log_id = "reports-77f1-11e7-adfe-LogID{}" task_id = "reports-77f1-11e7-adfe-TaskID{}" organization_template = { "OrganizationID": organization_id, "OrganizationName": "OrganizationName", "Contract": 1, "ContractStatus": 1
def create_report(trace_id, email, organization_id, project_id, data_body): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) try: project = pm_projects.get_projects_by_organization_id( trace_id, project_id, organization_id) except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # 組織情報を取得します。 if (not project): return common_utils.error_common(MsgConst.ERR_AWS_401, HTTPStatus.UNPROCESSABLE_ENTITY, pm_logger) # Parse JSON try: body_object = json.loads(data_body) report_name = body_object["name"] aws_accounts = body_object["awsAccounts"] output_file_type = body_object["outputFileType"] except Exception as e: return common_utils.error_exception(MsgConst.ERR_REQUEST_202, HTTPStatus.BAD_REQUEST, e, pm_logger, True) # Validate list_error = validate_report(trace_id, report_name, aws_accounts, output_file_type) if list_error: return common_utils.error_validate(MsgConst.ERR_REQUEST_201, HTTPStatus.UNPROCESSABLE_ENTITY, list_error, pm_logger) # Create report report_id = common_utils.get_uuid4() status = Status.Waiting.value html_output_status = Status.Waiting.value excel_output_status = Status.Waiting.value schema_version = CommonConst.SCHEMA_VERSION try: pm_reports.create_report(trace_id, report_id, report_name, email, aws_accounts, status, None, None, None, html_output_status, None, None, excel_output_status, None, None, schema_version, organization_id, project_id) except PmError as e: return common_utils.error_exception(MsgConst.ERR_DB_403, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # AWS利用状況情報収集ジョブの設定 # レポート中間ファイル作成ジョブの設定 # レポート出力ジョブの設定 codes = [ 'COLLECT_AWS_RESOURCE_INFO', 'OUTPUT_REPORT_JSON', 'OUTPUT_REPORT_EXCEL' ] job_id = [] for code in codes: response, job_id = job_report(trace_id, email, report_id, code, job_id) if response: # Delete report pm_reports.delete_reports(trace_id, report_id) return response try: report = pm_reports.query_report(trace_id, report_id, True) except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # return data response response = common_utils.get_response_by_response_body( HTTPStatus.CREATED, report) return common_utils.response(response, pm_logger)
def apply_change_email(user_id, mail_before_change, data_body): pm_logger = common_utils.begin_logger(user_id, __name__, inspect.currentframe()) # Parse JSON try: body_object = json.loads(data_body) except Exception as e: return common_utils.error_exception(MsgConst.ERR_REQUEST_202, HTTPStatus.BAD_REQUEST, e, pm_logger, True) mail_after_change = common_utils.get_value("mailAddress", body_object, None) caller_service_name = common_utils.get_value("callerServiceName", body_object, None) mail_lang = common_utils.get_value("mailLang", body_object, None) # validate list_errors = validate_param_apply_change_email(user_id, mail_lang, caller_service_name, mail_before_change) if list_errors: return common_utils.error_validate(MsgConst.ERR_REQUEST_201, HTTPStatus.UNPROCESSABLE_ENTITY, list_errors, pm_logger) # Cognito UserPoolsから変更するメールアドレス{mailaddress}に該当するユーザー情報情報を取得します。 try: list_users = aws_common.get_cognito_user_pools(user_id, mail_after_change, "email") except PmError as e: return common_utils.error_exception(MsgConst.ERR_COGNITO_501, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) if list_users: return common_utils.error_common(MsgConst.ERR_302, HTTPStatus.CONFLICT, pm_logger) # メールアドレス変更申請テーブルから申請レコードを取得します。 try: list_email_change_apply = pm_emailChangeApply.query_user_index(user_id) except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) if list_email_change_apply: return common_utils.error_common(MsgConst.ERR_302, HTTPStatus.CONFLICT, pm_logger) # メールアドレス変更申請テーブルに申請レコードを作成します。 apply_id = common_utils.get_uuid4() time_to_live = common_utils.get_time_to_live( CommonConst.EMAIL_CHANGE_APPLY_EXPIRATION_DATE) try: pm_emailChangeApply.create(user_id, apply_id, mail_before_change, mail_after_change, time_to_live, caller_service_name) except PmError as e: return common_utils.error_exception(MsgConst.ERR_DB_403, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # get record PM_EmailChangeApply try: result = pm_emailChangeApply.query_key(user_id, apply_id, convert_response=True) except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # S3から通知メール送信設定ファイルを取得します。 try: config = FileUtils.read_yaml(user_id, CommonConst.S3_SETTING_BUCKET, CommonConst.NOTIFY_CONFIG_CIS_RESULT_MAIL) except PmError as e: pm_logger.error( "メールアドレス変更通知メール送信設定ファイルの取得に失敗しました。:s3://%s/%s", common_utils.get_environ(CommonConst.S3_SETTING_BUCKET), CommonConst.NOTIFY_CONFIG_CIS_RESULT_MAIL) return common_utils.error_exception(MsgConst.ERR_S3_702, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) path_file_template = config[ CommonConst.KEY_GET_PATH_FILE_TEMPLATE_MAIL_SERVICE.format( language=mail_lang, serviceName=caller_service_name)] # 通知メール本文を作成 try: template_body_mail = FileUtils.read_decode( user_id, CommonConst.S3_SETTING_BUCKET, path_file_template) except PmError as e: pm_logger.error( "メールアドレス変更通知メール本文テンプレートファイルの取得に失敗しました。:s3://%s/%s", common_utils.get_environ(CommonConst.S3_SETTING_BUCKET), path_file_template) return common_utils.error_exception(MsgConst.ERR_S3_702, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # SESで通知メールを送信します。 bcc_addresses = [mail_after_change] template_body_mail = Template(template_body_mail) body_mail = template_body_mail.render(ApplyID=apply_id) mail_subject = config[CommonConst.KEY_MAIL_SUBJECT_SERVICE.format( language=mail_lang, serviceName=caller_service_name)] mail_form = config[CommonConst.KEY_MAIL_FROM_SERVICE.format( serviceName=caller_service_name)] try: aws_common.send_email(user_id, config['ses.region'], mail_form, bcc_addresses, mail_subject, body_mail) except PmError as e: pm_logger.error("通知メール送信に失敗しました。") return common_utils.error_exception(MsgConst.ERR_SES_801, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # return data response response = common_utils.get_response_by_response_body( HTTPStatus.CREATED, result) return common_utils.response(response, pm_logger)
def create_excluded_resources(trace_id, user_id, organization_id, project_id, coop_id, check_item_code, email, data_body): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) # AWSアカウントAWSAccountは、AWSアカウント連携テーブルに、AWSアカウント連携ID{coop_id}をキーとしてクエリを実行します。 try: awscoops_item = pm_awsAccountCoops.query_awscoop_coop_key( trace_id, coop_id) except Exception as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # 有効なAWSアカウントが存在しなかった場合(取得件数が0件) if (not awscoops_item): return common_utils.error_common(MsgConst.ERR_AWS_401, HTTPStatus.UNPROCESSABLE_ENTITY, pm_logger) # チェック項目コード if check_item_code not in LIST_CHECK_ITEM_CODE_EXCLUDED_RESOURCE: return common_utils.error_common(MsgConst.ERR_AWS_401, HTTPStatus.UNPROCESSABLE_ENTITY, pm_logger) # リクエストボディのJSONでパースエラーが発生した場合は、エラーログを出力してエラーレスポンスを返します。 try: body_object = json.loads(data_body) except Exception as e: return common_utils.error_exception(MsgConst.ERR_REQUEST_202, HTTPStatus.BAD_REQUEST, e, pm_logger, True) region_name = common_utils.get_value("regionName", body_object, None) resource_type = common_utils.get_value("resourceType", body_object, None) resource_name = common_utils.get_value("resourceName", body_object, None) exclusion_comment = common_utils.get_value("exclusionComment", body_object, None).strip() # 全てのチェックを行い、エラーがあった場合はエラーログを出力してエラーレスポンスを返します。 list_error = validate_create_excluded_resources(region_name, resource_type, resource_name, exclusion_comment) if list_error: return common_utils.error_validate(MsgConst.ERR_REQUEST_201, HTTPStatus.UNPROCESSABLE_ENTITY, list_error, pm_logger) aws_account = awscoops_item['AWSAccount'] check_item_refine_code = CommonConst.CHECK_ITEM_REFINE_CODE.format( organization_id, project_id, aws_account, check_item_code) try: excluded_resource = pm_exclusionResources.query_filter_region_name_and_resource_name( trace_id, check_item_refine_code, region_name, resource_type, resource_name) except Exception as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) if not excluded_resource: exclusion_resource_id = common_utils.get_uuid4() account_refine_code = CommonConst.ACCOUNT_REFINE_CODE.format( organization_id, project_id, aws_account) time_to_live_date = date_utils.get_current_date() + timedelta(days=180) time_to_live = Decimal(time_to_live_date.timestamp()) # リソース除外設定テーブルに除外設定レコードを作成します。 try: pm_exclusionResources.create( user_id, exclusion_resource_id, organization_id, project_id, aws_account, check_item_code, region_name, resource_type, resource_name, exclusion_comment, email, account_refine_code, check_item_refine_code, time_to_live) except Exception as e: return common_utils.error_exception( MsgConst.ERR_DB_403, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) else: exclusion_resource_id = excluded_resource[0]["ExclusionResourceID"] attribute = {'ExclusionComment': {"Value": exclusion_comment}} try: pm_exclusionResources.update(trace_id, exclusion_resource_id, attribute) except Exception as e: return common_utils.error_exception( MsgConst.ERR_DB_404, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) try: excluded_resource_new = pm_exclusionResources.query_key( trace_id, exclusion_resource_id, True) except Exception as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # return response data response = common_utils.get_response_by_response_body( HTTPStatus.CREATED, excluded_resource_new) return common_utils.response(response, pm_logger)