Exemplo n.º 1
0
def get_response_body(check_result_item, data):
    response_body = {
        "id": check_result_item["CheckResultItemID"],
        "checkHistoryId": check_result_item["CheckHistoryID"],
        "checkResultId": check_result_item["CheckResultID"],
        "checkItemCode": check_result_item["CheckItemCode"],
        "organizationName": check_result_item["OrganizationName"],
        "projectName": check_result_item["ProjectName"],
        "awsAccount": check_result_item["AWSAccount"],
        "awsAccountName": common_utils.get_value("AWSAccountName", check_result_item, None),
        "exclusionFlag": int(common_utils.get_value("ExclusionFlag", check_result_item, ExclusionFlag.Disable)),
        "checkResult": int(check_result_item["CheckResult"]),
        "resources": data["CheckResults"],
        "executedDateTime": check_result_item["ExecutedDateTime"],
        "createdAt": check_result_item["CreatedAt"],
        "updatedAt": check_result_item["UpdatedAt"],
    }
    return response_body
Exemplo n.º 2
0
def get_check_result(security_group, ip_permission, ip_range, region_name):
    result = {
        'Region': region_name,
        'Level': CommonConst.LEVEL_CODE_21,
        'DetectionItem': {
            'GroupId': security_group['GroupId'],
            'FromPort': common_utils.get_value('FromPort', ip_permission),
            'IpProtocol': common_utils.get_value('IpProtocol', ip_permission),
            'IpRanges': [{
                'CidrIp': ip_range['CidrIp']
            }],
            'Ipv6Ranges': ip_permission['Ipv6Ranges'],
            'PrefixListIds': ip_permission['PrefixListIds'],
            'ToPort': common_utils.get_value('ToPort', ip_permission),
            'UserIdGroupPairs': ip_permission['UserIdGroupPairs']
        }
    }
    return result
Exemplo n.º 3
0
def update_user_attributes(user_id, data_body):
    pm_logger = common_utils.begin_logger(user_id, __name__,
                                          inspect.currentframe())
    try:
        body_object = json.loads(data_body)
    except Exception as e:
        return common_utils.error_exception(MsgConst.ERR_REQUEST_202,
                                            HTTPStatus.BAD_REQUEST, e,
                                            pm_logger, True)
    try:
        user = pm_userAttribute.query_key(user_id)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    user_name = get_data_json_by_key("userName", body_object)
    company_name = get_data_json_by_key("companyName", body_object)
    department_name = get_data_json_by_key("departmentName", body_object)
    company_flg = common_utils.get_value("companyFlg", body_object, None)
    country_code = get_data_json_by_key("countryCode", body_object)
    caller_service_name = common_utils.get_value("callerServiceName",
                                                 body_object, None)

    # validate param info user attribute
    list_error = validate_info_user_attribute(caller_service_name)
    if list_error:
        return common_utils.error_validate(MsgConst.ERR_REQUEST_201,
                                           HTTPStatus.UNPROCESSABLE_ENTITY,
                                           list_error, pm_logger)

    if user is None:
        # Create User
        try:
            pm_userAttribute.create(user_id, user_name, company_name,
                                    department_name, MailStatus.Normal,
                                    company_flg, country_code,
                                    caller_service_name)
        except PmError as e:
            return common_utils.error_exception(
                MsgConst.ERR_DB_403, HTTPStatus.INTERNAL_SERVER_ERROR, e,
                pm_logger, True)
    else:
        # Update User
        attribute = {
            'UserName': {
                "Value": user_name
            },
            'CompanyName': {
                "Value": company_name
            },
            'DepartmentName': {
                "Value": department_name
            }
        }
        if company_flg is not None:
            attribute['CompanyFlg'] = {"Value": company_flg}
        if country_code is not None:
            attribute['CountryCode'] = {"Value": country_code}
        try:
            pm_userAttribute.update(user_id, attribute)
        except PmError as e:
            return common_utils.error_exception(
                MsgConst.ERR_DB_404, HTTPStatus.INTERNAL_SERVER_ERROR, e,
                pm_logger, True)
    # Get data response
    try:
        user = pm_userAttribute.query_key(user_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.OK, user)
    return common_utils.response(response, pm_logger)
