Exemple #1
0
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
Exemple #2
0
def execute_confirm_awscoop(task_id):
    pm_logger = common_utils.begin_logger(task_id, __name__,
                                          inspect.currentframe())

    coop_id = organizationTask_logic.check_process_status(task_id)
    if coop_id is None:
        pm_logger.error("組織タスク情報取得に失敗しました。: TaskID=%s", task_id)
        raise PmError()

    try:
        awscoop = pm_awsAccountCoops.query_awscoop_coop_key(task_id, coop_id)
    except PmError as e:
        pm_logger.error("AWSアカウント連携情報取得に失敗しました。: CoopID=%s", coop_id)
        raise common_utils.write_log_pm_error(e, pm_logger, exc_info=True)

    if (not awscoop):
        pm_logger.warning("AWSアカウント連携情報がありません。: CoopID=%s", coop_id)
        raise PmError()

    try:
        aws_common.create_session_client(task_id, awscoop['AWSAccount'],
                                         awscoop['RoleName'],
                                         awscoop['ExternalID'])
        pm_logger.info("クレデンシャルが正常に取得されました。: CoopID=%s", coop_id)
    except PmError as err:
        pm_logger.error("クレデンシャル取得に失敗しました。: CoopID=%s", coop_id)
        try:
            attribute = {'Effective': {"Value": Effective.Disable.value}}
            pm_awsAccountCoops.update_awscoops(task_id, coop_id, attribute)
        except PmError as e:
            pm_logger.error("AWSアカウント連携情報の更新に失敗しました。: CoopID=%s", coop_id)
            raise common_utils.write_log_pm_error(err,
                                                  pm_logger,
                                                  exc_info=True)
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
Exemple #4
0
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 delete_user(trace_id, organization_id, user_id, email):
    pm_logger = common_utils.begin_logger(trace_id, __name__,
                                          inspect.currentframe())
    # check the deletion condition
    if user_id == trace_id:
        try:
            count = pm_affiliation.query_users_check_authority_count(
                trace_id, user_id, organization_id, Authority.Owner)
        except PmError as e:
            return common_utils.error_exception(
                MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e,
                pm_logger, True)
        if count == 0:
            return common_utils.error_common(MsgConst.ERR_REQUEST_203,
                                             HTTPStatus.PRECONDITION_FAILED,
                                             pm_logger)
    # get user to delete
    try:
        user = pm_affiliation.query(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 user:
        return common_utils.error_common(MsgConst.ERR_301,
                                         HTTPStatus.NOT_FOUND, pm_logger)

    # delete user
    try:
        pm_affiliation.delete_affiliation(user_id, organization_id)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_DB_405,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # set task informaiton request delete in Organization Tasks
    task_id = str(uuid.uuid4())
    target = CommonConst.TARGET_DELETE_ORG_USER.format(user_id,
                                                       organization_id)

    try:
        # create task informaiton request delete in Organization Tasks
        pm_organizationTasks.create_organizationTask(
            trace_id, task_id, CommonConst.TASK_TYPE_CODE_DELETE_ORG_USER,
            target, trace_id, email, Status.Waiting.value, 0, 3)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_DB_403,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)
    try:
        # Send message to organization topic task
        aws_common.sns_organization_topic(
            trace_id, task_id, CommonConst.TASK_TYPE_CODE_DELETE_ORG_USER)
    except PmError as e:
        common_utils.write_log_pm_error(e, pm_logger, exc_info=True)

    response = common_utils.get_response_by_response_body(
        HTTPStatus.NO_CONTENT, None)
    return common_utils.response(response, pm_logger)
def main(argv):
    # コマンドラインパラメータ
    try:
        check_history_id = argv[1]
        log_id = CommonConst.BLANK
        language = CommonConst.LANGUAGE_DEFAULT
        if(len(argv) > 2):
            log_id = argv[2]
        if(len(argv) > 3 and argv[3] in CommonConst.LANGUAGE_SUPPORT):
            language = argv[3]
    except Exception as e:
        pm_logger = common_utils.begin_logger(None, __name__,
                                              inspect.currentframe())
        common_utils.write_log_exception(e, pm_logger, True)
        sys.exit(CommonConst.EXIT_CODE_ERROR)

    # バッチ処理開始
    pm_logger = common_utils.begin_logger(check_history_id, __name__,
                                          inspect.currentframe())
    error_code = None
    pm_logger.info("** バッチアプリケーション起動 ***************")
    pm_logger.info("== バッチアプリケーション処理開始 ================")
    pm_logger.info("チェック履歴ID: " + check_history_id)
    pm_logger.info("ログID: " + log_id)
    pm_logger.info("==================================================")
    try:
        awsResourceAggregate_logic.aws_resource_aggregate(
            check_history_id, log_id)
    except PmError as e:
        common_utils.write_log_pm_error(e, pm_logger, exc_info=True)
        error_code = e.message
    except Exception as e:
        common_utils.write_log_exception(e, pm_logger, True)
        error_code = 'CKEX_SECURITY-999'

    # チェック処理結果を記録
    exit_code = CommonConst.EXIT_CODE_SUCCESS
    try:
        check_status = CheckStatus.CheckCompleted
        if (error_code is None):
            check_status = CheckStatus.SummaryCompleted
        awsResourceChecker_logic.processing_finish(check_history_id,
                                                   error_code, check_status)
        if (error_code is not None):
            exit_code = CommonConst.EXIT_CODE_ERROR

        # チェック結果通知処理
        awsResourceAggregate_logic.check_result_notification(
            check_history_id, language)
    except PmError as e:
        common_utils.write_log_pm_error(e, pm_logger, exc_info=True)
        exit_code = CommonConst.EXIT_CODE_ERROR
    except Exception as e:
        common_utils.write_log_exception(e, pm_logger, True)
        exit_code = CommonConst.EXIT_CODE_ERROR
    pm_logger.info("-- 最新チェック結果作成終了 ----")
    sys.exit(exit_code)
