

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# AWS Config 사용자 지정 규칙
<a name="evaluate-config_develop-rules"></a>

AWS Config 사용자 지정 규칙은 처음부터 생성하는 규칙입니다. 사용자 AWS Config 지정 규칙을 생성하는 방법에는 Lambda 함수([AWS Lambda 개발자 안내서](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-concepts.html#gettingstarted-concepts-function))와 policy-as-code 언어인 Guard([Guard GitHub Repository](https://github.com/aws-cloudformation/cloudformation-guard))의 두 가지가 있습니다.

AWS Config Lambda로 생성된 사용자 지정 규칙을 *AWS Config 사용자 지정 Lambda 규칙*이라고 하고 Guard로 생성된 AWS Config 사용자 지정 규칙을 사용자 *AWS Config 지정 정책 규칙*이라고 합니다.

사용자 지정 규칙을 사용하기 전에 [고려 사항](evaluate-config.md#evaluate-config-considerations) 섹션을 참조하세요.

## AWS Config 사용자 지정 정책 규칙
<a name="evaluate-config_develop-rules-policy"></a>

Guard를 사용하여 작성된 규칙은 AWS Config 콘솔에서 생성하거나 AWS Config 규칙 APIs를 사용하여 생성할 수 있습니다. AWS Config 사용자 지정 정책 규칙을 사용하면 Java 또는 Python을 사용하여 AWS Config 사용자 지정 규칙을 관리하기 위한 Lambda 함수를 개발할 필요 없이 사용자 지정 규칙을 생성할 수 있습니다. AWS Config 사용자 지정 정책 규칙은 구성 변경에 의해 시작됩니다. Guard에 자세한 내용은 GitHub에서 [Guard GitHub 리포지토리](https://github.com/aws-cloudformation/cloudformation-guard)를 참조하세요.

## AWS Config 사용자 지정 Lambda 규칙
<a name="evaluate-config_develop-rules-lambda"></a>

사용자 지정 Lambda 규칙은 Java 또는 Python을 사용하여 AWS Config 사용자 지정 규칙에 대한 Lambda 함수를 생성할 수 있는 옵션을 제공합니다. * Lambda 함수*는 업로드하는 사용자 지정 코드 AWS Lambda이며 이벤트 소스에서 게시하는 이벤트에 의해 호출됩니다. Lambda 함수가 AWS Config 규칙과 연결된 경우 AWS Config 는 규칙이 시작될 때 이를 호출합니다. 그런 다음 Lambda 함수는에서 전송한 구성 정보를 평가하고 평가 결과를 AWS Config반환합니다. Lambda 함수에 대한 자세한 내용은 **AWS Lambda 개발자 안내서의 [함수 및 이벤트 소스](https://docs.aws.amazon.com/lambda/latest/dg/intro-core-components.html)를 참조하세요.

## AWS Config 사용자 지정 규칙의 형식 차이
<a name="evaluate-config_develop-schema"></a>

다음 표에는 [ConfigurationItem](https://docs.aws.amazon.com/config/latest/APIReference/API_ConfigurationItem.html) 데이터 유형 및 AWS Config 사용자 지정 규칙에 대한 필드의 형식 차이가 표시됩니다.


| ConfigurationItem | AWS Config 사용자 지정 규칙 | 
| --- | --- | 
| version | configurationItemVersion | 
| accountId | awsAccountId | 
| arn | ARN | 
| configurationItemMD5Hash | configurationStateMd5Hash | 

**Topics**
+ [사용자 지정 정책 규칙](#evaluate-config_develop-rules-policy)
+ [사용자 지정 Lambda 규칙](#evaluate-config_develop-rules-lambda)
+ [AWS Config 사용자 지정 규칙의 형식 차이](#evaluate-config_develop-schema)
+ [사용자 지정 정책 규칙 생성](evaluate-config_develop-rules_cfn-guard.md)
+ [사용자 지정 Lambda 규칙 생성](evaluate-config_develop-rules_lambda-functions.md)
+ [사용자 지정 Lambda 규칙을 사용하여 삭제된 리소스 관리](evaluate-config_develop-rules-delete.md)

# AWS Config 사용자 지정 정책 규칙 생성
<a name="evaluate-config_develop-rules_cfn-guard"></a>

 AWS Management Console AWS CLI또는 AWS Config API에서 AWS Config 사용자 지정 정책 규칙을 생성할 수 있습니다.

## AWS Config 사용자 지정 정책 규칙 추가
<a name="config-custom-policy-rules-add"></a>

------
#### [ Using the console ]

1. 에 로그인 AWS Management Console 하고 [https://console.aws.amazon.com/config/home](https://console.aws.amazon.com/config/home) AWS Config 콘솔을 엽니다.

1.  AWS Management Console 메뉴에서 리전 선택기가 AWS Config 규칙을 지원하는 리전으로 AWS 설정되어 있는지 확인합니다. 지원되는 리전의 목록은 **Amazon Web Services 일반 참조의 [AWS Config 리전 및 엔드포인트](https://docs.aws.amazon.com/general/latest/gr/awsconfig.html)를 참조하세요.

1. 왼쪽 탐색 창에서 **규칙**을 선택합니다.

1. **규칙** 페이지에서 **규칙 추가**를 선택합니다.

1. **규칙 유형 지정** 페이지에서 **Guard를 사용하여 사용자 지정 규칙 생성**을 선택합니다.

1. **규칙 구성** 페이지에서 다음 단계를 완료하여 규칙을 생성합니다.

   1. **규칙 이름**에 규칙의 고유 이름을 입력합니다.

   1. **설명**에 규칙에 대한 설명을 입력합니다.

   1. **Guard 런타임 버전**에서 AWS Config 사용자 지정 정책 규칙의 런타임 시스템을 선택합니다.

   1. **규칙 내용**의 경우 규칙의 Guard 사용자 지정 정책으로 채울 수 있습니다.

   1. **평가 모드에서** 리소스 생성 및 관리 프로세스에서 리소스를 평가하려는 시기 AWS Config 를 선택합니다. 규칙에 따라는 리소스가 프로비저닝되기 전, 리소스가 프로비저닝된 후 또는 둘 다 수행하기 전에 리소스 구성을 평가할 AWS Config 수 있습니다.

      1. 리소스를 배포하기 전에 리소스의 구성 설정에 대한 평가를 실행하려면 **사전 평가 켜기**를 선택합니다.

         사전 평가를 활성화한 후에는 [StartResourceEvaluation](https://docs.aws.amazon.com/config/latest/APIReference/API_StartResourceEvaluation.html) API 및 [GetResourceEvaluationSummary](https://docs.aws.amazon.com/config/latest/APIReference/API_GetResourceEvaluationSummary.html) API를 사용하여 이러한 명령에 지정한 리소스가 해당 계정의 해당 리전 사전 예방 규칙에 따라 NON\$1COMPLIANT 플래그가 지정되는지 확인할 수 있습니다.

          이 명령 사용에 대한 자세한 내용은 [AWS Config 규칙을 사용하여 리소스 평가를 참조하세요](https://docs.aws.amazon.com/config/latest/developerguide/evaluating-your-resources.html#evaluating-your-resources-proactive). 사전 평가를 지원하는 관리형 규칙 목록은 [평가 모드별 AWS Config 관리형 규칙 목록을 참조하세요](https://docs.aws.amazon.com/config/latest/developerguide/managed-rules-by-evaluation-mode.html).

      1. 기존 리소스의 구성 설정을 평가하려면 **탐지 평가 켜기**를 선택합니다.

         탐지 평가를 위해 AWS Config 사용자 지정 정책 규칙은 **구성 변경**에 의해 시작됩니다. 이 옵션은 미리 선택되어 있습니다.
         +  **리소스** - 지정된 리소스 유형 또는 유형 및 식별자와 일치하는 리소스가 생성, 변경 또는 삭제되는 경우.
         +  **태그** - 지정된 태그가 있는 리소스가 생성, 변경 또는 삭제되는 경우.
         +  **모든 변경** -에 의해 기록된 리소스 AWS Config 가 생성, 변경 또는 삭제되는 경우.

         AWS Config 는 규칙의 범위와 일치하는 리소스에 대한 변경을 감지하면 평가를 실행합니다. 범위를 사용하여 평가를 시작하는 리소스를 제한할 수 있습니다. 그렇지 않으면 사후 프로비저닝된 리소스가 변경될 때 평가가 시작됩니다.

   1. 규칙에 파라미터가 포함된 경우 **파라미터**에서 제공된 키의 값을 사용자 지정할 수 있습니다. 파라미터는 리소스가 규칙을 준수한다고 간주되기 위해 준수해야 하는 속성입니다.

1. **검토 및 생성** 페이지에서 모든 선택 사항을 검토한 후 AWS 계정에 규칙을 추가합니다.

1. 규칙 검토를 마치면 **규칙 추가**를 선택합니다.

------
#### [ Using the AWS CLI ]

[https://docs.aws.amazon.com/cli/latest/reference/configservice/put-config-rule.html](https://docs.aws.amazon.com/cli/latest/reference/configservice/put-config-rule.html) 명령을 사용합니다.

`Owner` 필드는 `CUSTOM_POLICY`여야 합니다. AWS Config 사용자 지정 정책 규칙에는 다음과 같은 추가 필드가 필요합니다.
+ `Runtime`: AWS Config 사용자 지정 정책 규칙의 런타임 시스템입니다.
+ `PolicyText`: AWS Config 사용자 지정 정책 규칙에 대한 논리가 포함된 정책 정의입니다.
+ `EnableDebugLogDelivery`: AWS Config 사용자 지정 정책 규칙에 대한 디버그 로깅을 활성화하기 위한 부울 표현식입니다. 기본값은 `false`입니다.

------
#### [ Using the API Reference ]

[PutConfigRule](https://docs.aws.amazon.com/config/latest/APIReference/API_PutConfigRule.html) 작업을 사용합니다.

`Owner` 필드는 `CUSTOM_POLICY`여야 합니다. AWS Config 사용자 지정 정책 규칙에는 다음과 같은 추가 필드가 필요합니다.
+ `Runtime`: AWS Config 사용자 지정 정책 규칙의 런타임 시스템입니다.
+ `PolicyText`: AWS Config 사용자 지정 정책 규칙에 대한 논리가 포함된 정책 정의입니다.
+ `EnableDebugLogDelivery`: AWS Config 사용자 지정 정책 규칙에 대한 디버그 로깅을 활성화하기 위한 부울 표현식입니다. 기본값은 `false`입니다.

------

## AWS Config 사용자 지정 정책 규칙에 대한 규칙 콘텐츠 작성
<a name="config-custom-policy-rules"></a>

 AWS Config 사용자 지정 정책 규칙을 사용하면 AWS CloudFormation Guard의 도메인별 언어(DSL)를 사용하여 리소스 구성을 평가할 수 있습니다. 이 주제에서는 사용자 지정 정책 규칙을 작성하기 위한 패턴과 모범 사례를 제공합니다.

Guard로 규칙을 작성하는 방법에 대한 자세한 내용은 [Guard 사용 설명서의 Guard 규칙 작성](https://docs.aws.amazon.com/cfn-guard/latest/ug/writing-rules.html) 및 [AWS CloudFormation Guard GitHub 리포지토리의 Guard 2.0 작업 모드를 참조하세요](https://github.com/aws-cloudformation/cloudformation-guard/tree/main/guard). AWS CloudFormation GitHub 

### 기본 규칙 구조
<a name="config-custom-policy-rules-structure"></a>

다음 기본 형식을 사용하여 규칙을 생성합니다.

```
# Basic rule format
rule <rule_name> when
    resourceType == "<AWS::Service::Resource>" {
    # Evaluation clauses
}

# Example with filtering
let resources_of_type = Resources.*[ Type == 'AWS::Service::Resource' ]
rule check_resources when %resources_of_type !empty {
    %resources_of_type.configuration.property == expected_value
}
```

### 핵심 구성 요소
<a name="config-custom-policy-rules-components"></a>

구성  
리소스 구성에 대한 내용을 포함합니다.

supplementaryConfiguration  
리소스 구성에 대한 추가 내용을 포함합니다. 구성 필드에 대해 반환된 정보를 보완하기 위해 특정 리소스 유형에 대해이 필드를 AWS Config 반환합니다.

resourceType  
AWS 평가 중인 리소스 유형입니다.

resourceId  
리소스의 ID(예: `sg-xxxxxx`)입니다.

accountId  
리소스와 연결된 12자리 AWS 계정 ID입니다.

### 일반적인 패턴
<a name="config-custom-policy-rules-patterns"></a>

------
#### [ Status checks ]

```
let allowed_status = ['ACTIVE', 'RUNNING']
rule check_resource_status when
    resourceType == "AWS::Service::Resource" {
    configuration.status IN %allowed_status
}
```

------
#### [ Required properties ]

```
rule check_required_properties when
    resourceType == "AWS::Service::Resource" {
    configuration.propertyName exists
    configuration.propertyName is_string  # or is_list, is_struct
}
```

------
#### [ Query blocks ]

```
configuration.Properties {
    property1 exists
    property2 is_string
    property3 IN [allowed_value1, allowed_value2]
}
```

------
#### [ Conditional evaluation ]

```
when configuration.feature_enabled == true {
    configuration.feature_settings exists
    configuration.feature_settings is_struct
}
```

------
#### [ Custom messages ]

```
rule check_compliance when
    resourceType == "AWS::Service::Resource" {
    configuration.property == expected_value <<Custom error message explaining the requirement>>
}}
```

------

### 고급 기능
<a name="config-custom-policy-rules-advanced"></a>

------
#### [ Range checks ]

```
rule check_numeric_limits {
    # Inclusive range (lower_limit <= value <= upper_limit)
    configuration.value IN r[minimum_value, maximum_value]  

    # Exclusive range (lower_limit < value < upper_limit)
    configuration.value IN r(exclusive_min, exclusive_max)  

    # Left inclusive, right exclusive (lower_limit <= value < upper_limit)
    configuration.value IN r[minimum_value, exclusive_max)

    # Left exclusive, right inclusive (lower_limit < value <= upper_limit)
    configuration.value IN r(exclusive_min, maximum_value]
}
```

------
#### [ Combining conditions ]

```
# AND conditions (implicit through new lines)
condition_1
condition_2

# OR conditions (explicit)
condition_3 OR
condition_4
```

------
#### [ Chaining rules ]

```
rule check_prerequisites {
    configuration.required_setting exists
}

rule check_details when check_prerequisites {
    configuration.required_setting == expected_value
}
```

------

### 모범 사례
<a name="config-custom-policy-rules-best-practices"></a>
+ 가독성을 높이기 위해 `let` 문과 함께 변수를 사용합니다.
+ 명명된 규칙 블록을 사용하여 관련 검사를 그룹화합니다.
+ 설명문을 포함합니다.
+ 적절한 연산자(`exists`, `is_string`, `is_list`)를 사용합니다.
+ 대/소문자를 구분하지 않는 일치와 함께 정규식 패턴을 사용합니다.

### 예: dynamodb-pitr-enabled
<a name="config-custom-policy-rules-example"></a>

다음 예제에서는 AWS Config 관리형 규칙의 AWS Config 사용자 지정 정책 규칙 버전에 대한 정책 정의를 보여줍니다[dynamodb-pitr-enabled](dynamodb-pitr-enabled.md). DynamoDB 테이블에 대해 특정 시점으로 복구가 활성화되어 있는지 확인합니다.

```
# Check if DynamoDB tables have Point-in-Time Recovery enabled
let status = ['ACTIVE']

rule tableisactive when
    resourceType == "AWS::DynamoDB::Table" {
    configuration.tableStatus == %status
}

rule checkcompliance when
    resourceType == "AWS::DynamoDB::Table"
    tableisactive {
    let pitr = supplementaryConfiguration.ContinuousBackupsDescription.pointInTimeRecoveryDescription.pointInTimeRecoveryStatus
    %pitr == "ENABLED" <<DynamoDB tables must have Point-in-Time Recovery enabled>>
}
```

# AWS Config 사용자 지정 Lambda 규칙 생성
<a name="evaluate-config_develop-rules_lambda-functions"></a>

 AWS Config AWS Lambda 함수를 사용하여 사용자 지정 규칙을 개발하고에 추가할 수 있습니다.

 AWS 리소스가 규칙을 준수하는지 여부를 평가하는 로직이 포함된 Lambda 함수와 각 사용자 지정 규칙을 연결합니다. 이 함수를 규칙에 연결하면, 이 규칙이 구성 변경에 대한 응답으로 또는 주기적으로 함수를 호출합니다. 그런 다음 함수는 리소스가 규칙을 준수하는지 여부를 평가하고 평가 결과를에 보냅니다 AWS Config.

## AWS 규칙 개발 키트(RDK)
<a name="rdk"></a>

 AWS 규칙 개발 키트(RDK)는 직관적이고 생산적인 "Compliance-as-Code" 워크플로를 지원하도록 설계되었습니다. 사용자 지정 Lambda 함수가 지원하는 배포 AWS Config 규칙과 관련된 차별화되지 않은 과도한 작업을 대부분 추상화하고 간소화된 develop-deploy-monitor 반복 프로세스를 제공합니다.

단계별 지침은 [AWS 규칙 개발 키트(RDK) 설명서](https://aws-config-rdk.readthedocs.io/en/master)를 참조하세요.

## AWS Config 규칙에 대한 AWS Lambda 함수 예제(Node.js)
<a name="evaluate-config_develop-rules_nodejs-sample"></a>

AWS Lambda 는 AWS 서비스에서 게시한 이벤트에 대한 응답으로 함수를 실행합니다. AWS Config 사용자 지정 Lambda 규칙의 함수는에서 게시한 이벤트를 수신한 다음 AWS Config이벤트에서 수신한 데이터와 AWS Config API에서 검색한 데이터를 사용하여 규칙의 규정 준수를 평가합니다. 구성 규칙의 함수 작업은 구성 변경으로 트리거된 평가를 수행하는지 주기적으로 트리거된 평가를 수행하는지에 따라 다릅니다.

 AWS Lambda 함수 내의 일반적인 패턴에 대한 자세한 내용은 *AWS Lambda 개발자 안내서*의 [프로그래밍 모델을](https://docs.aws.amazon.com/lambda/latest/dg/programming-model-v2.html) 참조하세요.

------
#### [ Example Function for Evaluations Triggered by Configuration Changes ]

AWS Config 는 사용자 지정 규칙의 범위 내에 있는 리소스에 대한 구성 변경을 감지하면 다음 예제와 같은 함수를 호출합니다.

 AWS Config 콘솔을 사용하여이 예제와 같은 함수와 연결된 규칙을 생성하는 경우 트리거 유형으로 **구성 변경을** 선택합니다. AWS Config API 또는를 사용하여 규칙을 AWS CLI 생성하는 경우 `MessageType` 속성을 `ConfigurationItemChangeNotification` 및 로 설정합니다`OversizedConfigurationItemChangeNotification`. 이러한 설정을 사용하면가 리소스 변경으로 인해 구성 항목 또는 크기 초과 구성 항목을 AWS Config 생성할 때마다 규칙을 트리거할 수 있습니다.

이 예제에서는 리소스를 평가하고 인스턴스가 리소스 유형 `AWS::EC2::Instance`와 일치하는지 확인합니다. AWS Config 가 구성 항목 또는 크기를 초과한 구성 항목 알림을 생성하면 규칙이 트리거됩니다.

```
'use strict';

import { ConfigServiceClient, GetResourceConfigHistoryCommand, PutEvaluationsCommand } from "@aws-sdk/client-config-service";

const configClient = new ConfigServiceClient({});

// Helper function used to validate input
function checkDefined(reference, referenceName) {
    if (!reference) {
        throw new Error(`Error: ${referenceName} is not defined`);
    }
    return reference;
}

// Check whether the message type is OversizedConfigurationItemChangeNotification,
function isOverSizedChangeNotification(messageType) {
    checkDefined(messageType, 'messageType');
    return messageType === 'OversizedConfigurationItemChangeNotification';
}

// Get the configurationItem for the resource using the getResourceConfigHistory API.
async function getConfiguration(resourceType, resourceId, configurationCaptureTime, callback) {
    const input = { resourceType, resourceId, laterTime: new Date(configurationCaptureTime), limit: 1 };
    const command = new GetResourceConfigHistoryCommand(input);
    await configClient.send(command).then(
        (data) => {
            callback(null, data.configurationItems[0]);
        },
        (error) => {
            callback(error, null);
        }
    );

}

// Convert the oversized configuration item from the API model to the original invocation model.
function convertApiConfiguration(apiConfiguration) {
    apiConfiguration.awsAccountId = apiConfiguration.accountId;
    apiConfiguration.ARN = apiConfiguration.arn;
    apiConfiguration.configurationStateMd5Hash = apiConfiguration.configurationItemMD5Hash;
    apiConfiguration.configurationItemVersion = apiConfiguration.version;
    apiConfiguration.configuration = JSON.parse(apiConfiguration.configuration);
    if ({}.hasOwnProperty.call(apiConfiguration, 'relationships')) {
        for (let i = 0; i < apiConfiguration.relationships.length; i++) {
            apiConfiguration.relationships[i].name = apiConfiguration.relationships[i].relationshipName;
        }
    }
    return apiConfiguration;
}

// Based on the message type, get the configuration item either from the configurationItem object in the invoking event or with the getResourceConfigHistory API in the getConfiguration function.
async function getConfigurationItem(invokingEvent, callback) {
    checkDefined(invokingEvent, 'invokingEvent');
    if (isOverSizedChangeNotification(invokingEvent.messageType)) {
        const configurationItemSummary = checkDefined(invokingEvent.configurationItemSummary, 'configurationItemSummary');
        await getConfiguration(configurationItemSummary.resourceType, configurationItemSummary.resourceId, configurationItemSummary.configurationItemCaptureTime, (err, apiConfigurationItem) => {
            if (err) {
                callback(err);
            }
            const configurationItem = convertApiConfiguration(apiConfigurationItem);
            callback(null, configurationItem);
        });
    } else {
        checkDefined(invokingEvent.configurationItem, 'configurationItem');
        callback(null, invokingEvent.configurationItem);
    }
}

// Check whether the resource has been deleted. If the resource was deleted, then the evaluation returns not applicable.
function isApplicable(configurationItem, event) {
    checkDefined(configurationItem, 'configurationItem');
    checkDefined(event, 'event');
    const status = configurationItem.configurationItemStatus;
    const eventLeftScope = event.eventLeftScope;
    return (status === 'OK' || status === 'ResourceDiscovered') && eventLeftScope === false;
}

// In this example, the resource is compliant if it is an instance and its type matches the type specified as the desired type.
// If the resource is not an instance, then this resource is not applicable.
function evaluateChangeNotificationCompliance(configurationItem, ruleParameters) {
    checkDefined(configurationItem, 'configurationItem');
    checkDefined(configurationItem.configuration, 'configurationItem.configuration');
    checkDefined(ruleParameters, 'ruleParameters');

    if (configurationItem.resourceType !== 'AWS::EC2::Instance') {
        return 'NOT_APPLICABLE';
    } else if (ruleParameters.desiredInstanceType === configurationItem.configuration.instanceType) {
        return 'COMPLIANT';
    }
    return 'NON_COMPLIANT';
}

// Receives the event and context from AWS Lambda.
export const handler = async (event, context) => {
    checkDefined(event, 'event');
    const invokingEvent = JSON.parse(event.invokingEvent);
    const ruleParameters = JSON.parse(event.ruleParameters);
    await getConfigurationItem(invokingEvent, async (err, configurationItem) => {

        let compliance = 'NOT_APPLICABLE';
        let annotation = '';
        const putEvaluationsRequest = {};
        if (isApplicable(configurationItem, event)) {
            // Invoke the compliance checking function.
            compliance = evaluateChangeNotificationCompliance(configurationItem, ruleParameters);
            if (compliance === "NON_COMPLIANT") {
                annotation = "This is an annotation describing why the resource is not compliant.";
            }
        }
        // Initializes the request that contains the evaluation results.
        if (annotation) {
            putEvaluationsRequest.Evaluations = [
                {
                    ComplianceResourceType: configurationItem.resourceType,
                    ComplianceResourceId: configurationItem.resourceId,
                    ComplianceType: compliance,
                    OrderingTimestamp: new Date(configurationItem.configurationItemCaptureTime),
                    Annotation: annotation
                },
            ];
        } else {
            putEvaluationsRequest.Evaluations = [
                {
                    ComplianceResourceType: configurationItem.resourceType,
                    ComplianceResourceId: configurationItem.resourceId,
                    ComplianceType: compliance,
                    OrderingTimestamp: new Date(configurationItem.configurationItemCaptureTime),
                },
            ];
        }
        putEvaluationsRequest.ResultToken = event.resultToken;

        // Sends the evaluation results to AWS Config.
        await configClient.send(new PutEvaluationsCommand(putEvaluationsRequest));
    });
};
```

**함수 작업**

함수는 실행 시 다음 작업을 수행합니다.

1. 함수는가 `event` 객체를 `handler` 함수에 AWS Lambda 전달할 때 실행됩니다. 이 예제에서 함수는 호출자에게 정보를 반환하는 데 사용하는 선택적 `callback` 파라미터를 수락합니다. AWS Lambda 또한 함수가 실행되는 동안 사용할 수 있는 정보와 메서드가 포함된 `context` 객체를 전달합니다. 참고로, 최신 버전의 Lambda에서는 컨텍스트가 더 이상 사용되지 않습니다.

1. 함수는 이벤트의 `messageType`이 구성 항목인지 크기를 초과한 구성 항목인지 확인한 다음, 해당 구성 항목을 반환합니다.

1. 핸들러는 `isApplicable` 함수를 호출하여 리소스가 삭제되었는지 여부를 확인합니다.
**참고**  
삭제된 리소스에 대해 보고하는 규칙은 불필요한 규칙 평가를 피하기 위해 `NOT_APPLICABLE` 평가 결과를 반환해야 합니다.

1. 핸들러는 `evaluateChangeNotificationCompliance` 함수를 호출하고 이벤트에 AWS Config 게시된 `configurationItem` 및 `ruleParameters` 객체를 전달합니다.

   함수는 먼저 리소스가 EC2 인스턴스인지 여부를 평가합니다. 리소스가 EC2 인스턴스가 아닌 경우, 함수는 준수 값 `NOT_APPLICABLE`을 반환합니다.

   그런 다음 함수는 구성 항목의 `instanceType` 속성이 `desiredInstanceType` 파라미터 값과 같은지 여부를 평가합니다. 값이 같으면 함수는 `COMPLIANT`를 반환합니다. 값이 같지 않으면 함수는 `NON_COMPLIANT`를 반환합니다.

1. 핸들러는 `putEvaluationsRequest` 객체를 초기화하여 평가 결과를 AWS Config 로 전송할 준비를 합니다. 이 객체에는 준수 결과를 식별하는 `Evaluations` 파라미터, 리소스 유형, 평가된 리소스의 ID가 포함되어 있습니다. `putEvaluationsRequest` 객체에는 규칙과 이벤트를 식별하는 이벤트의 결과 토큰도 포함됩니다 AWS Config.

1. 핸들러는 객체를 `config` 클라이언트의 `putEvaluations` 메서드로 전달 AWS Config 하여 평가 결과를 로 전송합니다.

------
#### [ Example Function for Periodic Evaluations ]

AWS Config 는 정기 평가를 위해 다음 예제와 같은 함수를 호출합니다. 주기적 평가는 사용자가 AWS Config에서 규칙을 정의할 때 지정한 간격으로 발생합니다.

 AWS Config 콘솔을 사용하여이 예제와 같은 함수와 연결된 규칙을 생성하는 경우 트리거 유형으로 **주기적**을 선택합니다. AWS Config API 또는를 사용하여 규칙을 AWS CLI 생성하는 경우 `MessageType` 속성을 로 설정합니다`ScheduledNotification`.

이 예제에서는 지정한 총 리소스 수가 지정한 최대치를 초과하는지 확인합니다.

```
'use strict';
import { ConfigServiceClient, ListDiscoveredResourcesCommand, PutEvaluationsCommand } from "@aws-sdk/client-config-service";

const configClient = new ConfigServiceClient({});

// Receives the event and context from AWS Lambda.
export const handler = async (event, context, callback) => {
    // Parses the invokingEvent and ruleParameters values, which contain JSON objects passed as strings.
    var invokingEvent = JSON.parse(event.invokingEvent),
        ruleParameters = JSON.parse(event.ruleParameters),
        numberOfResources = 0;

    if (isScheduledNotification(invokingEvent) && hasValidRuleParameters(ruleParameters, callback)) {
        await countResourceTypes(ruleParameters.applicableResourceType, "", numberOfResources, async function (err, count) {
            if (err === null) {
                var putEvaluationsRequest;
                const compliance = evaluateCompliance(ruleParameters.maxCount, count);
                var annotation = '';
                if (compliance === "NON_COMPLIANT") {
                    annotation = "Description of why the resource is not compliant.";
                }
                // Initializes the request that contains the evaluation results.
                if (annotation) {
                    putEvaluationsRequest = {
                        Evaluations: [{
                            // Applies the evaluation result to the AWS account published in the event.
                            ComplianceResourceType: 'AWS::::Account',
                            ComplianceResourceId: event.accountId,
                            ComplianceType: compliance,
                            OrderingTimestamp: new Date(),
                            Annotation: annotation
                        }],
                        ResultToken: event.resultToken
                    };
                } else {
                    putEvaluationsRequest = {
                        Evaluations: [{
                            // Applies the evaluation result to the AWS account published in the event.
                            ComplianceResourceType: 'AWS::::Account',
                            ComplianceResourceId: event.accountId,
                            ComplianceType: compliance,
                            OrderingTimestamp: new Date()
                        }],
                        ResultToken: event.resultToken
                    };
                }

                // Sends the evaluation results to AWS Config.
                try {
                    await configClient.send(new PutEvaluationsCommand(putEvaluationsRequest));
                }
                catch (e) {
                    callback(e, null);
                }
            } else {
                callback(err, null);
            }
        });
    } else {
        console.log("Invoked for a notification other than Scheduled Notification... Ignoring.");
    }
};

// Checks whether the invoking event is ScheduledNotification.
function isScheduledNotification(invokingEvent) {
    return (invokingEvent.messageType === 'ScheduledNotification');
}

// Checks the rule parameters to see if they are valid
function hasValidRuleParameters(ruleParameters, callback) {
    // Regular express to verify that applicable resource given is a resource type
    const awsResourcePattern = /^AWS::(\w*)::(\w*)$/;
    const isApplicableResourceType = awsResourcePattern.test(ruleParameters.applicableResourceType);
    // Check to make sure the maxCount in the parameters is an integer
    const maxCountIsInt = !isNaN(ruleParameters.maxCount) && parseInt(Number(ruleParameters.maxCount)) == ruleParameters.maxCount && !isNaN(parseInt(ruleParameters.maxCount, 10));
    if (!isApplicableResourceType) {
        callback("The applicableResourceType parameter is not a valid resource type.", null);
    }
    if (!maxCountIsInt) {
        callback("The maxCount parameter is not a valid integer.", null);
    }
    return isApplicableResourceType && maxCountIsInt;
}

// Checks whether the compliance conditions for the rule are violated.
function evaluateCompliance(maxCount, actualCount) {
    if (actualCount > maxCount) {
        return "NON_COMPLIANT";
    } else {
        return "COMPLIANT";
    }
}

// Counts the applicable resources that belong to the AWS account.
async function countResourceTypes(applicableResourceType, nextToken, count, callback) {
    const input = { resourceType: applicableResourceType, nextToken: nextToken };
    const command = new ListDiscoveredResourcesCommand(input);
    try {
        const response = await configClient.send(command);
        count = count + response.resourceIdentifiers.length;
        if (response.nextToken !== undefined && response.nextToken != null) {
            countResourceTypes(applicableResourceType, response.nextToken, count, callback);
        }
        callback(null, count);
    } catch (e) {
        callback(e, null);
    }
    return count;
}
```

**함수 작업**

함수는 실행 시 다음 작업을 수행합니다.

1. 함수는가 `event` 객체를 `handler` 함수에 AWS Lambda 전달할 때 실행됩니다. 이 예제에서 함수는 호출자에게 정보를 반환하는 데 사용하는 선택적 `callback` 파라미터를 수락합니다. AWS Lambda 또한 함수가 실행되는 동안 사용할 수 있는 정보와 메서드가 포함된 `context` 객체를 전달합니다. 참고로, 최신 버전의 Lambda에서는 컨텍스트가 더 이상 사용되지 않습니다.

1. 지정된 유형의 리소스 수를 세기 위해 핸들러는 `countResourceTypes` 함수를 호출한 다음, 이벤트에서 수신한 `applicableResourceType` 파라미터를 전달합니다. `countResourceTypes` 함수는 `listDiscoveredResources` 클라이언트의 `config` 메서드를 호출합니다. 그러면 해당하는 리소스의 식별자 목록이 반환됩니다. 함수는 이 목록의 길이를 사용하여 해당하는 리소스 수를 확인하고, 이 수를 핸들러에게 반환합니다.

1. 핸들러는 `putEvaluationsRequest` 객체를 초기화하여 평가 결과를 AWS Config 로 전송할 준비를 합니다. 이 객체에는 규정 준수 결과와 이벤트에 게시된를 식별하는 `Evaluations` 파라미터 AWS 계정 가 포함되어 있습니다. `Evaluations` 파라미터를 사용하여 AWS Config가 지원하는 리소스 유형에 결과를 적용할 수 있습니다. `putEvaluationsRequest` 객체에는 규칙과 이벤트를 식별하는 이벤트의 결과 토큰도 포함됩니다 AWS Config.

1. `putEvaluationsRequest` 객체 내에서 핸들러는 `evaluateCompliance` 함수를 호출합니다. 이 함수는 해당하는 리소스 수가 이벤트에서 제공한 `maxCount` 파라미터에 할당된 최대치를 초과하는지 여부를 테스트합니다. 리소스 수가 최대치를 초과하면 함수는 `NON_COMPLIANT`를 반환합니다. 리소스 수가 최대치를 초과하지 않으면 함수는 `COMPLIANT`를 반환합니다.

1. 핸들러는 객체를 `config` 클라이언트의 `putEvaluations` 메서드로 전달 AWS Config 하여 평가 결과를 로 전송합니다.

------

## AWS Config 규칙에 대한 AWS Lambda 함수 예제(Python)
<a name="evaluate-config_develop-rules_python-sample"></a>

AWS Lambda 는 AWS 서비스에서 게시한 이벤트에 대한 응답으로 함수를 실행합니다. AWS Config 사용자 지정 Lambda 규칙의 함수는에서 게시한 이벤트를 수신한 다음 AWS Config이벤트에서 수신한 데이터와 AWS Config API에서 검색한 데이터를 사용하여 규칙의 규정 준수를 평가합니다. 구성 규칙의 함수 작업은 구성 변경으로 트리거된 평가를 수행하는지 주기적으로 트리거된 평가를 수행하는지에 따라 다릅니다.

 AWS Lambda 함수 내의 일반적인 패턴에 대한 자세한 내용은 *AWS Lambda 개발자 안내서*의 [프로그래밍 모델을](https://docs.aws.amazon.com/lambda/latest/dg/programming-model-v2.html) 참조하세요.

------
#### [ Example Function for Evaluations Triggered by Configuration Changes ]

AWS Config 는 사용자 지정 규칙의 범위 내에 있는 리소스에 대한 구성 변경을 감지하면 다음 예제와 같은 함수를 호출합니다.

 AWS Config 콘솔을 사용하여이 예제와 같은 함수와 연결된 규칙을 생성하는 경우 트리거 유형으로 **구성 변경을** 선택합니다. AWS Config API 또는를 사용하여 규칙을 AWS CLI 생성하는 경우 `MessageType` 속성을 `ConfigurationItemChangeNotification` 및 로 설정합니다`OversizedConfigurationItemChangeNotification`. 이러한 설정을 사용하면가 리소스 변경으로 인해 구성 항목 또는 크기 초과 구성 항목을 AWS Config 생성할 때마다 규칙을 트리거할 수 있습니다.

```
import botocore 
import boto3
import json
import datetime

# Set to True to get the lambda to assume the Role attached on the Config Service (useful for cross-account).
ASSUME_ROLE_MODE = False

# This gets the client after assuming the Config service role
# either in the same AWS account or cross-account.
def get_client(service, event):
    """Return the service boto client. It should be used instead of directly calling the client.
    Keyword arguments:
    service -- the service name used for calling the boto.client()
    event -- the event variable given in the lambda handler
    """
    if not ASSUME_ROLE_MODE:
        return boto3.client(service)
    credentials = get_assume_role_credentials(event["executionRoleArn"])
    return boto3.client(service, aws_access_key_id=credentials['AccessKeyId'],
                        aws_secret_access_key=credentials['SecretAccessKey'],
                        aws_session_token=credentials['SessionToken']
                       )

# Helper function used to validate input
def check_defined(reference, reference_name):
    if not reference:
        raise Exception('Error: ', reference_name, 'is not defined')
    return reference

# Check whether the message is OversizedConfigurationItemChangeNotification or not
def is_oversized_changed_notification(message_type):
    check_defined(message_type, 'messageType')
    return message_type == 'OversizedConfigurationItemChangeNotification'

# Get configurationItem using getResourceConfigHistory API
# in case of OversizedConfigurationItemChangeNotification
def get_configuration(resource_type, resource_id, configuration_capture_time):
    result = AWS_CONFIG_CLIENT.get_resource_config_history(
        resourceType=resource_type,
        resourceId=resource_id,
        laterTime=configuration_capture_time,
        limit=1)
    configurationItem = result['configurationItems'][0]
    return convert_api_configuration(configurationItem)

# Convert from the API model to the original invocation model
def convert_api_configuration(configurationItem):
    for k, v in configurationItem.items():
        if isinstance(v, datetime.datetime):
            configurationItem[k] = str(v)
    configurationItem['awsAccountId'] = configurationItem['accountId']
    configurationItem['ARN'] = configurationItem['arn']
    configurationItem['configurationStateMd5Hash'] = configurationItem['configurationItemMD5Hash']
    configurationItem['configurationItemVersion'] = configurationItem['version']
    configurationItem['configuration'] = json.loads(configurationItem['configuration'])
    if 'relationships' in configurationItem:
        for i in range(len(configurationItem['relationships'])):
            configurationItem['relationships'][i]['name'] = configurationItem['relationships'][i]['relationshipName']
    return configurationItem

# Based on the type of message get the configuration item
# either from configurationItem in the invoking event
# or using the getResourceConfigHistory API in getConfiguration function.
def get_configuration_item(invokingEvent):
    check_defined(invokingEvent, 'invokingEvent')
    if is_oversized_changed_notification(invokingEvent['messageType']):
        configurationItemSummary = check_defined(invokingEvent['configurationItemSummary'], 'configurationItemSummary')
        return get_configuration(configurationItemSummary['resourceType'], configurationItemSummary['resourceId'], configurationItemSummary['configurationItemCaptureTime'])
    return check_defined(invokingEvent['configurationItem'], 'configurationItem')

# Check whether the resource has been deleted. If it has, then the evaluation is unnecessary.
def is_applicable(configurationItem, event):
    try:
        check_defined(configurationItem, 'configurationItem')
        check_defined(event, 'event')
    except:
        return True
    status = configurationItem['configurationItemStatus']
    eventLeftScope = event['eventLeftScope']
    if status == 'ResourceDeleted':
        print("Resource Deleted, setting Compliance Status to NOT_APPLICABLE.")
    return (status == 'OK' or status == 'ResourceDiscovered') and not eventLeftScope

def get_assume_role_credentials(role_arn):
    sts_client = boto3.client('sts')
    try:
        assume_role_response = sts_client.assume_role(RoleArn=role_arn, RoleSessionName="configLambdaExecution")
        return assume_role_response['Credentials']
    except botocore.exceptions.ClientError as ex:
        # Scrub error message for any internal account info leaks
        if 'AccessDenied' in ex.response['Error']['Code']:
            ex.response['Error']['Message'] = "AWS Config does not have permission to assume the IAM role."
        else:
            ex.response['Error']['Message'] = "InternalError"
            ex.response['Error']['Code'] = "InternalError"
        raise ex

def evaluate_change_notification_compliance(configuration_item, rule_parameters):
    check_defined(configuration_item, 'configuration_item')
    check_defined(configuration_item['configuration'], 'configuration_item[\'configuration\']')
    if rule_parameters:
        check_defined(rule_parameters, 'rule_parameters')

    if (configuration_item['resourceType'] != 'AWS::EC2::Instance'):
        return 'NOT_APPLICABLE'

    elif rule_parameters.get('desiredInstanceType'):
        if (configuration_item['configuration']['instanceType'] in rule_parameters['desiredInstanceType']):
            return 'COMPLIANT'
    return 'NON_COMPLIANT'

def lambda_handler(event, context):

    global AWS_CONFIG_CLIENT

    check_defined(event, 'event')
    invoking_event = json.loads(event['invokingEvent'])
    rule_parameters = {}
    if 'ruleParameters' in event:
        rule_parameters = json.loads(event['ruleParameters'])

    compliance_value = 'NOT_APPLICABLE'

    AWS_CONFIG_CLIENT = get_client('config', event)
    configuration_item = get_configuration_item(invoking_event)
    if is_applicable(configuration_item, event):
        compliance_value = evaluate_change_notification_compliance(
                configuration_item, rule_parameters)

    response = AWS_CONFIG_CLIENT.put_evaluations(
       Evaluations=[
           {
               'ComplianceResourceType': invoking_event['configurationItem']['resourceType'],
               'ComplianceResourceId': invoking_event['configurationItem']['resourceId'],
               'ComplianceType': compliance_value,
               'OrderingTimestamp': invoking_event['configurationItem']['configurationItemCaptureTime']
           },
       ],
       ResultToken=event['resultToken'])
```

**함수 작업**

함수는 실행 시 다음 작업을 수행합니다.

1. 함수는가 `event` 객체를 `handler` 함수에 AWS Lambda 전달할 때 실행됩니다. 이 예제에서 함수는 호출자에게 정보를 반환하는 데 사용하는 선택적 `callback` 파라미터를 수락합니다. AWS Lambda 또한 함수가 실행되는 동안 사용할 수 있는 정보와 메서드가 포함된 `context` 객체를 전달합니다. 참고로, 최신 버전의 Lambda에서는 컨텍스트가 더 이상 사용되지 않습니다.

1. 함수는 이벤트의 `messageType`이 구성 항목인지 크기를 초과한 구성 항목인지 확인한 다음, 해당 구성 항목을 반환합니다.

1. 핸들러는 `isApplicable` 함수를 호출하여 리소스가 삭제되었는지 여부를 확인합니다.
**참고**  
삭제된 리소스에 대해 보고하는 규칙은 불필요한 규칙 평가를 피하기 위해 `NOT_APPLICABLE` 평가 결과를 반환해야 합니다.

1. 핸들러는 `evaluateChangeNotificationCompliance` 함수를 호출하고 이벤트에 AWS Config 게시된 `configurationItem` 및 `ruleParameters` 객체를 전달합니다.

   함수는 먼저 리소스가 EC2 인스턴스인지 여부를 평가합니다. 리소스가 EC2 인스턴스가 아닌 경우, 함수는 준수 값 `NOT_APPLICABLE`을 반환합니다.

   그런 다음 함수는 구성 항목의 `instanceType` 속성이 `desiredInstanceType` 파라미터 값과 같은지 여부를 평가합니다. 값이 같으면 함수는 `COMPLIANT`를 반환합니다. 값이 같지 않으면 함수는 `NON_COMPLIANT`를 반환합니다.

1. 핸들러는 `putEvaluationsRequest` 객체를 초기화하여 평가 결과를 AWS Config 로 전송할 준비를 합니다. 이 객체에는 준수 결과를 식별하는 `Evaluations` 파라미터, 리소스 유형, 평가된 리소스의 ID가 포함되어 있습니다. `putEvaluationsRequest` 객체에는 규칙과 이벤트를 식별하는 이벤트의 결과 토큰도 포함됩니다 AWS Config.

1. 핸들러는 객체를 `config` 클라이언트의 `putEvaluations` 메서드로 전달 AWS Config 하여 평가 결과를 로 전송합니다.

------
#### [ Example Function for Periodic Evaluations ]

AWS Config 는 정기 평가를 위해 다음 예제와 같은 함수를 호출합니다. 주기적 평가는 사용자가 AWS Config에서 규칙을 정의할 때 지정한 간격으로 발생합니다.

 AWS Config 콘솔을 사용하여이 예제와 같은 함수와 연결된 규칙을 생성하는 경우 트리거 유형으로 **주기적**을 선택합니다. AWS Config API 또는를 사용하여 규칙을 AWS CLI 생성하는 경우 `MessageType` 속성을 로 설정합니다`ScheduledNotification`.

```
import botocore 
import boto3
import json
import datetime

# Set to True to get the lambda to assume the Role attached on the Config Service (useful for cross-account).
ASSUME_ROLE_MODE = False
DEFAULT_RESOURCE_TYPE = 'AWS::::Account'

# This gets the client after assuming the Config service role
# either in the same AWS account or cross-account.
def get_client(service, event):
    """Return the service boto client. It should be used instead of directly calling the client.
    Keyword arguments:
    service -- the service name used for calling the boto.client()
    event -- the event variable given in the lambda handler
    """
    if not ASSUME_ROLE_MODE:
        return boto3.client(service)
    credentials = get_assume_role_credentials(event["executionRoleArn"])
    return boto3.client(service, aws_access_key_id=credentials['AccessKeyId'],
                        aws_secret_access_key=credentials['SecretAccessKey'],
                        aws_session_token=credentials['SessionToken']
                       )

def get_assume_role_credentials(role_arn):
    sts_client = boto3.client('sts')
    try:
        assume_role_response = sts_client.assume_role(RoleArn=role_arn, RoleSessionName="configLambdaExecution")
        return assume_role_response['Credentials']
    except botocore.exceptions.ClientError as ex:
        # Scrub error message for any internal account info leaks
        if 'AccessDenied' in ex.response['Error']['Code']:
            ex.response['Error']['Message'] = "AWS Config does not have permission to assume the IAM role."
        else:
            ex.response['Error']['Message'] = "InternalError"
            ex.response['Error']['Code'] = "InternalError"
        raise ex

# Check whether the message is a ScheduledNotification or not.
def is_scheduled_notification(message_type):
    return message_type == 'ScheduledNotification'

def count_resource_types(applicable_resource_type, next_token, count):
    resource_identifier = AWS_CONFIG_CLIENT.list_discovered_resources(resourceType=applicable_resource_type, nextToken=next_token)
    updated = count + len(resource_identifier['resourceIdentifiers']);
    return updated

# Evaluates the configuration items in the snapshot and returns the compliance value to the handler.
def evaluate_compliance(max_count, actual_count):
    return 'NON_COMPLIANT' if int(actual_count) > int(max_count) else 'COMPLIANT'

def evaluate_parameters(rule_parameters):
    if 'applicableResourceType' not in rule_parameters:
        raise ValueError('The parameter with "applicableResourceType" as key must be defined.')
    if not rule_parameters['applicableResourceType']:
        raise ValueError('The parameter "applicableResourceType" must have a defined value.')
    return rule_parameters

# This generate an evaluation for config
def build_evaluation(resource_id, compliance_type, event, resource_type=DEFAULT_RESOURCE_TYPE, annotation=None):
    """Form an evaluation as a dictionary. Usually suited to report on scheduled rules.
    Keyword arguments:
    resource_id -- the unique id of the resource to report
    compliance_type -- either COMPLIANT, NON_COMPLIANT or NOT_APPLICABLE
    event -- the event variable given in the lambda handler
    resource_type -- the CloudFormation resource type (or AWS::::Account) to report on the rule (default DEFAULT_RESOURCE_TYPE)
    annotation -- an annotation to be added to the evaluation (default None)
    """
    eval_cc = {}
    if annotation:
        eval_cc['Annotation'] = annotation
    eval_cc['ComplianceResourceType'] = resource_type
    eval_cc['ComplianceResourceId'] = resource_id
    eval_cc['ComplianceType'] = compliance_type
    eval_cc['OrderingTimestamp'] = str(json.loads(event['invokingEvent'])['notificationCreationTime'])
    return eval_cc

def lambda_handler(event, context):

    global AWS_CONFIG_CLIENT

    evaluations = []
    rule_parameters = {}
    resource_count = 0
    max_count = 0

    invoking_event = json.loads(event['invokingEvent'])
    if 'ruleParameters' in event:
        rule_parameters = json.loads(event['ruleParameters'])
        valid_rule_parameters = evaluate_parameters(rule_parameters)

    compliance_value = 'NOT_APPLICABLE'

    AWS_CONFIG_CLIENT = get_client('config', event)
    if is_scheduled_notification(invoking_event['messageType']):
        result_resource_count = count_resource_types(valid_rule_parameters['applicableResourceType'], '', resource_count)

    if valid_rule_parameters.get('maxCount'):
        max_count = valid_rule_parameters['maxCount']

    compliance_value = evaluate_compliance(max_count, result_resource_count)
    evaluations.append(build_evaluation(event['accountId'], compliance_value, event, resource_type=DEFAULT_RESOURCE_TYPE))
    response = AWS_CONFIG_CLIENT.put_evaluations(Evaluations=evaluations, ResultToken=event['resultToken'])
```

**함수 작업**

함수는 실행 시 다음 작업을 수행합니다.

1. 함수는가 `event` 객체를 `handler` 함수에 AWS Lambda 전달할 때 실행됩니다. 이 예제에서 함수는 호출자에게 정보를 반환하는 데 사용하는 선택적 `callback` 파라미터를 수락합니다. AWS Lambda 또한 함수가 실행되는 동안 사용할 수 있는 정보와 메서드가 포함된 `context` 객체를 전달합니다. 참고로, 최신 버전의 Lambda에서는 컨텍스트가 더 이상 사용되지 않습니다.

1. 지정된 유형의 리소스 수를 세기 위해 핸들러는 `countResourceTypes` 함수를 호출한 다음, 이벤트에서 수신한 `applicableResourceType` 파라미터를 전달합니다. `countResourceTypes` 함수는 `listDiscoveredResources` 클라이언트의 `config` 메서드를 호출합니다. 그러면 해당하는 리소스의 식별자 목록이 반환됩니다. 함수는 이 목록의 길이를 사용하여 해당하는 리소스 수를 확인하고, 이 수를 핸들러에게 반환합니다.

1. 핸들러는 `putEvaluationsRequest` 객체를 초기화하여 평가 결과를 AWS Config 로 전송할 준비를 합니다. 이 객체에는 규정 준수 결과와 이벤트에 게시된를 식별하는 `Evaluations` 파라미터 AWS 계정 가 포함되어 있습니다. `Evaluations` 파라미터를 사용하여 AWS Config가 지원하는 리소스 유형에 결과를 적용할 수 있습니다. `putEvaluationsRequest` 객체에는 규칙과 이벤트를 식별하는 이벤트의 결과 토큰도 포함됩니다 AWS Config.

1. `putEvaluationsRequest` 객체 내에서 핸들러는 `evaluateCompliance` 함수를 호출합니다. 이 함수는 해당하는 리소스 수가 이벤트에서 제공한 `maxCount` 파라미터에 할당된 최대치를 초과하는지 여부를 테스트합니다. 리소스 수가 최대치를 초과하면 함수는 `NON_COMPLIANT`를 반환합니다. 리소스 수가 최대치를 초과하지 않으면 함수는 `COMPLIANT`를 반환합니다.

1. 핸들러는 객체를 `config` 클라이언트의 `putEvaluations` 메서드로 전달 AWS Config 하여 평가 결과를 로 전송합니다.

------

## AWS Config 규칙에 대한 이벤트 예제
<a name="evaluate-config_develop-rules_example-events"></a>

규칙에 대한 트리거가 발생하면는 이벤트를 게시하여 규칙의 AWS Lambda 함수를 AWS Config 호출합니다. 그런 다음 함수의 핸들러에 이벤트를 전달하여 함수를 AWS Lambda 실행합니다.

------
#### [ Example Event for Evaluations Triggered by Configuration Changes ]

AWS Config 는 규칙 범위 내에 있는 리소스에 대한 구성 변경을 감지하면 이벤트를 게시합니다. 다음 이벤트 예제에서는 규칙이 EC2 인스턴스의 구성 변경으로 트리거되었음을 보여 줍니다.

```
{ 
    "invokingEvent": "{\"configurationItem\":{\"configurationItemCaptureTime\":\"2016-02-17T01:36:34.043Z\",\"awsAccountId\":\"123456789012\",\"configurationItemStatus\":\"OK\",\"resourceId\":\"i-00000000\",\"ARN\":\"arn:aws:ec2:us-east-2:123456789012:instance/i-00000000\",\"awsRegion\":\"us-east-2\",\"availabilityZone\":\"us-east-2a\",\"resourceType\":\"AWS::EC2::Instance\",\"tags\":{\"Foo\":\"Bar\"},\"relationships\":[{\"resourceId\":\"eipalloc-00000000\",\"resourceType\":\"AWS::EC2::EIP\",\"name\":\"Is attached to ElasticIp\"}],\"configuration\":{\"foo\":\"bar\"}},\"messageType\":\"ConfigurationItemChangeNotification\"}",
    "ruleParameters": "{\"myParameterKey\":\"myParameterValue\"}",
    "resultToken": "myResultToken",
    "eventLeftScope": false,
    "executionRoleArn": "arn:aws:iam::123456789012:role/config-role",
    "configRuleArn": "arn:aws:config:us-east-2:123456789012:config-rule/config-rule-0123456",
    "configRuleName": "change-triggered-config-rule",
    "configRuleId": "config-rule-0123456",
    "accountId": "123456789012",
    "version": "1.0"
}
```

------
#### [ Example Event for Evaluations Triggered by Oversized Configuration Changes ]

일부 리소스 변경은 크기를 초과한 구성 항목을 생성합니다. 다음 이벤트 예제에서는 규칙이 EC2 인스턴스의 크기를 초과한 구성 변경으로 트리거되었음을 보여 줍니다.

```
{
        "invokingEvent": "{\"configurationItemSummary\": {\"changeType\": \"UPDATE\",\"configurationItemVersion\": \"1.2\",\"configurationItemCaptureTime\":\"2016-10-06T16:46:16.261Z\",\"configurationStateId\": 0,\"awsAccountId\":\"123456789012\",\"configurationItemStatus\": \"OK\",\"resourceType\": \"AWS::EC2::Instance\",\"resourceId\":\"i-00000000\",\"resourceName\":null,\"ARN\":\"arn:aws:ec2:us-west-2:123456789012:instance/i-00000000\",\"awsRegion\": \"us-west-2\",\"availabilityZone\":\"us-west-2a\",\"configurationStateMd5Hash\":\"8f1ee69b287895a0f8bc5753eca68e96\",\"resourceCreationTime\":\"2016-10-06T16:46:10.489Z\"},\"messageType\":\"OversizedConfigurationItemChangeNotification\"}",
        "ruleParameters": "{\"myParameterKey\":\"myParameterValue\"}",
        "resultToken": "myResultToken",
        "eventLeftScope": false,
        "executionRoleArn": "arn:aws:iam::123456789012:role/config-role",
        "configRuleArn": "arn:aws:config:us-east-2:123456789012:config-rule/config-rule-ec2-managed-instance-inventory",
        "configRuleName": "change-triggered-config-rule",
        "configRuleId": "config-rule-0123456",
        "accountId": "123456789012",
        "version": "1.0"
    }
```

------
#### [ Example Event for Evaluations Triggered by Periodic Frequency ]

AWS Config 는 사용자가 지정한 빈도(예: 24시간마다)로 리소스를 평가할 때 이벤트를 게시합니다. 다음 이벤트 예제에서는 규칙이 주기적 간격으로 트리거되었음을 보여 줍니다.

```
{
    "invokingEvent": "{\"awsAccountId\":\"123456789012\",\"notificationCreationTime\":\"2016-07-13T21:50:00.373Z\",\"messageType\":\"ScheduledNotification\",\"recordVersion\":\"1.0\"}",
    "ruleParameters": "{\"myParameterKey\":\"myParameterValue\"}",
    "resultToken": "myResultToken",
    "eventLeftScope": false,
    "executionRoleArn": "arn:aws:iam::123456789012:role/config-role",
    "configRuleArn": "arn:aws:config:us-east-2:123456789012:config-rule/config-rule-0123456",
    "configRuleName": "periodic-config-rule",
    "configRuleId": "config-rule-6543210",
    "accountId": "123456789012",
    "version": "1.0"
}
```

------

### 이벤트 속성
<a name="w2aac20c19c20c13b1b7"></a>

 AWS Config 이벤트에 대한 JSON 객체에는 다음 속성이 포함됩니다.

`invokingEvent`  
규칙에 대한 평가를 트리거하는 이벤트입니다. 이벤트가 리소스 구성 변경에 대한 응답으로 게시되는 경우, 이 속성의 값은 JSON `configurationItem` 또는 `configurationItemSummary`(크기를 초과한 구성 항목의 경우)를 포함하는 문자열입니다. 구성 항목은가 변경을 AWS Config 감지한 시점의 리소스 상태를 나타냅니다. 구성 항목의 예는의 `get-resource-config-history` AWS CLI 명령에서 생성된 출력을 참조하세요[구성 기록 보기](view-manage-resource-console.md#get-config-history-cli).  
주기적 평가에 대한 이벤트가 게시되는 경우, 값은 JSON 객체를 포함하는 문자열입니다. 객체에는 트리거된 평가에 대한 정보가 포함됩니다.  
각 이벤트 유형에 대해 함수는 문자열의 콘텐츠를 평가할 수 있도록 다음 Node.js 예와 같이 JSON 구문 분석기로 문자열을 구문 분석해야 합니다.  

```
var invokingEvent = JSON.parse(event.invokingEvent);
```

`ruleParameters`  
함수가 평가 논리의 일부로 처리하는 키/값 페어입니다. AWS Config 콘솔을 사용하여 사용자 지정 Lambda 규칙을 생성할 때 파라미터를 정의합니다. `PutConfigRule` AWS Config API 요청 또는 `put-config-rule` AWS CLI 명령에서 `InputParameters` 속성을 사용하여 파라미터를 정의할 수도 있습니다.  
파라미터의 JSON 코드는 문자열 안에 포함되어 있으므로, 함수는 문자열의 콘텐츠를 평가할 수 있도록 다음 Node.js 예와 같이 JSON 구문 분석기로 문자열을 구문 분석해야 합니다.  

```
var ruleParameters = JSON.parse(event.ruleParameters);
```

`resultToken`  
함수가 `PutEvaluations` 호출을 AWS Config 통해 전달해야 하는 토큰입니다.

`eventLeftScope`  
평가할 AWS 리소스가 규칙 범위에서 제거되었는지 여부를 나타내는 부울 값입니다. 값이 `true`이면 함수는 `NOT_APPLICABLE` 호출에서 `ComplianceType`을 `PutEvaluations` 속성의 값으로 전달하여 평가를 무시할 수 있음을 나타냅니다.

`executionRoleArn`  
할당된 IAM 역할의 ARN입니다 AWS Config.

`configRuleArn`  
가 규칙에 AWS Config 할당한 ARN입니다.

`configRuleName`  
에서 이벤트를 AWS Config 게시하고 함수를 호출하도록 규칙에 할당한 이름입니다.

`configRuleId`  
가 규칙에 AWS Config 할당한 ID입니다.

`accountId`  
규칙을 소유 AWS 계정 한의 ID입니다.

`version`  
에서 할당한 버전 번호입니다 AWS. 가 AWS Config 이벤트에 속성을 추가하면 AWS 버전이 증가합니다. 함수에 특정 버전과 일치하거나 이를 초과하는 이벤트에만 있는 속성이 필요한 경우, 해당 함수가 이 속성의 값을 확인할 수 있습니다.  
 AWS Config 이벤트의 현재 버전은 1.0입니다.

# AWS Config 사용자 지정 Lambda 규칙에 대한 삭제된 리소스 관리
<a name="evaluate-config_develop-rules-delete"></a>

삭제된 리소스에 대해 보고하는 규칙은 불필요한 규칙 평가를 피하기 위해 `NOT_APPLICABLE` 평가 결과를 반환해야 합니다.

리소스를 삭제하면가에 `ResourceDeleted` 대해를 `configurationItem` 사용하여를 AWS Config 생성합니다`configurationItemStatus`. 이 메타데이터를 사용하여 규칙이 삭제된 리소스를 보고하는지 확인할 수 있습니다. 구성 항목에 대한 자세한 내용은 [개념 \$1 구성 항목](https://docs.aws.amazon.com/config/latest/developerguide/config-concepts.html#config-items.html)을 참조하세요.

다음 코드 조각을 포함하여 삭제된 리소스를 확인하고 삭제된 리소스에 대해 보고하는 `NOT_APPLICABLE` 경우 AWS Config 사용자 지정 Lambda 규칙의 평가 결과를 로 설정합니다.

------
#### [ Custom Lambda Rules (Node.js) ]

```
// Check whether the resource has been deleted. If the resource was deleted, then the evaluation returns not applicable.
function isApplicable(configurationItem, event) {
    checkDefined(configurationItem, 'configurationItem');
    checkDefined(event, 'event');
    const status = configurationItem.configurationItemStatus;
    const eventLeftScope = event.eventLeftScope;
    return (status === 'OK' || status === 'ResourceDiscovered') && eventLeftScope === false;
}
```

------
#### [ Custom Lambda Rules (Python) ]

```
# Check whether the resource has been deleted. If the resource was deleted, then the evaluation returns not applicable.
def is_applicable(configurationItem, event):
    try:
        check_defined(configurationItem, 'configurationItem')
        check_defined(event, 'event')
    except:
        return True
    status = configurationItem['configurationItemStatus']
    eventLeftScope = event['eventLeftScope']
    if status == 'ResourceDeleted':
        print("Resource Deleted, setting Compliance Status to NOT_APPLICABLE.")
    return (status == 'OK' or status == 'ResourceDiscovered') and not eventLeftScope
```

------

**참고**  
AWS Config 관리형 규칙 및 AWS Config 사용자 지정 정책 규칙은 기본적으로이 동작을 처리합니다.  
 AWS Config Development Kit(RDK) 및 AWS Config Development Kit Library(RDKlib)를 사용하여 Python으로 AWS Config 사용자 지정 Lambd 규칙을 생성하는 경우 가져온 [평가자](https://github.com/awslabs/aws-config-rdklib/blob/master/rdklib/evaluator.py#L56) 클래스가이 동작을 확인합니다. RDK 및 RDKlib를 사용하여 규칙을 작성하는 방법에 대한 자세한 내용은 [RDK 및 RDKlib를 사용하여 규칙 작성](https://docs.aws.amazon.com/config/latest/developerguide/evaluate-config_components.html#evaluate-config_components_logic)을 참조하세요.