diff --git a/lambda/check-view-secutiry-option/check-view-option/aws/sns.py b/lambda/check-view-secutiry-option/check-view-option/aws/sns.py new file mode 100644 index 00000000..d81e7307 --- /dev/null +++ b/lambda/check-view-secutiry-option/check-view-option/aws/sns.py @@ -0,0 +1,31 @@ +import boto3 +import environments +from constants import AWS_RESOURCE_SNS + + +class SNSClient: + + def __init__(self) -> None: + self.__sns_client = boto3.client(AWS_RESOURCE_SNS) + + def publish(self, sns_topic_arn: str, subject: str, message: str) -> None: + publish_params = { + 'TopicArn': sns_topic_arn, + 'Subject': subject.rstrip('\n'), + 'Message': message + } + self.__sns_client.publish(**publish_params) + + +class SNSNotifier: + __sns_client: SNSClient = None + + def __init__(self) -> None: + self.__sns_client = SNSClient() + + def publish_to_mbj(self, subject: str, message: str): + self.__sns_client.publish(environments.MBJ_NOTICE_TOPIC, subject, message) + + def publish_to_nds(self, error_id: str, exception: Exception): + error_message = f'{error_id} のエラーが発生しました。ご確認ください\n詳細:{exception}' + self.__sns_client.publish(environments.NDS_NOTICE_TOPIC, environments.NDS_NOTICE_TITLE, error_message) diff --git a/lambda/check-view-secutiry-option/check-view-option/constants.py b/lambda/check-view-secutiry-option/check-view-option/constants.py index 9f6b0735..ac6b2bfa 100644 --- a/lambda/check-view-secutiry-option/check-view-option/constants.py +++ b/lambda/check-view-secutiry-option/check-view-option/constants.py @@ -9,6 +9,7 @@ CONFIG_BUCKET_NAME = 'CONFIG_BUCKET_NAME' LOG_LEVEL = 'LOG_LEVEL' MBJ_NOTICE_TOPIC = 'MBJ_NOTICE_TOPIC' NDS_NOTICE_TOPIC = 'NDS_NOTICE_TOPIC' +NDS_NOTICE_TITLE = 'NDS_NOTICE_TITLE' NOTICE_MAIL_BODY_TEMPLATE_PATH = 'NOTICE_MAIL_BODY_TEMPLATE_PATH' NOTICE_MAIL_TITLE_TEMPLATE_PATH = 'NOTICE_MAIL_TITLE_TEMPLATE_PATH' PARAM_NAME_DB_HOST = 'PARAM_NAME_DB_HOST' @@ -19,6 +20,7 @@ TZ = 'TZ' # aws AWS_RESOURCE_S3 = 's3' AWS_RESOURCE_SSM = 'ssm' +AWS_RESOURCE_SNS = 'sns' S3_RESPONSE_BODY = 'Body' SSM_PARAMETER_RESPONSE = 'Parameter' SSM_PARAMETER_NAME = 'Name' diff --git a/lambda/check-view-secutiry-option/check-view-option/environments.py b/lambda/check-view-secutiry-option/check-view-option/environments.py index 87156c19..3a292a68 100644 --- a/lambda/check-view-secutiry-option/check-view-option/environments.py +++ b/lambda/check-view-secutiry-option/check-view-option/environments.py @@ -2,7 +2,8 @@ import os from constants import (CHECK_TARGET_SCHEMA_NAMES_PATH, CONFIG_BUCKET_NAME, LOG_LEVEL, LOG_LEVEL_INFO, MBJ_NOTICE_TOPIC, - NDS_NOTICE_TOPIC, NOTICE_MAIL_BODY_TEMPLATE_PATH, + NDS_NOTICE_TITLE, NDS_NOTICE_TOPIC, + NOTICE_MAIL_BODY_TEMPLATE_PATH, NOTICE_MAIL_TITLE_TEMPLATE_PATH, PARAM_NAME_DB_HOST, PARAM_NAME_DB_USER_NAME, PARAM_NAME_DB_USER_PASSWORD, TZ) @@ -12,6 +13,7 @@ CHECK_TARGET_SCHEMA_NAMES_PATH = os.environ[CHECK_TARGET_SCHEMA_NAMES_PATH] CONFIG_BUCKET_NAME = os.environ[CONFIG_BUCKET_NAME] MBJ_NOTICE_TOPIC = os.environ[MBJ_NOTICE_TOPIC] NDS_NOTICE_TOPIC = os.environ[NDS_NOTICE_TOPIC] +NDS_NOTICE_TITLE = os.environ[NDS_NOTICE_TITLE] NOTICE_MAIL_BODY_TEMPLATE_PATH = os.environ[NOTICE_MAIL_BODY_TEMPLATE_PATH] NOTICE_MAIL_TITLE_TEMPLATE_PATH = os.environ[NOTICE_MAIL_TITLE_TEMPLATE_PATH] diff --git a/lambda/check-view-secutiry-option/check-view-option/exceptions.py b/lambda/check-view-secutiry-option/check-view-option/exceptions.py index 90cd6efb..aebd28c3 100644 --- a/lambda/check-view-secutiry-option/check-view-option/exceptions.py +++ b/lambda/check-view-secutiry-option/check-view-option/exceptions.py @@ -27,3 +27,8 @@ class DatabaseConnectionException(MeDaCaException): class QueryExecutionException(MeDaCaException): """クエリ実行に失敗した場合の例外""" pass + + +class SNSPublishException(MeDaCaException): + """AmazonSNSへの通知に失敗した場合の例外""" + pass diff --git a/lambda/check-view-secutiry-option/check-view-option/main.py b/lambda/check-view-secutiry-option/check-view-option/main.py index f626b0b8..0226d3e3 100644 --- a/lambda/check-view-secutiry-option/check-view-option/main.py +++ b/lambda/check-view-secutiry-option/check-view-option/main.py @@ -7,6 +7,7 @@ import json import botocore from aws.s3 import ConfigBucket +from aws.sns import SNSNotifier from aws.ssm import SSMParameterStore from constants import (CHECK_TARGET_SCHEMAS, INFORMATION_SCHEMA_SECURITY_TYPE_INVOKER, MAIL_INDENT, @@ -15,9 +16,10 @@ from constants import (CHECK_TARGET_SCHEMAS, RESPONSE_ERROR_CODE) from database import Database from dto.view_secutiry_option import ViewSecurityOption +from environments import MBJ_NOTICE_TOPIC from exceptions import (DatabaseConnectionException, FileNotFoundException, MeDaCaException, ParameterNotFoundException, - QueryExecutionException) + QueryExecutionException, SNSPublishException) from medaca_logger import MeDaCaLogger logger = MeDaCaLogger.get_logger() @@ -46,13 +48,18 @@ def handler(event, context): view_security_options = [ViewSecurityOption(*row) for row in check_result] mail_title, mail_body = make_notice_mail(view_security_options) - print(mail_title, mail_body) + + logger.info('I-05-06', f'メール送信指示をします 送信先トピック:{MBJ_NOTICE_TOPIC}') + notice_to_mbj(mail_title, mail_body) + logger.info('I-05-07', 'メール送信指示をしました') except MeDaCaException as e: logger.exception(e.error_id, e) + notice_to_nds(e.error_id, e) raise e except Exception as e: logger.exception('E-99', f'想定外のエラーが発生しました エラー内容:{e}') + notice_to_nds('E-99', e) raise e finally: logger.info('I-06-01', '処理終了 Viewセキュリティオプション付与チェック') @@ -158,7 +165,7 @@ def fetch_view_security_options(connection: Database, check_target_schemas: list raise QueryExecutionException('E-03-02', f'Viewセキュリティオプションチェックに失敗しました エラー内容:{e}') -def make_notice_mail(view_security_options: list[ViewSecurityOption]): +def make_notice_mail(view_security_options: list[ViewSecurityOption]) -> tuple[str]: config_bucket = ConfigBucket() logger.info( 'I-05-02', f'通知メール(タイトル)テンプレートファイル読込 読込元:{config_bucket.bucket_name}/{config_bucket.mail_title_file_path}') @@ -174,7 +181,7 @@ def make_notice_mail(view_security_options: list[ViewSecurityOption]): return mail_title_template, mail_body -def read_mail_title(config_bucket: ConfigBucket): +def read_mail_title(config_bucket: ConfigBucket) -> str: """メールタイトルを読み込む Args: @@ -199,7 +206,7 @@ def read_mail_title(config_bucket: ConfigBucket): return mail_title -def read_mail_body_template(config_bucket: ConfigBucket): +def read_mail_body_template(config_bucket: ConfigBucket) -> str: """メール本文を読み込む Args: @@ -223,6 +230,39 @@ def read_mail_body_template(config_bucket: ConfigBucket): return mail_body_template +def notice_to_mbj(mail_title: str, mail_body: str) -> None: + """MBJへ通知を行います + + Args: + mail_title (str): メールタイトル + mail_body (str): メール本文 + + Raises: + SNSPublishException: SNSでの通知失敗した場合のエラー + """ + try: + notifier = SNSNotifier() + notifier.publish_to_mbj(mail_title, mail_body) + except Exception as e: + raise SNSPublishException('E-98', f'通知の送信指示に失敗しました エラー内容:{e}') + + +def notice_to_nds(error_id: str, error_message: str) -> None: + """NDSに処理以上通知を行う + + Args: + error_id (str): エラーID + error_message (str): エラーメッセージ + Raises: + SNSPublishException: SNSでの通知失敗した場合のエラー + """ + try: + notifier = SNSNotifier() + notifier.publish_to_nds(error_id, error_message) + except Exception as e: + raise SNSPublishException('E-98', f'通知の送信指示に失敗しました エラー内容:{e}') + + # ローカル実行用 if __name__ == '__main__': handler({}, {})