def execute_send_result_email(trace_id, check_history_id, aws_request_id,
                              language):
    pm_logger = common_utils.begin_logger(trace_id, __name__,
                                          inspect.currentframe())
    try:
        send_result_email(trace_id, check_history_id, language)
    except PmError as e:
        common_utils.write_log_pm_error(e, pm_logger, exc_info=True)
        publish_error_message(trace_id, check_history_id, aws_request_id,
                              e.message)
def execute_security_check_with_executed_type(trace_id, organization_id,
                                              project_id, user_id, email,
                                              executed_type):
    pm_logger = common_utils.begin_logger(trace_id, __name__,
                                          inspect.currentframe())

    # リソース関連性のバリデーションチェックを行います。
    try:
        project = pm_projects.get_projects_by_organization_id(
            trace_id, project_id, organization_id)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)
    if not project:
        return common_utils.error_common(
            MsgConst.ERR_AWS_401, HTTPStatus.UNPROCESSABLE_ENTITY, pm_logger)

    try:
        check_history_id = common_utils.get_uuid4()
        executed_date_time = common_utils.get_current_date()
        pm_checkHistory.create(trace_id, check_history_id, organization_id,
                               project_id, CHECK_SECURITY, CheckStatus.Waiting,
                               None, executed_type, None, executed_date_time,
                               None, user_id)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_DB_403,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    try:
        topic_arn = common_utils.get_environ(
            CommonConst.SECURITYCHECK_EXECUTE_TOPIC)
        subject = "USER : {0}".format(user_id)
        message = {
            'CheckHistoryId': check_history_id
        }
        # Publish message
        aws_common.aws_sns(trace_id, subject, json.dumps(message), topic_arn)
    except PmError as e:
        common_utils.write_log_pm_error(e, pm_logger, exc_info=True)

    try:
        check_history = pm_checkHistory.query_key(trace_id, check_history_id,
                                                  True)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)
    # return data response
    response = common_utils.get_response_by_response_body(
        HTTPStatus.CREATED, check_history)
    return common_utils.response(response, pm_logger)
def 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)
Exemple #10
0
def main(argv):
    # コマンドラインパラメータ
    try:
        check_history_id = argv[1]
        log_id = CommonConst.BLANK
        if (len(argv) > 2):
            log_id = argv[2]
    except Exception as e:
        pm_logger = common_utils.begin_logger(None, __name__,
                                              inspect.currentframe())
        common_utils.write_log_exception(e, pm_logger, True)
        sys.exit(CommonConst.EXIT_CODE_ERROR)

    # バッチ処理開始
    pm_logger = common_utils.begin_logger(check_history_id, __name__,
                                          inspect.currentframe())
    error_code = None
    pm_logger.info("** バッチアプリケーション起動 ***************")
    pm_logger.info("== バッチアプリケーション処理開始 ================")
    pm_logger.info("チェック履歴ID: " + check_history_id)
    pm_logger.info("ログID: " + log_id)
    pm_logger.info("==================================================")
    try:
        awsResourceChecker_logic.aws_resource_checker(check_history_id, log_id)
    except PmError as e:
        error_code = e.message
        if error_code != "CKEX_SECURITY-900":
            common_utils.write_log_pm_error(e, pm_logger, exc_info=True)
    except Exception as e:
        common_utils.write_log_exception(e, pm_logger, True)
        error_code = 'CKEX_SECURITY-999'
    # チェック処理結果を記録
    exit_code = CommonConst.EXIT_CODE_SUCCESS
    try:
        check_status = CheckStatus.Waiting
        if (error_code is None):
            check_status = CheckStatus.CheckCompleted
        awsResourceChecker_logic.processing_finish(check_history_id,
                                                   error_code, check_status)
        if (error_code is not None):
            exit_code = CommonConst.EXIT_CODE_ERROR
    except PmError as e:
        common_utils.write_log_pm_error(e, pm_logger, exc_info=True)
        exit_code = CommonConst.EXIT_CODE_ERROR
    except Exception as e:
        common_utils.write_log_exception(e, pm_logger, True)
        exit_code = CommonConst.EXIT_CODE_ERROR
    pm_logger.info("** バッチアプリケーション終了 ***************")
    sys.exit(exit_code)
def update_check_results(trace_id, check_history_id, check_result_id, ok_count,
                         critical_count, ng_count, managed_count, error_count):
    pm_logger = common_utils.begin_logger(trace_id, __name__,
                                          inspect.currentframe())
    attribute = {
        'OKCount': {
            "Value": ok_count
        },
        'CriticalCount': {
            "Value": critical_count
        },
        'NGCount': {
            "Value": ng_count
        },
        'ManagedCount': {
            "Value": managed_count
        },
        'ErrorCount': {
            "Value": error_count
        }
    }
    try:
        pm_checkResults.update(trace_id, check_result_id, attribute)
    except PmError as e:
        pm_logger.error(
            "チェック結果の集計値の更新に失敗しました。: CheckHistoryID=%s, CheckResultID=%s",
            check_history_id, check_result_id)
        raise common_utils.write_log_pm_error(e, pm_logger, "AGG_SECURITY-006")
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 execute_send_checkerror_email(trace_id, aws_request_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:
        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)
    except PmError as e:
        common_utils.write_log_pm_error(e, pm_logger, exc_info=True)
        publish_error_message_send_checkerror_email(trace_id, check_history_id,
                                                    organization_id,
                                                    project_id, aws_request_id,
                                                    e.message)
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
Exemple #15
0
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 get_trails_status(trace_id, awsaccount, trail_client, region_name,
                      trail_arn):
    pm_logger = common_utils.begin_logger(trace_id, __name__,
                                          inspect.currentframe())
    try:
        status = trail_client.get_trail_status(Name=trail_arn)
    except ClientError as e:
        pm_logger.error("[%s/%s] CloudTrailのステータス情報の取得に失敗しました。", awsaccount,
                        region_name)
        data_body = {'TrailARN': trail_arn}
        pm_error = common_utils.write_log_exception(e, pm_logger)
        pm_error.pm_notification_error = PmNotificationError(
            code_error=CommonConst.KEY_CODE_ERROR_GET_TRAIL_STATUS,
            data_body=data_body)
        raise common_utils.write_log_pm_error(pm_error, pm_logger)
    return status
