def delete_notifymail(trace_id, organization_id, notify_code): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) # 全てのチェックを行い、エラーがあった場合はログを出力してエラーレスポンスを返します。 list_error = validate_notifymail(notify_code) if list_error: return common_utils.error_validate(MsgConst.ERR_REQUEST_201, HTTPStatus.UNPROCESSABLE_ENTITY, list_error, pm_logger) try: result = pm_orgNotifyMailDestinations.query_key( trace_id, organization_id, notify_code) except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) if (not result): return common_utils.error_common(MsgConst.ERR_301, HTTPStatus.NOT_FOUND, pm_logger) try: pm_orgNotifyMailDestinations.delete(trace_id, organization_id, notify_code) except PmError as e: return common_utils.error_exception(MsgConst.ERR_DB_404, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # return response data response = common_utils.get_response_by_response_body( HTTPStatus.NO_CONTENT, None) return common_utils.response(response, pm_logger)
def test_create_notifymail_success(self): notifymail_create['notifyCode'] = "CHECK_CIS" pm_orgNotifyMailDestinations.delete(trace_id, organization_id, notifymail_create['notifyCode']) test_user_id = user_id.format(str(3)) # handler path_parameters = {"organization_id": organization_id} notifymail_create['users'] = [user_id.format(str(3))] event_mock = event_create.get_event_object( path_parameters=path_parameters, trace_id=test_user_id, body=json.dumps(notifymail_create)) response = notifymail.create_notifymail_handler(event_mock, {}) # Get data response status_code = response['statusCode'] response_body = json.loads(response['body']) organizationId = response_body["organizationId"] notify_code = response_body['notifyCode'] destinations = response_body['destinations'] createdAt = response_body['createdAt'] updatedAt = response_body['updatedAt'] # Get data in database result_database = pm_orgNotifyMailDestinations.query_key( trace_id, organization_id, notifymail_create['notifyCode'], True) # Check data self.assertEqual(organizationId, result_database['organizationId']) self.assertEqual(notify_code, result_database['notifyCode']) self.assertEqual(destinations, result_database['destinations']) self.assertEqual(createdAt, result_database['createdAt']) self.assertEqual(updatedAt, result_database['updatedAt']) self.assertEqual(status_code, HTTPStatus.CREATED.value)
def execute_delete_organization_user(task_id): pm_logger = common_utils.begin_logger(task_id, __name__, inspect.currentframe()) # タスク情報を取得します。 # タスク情報のステータスチェックを行います。 target = organizationTask_logic.check_process_status(task_id) if target is None: pm_logger.error("組織タスク情報取得に失敗しました。: TaskID=%s", task_id) raise PmError() # タスク情報から処理対象(ユーザーID,組織ID)を取得します。 target = target.split(CommonConst.COMMA) user_id = target[0] organization_id = target[1] # 削除処理 # 組織別通知メール宛先テーブル(PM_OrgNotifyMailDestinations)に組織ID{organization_id}をキーとしてクエリを実行し、対象情報を取得する。 try: org_notify_mail_destinations = pm_orgNotifyMailDestinations.query_key( task_id, organization_id, CommonConst.NOTIFY_CODE) except PmError as e: pm_logger.error("組織別通知メール宛先情報取得に失敗しました。: OrganizationID=%s", organization_id) raise common_utils.write_log_pm_error(e, pm_logger) # キーに合致するレコードが存在しなかった場合 if (not org_notify_mail_destinations): # 処理を正常終了する。 return # 取得したレコードのDestinationsのListデータを編集する。 destinations = jmespath.search( "[?UserID != '{0}']".format(user_id), org_notify_mail_destinations['Destinations']) # 編集後のDestinationsは、組織別通知メール宛先テーブル(PM_OrgNotifyMailDestinations)へ組織ID{organization_id}をキーとしてupdate_itemで更新する。(UpdatedAtも現在日時で更新する) try: if (len(destinations) == 0): # 編集後のDestinationsのListデータが0件になる場合、組織別通知メール宛先テーブル(PM_OrgNotifyMailDestinations)の該当レコードを削除する。 pm_orgNotifyMailDestinations.delete(task_id, organization_id, CommonConst.NOTIFY_CODE) else: attribute = {'Destinations': {"Value": destinations}} pm_orgNotifyMailDestinations.update(task_id, organization_id, CommonConst.NOTIFY_CODE, attribute) except PmError as e: pm_logger.error("組織別通知メール宛先情報の更新に失敗しました。: OrganizationID=%s", organization_id) raise common_utils.write_log_pm_error(e, pm_logger)
def execute_change_email(apply_id): pm_logger = common_utils.begin_logger(apply_id, __name__, inspect.currentframe()) # バリデーションチェックを行います if common_utils.is_null(apply_id): return common_utils.error_common(MsgConst.ERR_201, HTTPStatus.UNPROCESSABLE_ENTITY, pm_logger) # set default value caller_service_name = 'insightwatch' # S3から通知メール送信設定ファイルを取得します。 try: config = FileUtils.read_yaml(apply_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) common_utils.error_exception(MsgConst.ERR_S3_702, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) return common_utils.get_response_by_response_body( HTTPStatus.OK, CommonConst.DEFAULT_RESPONSE_ERROR_PAGE[caller_service_name], is_response_json=False, content_type=CommonConst.CONTENT_TYPE_TEXT_HTML) # set data response error page default response_error_page = config[CommonConst.KEY_RESPONSE_ERROR_PAGE.format( serviceName=caller_service_name)] # メールアドレス変更申請テーブルから申請レコードを取得します。 try: email_change_apply_info = pm_emailChangeApply.query_key( apply_id, apply_id, None) except PmError: pm_logger.error("メールアドレス変更申請テーブルでレコード取得に失敗しました。変更申請ID: %s", apply_id) return common_utils.get_response_by_response_body( HTTPStatus.OK, response_error_page, is_response_json=False, content_type=CommonConst.CONTENT_TYPE_TEXT_HTML) if not email_change_apply_info: pm_logger.warning("メールアドレス変更申請テーブルでレコードが存在しませんでした。変更申請ID: %s", apply_id) return common_utils.get_response_by_response_body( HTTPStatus.OK, response_error_page, is_response_json=False, content_type=CommonConst.CONTENT_TYPE_TEXT_HTML) user_name = email_change_apply_info['UserID'] if common_utils.check_key('CallerServiceName', email_change_apply_info): caller_service_name = email_change_apply_info['CallerServiceName'] # data response page response_error_page = config[CommonConst.KEY_RESPONSE_ERROR_PAGE.format( serviceName=caller_service_name)] response_execute_change_email = config[ CommonConst.KEY_RESPONSE_EXECUTE_CHANGE_EMAIL.format( serviceName=caller_service_name)] # メールアドレス変更申請テーブルから取得した UserID でCognito に合致する該当するユーザー情報を取得します。 try: user_info = aws_common.get_cognito_user_info_by_user_name( apply_id, user_name) except PmError: pm_logger.error("Cognitoから情報取得に失敗しました。") return common_utils.get_response_by_response_body( HTTPStatus.OK, response_error_page, is_response_json=False, content_type=CommonConst.CONTENT_TYPE_TEXT_HTML) if not user_info: pm_logger.warning("Cognitoにユーザーが存在しませんでした。ユーザーID: %s", user_name) return common_utils.get_response_by_response_body( HTTPStatus.OK, response_error_page, is_response_json=False, content_type=CommonConst.CONTENT_TYPE_TEXT_HTML) before_mail_address = email_change_apply_info['BeforeMailAddress'] after_mail_address = email_change_apply_info['AfterMailAddress'] # get cognito email cognito_email = jmespath.search("[?Name=='email'].Value | [0]", user_info['UserAttributes']) if before_mail_address != cognito_email: pm_logger.warning("変更前メールアドレスがCognitoのメールアドレスと合致しませんでした。") return common_utils.get_response_by_response_body( HTTPStatus.OK, response_error_page, is_response_json=False, content_type=CommonConst.CONTENT_TYPE_TEXT_HTML) # Cognitoのメールアドレスを変更する try: user_attributes = [{ 'Name': 'email', 'Value': after_mail_address }, { 'Name': 'email_verified', 'Value': 'true' }] aws_common.update_cognito_user_attributes(apply_id, user_name, user_attributes) except PmError: pm_logger.error("Cognitoの項目変更に失敗しました。") return common_utils.get_response_by_response_body( HTTPStatus.OK, response_error_page, is_response_json=False, content_type=CommonConst.CONTENT_TYPE_TEXT_HTML) # get list affiliations try: affiliations = pm_affiliation.query_userid_key(apply_id, user_name) except PmError: pm_logger.error("ユーザー所属テーブルでレコード取得に失敗しました。") return common_utils.get_response_by_response_body( HTTPStatus.OK, response_error_page, is_response_json=False, content_type=CommonConst.CONTENT_TYPE_TEXT_HTML) for affiliation in affiliations: try: org_notify_mail_destinations = pm_orgNotifyMailDestinations.query_key( apply_id, affiliation['OrganizationID'], CommonConst.NOTIFY_CODE, None) except PmError: pm_logger.error("組織別通知メール宛先テーブルでレコード取得に失敗しました。") return common_utils.get_response_by_response_body( HTTPStatus.OK, response_error_page, is_response_json=False, content_type=CommonConst.CONTENT_TYPE_TEXT_HTML) if org_notify_mail_destinations: destinations_update = [] for destination in org_notify_mail_destinations['Destinations']: if destination['MailAddress'] == before_mail_address: destination['MailAddress'] = after_mail_address destinations_update.append(destination) # update pm_orgNotifyMailDestinations try: attribute = {'Destinations': {"Value": destinations_update}} pm_orgNotifyMailDestinations.update( apply_id, org_notify_mail_destinations['OrganizationID'], org_notify_mail_destinations['NotifyCode'], attribute) except PmError: pm_logger.error("組織別通知メール宛先テーブルでレコード更新に失敗しました。") return common_utils.get_response_by_response_body( HTTPStatus.OK, response_error_page, is_response_json=False, content_type=CommonConst.CONTENT_TYPE_TEXT_HTML) # update pm_affiliation try: attribute = {'MailAddress': {"Value": after_mail_address}} pm_affiliation.update_affiliation(apply_id, affiliation['UserID'], affiliation['OrganizationID'], attribute, affiliation['UpdatedAt']) except PmError: pm_logger.error("ユーザー所属テーブルでレコード更新に失敗しました。") return common_utils.get_response_by_response_body( HTTPStatus.OK, response_error_page, is_response_json=False, content_type=CommonConst.CONTENT_TYPE_TEXT_HTML) # メールアドレス変更申請テーブルで変更申請ID{applyid}をキーにして申請レコードを削除する。 try: pm_emailChangeApply.delete(apply_id, apply_id) except PmError: pm_logger.error("メールアドレス変更申請テーブルでレコード削除に失敗しました。変更申請ID: %s", apply_id) return common_utils.get_response_by_response_body( HTTPStatus.OK, response_error_page, is_response_json=False, content_type=CommonConst.CONTENT_TYPE_TEXT_HTML) # data response response = common_utils.get_response_by_response_body( HTTPStatus.OK, response_execute_change_email, is_response_json=False, content_type=CommonConst.CONTENT_TYPE_TEXT_HTML) return common_utils.response(response, pm_logger)
def create_notifymail(trace_id, organization_id, data_body): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) # リクエストボディのJSONでパースエラーが発生した場合は、ログを出力してエラーレスポンスを返します。 try: body_object = json.loads(data_body) notify_code = body_object["notifyCode"] users = body_object["users"] except Exception as e: return common_utils.error_exception(MsgConst.ERR_REQUEST_202, HTTPStatus.BAD_REQUEST, e, pm_logger, True) # 全てのチェックを行い、エラーがあった場合はログを出力してエラーレスポンスを返します。 list_error = validate_notifymail(notify_code, users) if list_error: return common_utils.error_validate(MsgConst.ERR_REQUEST_201, HTTPStatus.UNPROCESSABLE_ENTITY, list_error, pm_logger) # 宛先ユーザーのメールアドレスを取得します。 destinations = [] for user_id in users: try: affiliation = pm_affiliation.get_affiliation( user_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 affiliation): continue # 宛先ユーザー配列は、ユーザーIDとメールアドレスを属性として持つオブジェクトの配列として表現します。 destination = { "UserID": user_id, "MailAddress": affiliation['MailAddress'] } destinations.append(destination) if len(destinations) == 0: list_error = [] list_error.append( common_utils.get_error_validate(MsgConst.ERR_VAL_999, "users", users)) return common_utils.error_validate(MsgConst.ERR_REQUEST_201, HTTPStatus.UNPROCESSABLE_ENTITY, list_error, pm_logger) # 宛先情報を作成します。 try: pm_orgNotifyMailDestinations.create(trace_id, organization_id, notify_code, destinations) except PmError as e: return common_utils.error_exception(MsgConst.ERR_DB_403, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) # 宛先情報を取得します。 try: result = pm_orgNotifyMailDestinations.query_key( trace_id, organization_id, notify_code, True) except PmError as e: return common_utils.error_exception(MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e, pm_logger, True) response = common_utils.get_response_by_response_body( HTTPStatus.CREATED, result) # return data response return common_utils.response(response, pm_logger)
def send_result_email(trace_id, check_history_id, language): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) # チェック結果テーブルのCheckHistoryIndexから、チェック履歴ID{CheckHistoryId}をキーとしてチェック結果一覧を取得します。 try: list_check_result = pm_checkResults.query_history_index( trace_id, check_history_id) except PmError as e: msg_err = "チェック結果の取得に失敗しました。" pm_logger.error(msg_err) raise common_utils.write_log_pm_error(e, pm_logger, msg_err) if (not list_check_result): msg_err = "チェック結果の取得に失敗しました。" pm_logger.error(msg_err) raise PmError(message=msg_err) # チェック結果一覧のうちの一つから、組織IDを取得します。 organization_id = list_check_result[0]['OrganizationID'] organization_name = list_check_result[0]['OrganizationName'] project_name = list_check_result[0]['ProjectName'] # 宛先ユーザーの確認をします。ユーザー所属テーブルのOrganizationIndexから、組織IDをキー try: users = pm_affiliation.query_users_organization_index( trace_id, organization_id, InvitationStatus.Belong) except PmError as e: msg_err = "ユーザー所属情報の取得に失敗しました。:OrganizationID={0}".format( organization_id) pm_logger.error(msg_err) raise common_utils.write_log_pm_error(e, pm_logger, msg_err) # 組織別通知メール宛先テーブルから、組織ID、通知コードCHECK_CISをキーとして宛先情報を取得します。 try: org_notify_mail_destinations = pm_orgNotifyMailDestinations.query_key( trace_id, organization_id, CommonConst.NOTIFY_CODE) except PmError as e: msg_err = "宛先情報の取得に失敗しました。:OrganizationID={0}, CheckCode={1}".format( organization_id, CommonConst.NOTIFY_CODE) pm_logger.error(msg_err) raise common_utils.write_log_pm_error(e, pm_logger, msg_err) if (not org_notify_mail_destinations): msg_err = "宛先情報の取得に失敗しました。:OrganizationID={0}, CheckCode={1}".format( organization_id, CommonConst.NOTIFY_CODE) pm_logger.error(msg_err) raise PmError(message=msg_err) destinations = [] for destination in org_notify_mail_destinations['Destinations']: for user in users: if destination['UserID'] == user['UserID']: destinations.append(destination) break try: if (len(destinations) == 0): pm_orgNotifyMailDestinations.delete(trace_id, organization_id, CommonConst.NOTIFY_CODE) else: attribute = {'Destinations': {"Value": destinations}} pm_orgNotifyMailDestinations.update(trace_id, organization_id, CommonConst.NOTIFY_CODE, attribute) except PmError as e: msg_err = "通知メール宛先ユーザーの更新に失敗しました。:OrganizationID={0}, CheckCode={1}".format( organization_id, CommonConst.NOTIFY_CODE) pm_logger.error(msg_err) raise common_utils.write_log_pm_error(e, pm_logger, msg_err) # S3から通知メール送信設定ファイルを取得します。 try: config = FileUtils.read_yaml(trace_id, CommonConst.S3_SETTING_BUCKET, CommonConst.NOTIFY_CONFIG_CIS_RESULT_MAIL) except PmError as e: msg_err = "通知メール送信設定ファイルの取得に失敗しました。:s3://{0}/{1}".format( common_utils.get_environ(CommonConst.S3_SETTING_BUCKET), CommonConst.NOTIFY_CONFIG_CIS_RESULT_MAIL) pm_logger.error(msg_err) raise common_utils.write_log_pm_error(e, pm_logger, msg_err) language_mail = CommonConst.LANGUAGE_DEFAULT if language in CommonConst.LANGUAGE_SUPPORT: language_mail = language path_file_template = config[CommonConst.KEY_GET_PATH_FILE_TEMPLATE_MAIL. format(language=language_mail)] mail_subject_config = config[CommonConst.KEY_MAIL_SUBJECT.format( language=language_mail)] # 通知メール本文を作成 try: template_body = FileUtils.read_decode(trace_id, CommonConst.S3_SETTING_BUCKET, path_file_template) except PmError as e: msg_err = "知メール本文テンプレートファイルの取得に失敗しました。:s3://{0}/{1}".format( common_utils.get_environ(CommonConst.S3_SETTING_BUCKET), path_file_template) pm_logger.error(msg_err) raise common_utils.write_log_pm_error(e, pm_logger, msg_err) # 通知メール件名を作成 subject_template = Template(mail_subject_config) mail_subject = subject_template.render(project_name=project_name) # メール本文 executed_date_time = date_utils.toString( date_utils.toDate(list_check_result[0]['ExecutedDateTime'], date_utils.UTC), date_utils.PATTERN_YYYYMMDDHHMM, date_utils.ASIA_TOKYO) executed_date_time_utc = date_utils.toString( date_utils.toDate(list_check_result[0]['ExecutedDateTime'], date_utils.UTC), date_utils.PATTERN_YYYYMMDDHHMM, date_utils.UTC) check_results = [] for check_result in list_check_result: account_aws = CommonConst.AWS_ACCOUNT_MAIL.format( check_result['AWSAccount'][:4], check_result['AWSAccount'][4:8]) check_result = { "accountAWS": account_aws, "okCount": check_result['OKCount'], "ngCount": check_result['NGCount'], "criticalCount": check_result['CriticalCount'], "managedCount": check_result['ManagedCount'], "errorCount": check_result['ErrorCount'] } check_results.append(check_result) template = Template(template_body) context = { 'organizationName': organization_name, 'projectName': project_name, 'executedDateTime': executed_date_time, 'executedDateTimeUTC': executed_date_time_utc, 'checkResults': check_results } body = template.render(context) # SESで通知メールを送信します。 list_bcc_addresses = [] bcc_addresses = [] for index, destination in enumerate(destinations): bcc_addresses.append(destination['MailAddress']) if (len(bcc_addresses) >= 50 or len(destinations) == index + 1): list_bcc_addresses.append(bcc_addresses) bcc_addresses = [] for index, bcc_addresses in enumerate(list_bcc_addresses): try: aws_common.send_email(trace_id, config['ses.region'], config['mail.from'], bcc_addresses, mail_subject, body) except PmError as e: msg_err = "通知メール送信に失敗しました。({0}/{1})".format( index + 1, len(list_bcc_addresses)) pm_logger.error(msg_err) raise common_utils.write_log_pm_error(e, pm_logger, msg_err)
def check_result_notification(check_history_id, language): trace_id = check_history_id pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) try: list_check_result = pm_checkResults.query_history_index( trace_id, check_history_id) except PmError as e: pm_logger.error("チェック結果取得に失敗しました。: CheckHistoryID=%s", check_history_id) return if (not list_check_result): pm_logger.error("チェック結果がありません。: CheckHistoryID=%s", check_history_id) return is_all_record_ok = True for check_result in list_check_result: if (check_result['NGCount'] > 0 or check_result['CriticalCount'] > 0 or check_result['ErrorCount'] > 0): is_all_record_ok = False break # 全てOKだった場合は、ログを出力してこの処理をスキップします。 if (is_all_record_ok is True): pm_logger.info("チェック結果が全て正常なため、結果通知処理をスキップします。") return organization_id = list_check_result[0]['OrganizationID'] org_notify_mail_destinations = [] # Lambda関数呼び出し時のPayloadには、チェック履歴IDをJSONとして渡します。 payload = {'CheckHistoryId': check_history_id, 'Language': language} service_name = common_utils.get_service_name() stage = common_utils.get_stage() try: org_notify_mail_destinations = pm_orgNotifyMailDestinations.query_key( trace_id, organization_id, CommonConst.NOTIFY_CODE) except PmError as e: pm_logger.error("宛先の取得に失敗しました。結果通知処理をスキップします。") if (not org_notify_mail_destinations): pm_logger.info("宛先が未設定のため、結果通知処理をスキップします。") else: # セキュリティチェック結果通知メール送信処理のLambdaを非同期で呼び出します。 function_name = CommonConst.EXECUTE_SEND_RESULT_EMAIL.format( service_name, stage) aws_common.lambda_invoke(trace_id, function_name, json.dumps(payload)) # 組織別Slack通知設定テーブルから、組織ID、通知コードCHECK_CISをキーとして設定情報を取得します。 try: org_notify_slack = pm_orgNotifySlack.query_key(trace_id, organization_id, CommonConst.NOTIFY_CODE) except PmError as e: pm_logger.error("Slack通知設定の取得に失敗しました。結果Slack通知処理をスキップします。") return if (not org_notify_slack): pm_logger.info("Slack通知が未設定のため、結果Slack通知処理をスキップします。") return # セキュリティチェック結果通知Slack送信のLambdaを非同期で呼び出します。 function_name_send_slack = CommonConst.EXECUTE_SEND_RESULT_SLACK.format( service_name, stage) aws_common.lambda_invoke(trace_id, function_name_send_slack, json.dumps(payload))