fix:SAPデータ復号化処理 コードレビュー指摘部分を修正した

This commit is contained in:
*lcOeIaePm0 2022-05-26 00:23:56 +09:00
parent 1924b6f7ec
commit 9bfd316292

View File

@ -1,9 +1,10 @@
from logging import exception
import logging
import os
import sys
import boto3
import gnupg
import datetime
import logging
from abc import *
# 環境変数
SECRET_KEY_FILE_BUCKET_NAME = os.environ["SECRET_KEY_FILE_BUCKET_NAME"]
@ -15,14 +16,13 @@ DATA_SOURCE_SAP_SUP = os.environ["DATA_SOURCE_SAP_SUP"]
DATA_SOURCE_SAP_FIN = os.environ["DATA_SOURCE_SAP_FIN"]
NDS_NOTICE_TOPIC = os.environ["NDS_NOTICE_TOPIC"]
NDS_NOTICE_TITLE = os.environ["NDS_NOTICE_TITLE"]
LOG_LEVEL = os.environ["LOG_LEVEL"]
# 定数
DIRECTORY_RECV = '/recv/'
DIRECTORY_RECV_ERROR = '/recv_error/'
EXTENSION_ERROR = '.error'
EXTENSION_DECRYPT_ERROR = '.decrypt_error'
LOG_INFO = 'Info'
LOG_ERROR = 'Error'
INDEX_EXTENSION_DELETE_NUM = -4
PATH_TEMP = '/tmp'
PATH_TEMP_PRIVATE_KEY = '/tmp/private.key'
@ -38,173 +38,159 @@ s3_client = boto3.client('s3')
s3_resource = boto3.resource('s3')
sns_client = boto3.client('sns')
# logger設定
logger = logging.getLogger()
formatter = logging.Formatter(
'[%(levelname)s]\t%(asctime)s\t%(message)s\n',
'%Y-%m-%d %H:%M:%S'
)
for handler in logger.handlers:
handler.setFormatter(formatter)
level = logging.getLevelName(LOG_LEVEL)
if not isinstance(level, int):
level = logging.INFO
logger.setLevel(level)
def handler(event, context):
# ① 処理開始ログを出力する
try:
print_log(LOG_INFO, 'I-01-01', '処理開始 SAPデータ復号処理')
today = datetime.date.today().strftime('%Y/%m/%d')
print_log(LOG_INFO, 'I-01-02', f'処理稼働日:{today}')
except Exception as e:
print_log(LOG_ERROR, 'E-99', f'想定外のエラーが発生しました エラー内容:{e}')
error_exit(event, EXTENSION_ERROR, 'E-99', e)
# ① 処理開始ログを出力する
logger.info('I-01-01 処理開始 SAPデータ復号処理')
execute_date = datetime.date.today().strftime('%Y/%m/%d')
logger.info(f'I-01-02 処理稼働日:{execute_date}')
# ② 処理開始時に受け取ったイベント情報の以下内容をログに出力しメモリに保持する
try:
print_log(LOG_INFO, 'I-02-01', 'イベント情報出力処理')
# ② 処理開始時に受け取ったイベント情報の以下内容をログに出力しメモリに保持する
logger.info('I-02-01 イベント情報出力処理')
s3_event = S3EventInfo(event["Records"][0]["s3"])
logger.info(f'I-02-02 バケット名:{s3_event.bucket_name}')
logger.info(f'I-02-03 ファイルパス:{s3_event.file_path}')
logger.info(f'I-02-04 データソース名:{s3_event.data_source_name}')
s3_event = event["Records"][0]["s3"]
event_bucket_name = s3_event["bucket"]["name"]
event_file_path = s3_event["object"]["key"]
event_file_name = os.path.basename(event_file_path)
event_data_source_name = os.path.dirname(event_file_path).split('/')[0]
print_log(LOG_INFO, 'I-02-02', f'バケット名:{event_bucket_name}')
print_log(LOG_INFO, 'I-02-03', f'ファイルパス:{event_file_path}')
print_log(LOG_INFO, 'I-02-04', f'データソース名:{event_data_source_name}')
except Exception as e:
print_log(LOG_ERROR, 'E-99', f'想定外のエラーが発生しました エラー内容:{e}')
error_exit(event, EXTENSION_ERROR, 'E-99', e)
# ③ S3から秘密鍵ファイルを読み込む
try:
print_log(LOG_INFO, 'I-03-01', f'秘密鍵ファイル読込 読込元:{SECRET_KEY_FILE_BUCKET_NAME}/{SECRET_KEY_FILE_PATH}')
s3_client.download_file(SECRET_KEY_FILE_BUCKET_NAME, SECRET_KEY_FILE_PATH, PATH_TEMP_PRIVATE_KEY)
print_log(LOG_INFO, 'I-03-02', '秘密鍵ファイルを読み込みました')
except Exception as e:
print_log(LOG_ERROR, 'E-03-01', f'秘密鍵ファイルの読み込みに失敗しました エラー内容:{e}')
error_exit(event, EXTENSION_ERROR, 'I-03-01', e)
# ④ S3からPGP暗号化ファイルを読み込む
try:
print_log(LOG_INFO, 'I-04-01', f'PGP暗号化ファイル読込 読込元{event_bucket_name}/{event_file_path}')
s3_client.download_file(event_bucket_name, event_file_path, PATH_TEMP_ENCRYPT_FILE)
print_log(LOG_INFO, 'I-04-02', 'PGP暗号化ファイルを読み込みました')
except Exception as e:
# ③ S3からPGP暗号化ファイルを読み込む
try:
print_log(LOG_ERROR, 'E-04-01', f'PGP暗号化ファイルの読み込みに失敗しました エラー内容{e}')
result_error_file_name = event_file_name + EXTENSION_ERROR
result_error_key = event_data_source_name + DIRECTORY_RECV + result_error_file_name
result_error_obj = s3_resource.Object(event_bucket_name, result_error_key)
result_error_obj.put(Body='')
print_log(LOG_ERROR, 'E-04-02', f'recvディレクトリにエラーファイルを作成しました ファイル名{result_error_file_name} 出力先:{event_bucket_name}/{result_error_key}')
print_log(LOG_ERROR, 'E-04-03', f'処理異常通知の送信指示をしました 通知先トピック:{NDS_NOTICE_TOPIC}')
error_msg = f'E-04-01 のエラーが発生しました。ご確認ください\n詳細:{e}'
params = {
'TopicArn': NDS_NOTICE_TOPIC,
'Subject': NDS_NOTICE_TITLE,
'Message': error_msg
}
sns_client.publish(**params)
print_log(LOG_ERROR, 'E-04-04', 'エラー終了 処理を中断します')
sys.exit()
logger.info(f'I-03-01 PGP暗号化ファイル読込 読込元{s3_event.bucket_name}/{s3_event.file_path}')
s3_client.download_file(s3_event.bucket_name, s3_event.file_path, PATH_TEMP_ENCRYPT_FILE)
logger.info('I-03-02 PGP暗号化ファイルを読み込みました')
except Exception as e:
print_log(LOG_ERROR, 'E-99', f'想定外のエラーが発生しました エラー内容:{e}')
error_exit(event, EXTENSION_ERROR, 'E-99', e)
logger.error(f'E-03-01 PGP暗号化ファイルの読み込みに失敗しました エラー内容{e}')
raise EncryptFileReadException('E-03-01', EXTENSION_ERROR, e)
# ⑤ 「③」で読み込んだ秘密鍵ファイルをPGPライブラリにインポートを行う
try:
print_log(LOG_INFO, 'I-05-01', '秘密鍵ファイルインポート')
gpg = gnupg.GPG(gnupghome=PATH_TEMP)
with open(PATH_TEMP_PRIVATE_KEY) as key_file:
gpg.import_keys(key_file.read())
print_log(LOG_INFO, 'I-05-02', '秘密鍵ファイルをインポートしました')
except Exception as e:
print_log(LOG_ERROR, 'E-05-01', f'秘密鍵ファイルのインポートに失敗しました エラー内容:{e}')
error_exit(event, EXTENSION_ERROR, 'E-05-01', e)
# ④ S3から秘密鍵ファイルを読み込む
try:
logger.info('I-04-01 秘密鍵ファイル読込 読込元:{SECRET_KEY_FILE_BUCKET_NAME}/{SECRET_KEY_FILE_PATH}')
s3_client.download_file(SECRET_KEY_FILE_BUCKET_NAME, SECRET_KEY_FILE_PATH, PATH_TEMP_PRIVATE_KEY)
logger.info('I-04-02 秘密鍵ファイルを読み込みました')
except Exception as e:
logger.error(f'E-04-01 秘密鍵ファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-04-01', EXTENSION_ERROR, e)
# ⑥ 「④」で読み込んだPGP暗号化ファイルを「⑤」でインポートした秘密鍵ファイルで復号する
try:
print_log(LOG_INFO, 'I-06-01', 'PGP暗号化ファイルの復号化')
with open(PATH_TEMP_ENCRYPT_FILE, 'rb') as temp_encrypr_file:
gpg.decrypt_file(temp_encrypr_file, output=PATH_TEMP_DECRYPT_FILE)
decrypt_file = open(PATH_TEMP_DECRYPT_FILE, 'rb')
print_log(LOG_INFO, 'I-06-02', 'PGP暗号化ファイルを復号しました')
except Exception as e:
print_log(LOG_ERROR, 'E-06-01', f'PGP暗号化ファイルの復号化に失敗しました エラー内容:{e}')
error_exit(event, EXTENSION_DECRYPT_ERROR, 'E-06-01', e)
# ⑤ 「③」で読み込んだ秘密鍵ファイルをPGPライブラリにインポートを行う
try:
logger.info('I-05-01 秘密鍵ファイルインポート')
gpg = gnupg.GPG(gnupghome=PATH_TEMP)
with open(PATH_TEMP_PRIVATE_KEY) as key_file:
gpg.import_keys(key_file.read())
logger.info('I-05-02 秘密鍵ファイルをインポートしました')
except Exception as e:
logger.error(f'E-05-01 秘密鍵ファイルのインポートに失敗しました エラー内容:{e}')
raise PrivateKeyImportException('E-05-01', EXTENSION_ERROR, e)
# ⑦ 各ファイルをS3に出力する
try:
print_log(LOG_INFO, 'I-07-01', '各ファイルをS3に出力する')
# ⑥ 「④」で読み込んだPGP暗号化ファイルを「⑤」でインポートした秘密鍵ファイルで復号する
try:
logger.info('I-06-01 PGP暗号化ファイルの復号化')
with open(PATH_TEMP_ENCRYPT_FILE, 'rb') as temp_encrypr_file:
gpg.decrypt_file(temp_encrypr_file, output=PATH_TEMP_DECRYPT_FILE)
decrypt_file = open(PATH_TEMP_DECRYPT_FILE, 'rb')
logger.info('I-06-02 PGP暗号化ファイルを復号しました')
except Exception as e:
logger.error(f'E-06-01 PGP暗号化ファイルの復号化に失敗しました エラー内容{e}')
raise DecryptException('E-06-01', EXTENSION_DECRYPT_ERROR, e)
# 「⑥」で復号化したファイルをSAPデータ保管用バケットに出力する
decrypt_file_name = event_file_name[:INDEX_EXTENSION_DELETE_NUM]
decrypt_file_key = f'{today}/{decrypt_file_name}'
decrypt_bucket_name = TARGET_BUCKET_BY_DATA_SOURCE[event_data_source_name]
print_log(LOG_INFO, 'I-07-02', f'復号化ファイル出力 ファイル名:{decrypt_file_name} 出力先:{decrypt_bucket_name}/{decrypt_file_key}')
decrypt_file_obj = s3_resource.Object(decrypt_bucket_name, decrypt_file_key)
decrypt_file_obj.put(Body=decrypt_file)
decrypt_file.close
print_log(LOG_INFO, 'I-07-03', '復号化ファイルをS3に出力しました')
except Exception as e:
print_log(LOG_ERROR, 'E-07-01', f'復号化ファイルのS3出力に失敗しました エラー内容{e}')
error_exit(event, EXTENSION_ERROR, 'E-07-01', e)
# ⑦ 各ファイルをS3に出力する
try:
logger.info('I-07-01 各ファイルをS3に出力する')
# 「⑥」で復号化したファイルをSAPデータ保管用バケットに出力する
decrypt_file_name = s3_event.file_name[:INDEX_EXTENSION_DELETE_NUM]
decrypt_file_key = f'{execute_date}/{decrypt_file_name}'
decrypt_bucket_name = TARGET_BUCKET_BY_DATA_SOURCE[s3_event.data_source_name]
logger.info(f'I-07-02 復号化ファイル出力 ファイル名:{decrypt_file_name} 出力先:{decrypt_bucket_name}/{decrypt_file_key}')
decrypt_file_obj = s3_resource.Object(decrypt_bucket_name, decrypt_file_key)
decrypt_file_obj.put(Body=decrypt_file)
decrypt_file.close
logger.info('I-07-03 復号化ファイルをS3に出力しました')
except Exception as e:
logger.error(f'E-07-01 復号化ファイルのS3出力に失敗しました エラー内容{e}')
raise FileOutputException('E-07-01', EXTENSION_ERROR, e)
try:
# 「④」で読み込んだPGP暗号化ファイルを以下に移動コピー削除する
copy_source = {
'Bucket': event_bucket_name,
'Key': event_file_path
}
backup_file_key = f'{event_data_source_name}/{today}/{event_file_name}'
print_log(LOG_INFO, 'I-07-04', f'PGP暗号化ファイル移動 移動元{event_bucket_name}/{event_file_path} 移動先:{SAP_DATA_BACKUP_BUCKET_NAME}/{backup_file_key}')
backup_file_obj = s3_resource.Object(SAP_DATA_BACKUP_BUCKET_NAME, backup_file_key)
backup_file_obj.copy(copy_source)
s3_client.delete_object(Bucket=event_bucket_name, Key=event_file_path)
print_log(LOG_INFO, 'I-07-05', 'PGP暗号化ファイルをバックアップ用バケットに移動しました')
try:
copy_source = {
'Bucket': s3_event.bucket_name,
'Key': s3_event.file_path
}
backup_file_key = f'{s3_event.data_source_name}/{execute_date}/{s3_event.file_name}'
logger.info(f'I-07-04 PGP暗号化ファイル移動 移動元{s3_event.bucket_name}/{s3_event.file_path} 移動先:{SAP_DATA_BACKUP_BUCKET_NAME}/{backup_file_key}')
backup_file_obj = s3_resource.Object(SAP_DATA_BACKUP_BUCKET_NAME, backup_file_key)
backup_file_obj.copy(copy_source)
s3_client.delete_object(Bucket=s3_event.bucket_name, Key=s3_event.file_path)
logger.info('I-07-05 PGP暗号化ファイルをバックアップ用バケットに移動しました')
except Exception as e:
logger.error(f'E-07-02 PGP暗号化ファイルのS3出力に失敗しました エラー内容{e}')
raise FileOutputException('E-07-02', EXTENSION_ERROR, e)
# ⑧ 処理終了ログを出力する
logger.info('I-08-01 処理終了 SAPデータ復号処理')
except EncryptFileReadException as e:
create_status_file(event, e.extension)
error_notice(e.id, e.arg)
except CustomException as e:
create_status_file(event, e.extension)
move_encrypt_file(event)
error_notice(e.id, e.arg)
except Exception as e:
print_log(LOG_ERROR, 'E-07-02', f'PGP暗号化ファイルのS3出力に失敗しました エラー内容{e}')
error_exit(event, EXTENSION_ERROR, 'E-07-02', e)
logger.error(f'E-99 想定外のエラーが発生しました エラー内容:{e}')
create_status_file(event, EXTENSION_ERROR)
move_encrypt_file(event)
error_notice('E-99', e)
return
# ⑧ 処理終了ログを出力する
# エラーステータスファイル作成
def create_status_file(s3_event, extension) -> None:
try:
print_log(LOG_INFO, 'I-08-01', '処理終了 SAPデータ復号処理')
except Exception as e:
print_log(LOG_ERROR, 'E-99', f'想定外のエラーが発生しました エラー内容:{e}')
error_exit(event, EXTENSION_ERROR, 'E-99', e)
def print_log(log_level, log_id, msg):
try:
print(f'{datetime.datetime.now():%Y-%m-%d %H:%M:%S} {log_level} {log_id} {msg}')
except Exception as e:
exception_msg = f'Error E-99 想定外のエラーが発生しました エラー内容:{e}'
print(f'{datetime.datetime.now():%Y-%m-%d %H:%M:%S} {exception_msg}')
raise Exception(exception_msg)
def error_exit(event, extension, error_log_id, exception):
# ① エラー処理を行う
try:
print_log(LOG_ERROR, 'E-ERR-01', 'エラー処理開始')
s3_event = event["Records"][0]["s3"]
event_bucket_name = s3_event["bucket"]["name"]
event_file_path = s3_event["object"]["key"]
event_file_name = os.path.basename(event_file_path)
event_data_source_name = os.path.dirname(event_file_path).split('/')[0]
result_error_file_name = event_file_name + extension
result_error_key = event_data_source_name + DIRECTORY_RECV + result_error_file_name
result_error_obj = s3_resource.Object(event_bucket_name, result_error_key)
result_error_file_name = s3_event.file_name + extension
result_error_key = s3_event.data_source_name + DIRECTORY_RECV + result_error_file_name
result_error_obj = s3_resource.Object(s3_event.bucket_name, result_error_key)
result_error_obj.put(Body='')
print_log(LOG_ERROR, 'E-ERR-02', f'recvディレクトリにエラーファイルを作成しました ファイル名{result_error_file_name} 出力先:{event_bucket_name}/{result_error_key}')
logger.error(f'E-ERR-01 recvディレクトリにエラーファイルを作成しました ファイル名{result_error_file_name} 出力先:{s3_event.bucket_name}/{result_error_key}')
except Exception as e:
logger.error(f'E-96 エラーステータスファイルの作成に失敗しました エラー内容:{e}')
return
# PGP暗号化ファイル移動
def move_encrypt_file(s3_event) -> None:
try:
copy_source = {
'Bucket': event_bucket_name,
'Key': event_file_path
'Bucket': s3_event.bucket_name,
'Key': s3_event.file_path
}
error_file_name = f'{datetime.datetime.now():%Y%m%d%H%M%S}_{event_file_name}'
error_key = event_data_source_name + DIRECTORY_RECV_ERROR + error_file_name
error_obj = s3_resource.Object(event_bucket_name, error_key)
error_file_name = f'{datetime.datetime.now():%Y%m%d%H%M%S}_{s3_event.file_name}'
error_key = s3_event.data_source_name + DIRECTORY_RECV_ERROR + error_file_name
error_obj = s3_resource.Object(s3_event.bucket_name, error_key)
error_obj.copy(copy_source)
s3_client.delete_object(Bucket=event_bucket_name, Key=event_file_path)
print_log(LOG_ERROR, 'E-ERR-03', f'recv_errorディレクトリにファイルを移動しました 移動元{event_bucket_name}/{event_file_path} 移動先:{event_bucket_name}/{error_key}')
s3_client.delete_object(Bucket=s3_event.bucket_name, Key=s3_event.file_path)
logger.error(f'E-ERR-02 recv_errorディレクトリにファイルを移動しました 移動元{s3_event.bucket_name}/{s3_event.file_path} 移動先:{s3_event.bucket_name}/{error_key}')
except Exception as e:
logger.error(f'E-97 PGP暗号化ファイルの移動に失敗しました エラー内容{e}')
return
print_log(LOG_ERROR, 'E-ERR-04', f'処理異常通知の送信指示をしました 通知先トピック:{NDS_NOTICE_TOPIC}')
# 保守要員チーム通知
def error_notice(error_log_id, exception) -> None:
try:
error_msg = f'{error_log_id} のエラーが発生しました。ご確認ください\n詳細:{exception}'
params = {
'TopicArn': NDS_NOTICE_TOPIC,
@ -212,9 +198,60 @@ def error_exit(event, extension, error_log_id, exception):
'Message': error_msg
}
sns_client.publish(**params)
print_log(LOG_ERROR, 'E-ERR-05', 'エラー終了 処理を中断します')
sys.exit()
logger.error(f'E-ERR-03 処理異常通知の送信指示をしました 通知先トピック:{NDS_NOTICE_TOPIC}')
except Exception as e:
print_log(LOG_ERROR, 'E-99', f'想定外のエラーが発生しました エラー内容:{e}')
sys.exit()
logger.error(f'E-98 処理異常通知の送信指示に失敗しました エラー内容:{e}')
return
# S3イベント情報を保持するクラス
class S3EventInfo:
def __init__(self, s3_event) -> None:
self._bucket_name = s3_event["bucket"]["name"]
self._file_path = s3_event["object"]["key"]
self._file_name = os.path.basename(s3_event["object"]["key"])
self._data_source_name = os.path.dirname(s3_event["object"]["key"]).split('/')[0]
@property
def bucket_name(self):
return self._bucket_name
@property
def file_path(self):
return self._file_path
@property
def file_name(self):
return self._file_name
@property
def data_source_name(self):
return self._data_source_name
# カスタムExceptionクラス
class CustomException(Exception, metaclass=ABCMeta):
def __init__(self, id, extension, arg):
self.id = id
self.extension = extension
self.arg = arg
class FileReadException(CustomException):
pass
class EncryptFileReadException(CustomException):
pass
class FileOutputException(CustomException):
pass
class PrivateKeyImportException(CustomException):
pass
class DecryptException(CustomException):
pass