def get_event_selectors(trace_id, awsaccount, trail_client, region_name,
                        trail_arn):
    pm_logger = common_utils.begin_logger(trace_id, __name__,
                                          inspect.currentframe())
    event_selectors = []
    try:
        result = trail_client.get_event_selectors(TrailName=trail_arn)
    except ClientError as e:
        pm_logger.error("[%s/%s] CloudTrailのイベントセレクタ情報の取得に失敗しました。", awsaccount,
                        region_name)
        data_body = {'TrailARN': trail_arn}
        pm_error = common_utils.write_log_exception(e, pm_logger)
        pm_error.pm_notification_error = PmNotificationError(
            code_error=CommonConst.KEY_CODE_ERROR_GET_EVENT_SELECTORS,
            data_body=data_body)
        raise common_utils.write_log_pm_error(pm_error, pm_logger)
    if common_utils.check_key("EventSelectors", result):
        event_selectors = result["EventSelectors"]
    return event_selectors
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 aws_resource_aggregate(check_history_id, log_id):
    trace_id = check_history_id
    pm_logger = common_utils.begin_logger(trace_id, __name__,
                                          inspect.currentframe())
    # バリデーションチェック
    if common_utils.is_null(check_history_id):
        pm_logger.error("チェック履歴IDが指定されていません。")
        raise PmError(message="AGG_SECURITY-001")

    # ログストリーム名取得
    if common_utils.is_null(log_id) is False:
        try:
            awsResourceChecker_logic.update_log_stream_name_to_s3(
                trace_id, check_history_id, log_id)
        except PmError as e:
            common_utils.write_log_pm_error(e, pm_logger, exc_info=True)

    # チェック履歴情報の取得とステータス更新
    pm_logger.info("-- チェック履歴情報取得処理開始 ----")
    try:
        check_history = pm_checkHistory.query_key(trace_id, check_history_id)
    except PmError as e:
        pm_logger.error("チェック履歴情報の取得に失敗しました。: CheckHistoryID=%s",
                        check_history_id)
        raise common_utils.write_log_pm_error(e, pm_logger, "AGG_SECURITY-002")
    if (not check_history):
        pm_logger.error("チェック履歴情報がありません。: CheckHistoryID=%s", check_history_id)
        pm_error = PmError(message="AGG_SECURITY-002")
        raise pm_error
    pm_logger.info("-- チェック履歴情報取得処理終了 ----")

    # 取得したチェック履歴情報のステータスをチェックします。
    pm_logger.info("-- チェック履歴情報ステータスチェック開始  ----")
    if (check_history['CheckStatus'] != CheckStatus.CheckCompleted):
        pm_logger.error(
            "チェック実行ステータスが一致しません。: CheckHistoryID=%s, CheckStatus=%s",
            check_history_id, check_history['CheckStatus'])
        pm_error = PmError(message="AGG_SECURITY-003")
        raise pm_error

    # チェック履歴情報のステータスを更新します。
    attribute = {'CheckStatus': {"Value": CheckStatus.SummaryProgress}}
    try:
        pm_checkHistory.update(trace_id, check_history_id, attribute,
                               check_history['UpdatedAt'])
        pm_logger.info("-- チェック履歴情報ステータスチェック終了 ----")
    except PmError as e:
        pm_logger.error("チェック履歴情報のステータス更新に失敗しました。: CheckHistoryID=%s",
                        check_history_id)
        raise common_utils.write_log_pm_error(e, pm_logger, "AGG_SECURITY-004")

    # 個別チェック結果取得
    pm_logger.info("-- 個別チェック結果取得開始 ----")
    try:
        list_check_result_items = pm_checkResultItems.query_check_history_index_fiter_ne_exclusion_flag(
            trace_id, check_history_id, ExclusionFlag.Enable)
    except PmError as e:
        pm_logger.error("個別チェック結果取得に失敗しました。: CheckHistoryID=%s",
                        check_history_id)
        raise common_utils.write_log_pm_error(e, pm_logger, "AGG_SECURITY-005")
    if (not list_check_result_items):
        pm_logger.error("個別チェック結果がありません。: CheckHistoryID=%s", check_history_id)
        raise PmError(message="AGG_SECURITY-005")
    pm_logger.info("-- 個別チェック結果取得終了 ----")

    # 個別チェック結果集計 / チェック結果更新
    pm_logger.info("-- 個別チェック結果集計開始 ----")
    list_check_result_items = sorted(list_check_result_items,
                                     key=itemgetter('CheckResultID'))

    check_result_id = list_check_result_items[0]['CheckResultID']
    ok_count = critical_count = ng_count = managed_count = error_count = 0
    count = 0
    for check_result_item in list_check_result_items:
        count += 1
        check_result = check_result_item['CheckResult']
        if (check_result_item['CheckResultID'] == check_result_id):
            if check_result == CheckResult.Normal:
                ok_count += 1
            elif check_result == CheckResult.MinorInadequacies:
                ng_count += 1
            elif check_result == CheckResult.CriticalDefect:
                critical_count += 1
            elif check_result == CheckResult.MembersManagement:
                managed_count += 1
            elif check_result == CheckResult.Error:
                error_count += 1
        else:
            update_check_results(trace_id, check_history_id, check_result_id,
                                 ok_count, critical_count, ng_count,
                                 managed_count, error_count)
            check_result_id = check_result_item['CheckResultID']
            ok_count = critical_count = ng_count = managed_count = error_count = 0
            if check_result == CheckResult.Normal:
                ok_count += 1
            elif check_result == CheckResult.MinorInadequacies:
                ng_count += 1
            elif check_result == CheckResult.CriticalDefect:
                critical_count += 1
            elif check_result == CheckResult.MembersManagement:
                managed_count += 1
            elif check_result == CheckResult.Error:
                error_count += 1

        # update data PM_CheckResults
        if (count == len(list_check_result_items)):
            update_check_results(trace_id, check_history_id, check_result_id,
                                 ok_count, critical_count, ng_count,
                                 managed_count, error_count)
    pm_logger.info("-- 個別チェック結果集計終了 ----")

    # 最新チェック結果作成
    pm_logger.info("-- 最新チェック結果作成開始 ----")
    organization_id = check_history['OrganizationID']
    project_id = check_history['ProjectID']
    try:
        pm_latestCheckResult.create(trace_id, organization_id, project_id,
                                    check_history_id)
    except PmError as e:
        pm_logger.error("最新チェック結果テーブルのレコード作成に失敗しました。: CheckHistoryID=%s",
                        check_history_id)
        raise common_utils.write_log_pm_error(e, pm_logger, "AGG_SECURITY-007")