Exemplo n.º 4
0
def apply_change_email(user_id, mail_before_change, data_body):
    pm_logger = common_utils.begin_logger(user_id, __name__,
                                          inspect.currentframe())
    # Parse JSON
    try:
        body_object = json.loads(data_body)
    except Exception as e:
        return common_utils.error_exception(MsgConst.ERR_REQUEST_202,
                                            HTTPStatus.BAD_REQUEST, e,
                                            pm_logger, True)

    mail_after_change = common_utils.get_value("mailAddress", body_object,
                                               None)
    caller_service_name = common_utils.get_value("callerServiceName",
                                                 body_object, None)

    mail_lang = common_utils.get_value("mailLang", body_object, None)

    # validate
    list_errors = validate_param_apply_change_email(user_id, mail_lang,
                                                    caller_service_name,
                                                    mail_before_change)
    if list_errors:
        return common_utils.error_validate(MsgConst.ERR_REQUEST_201,
                                           HTTPStatus.UNPROCESSABLE_ENTITY,
                                           list_errors, pm_logger)

    # Cognito UserPoolsから変更するメールアドレス{mailaddress}に該当するユーザー情報情報を取得します。
    try:
        list_users = aws_common.get_cognito_user_pools(user_id,
                                                       mail_after_change,
                                                       "email")
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_COGNITO_501,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)
    if list_users:
        return common_utils.error_common(MsgConst.ERR_302, HTTPStatus.CONFLICT,
                                         pm_logger)

    # メールアドレス変更申請テーブルから申請レコードを取得します。
    try:
        list_email_change_apply = pm_emailChangeApply.query_user_index(user_id)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)
    if list_email_change_apply:
        return common_utils.error_common(MsgConst.ERR_302, HTTPStatus.CONFLICT,
                                         pm_logger)

    # メールアドレス変更申請テーブルに申請レコードを作成します。
    apply_id = common_utils.get_uuid4()
    time_to_live = common_utils.get_time_to_live(
        CommonConst.EMAIL_CHANGE_APPLY_EXPIRATION_DATE)
    try:
        pm_emailChangeApply.create(user_id, apply_id, mail_before_change,
                                   mail_after_change, time_to_live,
                                   caller_service_name)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_DB_403,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # get record PM_EmailChangeApply
    try:
        result = pm_emailChangeApply.query_key(user_id,
                                               apply_id,
                                               convert_response=True)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # S3から通知メール送信設定ファイルを取得します。
    try:
        config = FileUtils.read_yaml(user_id, CommonConst.S3_SETTING_BUCKET,
                                     CommonConst.NOTIFY_CONFIG_CIS_RESULT_MAIL)
    except PmError as e:
        pm_logger.error(
            "メールアドレス変更通知メール送信設定ファイルの取得に失敗しました。:s3://%s/%s",
            common_utils.get_environ(CommonConst.S3_SETTING_BUCKET),
            CommonConst.NOTIFY_CONFIG_CIS_RESULT_MAIL)
        return common_utils.error_exception(MsgConst.ERR_S3_702,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    path_file_template = config[
        CommonConst.KEY_GET_PATH_FILE_TEMPLATE_MAIL_SERVICE.format(
            language=mail_lang, serviceName=caller_service_name)]
    # 通知メール本文を作成
    try:
        template_body_mail = FileUtils.read_decode(
            user_id, CommonConst.S3_SETTING_BUCKET, path_file_template)
    except PmError as e:
        pm_logger.error(
            "メールアドレス変更通知メール本文テンプレートファイルの取得に失敗しました。:s3://%s/%s",
            common_utils.get_environ(CommonConst.S3_SETTING_BUCKET),
            path_file_template)
        return common_utils.error_exception(MsgConst.ERR_S3_702,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # SESで通知メールを送信します。
    bcc_addresses = [mail_after_change]
    template_body_mail = Template(template_body_mail)
    body_mail = template_body_mail.render(ApplyID=apply_id)
    mail_subject = config[CommonConst.KEY_MAIL_SUBJECT_SERVICE.format(
        language=mail_lang, serviceName=caller_service_name)]
    mail_form = config[CommonConst.KEY_MAIL_FROM_SERVICE.format(
        serviceName=caller_service_name)]

    try:
        aws_common.send_email(user_id, config['ses.region'], mail_form,
                              bcc_addresses, mail_subject, body_mail)
    except PmError as e:
        pm_logger.error("通知メール送信に失敗しました。")
        return common_utils.error_exception(MsgConst.ERR_SES_801,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # return data response
    response = common_utils.get_response_by_response_body(
        HTTPStatus.CREATED, result)
    return common_utils.response(response, pm_logger)
Exemplo n.º 5
0
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
Exemplo n.º 6
0
def execute_check_results_assessment(trace_id, check_item_code,
                                     check_history_id, organization_id,
                                     project_id, aws_account, result_json_path,
                                     level):
    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,
                                                     "Assessment_Result.json")

    try:
        # リソース情報取得
        if (aws_common.check_exists_file_s3(trace_id, "S3_CHECK_BUCKET",
                                            s3_file_name)) is True:
            try:
                assessment_items = 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:
                assessment_items = pm_assessmentItems.query_organization_index_filter_awsaccount(
                    trace_id, organization_id, project_id, aws_account)
            except PmError as e:
                raise common_utils.write_log_pm_error(e, pm_logger)

            # 取得したクエリ結果をS3に保存します。(リソース情報ファイル)
            try:
                FileUtils.upload_json(trace_id, "S3_CHECK_BUCKET",
                                      assessment_items, s3_file_name)
            except PmError as e:
                pm_logger.error("[%s] リソース情報ファイのS3保存に失敗しました。", aws_account)

        # チェック処理
        try:
            check_results = []
            assessment_result = None
            for assessment_item in assessment_items:
                if (assessment_item['CheckItemCode'] == check_item_code):
                    assessment_result = {
                        'AssessmentComment':
                        common_utils.get_value('AssessmentComment',
                                               assessment_item),
                        'UserID':
                        common_utils.get_value('UserID', assessment_item),
                        'MailAddress':
                        common_utils.get_value('MailAddress', assessment_item),
                        'CreatedAt':
                        assessment_item['CreatedAt']
                    }
                    break

            if (assessment_result is None):
                LEVEL_DIVISION = {
                    "1": CommonConst.LEVEL_CODE_21,  # 重大な不備
                    "2": CommonConst.LEVEL_CODE_11  # 軽微な不備
                }
                result = {
                    'Region': 'Global',
                    'Level': LEVEL_DIVISION[level],
                    'DetectionItem': {
                        'NoEvaluation': True
                    }
                }
                check_results.append(result)
        except Exception as e:
            pm_logger.error("[%s] チェック処理中にエラーが発生しました。", aws_account)
            raise common_utils.write_log_exception(e, pm_logger)

        # チェック結果JSONファイル
        try:
            current_date = date_utils.get_current_date_by_format(
                date_utils.PATTERN_YYYYMMDDHHMMSS)
            check_result_json = {
                'AWSAccount': aws_account,
                'CheckResults': check_results,
                'DateTime': current_date
            }
            if assessment_result is not None:
                check_result_json['AssessmentResult'] = assessment_result
            FileUtils.upload_json(trace_id, "S3_CHECK_BUCKET",
                                  check_result_json, result_json_path)
        except Exception as e:
            pm_logger.error("[%s] チェック結果JSONファイルの保存に失敗しました。", aws_account)
            raise common_utils.write_log_exception(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,
            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.Normal
    elif (level == CommonConst.LEVEL_CODE_1):
        return CheckResult.CriticalDefect
    return CheckResult.MinorInadequacies
def execute_force_invites(trace_id, body_object, organization_id):
    pm_logger = common_utils.begin_logger(trace_id, __name__,
                                          inspect.currentframe())

    # parse json
    try:
        body_object_json = json.loads(body_object)
    except Exception as e:
        return common_utils.error_exception(MsgConst.ERR_REQUEST_202,
                                            HTTPStatus.BAD_REQUEST, e,
                                            pm_logger, True)

    caller_service_name = common_utils.get_value("callerServiceName",
                                                 body_object_json, None)
    mail_lang = common_utils.get_value("mailLang", body_object_json, None)
    mail_address = common_utils.get_value("mailAddress", body_object_json,
                                          None)
    authority = common_utils.get_value("authority", body_object_json, None)

    # validate param execute invite unregistered
    list_error = validate_param_invite_unregistered_user(
        trace_id, mail_lang, caller_service_name, mail_address, authority)
    if list_error:
        return common_utils.error_validate(MsgConst.ERR_REQUEST_201,
                                           HTTPStatus.UNPROCESSABLE_ENTITY,
                                           list_error, pm_logger)

    # get list cognito users
    try:
        list_users = aws_common.get_cognito_user_pools(trace_id, mail_address)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_COGNITO_501,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)
    if list_users:
        return common_utils.error_common(MsgConst.ERR_302, HTTPStatus.CONFLICT,
                                         pm_logger)

    # regist Cognito UserPools
    temporary_password = ''
    pattern = re.compile(CommonConst.FORMAT_PASSWORD_TEMPORARY)
    while pattern.match(temporary_password) is None:
        temporary_password = common_utils.get_password_temporary(
            CommonConst.NUMBER_CHARACTERS_PASSWORD_TEMPORARY)

    user_attributes = [{"Name": "email", "Value": mail_address}]
    user_name = common_utils.get_uuid4()
    message_action = MessageAction.Suppress
    try:
        aws_common.process_admin_create_user_pools(trace_id, user_name,
                                                   user_attributes,
                                                   temporary_password,
                                                   message_action)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_COGNITO_501,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # enable confirm email
    try:
        user_attributes = [{'Name': 'email_verified', 'Value': 'true'}]
        aws_common.update_cognito_user_attributes(trace_id, user_name,
                                                  user_attributes)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_COGNITO_501,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # get affiliation
    try:
        affiliation = pm_affiliation.get_affiliation(user_name,
                                                     organization_id)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)
    if affiliation and affiliation["InvitationStatus"] != InvitationStatus.Deny:
        return common_utils.error_common(MsgConst.ERR_302, HTTPStatus.CONFLICT,
                                         pm_logger)

    # get organization
    try:
        organization = pm_organizations.get_organization(
            trace_id, organization_id)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)
    if len(organization) == 0:
        return common_utils.error_common(MsgConst.ERR_301,
                                         HTTPStatus.NOT_FOUND, pm_logger)

    # create affiliation
    try:
        pm_affiliation.create_affiliation(trace_id, mail_address, user_name,
                                          organization_id, authority,
                                          InvitationStatus.Invited)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_DB_403,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # Get data affiliation
    try:
        affiliation_result = pm_affiliation.get_affiliation(
            user_name, organization_id, True)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # Get data user_attribute
    try:
        user_attribute = pm_userAttribute.query_key(trace_id)
    except PmError as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # S3から通知メール送信設定ファイルを取得します。
    try:
        config = FileUtils.read_yaml(trace_id, CommonConst.S3_SETTING_BUCKET,
                                     CommonConst.NOTIFY_CONFIG_CIS_RESULT_MAIL)
    except PmError as e:
        pm_logger.error("メール送信設定ファイルの取得に失敗しました。:s3://{0}/{1}".format(
            common_utils.get_environ(CommonConst.S3_SETTING_BUCKET),
            CommonConst.NOTIFY_CONFIG_CIS_RESULT_MAIL))
        return common_utils.error_exception(MsgConst.ERR_S3_702,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # メッセージ本文を作成します。
    path_file_template = config[
        CommonConst.KEY_GET_PATH_FILE_TEMPLATE_USER_INVITE_MAIL.format(
            language=mail_lang, serviceName=caller_service_name)]
    try:
        template_body_mail = FileUtils.read_decode(
            trace_id, CommonConst.S3_SETTING_BUCKET, path_file_template)
    except PmError as e:
        pm_logger.error("招待メール本文テンプレートファイルの取得に失敗しました。:s3://{0}/{1}".format(
            common_utils.get_environ(CommonConst.S3_SETTING_BUCKET),
            path_file_template))
        return common_utils.error_exception(MsgConst.ERR_S3_702,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # SESで通知メールを送信します。
    bcc_addresses = [mail_address]
    user_name_sign_in = common_utils.get_value("UserName", user_attribute,
                                               None)
    if not user_name_sign_in:
        try:
            affiliation_sign_in = pm_affiliation.get_affiliation(
                trace_id, organization_id)
        except PmError as e:
            return common_utils.error_exception(
                MsgConst.ERR_402, HTTPStatus.INTERNAL_SERVER_ERROR, e,
                pm_logger, True)
        user_name_sign_in = common_utils.get_value("MailAddress",
                                                   affiliation_sign_in, None)

    organization_name = common_utils.get_value("OrganizationName",
                                               organization, None)
    time_zone = date_utils.get_time_zone_by_language(mail_lang)
    time_to_live_date = date_utils.get_current_date() + timedelta(days=6)
    time_to_live = date_utils.toString(time_to_live_date,
                                       date_utils.PATTERN_YYYYMMDD_SLASH,
                                       time_zone)
    template_body_mail = Template(template_body_mail)
    context = {
        'mailAddress': mail_address,
        'userName': user_name_sign_in,
        'organizationName': organization_name,
        'temporaryPassword': temporary_password,
        'timeToLive': time_to_live
    }
    body_mail = template_body_mail.render(context)
    mail_subject = config[CommonConst.KEY_MAIL_SUBJECT_USER_INVITE.format(
        language=mail_lang, serviceName=caller_service_name)]
    mail_from = config[CommonConst.KEY_INVITE_MAIL_FROM_SERVICE.format(
        serviceName=caller_service_name)]
    ses_region = config['ses.region']
    try:
        aws_common.send_email(user_name, ses_region, mail_from, bcc_addresses,
                              mail_subject, body_mail)
    except PmError as e:
        pm_logger.error("通知メール送信に失敗しました。")
        return common_utils.error_exception(MsgConst.ERR_SES_801,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    response = common_utils.get_response_by_response_body(
        HTTPStatus.CREATED, affiliation_result)

    # return data response
    return common_utils.response(response, pm_logger)
def create_excluded_resources(trace_id, user_id, organization_id, project_id,
                              coop_id, check_item_code, email, data_body):
    pm_logger = common_utils.begin_logger(trace_id, __name__,
                                          inspect.currentframe())
    # AWSアカウントAWSAccountは、AWSアカウント連携テーブルに、AWSアカウント連携ID{coop_id}をキーとしてクエリを実行します。
    try:
        awscoops_item = pm_awsAccountCoops.query_awscoop_coop_key(
            trace_id, coop_id)
    except Exception as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # 有効なAWSアカウントが存在しなかった場合(取得件数が0件)
    if (not awscoops_item):
        return common_utils.error_common(MsgConst.ERR_AWS_401,
                                         HTTPStatus.UNPROCESSABLE_ENTITY,
                                         pm_logger)

    # チェック項目コード
    if check_item_code not in LIST_CHECK_ITEM_CODE_EXCLUDED_RESOURCE:
        return common_utils.error_common(MsgConst.ERR_AWS_401,
                                         HTTPStatus.UNPROCESSABLE_ENTITY,
                                         pm_logger)

    # リクエストボディのJSONでパースエラーが発生した場合は、エラーログを出力してエラーレスポンスを返します。
    try:
        body_object = json.loads(data_body)
    except Exception as e:
        return common_utils.error_exception(MsgConst.ERR_REQUEST_202,
                                            HTTPStatus.BAD_REQUEST, e,
                                            pm_logger, True)

    region_name = common_utils.get_value("regionName", body_object, None)
    resource_type = common_utils.get_value("resourceType", body_object, None)
    resource_name = common_utils.get_value("resourceName", body_object, None)
    exclusion_comment = common_utils.get_value("exclusionComment", body_object,
                                               None).strip()

    # 全てのチェックを行い、エラーがあった場合はエラーログを出力してエラーレスポンスを返します。
    list_error = validate_create_excluded_resources(region_name, resource_type,
                                                    resource_name,
                                                    exclusion_comment)
    if list_error:
        return common_utils.error_validate(MsgConst.ERR_REQUEST_201,
                                           HTTPStatus.UNPROCESSABLE_ENTITY,
                                           list_error, pm_logger)

    aws_account = awscoops_item['AWSAccount']
    check_item_refine_code = CommonConst.CHECK_ITEM_REFINE_CODE.format(
        organization_id, project_id, aws_account, check_item_code)
    try:
        excluded_resource = pm_exclusionResources.query_filter_region_name_and_resource_name(
            trace_id, check_item_refine_code, region_name, resource_type,
            resource_name)
    except Exception as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    if not excluded_resource:
        exclusion_resource_id = common_utils.get_uuid4()
        account_refine_code = CommonConst.ACCOUNT_REFINE_CODE.format(
            organization_id, project_id, aws_account)
        time_to_live_date = date_utils.get_current_date() + timedelta(days=180)
        time_to_live = Decimal(time_to_live_date.timestamp())
        # リソース除外設定テーブルに除外設定レコードを作成します。
        try:
            pm_exclusionResources.create(
                user_id, exclusion_resource_id, organization_id, project_id,
                aws_account, check_item_code, region_name, resource_type,
                resource_name, exclusion_comment, email, account_refine_code,
                check_item_refine_code, time_to_live)
        except Exception as e:
            return common_utils.error_exception(
                MsgConst.ERR_DB_403, HTTPStatus.INTERNAL_SERVER_ERROR, e,
                pm_logger, True)
    else:
        exclusion_resource_id = excluded_resource[0]["ExclusionResourceID"]
        attribute = {'ExclusionComment': {"Value": exclusion_comment}}
        try:
            pm_exclusionResources.update(trace_id, exclusion_resource_id,
                                         attribute)
        except Exception as e:
            return common_utils.error_exception(
                MsgConst.ERR_DB_404, HTTPStatus.INTERNAL_SERVER_ERROR, e,
                pm_logger, True)

    try:
        excluded_resource_new = pm_exclusionResources.query_key(
            trace_id, exclusion_resource_id, True)
    except Exception as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # return response data
    response = common_utils.get_response_by_response_body(
        HTTPStatus.CREATED, excluded_resource_new)
    return common_utils.response(response, pm_logger)
def execute_copy_item_setting(trace_id, organization_id_destination,
                              project_id_destination, coop_id_destination,
                              body_object, email, user_id):
    pm_logger = common_utils.begin_logger(trace_id, __name__,
                                          inspect.currentframe())

    # Parse JSON
    try:
        body_object_json = json.loads(body_object)
        organization_id_source = body_object_json['copy_source'][
            'organization_id']
        project_id_source = body_object_json['copy_source']['project_id']
        coop_id_source = body_object_json['copy_source']['coop_id']
    except Exception as e:
        return common_utils.error_exception(MsgConst.ERR_REQUEST_202,
                                            HTTPStatus.BAD_REQUEST, e,
                                            pm_logger, True)

    # アクセス権限チェックを行います。コピー元の組織ID
    response_authority_source = checkauthority.authority(
        trace_id, user_id, organization_id_source, Authority.Editor)
    if response_authority_source:
        return common_utils.response(response_authority_source, pm_logger)

    # アクセス権限チェックを行います。コピー先の組織ID
    response_authority_destination = checkauthority.authority(
        trace_id, user_id, organization_id_destination, Authority.Editor)
    if response_authority_destination:
        return common_utils.response(response_authority_destination, pm_logger)

    # リソース関連性のバリデーションチェックを行います。
    # コピー元のAWSアカウント連携ID{coop_id}をキーとして、AWSアカウント連携テーブルへクエリを実行する。
    try:
        awscoops_item_source = pm_awsAccountCoops.query_awscoop_coop_key(
            trace_id, coop_id_source)
    except Exception as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # 有効なAWSアカウントが存在しなかった場合(取得件数が0件)
    if not awscoops_item_source:
        return common_utils.error_common(MsgConst.ERR_AWS_401,
                                         HTTPStatus.UNPROCESSABLE_ENTITY,
                                         pm_logger)

    # コピー先のAWSアカウント連携ID{coopId}をキーとして、AWSアカウント連携テーブルへクエリを実行する。
    try:
        awscoops_item_destination = pm_awsAccountCoops.query_awscoop_coop_key(
            trace_id, coop_id_destination)
    except Exception as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # 有効なAWSアカウントが存在しなかった場合(取得件数が0件)
    if not awscoops_item_destination:
        return common_utils.error_common(MsgConst.ERR_AWS_401,
                                         HTTPStatus.UNPROCESSABLE_ENTITY,
                                         pm_logger)

    # コピー元のチェック項目除外情報を取得します。
    account_refine_code_source = CommonConst.ACCOUNT_REFINE_CODE.format(
        organization_id_source, project_id_source,
        awscoops_item_source['AWSAccount'])
    try:
        exclusion_items_source = pm_exclusionitems.query_filter_account_refine_code(
            trace_id, account_refine_code_source)
    except Exception as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # コピー元のマニュアル評価情報を取得します。
    try:
        assessment_items_source = pm_assessmentItems.query_filter_account_refine_code(
            trace_id, account_refine_code_source)
    except Exception as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # PM_AssessmentItemsとPM_ExclusionItems両方のレコードが取得できなかった場合、エラーログを出力してエラーレスポンスを返します。
    if len(exclusion_items_source) == 0 and len(assessment_items_source) == 0:
        return common_utils.error_common(MsgConst.ERR_301,
                                         HTTPStatus.NOT_FOUND, pm_logger)

    aws_account_destination = awscoops_item_destination['AWSAccount']
    account_refine_code_destination = CommonConst.ACCOUNT_REFINE_CODE.format(
        organization_id_destination, project_id_destination,
        aws_account_destination)
    time_to_live_exclusion_destination = common_utils.get_time_to_live(
        CommonConst.EXCLUSION_EXPIRATION_DATE)

    # 作成処理は、先に取得した「コピー元のチェック項目除外情報」のレコード数分、繰り返します。
    try:
        for exclusion_item in exclusion_items_source:
            exclusion_item_id_destination = CommonConst.EXCLUSIONITEM_ID.format(
                organization_id_destination, project_id_destination,
                aws_account_destination, exclusion_item['CheckItemCode'])
            pm_exclusionitems.create(
                trace_id, exclusion_item_id_destination,
                organization_id_destination, project_id_destination,
                aws_account_destination, exclusion_item['CheckItemCode'],
                time_to_live_exclusion_destination,
                common_utils.get_value("ExclusionComment", exclusion_item),
                user_id, email, account_refine_code_destination)
    except Exception:
        return common_utils.error_common(MsgConst.ERR_DB_403,
                                         HTTPStatus.INTERNAL_SERVER_ERROR,
                                         pm_logger)

    time_to_live_assessment_destination = common_utils.get_time_to_live(
        CommonConst.ASSESSMENT_EXPIRATION_DATE)

    # 作成処理は、先に取得した「コピー元のマニュアル評価情報」のレコード数分、繰り返します。
    try:
        for assessment_item in assessment_items_source:
            assessment_item_id_destination = CommonConst.ASSESSMENTITEM_ID.format(
                organization_id_destination, project_id_destination,
                aws_account_destination, assessment_item['CheckItemCode'])
            pm_assessmentItems.create(
                trace_id, assessment_item_id_destination,
                organization_id_destination, project_id_destination,
                aws_account_destination, assessment_item['CheckItemCode'],
                time_to_live_assessment_destination,
                common_utils.get_value("AssessmentComment", assessment_item),
                user_id, email, account_refine_code_destination)
    except Exception:
        return common_utils.error_common(MsgConst.ERR_DB_403,
                                         HTTPStatus.INTERNAL_SERVER_ERROR,
                                         pm_logger)

    # return response data
    response = common_utils.get_response_by_response_body(
        HTTPStatus.NO_CONTENT, None)
    return common_utils.response(response, pm_logger)
def list_item_settings(trace_id, organization_id, project_id, coop_id,
                       group_filter):
    pm_logger = common_utils.begin_logger(trace_id, __name__,
                                          inspect.currentframe())

    # リソース関連性のバリデーションチェックを行います。
    # プロジェクトテーブルに、プロジェクトID{project_id}をキーとしてクエリを実行します。
    try:
        project = pm_projects.get_projects_by_organization_id(
            trace_id, project_id, organization_id)
    except Exception as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # プロジェクトに該当レコードが存在しなかった場合(取得件数が0件)
    if (not project):
        return common_utils.error_common(MsgConst.ERR_AWS_401,
                                         HTTPStatus.UNPROCESSABLE_ENTITY,
                                         pm_logger)

    # AWSアカウントAWSAccountは、AWSアカウント連携テーブルに、AWSアカウント連携ID{coop_id}をキーとしてクエリを実行します。
    try:
        awscoops_item = pm_awsAccountCoops.query_awscoop_coop_key(
            trace_id, coop_id)
    except Exception as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # 有効なAWSアカウントが存在しなかった場合(取得件数が0件)
    if (not awscoops_item):
        return common_utils.error_common(MsgConst.ERR_AWS_401,
                                         HTTPStatus.UNPROCESSABLE_ENTITY,
                                         pm_logger)

    # チェック項目除外情報を取得します。
    account_refine_code = CommonConst.ACCOUNT_REFINE_CODE.format(
        organization_id, project_id, awscoops_item['AWSAccount'])
    try:
        exclusion_items = pm_exclusionitems.query_filter_account_refine_code(
            trace_id, account_refine_code, group_filter)
    except Exception as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # マニュアル評価情報を取得します。
    try:
        assessment_items = pm_assessmentItems.query_filter_account_refine_code(
            trace_id, account_refine_code, group_filter)
    except Exception as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # リソース除外情報を取得します。
    try:
        exclusion_resources = pm_exclusionResources.query_filter_account_refine_code(
            trace_id, account_refine_code, group_filter)
    except Exception as e:
        return common_utils.error_exception(MsgConst.ERR_402,
                                            HTTPStatus.INTERNAL_SERVER_ERROR,
                                            e, pm_logger, True)

    # メンバーズ加入アカウントの確認をします
    members = common_utils.get_value('Members', awscoops_item, Members.Disable)
    if (isinstance(members, Decimal)):
        members = int(members)

    # セキュリティチェック項目設定一覧の配列を作成します。
    security_item_settings = []
    list_check_item_code_exclusion = jmespath.search('[*].CheckItemCode',
                                                     exclusion_items)
    list_check_item_code_assessment = jmespath.search('[*].CheckItemCode',
                                                      assessment_items)
    list_check_item_code_exclusion_resource = jmespath.search(
        '[*].CheckItemCode', exclusion_resources)
    for check_item_code in LIST_CHECK_ITEM_CODE:
        # リクエストパラメータgroupFilterにてフィルタ文字列が指定されていた場合、その文字列に該当するチェック項目コードを持つチェックだけ配列へ含めます。
        if (common_utils.is_null(group_filter) is False
                and group_filter not in check_item_code):
            continue

        # マネージド項目有無managedFlag
        managed_flag = ManagedFlag.NotManaged
        if (check_item_code in LIST_CHECK_ITEM_CODE_MANAGED):
            if members == Members.Enable:
                managed_flag = ManagedFlag.Managed

        # チェック項目除外有無exclusionFlag
        exclusion_flag = ExclusionFlag.Disable
        if (check_item_code in list_check_item_code_exclusion):
            exclusion_flag = ExclusionFlag.Enable

        # マニュアル評価設定有無assessmentFlag
        assessment_flag = AssessmentFlag.NotManual
        if (check_item_code in LIST_CHECK_ITEM_CODE_ASSESSMENT):
            assessment_flag = AssessmentFlag.NotAssessment

            if (check_item_code in list_check_item_code_assessment):
                assessment_flag = AssessmentFlag.Assessment

        # リソース除外設定有無excludedResourceFlag
        excluded_resource_flag = ExcludedResourceFlag.Other
        if (check_item_code in LIST_CHECK_ITEM_CODE_EXCLUDED_RESOURCE):
            excluded_resource_flag = ExcludedResourceFlag.Disable

            if (check_item_code in list_check_item_code_exclusion_resource):
                excluded_resource_flag = ExcludedResourceFlag.Enable

        security_item_setting = {
            "checkItemCode": check_item_code,
            "managedFlag": managed_flag,
            "exclusionFlag": exclusion_flag,
            "assessmentFlag": assessment_flag,
            "excludedResourceFlag": excluded_resource_flag
        }
        security_item_settings.append(security_item_setting)

    # 作成したSecurityItemSettingの配列をレスポンスとして作成します。
    response = common_utils.get_response_by_response_body(
        HTTPStatus.OK, security_item_settings)
    return common_utils.response(response, pm_logger)