def get_account_password_policy(trace_id, check_history_id, organization_id, project_id, awsaccount, session, result_json_path): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) s3_file_name = CommonConst.PATH_CHECK_RAW.format( check_history_id, organization_id, project_id, awsaccount, "IBP/IAM_AccountPasswordPolicy.json") # リソース情報取得 if (aws_common.check_exists_file_s3(trace_id, "S3_CHECK_BUCKET", s3_file_name)) is True: try: account_password_policy = FileUtils.read_json( trace_id, "S3_CHECK_BUCKET", s3_file_name) except PmError as e: raise common_utils.write_log_pm_error(e, pm_logger) else: try: account_password_policy = IAMUtils.get_account_password_policy( trace_id, session, awsaccount) except PmError as e: raise common_utils.write_log_pm_error(e, pm_logger) # アカウントパスワードポリシー情報をS3に保存します。 try: FileUtils.upload_json(trace_id, "S3_CHECK_BUCKET", account_password_policy, s3_file_name) except PmError as e: pm_logger.error("[%s] アカウントパスワードポリシー情報のS3保存に失敗しました。", awsaccount) raise common_utils.write_log_pm_error(e, pm_logger) return account_password_policy
def get_list_buckets(trace_id, check_history_id, organization_id, project_id, s3_client, aws_account): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) s3_file_name = CommonConst.PATH_CHECK_RAW.format( check_history_id, organization_id, project_id, aws_account, "ASC/S3_ListBuckets.json") # リソース情報取得 if (aws_common.check_exists_file_s3(trace_id, "S3_CHECK_BUCKET", s3_file_name)) is True: try: list_buckets = FileUtils.read_json(trace_id, "S3_CHECK_BUCKET", s3_file_name) except PmError as e: raise common_utils.write_log_exception(e, pm_logger) else: # S3バケット一覧を取得します。 try: list_buckets = S3Utils.list_buckets(trace_id, s3_client, aws_account) except PmError as e: raise common_utils.write_log_exception(e, pm_logger) # S3バケット一覧情報をS3に保存します。 try: FileUtils.upload_json(trace_id, "S3_CHECK_BUCKET", list_buckets, s3_file_name) except PmError as e: pm_logger.error("[%s] S3バケット一覧情報のS3保存に失敗しました。", aws_account) raise common_utils.write_log_exception(e, pm_logger) return list_buckets
def get_bucket_acl(trace_id, check_history_id, organization_id, project_id, aws_account, region_name, bucket_name, s3_client): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) s3_file_name = CommonConst.PATH_CHECK_RAW.format( check_history_id, organization_id, project_id, aws_account, "ASC/S3_ACL_" + region_name + "_" + bucket_name + ".json") # リソース情報取得 if (aws_common.check_exists_file_s3(trace_id, "S3_CHECK_BUCKET", s3_file_name)) is True: try: bucket_acl = FileUtils.read_json(trace_id, "S3_CHECK_BUCKET", s3_file_name) except PmError as e: raise common_utils.write_log_pm_error(e, pm_logger) else: try: bucket_acl = S3Utils.get_bucket_acl( trace_id, s3_client, bucket_name, aws_account, region_name) except PmError as e: raise common_utils.write_log_pm_error(e, pm_logger) # 取得したS3バケットのアクセスコントロールリスト情報をS3に保存する。(アクセスコントロールリスト情報) try: FileUtils.upload_json(trace_id, "S3_CHECK_BUCKET", bucket_acl, s3_file_name) except PmError as e: pm_logger.error("[%s] S3バケットACL情報のS3保存に失敗しました。(%s)/(%s)", aws_account, region_name, bucket_name) return bucket_acl
def test_upload_json_success(self): # connect s3 resource_s3 = s3_utils.resource_connect() check_bucket = common_utils.get_environ("S3_CHECK_BUCKET") # prepare data resource_s3.create_bucket(Bucket=check_bucket) more_binary_data = json.dumps(data_file, indent=4, default=FileUtils.convert_handler, ensure_ascii=False) with patch.object(PmLogAdapter, 'info', return_value=None) as mock_method_info: with patch.object(boto3, 'client') as mock_method_client: mock_method_client.return_value = client_s3 with patch.object(client_s3, 'put_object') as mock_method: # call function test FileUtils.upload_json(trace_id, "S3_CHECK_BUCKET", data_file, s3_file_name) # check write log info mock_method_info.assert_any_call( "Upload file json [%s] success on bucket [%s]", s3_file_name, check_bucket) # check connect client mock_method_client.assert_called_with('s3') # check param call function put_object mock_method.assert_any_call(Body=more_binary_data, Bucket=check_bucket, Key=s3_file_name)
def test_upload_csv_success(self): # connect s3 resource_s3 = s3_utils.resource_connect() check_bucket = common_utils.get_environ("S3_CHECK_BUCKET") # prepare data resource_s3.create_bucket(Bucket=check_bucket) with patch.object(PmLogAdapter, 'info', return_value=None) as mock_method_info: with patch.object(boto3, 'client') as mock_method_client: mock_method_client.return_value = client_s3 with patch.object(client_s3, 'put_object') as mock_method: # call function test FileUtils.upload_csv(trace_id, "S3_CHECK_BUCKET", data_file, s3_file_name) # check write log info mock_method_info.assert_any_call( "Upload file csv [%s] success on bucket [%s]", s3_file_name, check_bucket) # check connect client mock_method_client.assert_called_with('s3') # check param call function put_object mock_method.assert_any_call(Body=data_file, Bucket=check_bucket, Key=s3_file_name)
def get_trail_event_selectors(trace_id, check_history_id, organization_id, project_id, awsaccount, region_name, trail_client, cloud_trail): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) s3_file_name = CommonConst.PATH_CHECK_RAW.format( check_history_id, organization_id, project_id, awsaccount, "CloudTrail_EventSelectors_" + region_name + "_" + cloud_trail["Name"] + ".json") event_selectors = [] # Check Exist File リソース情報ファイル if (aws_common.check_exists_file_s3(trace_id, "S3_CHECK_BUCKET", s3_file_name)) is True: try: event_selectors = FileUtils.read_json(trace_id, "S3_CHECK_BUCKET", s3_file_name) except PmError as e: raise common_utils.write_log_pm_error(e, pm_logger) else: event_selectors = CloudTrailUtils.get_event_selectors( trace_id, awsaccount, trail_client, region_name, cloud_trail["TrailARN"]) # Upload File リソース情報ファイル try: FileUtils.upload_s3(trace_id, event_selectors, s3_file_name, True) except PmError as e: pm_logger.error("[%s/%s] CloudTrailのイベントセレクタ情報のS3保存に失敗しました。", awsaccount, region_name) raise common_utils.write_log_pm_error(e, pm_logger) return event_selectors
def check_ibp_item_02_01(trace_id, check_history_id, organization_id, project_id, aws_account, session, result_json_path): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) check_results = [] # IAMユーザの一覧を取得する。 try: list_users = IAMUtils.get_list_users(trace_id, session, aws_account) except PmError as e: pm_logger.error("[%s] IAMユーザー一覧情報取得に失敗しました。", aws_account) return CheckResult.Error try: # 取得したユーザ一覧をS3に保存する(リソース情報ファイル)。 s3_file_name = CommonConst.PATH_CHECK_RAW.format( check_history_id, organization_id, project_id, aws_account, "IBP/IAM_ListUsers.json") FileUtils.upload_json(trace_id, "S3_CHECK_BUCKET", list_users, s3_file_name) except PmError as e: pm_logger.error("[%s] IAMユーザー一覧情報のS3保存に失敗しました。", aws_account) return CheckResult.Error # チェックルール # Check-1. IAMユーザが存在するか try: if (len(list_users) == 0): result = { 'Region': 'Global', 'Level': CommonConst.LEVEL_CODE_21, 'DetectionItem': { 'NoIAMUser': True } } check_results.append(result) except Exception as e: pm_logger.error("[%s] チェック処理中にエラーが発生しました。", aws_account) return CheckResult.Error # Export File CHECK_IBP_ITEM_02_01.json try: current_date = date_utils.get_current_date_by_format( date_utils.PATTERN_YYYYMMDDHHMMSS) check_ibp_item_02_01 = { 'AWSAccount': aws_account, 'CheckResults': check_results, 'DateTime': current_date } FileUtils.upload_json(trace_id, "S3_CHECK_BUCKET", check_ibp_item_02_01, result_json_path) except Exception as e: pm_logger.error("[%s] チェック結果JSONファイルの保存に失敗しました。", aws_account) return CheckResult.Error # チェック結果 if len(check_results) > 0: return CheckResult.CriticalDefect return CheckResult.Normal
def check_asc_item_copy_cis_check(trace_id, check_history_id, organization_id, project_id, aws_account, session, result_json_path, check_cis_item): cw_logger = common_utils.begin_cw_logger(trace_id, __name__, inspect.currentframe()) error_cis = LIST_ERROR_CIS[check_cis_item] try: try: check_result_items = pm_checkResultItems.query_by_check_history_id_and_check_item_code_and_aws_account( trace_id, check_history_id, check_cis_item, aws_account, is_cw_logger=True) except Exception as e: cw_logger.error("[%s] %sのチェック結果を取得できませんでした。", aws_account, error_cis) return CheckResult.Error # チェック結果が「マネージド-1」だった場合は、チェック結果ファイルは作られていないのでファイル取得はスキップします。 check_result = check_result_items[0]["CheckResult"] if check_result == CheckResult.MembersManagement: return check_result s3_file_name = CommonConst.PATH_CHECK_RESULT.format( check_history_id, organization_id, project_id, aws_account, check_cis_item + ".json") try: check_results_s3 = FileUtils.read_json(trace_id, CommonConst.S3_CHECK_BUCKET, s3_file_name, is_cw_logger=True) except PmError as e: cw_logger.error("[%s] %sのチェック結果ファイルを取得できませんでした。", aws_account, error_cis) return CheckResult.Error except Exception as e: cw_logger.error("[%s] チェック処理中にエラーが発生しました。", aws_account) return CheckResult.Error # Export File Json try: FileUtils.upload_s3(trace_id, check_results_s3, result_json_path, format_json=True, is_cw_logger=True) except Exception as e: cw_logger.error("[%s] チェック結果JSONファイルの保存に失敗しました。", aws_account) return CheckResult.Error # チェック結果 return check_result
def test_read_csv_success(self): # prepare data check_bucket = common_utils.get_environ("S3_CHECK_BUCKET") data_file = copy.deepcopy(DataTestS3.DATA_TEST_UPLOAD_CSV) client_s3.create_bucket(Bucket=check_bucket) client_s3.put_object(Body=data_file, Bucket=check_bucket, Key=s3_file_name) object_csv = client_s3.get_object(Bucket=check_bucket, Key=s3_file_name) object_csv_copy = copy.deepcopy(object_csv) with patch.object(PmLogAdapter, 'info', return_value=None) as mock_method_info: with patch.object(boto3, 'client') as mock_method_client: mock_method_client.return_value = client_s3 with patch.object(client_s3, 'get_object') as mock_method: mock_method.return_value = object_csv # call function test actual_response = FileUtils.read_csv( trace_id, 'S3_CHECK_BUCKET', s3_file_name) # check result expected_result = str(object_csv_copy['Body'].read().decode()) self.assertEqual(expected_result, actual_response) # check write log info mock_method_info.assert_any_call('read csv success') # check connect client mock_method_client.assert_called_with('s3') # check param call function get_object mock_method.assert_any_call(Bucket=check_bucket, Key=s3_file_name)
def test_read_object_success(self): data_file = copy.deepcopy(DataYaml.DATA_FILE_YAML) # prepare data check_bucket = common_utils.get_environ("S3_CHECK_BUCKET") client_s3.create_bucket(Bucket=check_bucket) client_s3.put_object(Body=data_file, Bucket=check_bucket, Key=s3_file_name) object_file = client_s3.get_object(Bucket=check_bucket, Key=s3_file_name) object_file_copy = copy.deepcopy(object_file) with patch.object(boto3, 'client') as mock_method_client: mock_method_client.return_value = client_s3 with patch.object(client_s3, 'get_object') as mock_method: mock_method.return_value = object_file # call function test actual_response = FileUtils.read_object( trace_id, 'S3_CHECK_BUCKET', s3_file_name) # check result expected_result = object_file_copy['Body'].read() self.assertEqual(expected_result, actual_response) # check connect client mock_method_client.assert_called_with('s3') # check param call function get_object mock_method.assert_any_call(Bucket=check_bucket, Key=s3_file_name)
def list_subscriptions_by_topic(trace_id, check_history_id, organization_id, project_id, awsaccount, region_name, sns_client, topic_arn): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) topic_name = topic_arn.split(":")[5] s3_file_name = CommonConst.PATH_CHECK_RAW.format( check_history_id, organization_id, project_id, awsaccount, "SNS_Topic_Subscriptions_Info_" + region_name + "_" + topic_name + ".json") subscriptions = [] # リソース情報取得 if (aws_common.check_exists_file_s3(trace_id, "S3_CHECK_BUCKET", s3_file_name)) is True: try: subscriptions = FileUtils.read_json(trace_id, "S3_CHECK_BUCKET", s3_file_name) except PmError as e: raise common_utils.write_log_pm_error(e, pm_logger) else: # 対象のAWSアカウントのリージョンごと(GovCloud、北京を除く)にCloudTrail情報を取得する。 try: subscriptions = SNSUtils.list_subscriptions_by_topic( trace_id, sns_client, awsaccount, region_name, topic_arn) except PmError as e: data_body = {'TopicArn': topic_arn} e.pm_notification_error = PmNotificationError( code_error=CommonConst.KEY_CODE_ERROR_GET_SUBSCRIPTIONS, data_body=data_body) raise common_utils.write_log_pm_error(e, pm_logger) # 取得したSNS Topicサブスクリプション情報情報をS3に保存する(リソース情報ファイル) try: FileUtils.upload_json(trace_id, "S3_CHECK_BUCKET", subscriptions, s3_file_name) except PmError as e: pm_logger.error("[%s/%s] SNS Topicサブスクリプション情報の情報のS3保存に失敗しました。", awsaccount, region_name) raise common_utils.write_log_pm_error(e, pm_logger) # 情報の取得件数が0でした。 if (len(subscriptions) == 0): pm_logger.warning("[%s/%s] SNS Topicサブスクリプション情報情報の取得件数が0でした。", awsaccount, region_name) return subscriptions
def test_read_yaml_success(self): trace_id = copy.deepcopy(DataCommon.USER_ID_TEST.format(str(3))) with patch('premembers.common.FileUtils.read_object', return_value=DataYaml.DATA_FILE_YAML): response = FileUtils.read_yaml( trace_id, CommonConst.S3_SETTING_BUCKET, CommonConst.NOTIFY_CONFIG_CIS_RESULT_MAIL) self.assertEqual(DataJson.DATA_AFTER_YAML_LOAD, response)
def test_upload_s3_case_not_has_param_format_json(self): # mock method upload_json with patch('premembers.common.FileUtils.upload_json' ) as mock_method_upload_json: # mock method upload_csv with patch('premembers.common.FileUtils.upload_csv' ) as mock_method_upload_csv: # call function test FileUtils.upload_s3(trace_id, data_file, s3_file_name) # check param call function upload_json mock_method_upload_json.assert_not_called() # check param call function upload_csv mock_method_upload_csv.assert_called_once_with(trace_id, "S3_CHECK_BUCKET", data_file, s3_file_name)
def test_read_json_error_client(self): # create mock error client s3 self.create_mock_boto3_client_error() expected_error_response = copy.deepcopy(DataCommon.ERROR_RESPONSE) expected_operation_name = copy.deepcopy(DataCommon.OPERATION_NAME) FileUtils.global_s3_client = None with self.assertRaises(PmError) as exception: # call function test FileUtils.read_json(trace_id, 'S3_CHECK_BUCKET', s3_file_name) # check error actual_cause_error = exception.exception.cause_error self.assertEqual(expected_error_response['Error'], actual_cause_error.response['Error']) self.assertEqual(expected_operation_name, actual_cause_error.operation_name)
def describe_metric_filters(trace_id, check_history_id, organization_id, project_id, awsaccount, region_name, logs_client, cloud_trail_log_group_name): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) s3_file_name = CommonConst.PATH_CHECK_RAW.format( check_history_id, organization_id, project_id, awsaccount, "CloudWatch_Logs_Metric_Filters_Info_" + region_name + "_" + cloud_trail_log_group_name.replace( CommonConst.SLASH, "-SLASH-") + ".json") metric_filters = [] # リソース情報取得 if (aws_common.check_exists_file_s3(trace_id, "S3_CHECK_BUCKET", s3_file_name)) is True: try: metric_filters = FileUtils.read_json(trace_id, "S3_CHECK_BUCKET", s3_file_name) except PmError as e: raise common_utils.write_log_pm_error(e, pm_logger) else: try: metric_filters = LogsUtils.describe_metric_filters( trace_id, logs_client, awsaccount, region_name, cloud_trail_log_group_name) except PmError as e: data_body = {'CloudTrailLogGroupName': cloud_trail_log_group_name} e.pm_notification_error = PmNotificationError( code_error=CommonConst.KEY_CODE_ERROR_GET_METRIC_FILTERS, data_body=data_body) raise common_utils.write_log_pm_error(e, pm_logger) try: FileUtils.upload_json(trace_id, "S3_CHECK_BUCKET", metric_filters, s3_file_name) except PmError as e: pm_logger.error("[%s/%s] メトリクスフィルタ情報のS3保存に失敗しました。", awsaccount, region_name) raise common_utils.write_log_pm_error(e, pm_logger) # 情報の取得件数が0でした。 if (len(metric_filters) == 0): pm_logger.warning("[%s/%s] メトリクスフィルタ情報の取得件数が0でした。", awsaccount, region_name) return metric_filters
def test_read_json_error_call_get_object(self): # create mock throw error when called function get_object expected_error_response = copy.deepcopy(DataCommon.ERROR_RESPONSE) expected_operation_name = copy.deepcopy(DataCommon.OPERATION_NAME) with patch.object(client_s3, 'get_object') as mock_method: mock_method.side_effect = ClientError( error_response=expected_error_response, operation_name=expected_operation_name) with self.assertRaises(PmError) as exception: # call function test FileUtils.read_json(trace_id, 'S3_CHECK_BUCKET', s3_file_name) # check error actual_cause_error = exception.exception.cause_error self.assertEqual(expected_error_response['Error'], actual_cause_error.response['Error']) self.assertEqual(expected_operation_name, actual_cause_error.operation_name)
def test_read_decode_success(self): trace_id = copy.deepcopy(DataCommon.USER_ID_TEST.format(str(3))) data_read_decode = copy.deepcopy( DataText.CHECK_RESULT_SLACK_TEMPLATE.encode('utf-8')) with patch('premembers.common.FileUtils.read_object', return_value=data_read_decode): response = FileUtils.read_decode( trace_id, CommonConst.S3_SETTING_BUCKET, CommonConst.NOTIFY_CONFIG_CIS_RESULT_MAIL) self.assertEqual(DataText.CHECK_RESULT_SLACK_TEMPLATE, response)
def check_ibp_item_07_08(trace_id, check_history_id, organization_id, project_id, aws_account, session, result_json_path): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) check_results = [] # チェック結果 try: account_password_policy = ibp_item_common_logic.get_account_password_policy( trace_id, check_history_id, organization_id, project_id, aws_account, session, result_json_path) if (common_utils.check_key("AllowUsersToChangePassword", account_password_policy) is False or account_password_policy['AllowUsersToChangePassword'] is False): check_results.append(get_check_ibp_item_07_08_result()) except PmError as e: if e.cause_error.response['Error'][ 'Code'] == CommonConst.NO_SUCH_ENTITY: check_results.append(get_check_ibp_item_07_08_result()) else: pm_logger.error("[%s] チェック処理中にエラーが発生しました。", aws_account) return CheckResult.Error # Export File CHECK_IBP_ITEM_07_08.json try: current_date = date_utils.get_current_date_by_format( date_utils.PATTERN_YYYYMMDDHHMMSS) check_password_policy = { 'AWSAccount': aws_account, 'CheckResults': check_results, 'DateTime': current_date } FileUtils.upload_s3(trace_id, check_password_policy, result_json_path, True) except Exception as e: pm_logger.error("[%s] チェック結果JSONファイルの保存に失敗しました。", aws_account) return CheckResult.Error # チェック結果 if len(check_results) == 0: return CheckResult.Normal return CheckResult.CriticalDefect
def get_cloud_trails(trace_id, check_history_id, organization_id, project_id, awsaccount, region_name, session): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) s3_file_name = CommonConst.PATH_CHECK_RAW.format( check_history_id, organization_id, project_id, awsaccount, "CloudTrail_" + region_name + ".json") cloud_trails = [] # Check Exist File S3 CloudTrail_{region_name}.json if (aws_common.check_exists_file_s3(trace_id, "S3_CHECK_BUCKET", s3_file_name)) is True: try: cloud_trails = FileUtils.read_json(trace_id, "S3_CHECK_BUCKET", s3_file_name) except PmError as e: raise common_utils.write_log_pm_error(e, pm_logger) else: # 対象のAWSアカウントのリージョンごと(GovCloud、北京を除く)にCloudTrail情報を取得する。 trail_client = CloudTrailUtils.get_trail_client( trace_id, session, region_name, awsaccount) try: cloud_trails = CloudTrailUtils.describe_cloud_trails( trace_id, awsaccount, trail_client, region_name) except PmError as e: raise common_utils.write_log_pm_error(e, pm_logger) if (len(cloud_trails) == 0): pm_logger.warning("[%s/%s] CloudTrail情報の取得件数が0でした。", awsaccount, region_name) # 取得したCloudTrail情報をS3に保存する(リソース情報ファイル) try: FileUtils.upload_json(trace_id, "S3_CHECK_BUCKET", cloud_trails, s3_file_name) except PmError as e: pm_logger.error("[%s/%s] CloudTrailの情報のS3保存に失敗しました。", awsaccount, region_name) raise common_utils.write_log_pm_error(e, pm_logger) return cloud_trails
def describe_alarms(trace_id, check_history_id, organization_id, project_id, awsaccount, region_name, cloudwatch_client): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) s3_file_name = CommonConst.PATH_CHECK_RAW.format( check_history_id, organization_id, project_id, awsaccount, "CloudWatch_Alarm_Info_" + region_name + ".json") metric_alarms = [] # リソース情報取得 if (aws_common.check_exists_file_s3(trace_id, "S3_CHECK_BUCKET", s3_file_name)) is True: try: metric_alarms = FileUtils.read_json(trace_id, "S3_CHECK_BUCKET", s3_file_name) except PmError as e: raise common_utils.write_log_pm_error(e, pm_logger) else: try: metric_alarms = CloudWatchlUtils.describe_alarms( trace_id, awsaccount, cloudwatch_client, region_name) except PmError as e: raise common_utils.write_log_pm_error(e, pm_logger) # 取得したCloudWatchAlarm情報をS3に保存する(リソース情報ファイル) try: FileUtils.upload_json(trace_id, "S3_CHECK_BUCKET", metric_alarms, s3_file_name) except PmError as e: pm_logger.error("[%s/%s] CloudWatchAlarmの情報のS3保存に失敗しました。", awsaccount, region_name) raise common_utils.write_log_pm_error(e, pm_logger) # 情報の取得件数が0でした。 if (len(metric_alarms) == 0): pm_logger.warning("[%s/%s] CloudWatchAlarm情報の取得件数が0でした。", awsaccount, region_name) return metric_alarms
def test_read_json_success(self): # prepare data bucket_name = common_utils.get_environ("S3_CHECK_BUCKET") client_s3.create_bucket(Bucket=bucket_name) body = json.dumps(data_test_upload_s3) client_s3.put_object(Bucket=bucket_name, Key=s3_file_name, Body=body) with patch.object(PmLogAdapter, 'info', return_value=None) as mock_method_info: with patch.object(boto3, "client", return_value=client_s3): # call function test actual_result = FileUtils.read_json(trace_id, "S3_CHECK_BUCKET", s3_file_name) # check result self.assertEqual(data_test_upload_s3, actual_result) # check write log info mock_method_info.assert_any_call('read json success')
def check_asc_item_13_01(trace_id, check_history_id, organization_id, project_id, aws_account, session, result_json_path): cw_logger = common_utils.begin_cw_logger(trace_id, __name__, inspect.currentframe()) check_results = [] is_authorized = True s3_client = S3Utils.get_s3_client(trace_id, session, aws_account, is_cw_logger=True) try: list_buckets = asc_item_common_logic.get_list_buckets( trace_id, check_history_id, organization_id, project_id, s3_client, aws_account) except PmError as e: return CheckResult.Error # 取得したS3バケットのアクセスコントロールリスト情報をS3に保存する(リソース情報ファイル)。 for bucket in list_buckets['Buckets']: bucket_name = bucket['Name'] region_name = None try: region_name = S3Utils.get_bucket_location( trace_id, s3_client, bucket_name, aws_account) if region_name is None: region_name = CommonConst.US_EAST_REGION bucket_encryption_rules = S3Utils.get_bucket_encryption( trace_id, s3_client, bucket_name, aws_account, region_name, is_cw_logger=True) except PmError as e: if e.cause_error.response['Error'][ 'Code'] in CommonConst.SERVER_SIDE_ENCRYPTION_CONFIGURATION_NOT_FOUND_ERROR: check_results.append(get_check_asc_item_13_01_result( region_name, bucket_name)) continue elif e.cause_error.response['Error'][ 'Code'] in CommonConst.S3_SKIP_EXCEPTION: error_operation = e.cause_error.operation_name, error_code = e.cause_error.response['Error']['Code'], error_message = e.cause_error.response['Error']['Message'] if region_name is None: region_name = CommonConst.ERROR check_results.append( asc_item_common_logic.get_error_authorized_result( region_name, bucket_name, error_operation, error_code, error_message)) is_authorized = False continue else: return CheckResult.Error if len(bucket_encryption_rules) == 0: continue try: s3_file_name = CommonConst.PATH_CHECK_RAW.format( check_history_id, organization_id, project_id, aws_account, "ASC/S3_Encryption_" + region_name + "_" + bucket_name + ".json") FileUtils.upload_json(trace_id, "S3_CHECK_BUCKET", bucket_encryption_rules, s3_file_name, is_cw_logger=True) except PmError as e: cw_logger.error("[%s] S3バケット暗号化情報のS3保存に失敗しました。(%s/%s)", aws_account, region_name, bucket_name) return CheckResult.Error # チェック処理 try: for bucket_encryption_rule in bucket_encryption_rules: if (common_utils.check_key( "SSEAlgorithm", bucket_encryption_rule['ApplyServerSideEncryptionByDefault'] ) is False): check_results.append(get_check_asc_item_13_01_result( region_name, bucket_name)) break except Exception as e: cw_logger.error("[%s] チェック処理中にエラーが発生しました。(%s/%s)", aws_account, region_name, bucket_name) return CheckResult.Error # Export File json try: current_date = date_utils.get_current_date_by_format( date_utils.PATTERN_YYYYMMDDHHMMSS) check_asc_item_13_01 = { 'AWSAccount': aws_account, 'CheckResults': check_results, 'DateTime': current_date } FileUtils.upload_s3(trace_id, check_asc_item_13_01, result_json_path, format_json=True, is_cw_logger=True) except Exception as e: cw_logger.error("[%s] チェック結果JSONファイルの保存に失敗しました。", aws_account) return CheckResult.Error # チェック結果 if is_authorized is False: return CheckResult.Error if len(check_results) > 0: return CheckResult.CriticalDefect return CheckResult.Normal
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
def execute_send_result_slack(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) common_utils.write_log_pm_error(e, pm_logger, msg_err) return if (not list_check_result): msg_err = "チェック結果の取得に失敗しました。" pm_logger.error(msg_err) return # チェック結果一覧のうちの一つから、組織IDを取得します。 organization_id = list_check_result[0]['OrganizationID'] organization_name = list_check_result[0]['OrganizationName'] project_name = list_check_result[0]['ProjectName'] # 組織別Slack通知設定テーブルから、組織ID、通知コードCHECK_CISをキーとして設定情報を取得します。 try: org_notify_slack = pm_orgNotifySlack.query_key(trace_id, organization_id, CommonConst.NOTIFY_CODE) except PmError as e: msg_err = "Slack設定情報の取得に失敗しました。:OrganizationID={0}, CheckCode={1}".format( organization_id, CommonConst.NOTIFY_CODE) pm_logger.error(msg_err) common_utils.write_log_pm_error(e, pm_logger, msg_err) return if (not org_notify_slack): msg_err = "Slack設定情報の取得に失敗しました。:OrganizationID={0}, CheckCode={1}".format( organization_id, CommonConst.NOTIFY_CODE) pm_logger.error(msg_err) return # S3から通知Slack設定ファイルを取得します。 try: config = FileUtils.read_yaml(trace_id, CommonConst.S3_SETTING_BUCKET, CommonConst.NOTIFY_CONFIG_CIS_RESULT_MAIL) except PmError as e: msg_err = "通知Slack設定ファイルの取得に失敗しました。:s3://{0}/{1}".format( common_utils.get_environ(CommonConst.S3_SETTING_BUCKET), CommonConst.NOTIFY_CONFIG_CIS_RESULT_MAIL) pm_logger.error(msg_err) common_utils.write_log_pm_error(e, pm_logger, msg_err) return if language not in CommonConst.LANGUAGE_SUPPORT: language = CommonConst.LANGUAGE_DEFAULT path_file_template = config[ CommonConst.KEY_GET_PATH_FILE_TEMPLATE_SLACK.format(language=language)] # メッセージ本文を作成します。 try: template_message = FileUtils.read_decode(trace_id, CommonConst.S3_SETTING_BUCKET, path_file_template) except PmError as e: msg_err = "Slack通知本文テンプレートファイルの取得に失敗しました。:s3://{0}/{1}".format( common_utils.get_environ(CommonConst.S3_SETTING_BUCKET), path_file_template) pm_logger.error(msg_err) common_utils.write_log_pm_error(e, pm_logger, msg_err) return executed_date_time = date_utils.toString( date_utils.toDate(list_check_result[0]['ExecutedDateTime'], date_utils.UTC), date_utils.PATTERN_YYYYMMDDHHMM, date_utils.get_time_zone_by_language(language)) 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_message) context = { 'organizationName': organization_name, 'projectName': project_name, 'executedDateTime': executed_date_time, 'checkResults': check_results } body = template.render(context) mentions = slack_common.convert_command_slack(org_notify_slack['Mentions']) body = CommonConst.KEY_BODY_MESSAGE_SLACK.format(mentions=mentions, body=body) notify_slack = { "username": config[CommonConst.KEY_USER_NAME_SLACK.format(language=language)], "icon_url": config['slack.iconurl'], "text": body } notify_slack = json.dumps(notify_slack) try: slack_common.send_message_slack(trace_id, org_notify_slack['WebhookURL'], notify_slack) except PmError as e: msg_err = "Slack通知のリクエスト送信に失敗しました。:OrganizationID={0}, CheckCode={1}".format( organization_id, CommonConst.NOTIFY_CODE) pm_logger.warning(msg_err) common_utils.write_log_pm_error(e, pm_logger, msg_err)
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 send_checkerror_email(trace_id, aws_account, check_history_id, organization_id, project_id, error_code, execute_user_id, region_name, check_code_item, data_body): pm_logger = common_utils.begin_logger(trace_id, __name__, inspect.currentframe()) # 組織情報を取得する。 try: organization = pm_organizations.get_organization( trace_id, organization_id) 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) # プロジェクト情報を取得する。 try: project = pm_projects.query_key(trace_id, project_id) except PmError as e: msg_err = "プロジェクト情報の取得に失敗しました。ProjectID={0}".format(project_id) pm_logger.error(msg_err) raise common_utils.write_log_pm_error(e, pm_logger, msg_err) # チェック実行ユーザーのメールアドレスと言語を取得します。 try: user_info = aws_common.get_cognito_user_info_by_user_name( trace_id, execute_user_id) except PmError as e: msg_err = "Cognitoから情報取得に失敗しました。" pm_logger.error(msg_err) raise common_utils.write_log_pm_error(e, pm_logger, msg_err) language = jmespath.search("[?Name=='locale'].Value | [0]", user_info['UserAttributes']) mail_execute_user = jmespath.search("[?Name=='email'].Value | [0]", user_info['UserAttributes']) # 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_ENGLISH if language in CommonConst.LANGUAGE_SUPPORT: language_mail = language path_file_template_check_error_notice_mail = config[ CommonConst.KEY_GET_PATH_FILE_TEMPLATE_CHECK_ERROR_NOTICE_MAIL.format( language=language_mail)] path_file_message_notice_error_execute_check_security = config[ CommonConst.KEY_GET_PATH_MESSAGE_NOTICE_ERROR_EXECUTE_CHECK_SECURITY. format(language=language_mail)] mail_subject_config = config[ CommonConst.KEY_CHECK_ERROR_NOTICE_MAIL_SUBJECT.format( language=language_mail)] # エラー通知内容設定ファイルを取得します。 try: messages_notice_error_execute_check_security = FileUtils.read_yaml( trace_id, CommonConst.S3_SETTING_BUCKET, path_file_message_notice_error_execute_check_security) except PmError as e: msg_err = "エラー通知内容設定ファイルの取得に失敗しました。:s3://{0}/{1}".format( common_utils.get_environ(CommonConst.S3_SETTING_BUCKET), path_file_message_notice_error_execute_check_security) pm_logger.error(msg_err) raise common_utils.write_log_pm_error(e, pm_logger, msg_err) # S3から通知メール本文テンプレートファイルを取得します。 try: template_body = FileUtils.read_decode( trace_id, CommonConst.S3_SETTING_BUCKET, path_file_template_check_error_notice_mail) except PmError as e: msg_err = "通知メール本文テンプレートファイルの取得に失敗しました。:s3://{0}/{1}".format( common_utils.get_environ(CommonConst.S3_SETTING_BUCKET), path_file_template_check_error_notice_mail) pm_logger.error(msg_err) raise common_utils.write_log_pm_error(e, pm_logger, msg_err) # に該当する通知内容を取得します。 content_message = messages_notice_error_execute_check_security[ CommonConst.KEY_GET_MESSAGE_NOTICE_ERROR_EXECUTE_CHECK_SECURITY.format( errorCode=error_code)] if data_body is not None: content_message = content_message.format_map(data_body) # 通知メール件名を作成 subject_template = Template(mail_subject_config) project_name = project['ProjectName'] mail_subject = subject_template.render(project_name=project_name) if check_code_item is not None: check_code_item = CommonConst.LIST_CHECK_ITEM_CODE_CONVERT[ check_code_item] template = Template(template_body) context = { 'organizationName': organization['OrganizationName'], 'projectName': project_name, 'checkCodeItem': check_code_item, 'awsAccount': aws_account, 'regionName': region_name, 'contentMessage': content_message } body = template.render(context) # SESで通知メールを送信します bcc_addresses = [mail_execute_user] try: aws_common.send_email(trace_id, config['ses.region'], config['mail.from'], bcc_addresses, mail_subject, body) except PmError as e: msg_err = "通知メール送信に失敗しました。" pm_logger.error(msg_err) raise common_utils.write_log_pm_error(e, pm_logger, msg_err)
def check_asc_item_12_01(trace_id, check_history_id, organization_id, project_id, aws_account, session, result_json_path): cw_logger = common_utils.begin_cw_logger(trace_id, __name__, inspect.currentframe()) check_results = [] is_authorized = True # 取得したクレデンシャル情報を使用して、S3クライアントを作成します。 try: s3_client = S3Utils.get_s3_client(trace_id, session, aws_account, is_cw_logger=True) except PmError as e: raise common_utils.write_log_pm_error(e, cw_logger) # S3バケット一覧を取得します。 try: list_buckets = S3Utils.list_buckets(trace_id, s3_client, aws_account, is_cw_logger=True) except PmError as e: return CheckResult.Error # S3バケット一覧情報をS3に保存します。 try: s3_file_name = CommonConst.PATH_CHECK_RAW.format( check_history_id, organization_id, project_id, aws_account, "ASC/S3_ListBuckets.json") FileUtils.upload_json(trace_id, "S3_CHECK_BUCKET", list_buckets, s3_file_name, is_cw_logger=True) except PmError as e: cw_logger.error("[%s] S3バケット一覧情報のS3保存に失敗しました。", aws_account) return CheckResult.Error for bucket in list_buckets["Buckets"]: bucket_name = bucket['Name'] region_name = None try: # 取得したS3バケット一覧情報ファイルをもとに、各バケットのリージョンを取得する。 region_name = S3Utils.get_bucket_location(trace_id, s3_client, bucket_name, aws_account, is_cw_logger=True) if region_name is None: region_name = CommonConst.US_EAST_REGION # 取得したS3バケット一覧情報ファイルをもとに、該当のS3バケットのアクセスコントロールリストを取得する。 bucket_acl = S3Utils.get_bucket_acl(trace_id, s3_client, bucket_name, aws_account, region_name) # 取得したS3バケット情報ファイルをもとに、該当のS3バケットのバケットポリシーを取得する。 bucket_policy = S3Utils.get_bucket_policy(trace_id, s3_client, bucket_name, aws_account, region_name, is_cw_logger=True) if bucket_policy is None: continue except PmError as e: if e.cause_error.response['Error'][ 'Code'] in CommonConst.S3_SKIP_EXCEPTION: error_operation = e.cause_error.operation_name, error_code = e.cause_error.response['Error']['Code'], error_message = e.cause_error.response['Error']['Message'] if region_name is None: region_name = CommonConst.ERROR check_results.append( asc_item_common_logic.get_error_authorized_result( region_name, bucket_name, error_operation, error_code, error_message)) is_authorized = False continue else: return CheckResult.Error # 取得したS3バケットのアクセスコントロールリスト情報をS3に保存する。(アクセスコントロールリスト情報) try: s3_file_name = CommonConst.PATH_CHECK_RAW.format( check_history_id, organization_id, project_id, aws_account, "ASC/S3_ACL_" + region_name + "_" + bucket_name + ".json") FileUtils.upload_json(trace_id, "S3_CHECK_BUCKET", bucket_acl, s3_file_name, is_cw_logger=True) except PmError as e: cw_logger.error("[%s] S3バケットACL情報のS3保存に失敗しました。(%s)/(%s)", aws_account, region_name, bucket_name) return CheckResult.Error # 取得したS3バケットのバケットポリシー情報をS3に保存する。(バケットポリシー情報) try: s3_file_name = CommonConst.PATH_CHECK_RAW.format( check_history_id, organization_id, project_id, aws_account, "ASC/S3_Bucketpolicy_" + region_name + "_" + bucket_name + ".json") FileUtils.upload_json(trace_id, "S3_CHECK_BUCKET", bucket_policy, s3_file_name, is_cw_logger=True) except PmError as e: cw_logger.error("[%s] S3バケットポリシー情報のS3保存に失敗しました。(%s/%s)", aws_account, region_name, bucket_name) return CheckResult.Error # チェック処理 bucket_acl_abnormity = False bucket_policy_abnormity = False try: # Check-1. ACLによりAllUsersに操作権限が与えられたS3バケットが存在するか # Check-2. ACLによりAuthenticatedUsersに操作権限が与えられたS3バケットが存在するか for grant in bucket_acl["Grants"]: if (common_utils.check_key("URI", grant['Grantee'])): if grant['Grantee']["URI"] in ACL_URI: bucket_acl_abnormity = True break # Check-3. バケットポリシーのプリンシパルにて全てのユーザに操作権限が与えられたS3バケットが存在するか bucket_policy = ast.literal_eval(bucket_policy['Policy']) for statement in bucket_policy["Statement"]: if (statement["Effect"] == CommonConst.ALLOW and statement["Principal"] == CommonConst.ALL): bucket_policy_abnormity = True break if bucket_acl_abnormity is True or bucket_policy_abnormity is True: check_results.append( get_check_accessible_result(region_name, bucket_acl_abnormity, bucket_policy_abnormity, bucket_name)) except Exception as e: cw_logger.error("[%s] チェック処理中にエラーが発生しました。(%s/%s)", aws_account, region_name, bucket_name) return CheckResult.Error # Export File CHECK_ASC_ITEM_12_01.json try: current_date = date_utils.get_current_date_by_format( date_utils.PATTERN_YYYYMMDDHHMMSS) check_bucket = { 'AWSAccount': aws_account, 'CheckResults': check_results, 'DateTime': current_date } FileUtils.upload_s3(trace_id, check_bucket, result_json_path, format_json=True, is_cw_logger=True) except Exception as e: cw_logger.error("[%s] チェック結果JSONファイルの保存に失敗しました。", aws_account) return CheckResult.Error # チェック結果 if is_authorized is False: return CheckResult.Error if len(check_results) > 0: return CheckResult.CriticalDefect return CheckResult.Normal
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 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 check_asc_item_07_01(trace_id, check_history_id, organization_id, project_id, aws_account, session, result_json_path): cw_logger = common_utils.begin_cw_logger(trace_id, __name__, inspect.currentframe()) check_results = [] try: regions = aws_common.get_regions(trace_id, session, is_cw_logger=True) except PmError as e: cw_logger.error("Regionの情報の取得に失敗しました。") raise common_utils.write_log_pm_error(e, cw_logger) for region in regions: region_name = region["RegionName"] if region_name in REGION_IGNORE: continue ec2_client = Ec2Utils.get_ec2_client(trace_id, session, region_name, aws_account, is_cw_logger=True) try: # EBS情報を取得する。 ebs_volumes = Ec2Utils.describe_volumes(trace_id, aws_account, ec2_client, region_name, is_cw_logger=True) except PmError as e: return CheckResult.Error # 取得件数が0件の場合、ログを出力し、次のリージョンの処理に進みます。 if (len(ebs_volumes) == 0): cw_logger.info("[%s/%s] EBSボリューム情報の取得件数が0でした。", aws_account, region_name) continue try: # 取得したEBS情報をS3に保存する(EBS情報ファイル)。 s3_file_name = CommonConst.PATH_CHECK_RAW.format( check_history_id, organization_id, project_id, aws_account, "ASC/EBS_Volumes_" + region_name + ".json") FileUtils.upload_s3(trace_id, ebs_volumes, s3_file_name, True, is_cw_logger=True) except PmError as e: cw_logger.error("[%s/%s] EBSボリューム情報情報のS3保存に失敗しました。", aws_account, region_name) return CheckResult.Error # チェックルール try: for ebs_volume in ebs_volumes: if (ebs_volume['Encrypted'] is False): check_result = get_check_asc_item_07_01_result( ebs_volume, region_name) check_results.append(check_result) except PmError as e: cw_logger.error("[%s/%s] チェック処理中にエラーが発生しました。", aws_account, region_name) return CheckResult.Error # Export File ASC/CHECK_ ASC_ITEM_07_01.json try: current_date = date_utils.get_current_date_by_format( date_utils.PATTERN_YYYYMMDDHHMMSS) check_acs_item_7_01 = { 'AWSAccount': aws_account, 'CheckResults': check_results, 'DateTime': current_date } FileUtils.upload_s3(trace_id, check_acs_item_7_01, result_json_path, format_json=True, is_cw_logger=True) except Exception as e: cw_logger.error("[%s] チェック結果JSONファイルの保存に失敗しました。", aws_account) return CheckResult.Error # チェック結果 if len(check_results) > 0: return CheckResult.CriticalDefect return CheckResult.Normal