Exemple #22
0
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
Exemple #23
0
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
def execute_security_group_port(trace_id, check_history_id, organization_id,
                                project_id, awsaccount, session,
                                result_json_path, port, check_item_code,
                                excluded_resources):
    pm_logger = common_utils.begin_logger(trace_id, __name__,
                                          inspect.currentframe())
    check_results = []
    # Export File VPC_SecurityGroups_{region}.json
    try:
        regions = aws_common.get_regions(trace_id, session)
    except PmError as e:
        pm_logger.error("Regionの情報の取得に失敗しました。")
        e.pm_notification_error = PmNotificationError(
            check_item_code=check_item_code,
            code_error=CommonConst.KEY_CODE_ERROR_DEFAULT)
        raise common_utils.write_log_pm_error(e, pm_logger)
    for region in regions:
        region_name = region["RegionName"]
        try:
            if region_name in REGION_IGNORE:
                continue
            ec2_client = Ec2Utils.get_ec2_client(trace_id, session,
                                                 region_name, awsaccount)
            s3_file_name = CommonConst.PATH_CHECK_RAW.format(
                check_history_id, organization_id, project_id, awsaccount,
                "VPC_SecurityGroups_" + region_name + ".json")
            if (aws_common.check_exists_file_s3(trace_id, "S3_CHECK_BUCKET",
                                                s3_file_name)) is True:
                try:
                    security_groups = 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:
                    security_groups = Ec2Utils.describe_security_groups(
                        trace_id, awsaccount, ec2_client, region_name)
                except PmError as e:
                    raise common_utils.write_log_pm_error(e, pm_logger)
                if (len(security_groups) == 0):
                    pm_logger.info("[%s/%s] セキュリティグループ情報の取得件数が0でした。",
                                   awsaccount, region_name)
                    continue
                try:
                    FileUtils.upload_s3(trace_id, security_groups,
                                        s3_file_name, True)
                except PmError as e:
                    pm_logger.error("[%s/%s] セキュリティグループ情報のS3保存に失敗しました。",
                                    awsaccount, region_name)
                    raise common_utils.write_log_pm_error(e, pm_logger)
            try:
                for security_group in security_groups:
                    # check excluded resources
                    resource_name = security_group['GroupId']
                    if common_utils.check_excluded_resources(
                            check_item_code, region_name, ResourceType.GroupId,
                            resource_name, excluded_resources):
                        continue

                    for ip_permission in security_group['IpPermissions']:
                        if ip_permission['IpProtocol'] != '-1':
                            if ip_permission['IpProtocol'] != CommonConst.TCP:
                                continue
                            if common_utils.check_key(
                                    'FromPort', ip_permission
                            ) is False or ip_permission['FromPort'] > port:
                                continue
                            if common_utils.check_key(
                                    'ToPort', ip_permission
                            ) is False or ip_permission['ToPort'] < port:
                                continue
                        for ip_range in ip_permission['IpRanges']:
                            if common_utils.check_key('CidrIp', ip_range):
                                if (CommonConst.CIDR_IP_NOT_SECURITY ==
                                        ip_range['CidrIp']):
                                    check_result = get_check_result(
                                        security_group, ip_permission,
                                        ip_range, region_name)
                                    check_results.append(check_result)
                                    break
            except Exception as e:
                pm_logger.error("[%s/%s] チェック処理中にエラーが発生しました。", awsaccount,
                                region_name)
                raise common_utils.write_log_pm_error(e, pm_logger)
        except Exception as e:
            pm_error = common_utils.write_log_exception(e, pm_logger)
            pm_error.pm_notification_error = PmNotificationError(
                check_item_code=check_item_code,
                region=region_name,
                code_error=CommonConst.KEY_CODE_ERROR_DEFAULT)
            raise common_utils.write_log_pm_error(pm_error, pm_logger)

    result_security_group = CheckResult.Normal
    if (len(check_results) > 0):
        result_security_group = CheckResult.CriticalDefect

    # 検出結果を1つのチェック結果JSONファイルに保存する。
    try:
        current_date = date_utils.get_current_date_by_format(
            date_utils.PATTERN_YYYYMMDDHHMMSS)
        check_rule_security_group = {
            'AWSAccount': awsaccount,
            'CheckResults': check_results,
            'DateTime': current_date
        }
        FileUtils.upload_s3(trace_id, check_rule_security_group,
                            result_json_path, True)
    except Exception as e:
        pm_logger.error("[%s] チェック結果JSONファイルの保存に失敗しました。", awsaccount)
        pm_error = common_utils.write_log_exception(e, pm_logger)
        pm_error.pm_notification_error = PmNotificationError(
            check_item_code=check_item_code,
            code_error=CommonConst.KEY_CODE_ERROR_DEFAULT)
        raise common_utils.write_log_pm_error(pm_error, pm_logger)

    return result_security_group
def check_cis_item_4_03(trace_id, check_history_id, organization_id,
                        project_id, awsaccount, session, result_json_path,
                        check_item_code, excluded_resources):
    pm_logger = common_utils.begin_logger(trace_id, __name__,
                                          inspect.currentframe())
    check_results = []
    try:
        regions = aws_common.get_regions(trace_id, session)
    except PmError as e:
        pm_logger.error("Regionの情報の取得に失敗しました。")
        e.pm_notification_error = PmNotificationError(
            check_item_code=check_item_code,
            code_error=CommonConst.KEY_CODE_ERROR_DEFAULT)
        raise common_utils.write_log_pm_error(e, pm_logger)
    for region in regions:
        region_name = region["RegionName"]
        try:
            if region_name in REGION_IGNORE:
                continue
            ec2_client = Ec2Utils.get_ec2_client(trace_id, session,
                                                 region_name, awsaccount)
            # 対象のAWSアカウントのリージョンごと(GovCloud、北京を除く)にセキュリティグループ情報を取得する。
            s3_file_name = CommonConst.PATH_CHECK_RAW.format(
                check_history_id, organization_id, project_id, awsaccount,
                "VPC_SecurityGroups_" + region_name + ".json")
            if (aws_common.check_exists_file_s3(trace_id, "S3_CHECK_BUCKET",
                                                s3_file_name)) is True:
                try:
                    security_groups = 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:
                    security_groups = Ec2Utils.describe_security_groups(
                        trace_id, awsaccount, ec2_client, region_name)
                except PmError as e:
                    raise common_utils.write_log_pm_error(e, pm_logger)
                if (len(security_groups) == 0):
                    pm_logger.info("[%s/%s] セキュリティグループ情報の取得件数が0でした。",
                                   awsaccount, region_name)
                try:
                    if (len(security_groups) > 0):
                        FileUtils.upload_s3(trace_id, security_groups,
                                            s3_file_name, True)
                except PmError as e:
                    pm_logger.error("[%s/%s] セキュリティグループ情報のS3保存に失敗しました。",
                                    awsaccount, region_name)
                    raise common_utils.write_log_pm_error(e, pm_logger)

            # 対象のAWSアカウントのリージョンごと(GovCloud、北京を除く)にEC2インスタンス情報を取得する。
            s3_file_name_iam_instances = CommonConst.PATH_CHECK_RAW.format(
                check_history_id, organization_id, project_id, awsaccount,
                "IAM_Instances_" + region_name + ".json")
            if (aws_common.check_exists_file_s3(
                    trace_id, "S3_CHECK_BUCKET",
                    s3_file_name_iam_instances)) is True:
                try:
                    reservation_instances = FileUtils.read_json(
                        trace_id, "S3_CHECK_BUCKET",
                        s3_file_name_iam_instances)
                except PmError as e:
                    raise common_utils.write_log_pm_error(e, pm_logger)
            else:
                try:
                    reservation_instances = Ec2Utils.describe_instances(
                        trace_id, awsaccount, ec2_client, region_name)
                except PmError as e:
                    raise common_utils.write_log_pm_error(e, pm_logger)
                if (len(reservation_instances) == 0):
                    pm_logger.info("[%s/%s] EC2インスタンス情報の取得件数が0でした。",
                                   awsaccount, region_name)
            try:
                if (len(reservation_instances) > 0):
                    s3_file_name = CommonConst.PATH_CHECK_RAW.format(
                        check_history_id, organization_id, project_id,
                        awsaccount,
                        "VPC_SG_Instances_" + region_name + ".json")
                    FileUtils.upload_s3(trace_id, reservation_instances,
                                        s3_file_name, True)
            except PmError as e:
                pm_logger.error("[%s/%s] EC2インスタンス情報のS3保存に失敗しました。", awsaccount,
                                region_name)
                raise common_utils.write_log_pm_error(e, pm_logger)

            check1 = []
            check2 = []
            try:
                # リソース情報ファイルのセキュリティグループ情報から、インバウンドルール、アウトバウンドルールを設定しているdefaultセキュリティグループを検出する。
                for security_group in security_groups:
                    # check excluded resources
                    resource_name = security_group['GroupId']
                    if common_utils.check_excluded_resources(
                            check_item_code, region_name, ResourceType.GroupId,
                            resource_name, excluded_resources):
                        continue

                    if (security_group['GroupName'] == CommonConst.DEFAULT
                            and len(security_group['IpPermissions']) > 0 and
                            len(security_group['IpPermissionsEgress']) > 0):
                        check1.append(security_group['GroupId'])

                # リソース情報ファイルのEC2インスタンス情報から、defaultセキュリティグループをアタッチしたEC2インスタンスを検出する、。
                for reservation_instance in reservation_instances:
                    for instance in reservation_instance['Instances']:
                        for security_group in instance['SecurityGroups']:
                            if security_group[
                                    'GroupName'] == CommonConst.DEFAULT:
                                if common_utils.check_key('Tags',
                                                          instance) is True:
                                    name_tag = next(
                                        filter(
                                            lambda tag: tag['Key'] == 'Name',
                                            instance['Tags']), None)
                                    instance[
                                        'InstanceName'] = None if name_tag is None else name_tag[
                                            'Value']
                                check2.append(instance)

                if (len(check1) > 0 or len(check2) > 0):
                    check_results.append(
                        get_check_cis_item_4_03_result(check1, check2,
                                                       region_name))
            except Exception as e:
                pm_logger.error("[%s/%s] チェック処理中にエラーが発生しました。", awsaccount,
                                region_name)
                raise common_utils.write_log_pm_error(e, pm_logger)
        except Exception as e:
            pm_error = common_utils.write_log_exception(e, pm_logger)
            pm_error.pm_notification_error = PmNotificationError(
                check_item_code=check_item_code,
                region=region_name,
                code_error=CommonConst.KEY_CODE_ERROR_DEFAULT)
            raise common_utils.write_log_pm_error(pm_error, pm_logger)

    # Export File CHECK_CIS12_ITEM_4_03.json
    try:
        current_date = date_utils.get_current_date_by_format(
            date_utils.PATTERN_YYYYMMDDHHMMSS)
        check_cis_item_4_03 = {
            'AWSAccount': awsaccount,
            'CheckResults': check_results,
            'DateTime': current_date
        }
        FileUtils.upload_s3(trace_id, check_cis_item_4_03, result_json_path,
                            True)
    except Exception as e:
        pm_logger.error("[%s] チェック結果JSONファイルの保存に失敗しました。", awsaccount)
        pm_error = common_utils.write_log_exception(e, pm_logger)
        pm_error.pm_notification_error = PmNotificationError(
            check_item_code=check_item_code,
            code_error=CommonConst.KEY_CODE_ERROR_DEFAULT)
        raise common_utils.write_log_pm_error(pm_error, pm_logger)

    # チェック結果
    if len(check_results) > 0:
        return CheckResult.MinorInadequacies
    return CheckResult.Normal
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 check_cis_metric(trace_id, check_history_id, organization_id, project_id,
                     awsaccount, session, result_json_path, check_item_code,
                     level_code, check_result):
    pm_logger = common_utils.begin_logger(trace_id, __name__,
                                          inspect.currentframe())
    check_results = []
    is_all_region_enable = False
    is_check5_successful = False
    # Get all region
    try:
        regions = aws_common.get_regions(trace_id, session)
    except PmError as e:
        pm_logger.error("Regionの情報の取得に失敗しました。")
        e.pm_notification_error = PmNotificationError(
            check_item_code=check_item_code,
            code_error=CommonConst.KEY_CODE_ERROR_DEFAULT)
        raise common_utils.write_log_pm_error(e, pm_logger)

    for region in regions:
        try:
            region_name = region["RegionName"]
            if region_name in REGION_IGNORE:
                continue

            # Default value check
            is_region_error = True

            try:
                cloud_trails = cis_item_common_logic.get_cloud_trails(
                    trace_id, check_history_id, organization_id, project_id,
                    awsaccount, region_name, session)
            except PmError as e:
                raise common_utils.write_log_pm_error(e, pm_logger)
            logs_client = LogsUtils.get_logs_client(trace_id, session,
                                                    region_name, awsaccount)
            cloudwatch_client = CloudWatchlUtils.get_cloudwatch_client(
                trace_id, session, region_name, awsaccount)
            sns_client = SNSUtils.get_sns_client(trace_id, session,
                                                 region_name, awsaccount)
            trail_client = CloudTrailUtils.get_trail_client(
                trace_id, session, region_name, awsaccount)
            for cloud_trail in cloud_trails:
                try:
                    # Check-0. マルチリージョン設定されたCloudTrailが存在するか。
                    trail_status = cis_item_common_logic.get_trails_status(
                        trace_id, check_history_id, organization_id,
                        project_id, awsaccount, region_name, trail_client,
                        cloud_trail)
                    if (len(trail_status) == 0):
                        continue

                    event_selectors = cis_item_common_logic.get_trail_event_selectors(
                        trace_id, check_history_id, organization_id,
                        project_id, awsaccount, region_name, trail_client,
                        cloud_trail)

                    # 全リージョンに対し有効なCloudTrailが存在するか
                    # ロギングが有効か
                    if (is_all_region_enable is False
                            and cloud_trail['IsMultiRegionTrail'] is True
                            and trail_status['IsLogging'] is True):

                        # すべての管理操作の書き込みが有効か
                        for event_selector in event_selectors:
                            if (event_selector['IncludeManagementEvents'] is True
                                    and event_selector['ReadWriteType'] == CommonConst.EVENT_SELECTOR_READ_WRITE_TYPE_ALL):
                                is_all_region_enable = True
                                break
                    if (is_all_region_enable is False):
                        continue

                    # Check-1. CloudTrailのロググループに対してメトリクスは設定されているか。
                    if common_utils.check_key(
                            'CloudWatchLogsLogGroupArn', cloud_trail
                    ) is False or not cloud_trail['CloudWatchLogsLogGroupArn']:
                        continue

                    # Check-2. 許可されていないAPIコールに対するメトリクスは設定されているか。
                    metric_filters = describe_metric_filters(
                        trace_id, check_history_id, organization_id,
                        project_id, awsaccount, region_name, logs_client,
                        cloud_trail['CloudWatchLogsLogGroupArn'].split(":")[6])

                    list_filter_pattern_result = get_list_filter_pattern_match_result(
                        trace_id, check_item_code, metric_filters)
                    if (not list_filter_pattern_result):
                        continue

                    # Check-3. メトリクスに対しアラームは設定されているか。
                    metric_alarms = describe_alarms(
                        trace_id, check_history_id, organization_id,
                        project_id, awsaccount, region_name, cloudwatch_client)

                    metric_names = []
                    for filter_pattern_result in list_filter_pattern_result:
                        metric_names.extend(
                            jmespath.search(
                                'metricTransformations[*].metricName',
                                filter_pattern_result))

                    metric_alarms_matching = []
                    for metric_alarm in metric_alarms:
                        pm_logger.info(
                            "アラーム名=%s",
                            common_utils.get_value("AlarmName", metric_alarm))

                        if (common_utils.check_key('MetricName',
                                                   metric_alarm) is True and
                                metric_alarm['MetricName'] in metric_names):
                            metric_alarms_matching.append(metric_alarm)

                    if not metric_alarms_matching:
                        continue

                    # Check-4. アラームからキックされたSNSに対し通知先は設定されているか。
                    for metric_alarm in metric_alarms_matching:
                        for alarm_action in metric_alarm['AlarmActions']:
                            if alarm_action.startswith(CommonConst.ARN_SNS):
                                subscriptions = list_subscriptions_by_topic(
                                    trace_id, check_history_id,
                                    organization_id, project_id, awsaccount,
                                    region_name, sns_client, alarm_action)
                                if len(subscriptions) > 0:
                                    is_region_error = False
                                    break

                    # Check-5. 設定されたCloudTrailは全Region有効なTrailか。
                    if (is_region_error is False
                            and is_all_region_enable is True):
                        is_check5_successful = True
                        break
                except Exception as e:
                    pm_logger.error("[%s/%s] チェック処理中にエラーが発生しました。", awsaccount,
                                    region_name)
                    raise common_utils.write_log_exception(e, pm_logger)

            if is_check5_successful is True:
                check_results = []
                break
            if (is_region_error is True):
                result = {'Region': region_name, 'Level': level_code}
                check_results.append(result)
        except Exception as e:
            pm_error = common_utils.write_log_exception(e, pm_logger)
            if not pm_error.pm_notification_error:
                pm_error.pm_notification_error = PmNotificationError(
                    check_item_code=check_item_code,
                    region=region_name,
                    code_error=CommonConst.KEY_CODE_ERROR_DEFAULT)
            else:
                pm_error.pm_notification_error.check_item_code = check_item_code
                pm_error.pm_notification_error.aws_account = awsaccount
                pm_error.pm_notification_error.region = region_name
            raise common_utils.write_log_pm_error(pm_error, pm_logger)

    # 検出結果を1つのチェック結果JSONファイルに保存する。
    try:
        current_date = date_utils.get_current_date_by_format(
            date_utils.PATTERN_YYYYMMDDHHMMSS)
        check_cis_item_3 = {
            'AWSAccount': awsaccount,
            'CheckResults': check_results,
            'DateTime': current_date
        }
        FileUtils.upload_s3(trace_id, check_cis_item_3, result_json_path,
                            True)
    except Exception as e:
        pm_logger.error("[%s] チェック結果JSONファイルの保存に失敗しました。", awsaccount)
        pm_error = common_utils.write_log_exception(e, pm_logger)
        pm_error.pm_notification_error = PmNotificationError(
            check_item_code=check_item_code,
            code_error=CommonConst.KEY_CODE_ERROR_DEFAULT)
        raise common_utils.write_log_pm_error(pm_error, pm_logger)

    if len(check_results) > 0:
        return check_result
    return CheckResult.Normal
def check_asc_item_16_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 = []
    is_authorized = True

    # 取得したクレデンシャル情報を使用して、S3クライアントを作成します。
    try:
        s3_client = S3Utils.get_s3_client(trace_id, session, aws_account)
    except PmError as e:
        raise common_utils.write_log_pm_error(e, pm_logger)

    # S3バケット一覧を取得します。
    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

    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)
            if region_name is None:
                region_name = CommonConst.US_EAST_REGION

            # 取得したS3バケット情報ファイルをもとに、該当のS3バケットのアクセスコントロールリストを取得する。
            bucket_acl = get_bucket_acl(
                trace_id, check_history_id, organization_id, project_id,
                aws_account, region_name, bucket_name, s3_client)

            # 取得したS3バケット情報をもとに、S3のロギング情報を取得する。
            bucket_logging = S3Utils.get_bucket_logging(
                trace_id, aws_account, s3_client, bucket_name, region_name)
        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_ClientLogging_" + region_name + "_" + bucket_name +
                ".json")
            FileUtils.upload_json(trace_id, "S3_CHECK_BUCKET", bucket_logging,
                                  s3_file_name)
        except PmError as e:
            pm_logger.error("[%s] S3バケットロギング情報の取得に失敗しました。(%s/%s)", aws_account,
                            region_name, bucket_name)
            return CheckResult.Error

        # チェック処理
        bucket_abnormity = True
        try:

            # Check-1. ACLによりLogDeliveryに操作権限が与えられたS3バケットが存在するか
            for grant in bucket_acl["Grants"]:
                if (common_utils.check_key("URI", grant['Grantee']) and
                        grant['Grantee']["URI"] == LOG_DELIVERY_URI):
                    bucket_abnormity = False
                    break

            # Check-2. S3バケットでログ記録が有効になっていないものは存在するか
            if bucket_abnormity is True and len(bucket_logging) == 0:
                result = {
                    'Region': region_name,
                    'Level': CommonConst.LEVEL_CODE_21,
                    'DetectionItem': {
                        'BucketName': bucket_name
                    }
                }
                check_results.append(result)
        except Exception as e:
            pm_logger.error("[%s] チェック処理中にエラーが発生しました。(%s/%s)", aws_account,
                            region_name, bucket_name)
            return CheckResult.Error

    # Export File CHECK_ASC_ITEM_16_01.json
    try:
        current_date = date_utils.get_current_date_by_format(
            date_utils.PATTERN_YYYYMMDDHHMMSS)
        check_asc_item_16_01 = {
            'AWSAccount': aws_account,
            'CheckResults': check_results,
            'DateTime': current_date
        }
        FileUtils.upload_s3(trace_id, check_asc_item_16_01, result_json_path,
                            True)
    except Exception as e:
        pm_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 update_awscoop(trace_id, project_id, organization_id, coop_id, data_body):
    pm_logger = common_utils.begin_logger(trace_id, __name__,
                                          inspect.currentframe())
    # Parse JSON
    try:
        body_object = json.loads(data_body)
        aws_account = body_object["awsAccount"]
        role_name = body_object["roleName"]
        description = body_object["description"]
        aws_account_name = body_object['awsAccountName']
    except Exception as e:
        return common_utils.error_exception(MsgConst.ERR_REQUEST_202,
                                            HTTPStatus.BAD_REQUEST, e,
                                            pm_logger, True)

    # Validate
    list_error = validate_update_awscoop(aws_account, role_name)
    if list_error:
        return common_utils.error_validate(MsgConst.ERR_REQUEST_201,
                                           HTTPStatus.UNPROCESSABLE_ENTITY,
                                           list_error, pm_logger)

    # Get data AWSアカウント連携
    try:
        awscoops_item = pm_awsAccountCoops.get_awscoops_update(
            trace_id, coop_id, project_id, organization_id)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # 組織情報を取得します。
    if awscoops_item is None:
        return common_utils.error_common(MsgConst.ERR_301,
                                         HTTPStatus.NOT_FOUND, pm_logger)

    # ロールのアクセス確認
    if common_utils.is_null(description):
        description = None
    if common_utils.is_null(aws_account_name):
        aws_account_name = None
    external_id = awscoops_item['ExternalID']
    effective = Effective.Disable.value
    members = None
    if (checkaccess.check_access_to_aws(trace_id, aws_account, role_name,
                                        external_id)):
        effective = Effective.Enable.value

        # IAMクライアントを用いて、IAMロールcm-membersportalを取得します。
        try:
            session = aws_common.create_session_client(trace_id, aws_account,
                                                       role_name, external_id)
            members = IAMUtils.get_membership_aws_account(
                trace_id, session, aws_account)
        except PmError as e:
            common_utils.write_log_pm_error(e, pm_logger, exc_info=True)

    # update project
    attribute = {
        'AWSAccount': {
            "Value": aws_account
        },
        'RoleName': {
            "Value": role_name
        },
        'Description': {
            "Value": description
        },
        'Effective': {
            "Value": effective
        },
        'AWSAccountName': {
            "Value": aws_account_name
        }
    }
    if (members is not None):
        attribute['Members'] = {"Value": members}
    updated_at = awscoops_item['UpdatedAt']

    try:
        pm_awsAccountCoops.update_awscoops(trace_id, coop_id, attribute,
                                           updated_at)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_DB_403,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # Get data response
    try:
        awscoops_item = pm_awsAccountCoops.query_awscoop_coop_key(
            trace_id, coop_id, convert_response=True)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # return data response
    response = common_utils.get_response_by_response_body(
        HTTPStatus.OK, awscoops_item)
    return common_utils.response(response, pm_logger)
def execute_delete_invalid_user(trace_id):
    pm_logger = common_utils.begin_logger(trace_id, __name__,
                                          inspect.currentframe())

    # Get Cognito UserPools status UNCONFIRMED
    try:
        list_user_unconfirmed = aws_common.get_cognito_user_pools(
            trace_id,
            CommonConst.COGNITO_STATUS_UNCONFIRMED,
            attribute_filter=CommonConst.ATTRIBUTE_FILTER_USER_STATUS)
    except PmError as e:
        pm_logger.error("[%s]Cognitoユーザー一覧情報取得に失敗しました。",
                        CommonConst.COGNITO_STATUS_UNCONFIRMED)
        raise common_utils.write_log_pm_error(e, pm_logger)

    # get current date
    current_date_time = date_utils.toDate(
        date_utils.get_current_date_by_format(
            date_utils.PATTERN_YYYYMMDDHHMMSS), date_utils.UTC)

    # loop user cognito UserPools status UNCONFIRMED
    for user_unconfirmed in list_user_unconfirmed:
        user_create_date = date_utils.toDate(
            date_utils.toString(user_unconfirmed['UserCreateDate'],
                                date_utils.PATTERN_YYYYMMDDHHMM),
            date_utils.UTC)
        if date_utils.difference_days(
                user_create_date,
                current_date_time) > CommonConst.TERM_USER_UNCONFIRMED_DAY:
            # delete Cognito UserPools status UNCONFIRMED update period greater than 1 days
            try:
                aws_common.delete_cognito_user_by_user_name(
                    trace_id, user_unconfirmed['Username'])
            except PmError as e:
                pm_logger.warning("CognitoでUserName = %sのユーザー削除に失敗しました。",
                                  user_unconfirmed['Username'])
                raise common_utils.write_log_pm_error(e, pm_logger)

    # Get Cognito UserPools status FORCE_CHANGE_PASSWORD
    try:
        list_user_force_change_password = aws_common.get_cognito_user_pools(
            trace_id,
            CommonConst.COGNITO_STATUS_FORCE_CHANGE_PASSWORD,
            attribute_filter=CommonConst.ATTRIBUTE_FILTER_USER_STATUS)
    except PmError as e:
        pm_logger.error("[%s]Cognitoユーザー一覧情報取得に失敗しました。",
                        CommonConst.COGNITO_STATUS_FORCE_CHANGE_PASSWORD)
        raise common_utils.write_log_pm_error(e, pm_logger)

    current_date = date_utils.toDate(
        date_utils.toString(current_date_time,
                            date_utils.PATTERN_YYYYMMDD_SLASH), date_utils.UTC)
    # loop user cognito UserPools status FORCE_CHANGE_PASSWORD
    for user_force_change_password in list_user_force_change_password:
        user_create_date = date_utils.toDate(
            date_utils.toString(user_force_change_password['UserCreateDate'],
                                date_utils.PATTERN_YYYYMMDD_SLASH),
            date_utils.UTC)
        if date_utils.difference_days(
                user_create_date, current_date
        ) > CommonConst.TERM_USER_FORCE_CHANGE_PASSWORD_DAY:
            # get list affiliations
            try:
                affiliations = pm_affiliation.query_userid_key(
                    trace_id, user_force_change_password['Username'])
            except PmError as e:
                pm_logger.warning(
                    "PM_Affiliationテーブルにて、UserID = %sのレコード取得に失敗しました。",
                    user_force_change_password['Username'])
                raise common_utils.write_log_pm_error(e, pm_logger)

            # delete affiliations user status FORCE_CHANGE_PASSWORD update period greater than 6 days
            for affiliation in affiliations:
                try:
                    pm_affiliation.delete_affiliation(
                        affiliation['UserID'], affiliation['OrganizationID'])
                except PmError as e:
                    pm_logger.warning(
                        "PM_Affiliationテーブルのレコード削除に失敗しました。UserID : %s / OrganizationID : %s",
                        affiliation['UserID'], affiliation['OrganizationID'])
                    raise common_utils.write_log_pm_error(e, pm_logger)

            # delete Cognito UserPools status FORCE_CHANGE_PASSWORD update period greater than 6 days
            try:
                aws_common.delete_cognito_user_by_user_name(
                    trace_id, user_force_change_password['Username'])
            except PmError as e:
                pm_logger.warning("CognitoでUserName = %sのユーザー削除に失敗しました。",
                                  user_force_change_password['Username'])
                raise common_utils.write_log_pm_error(e, pm_logger)