

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Membuat Aturan Lambda AWS Config Kustom
<a name="evaluate-config_develop-rules_lambda-functions"></a>

Anda dapat mengembangkan aturan khusus dan menambahkannya AWS Config dengan AWS Lambda fungsi.

Anda mengaitkan setiap aturan kustom dengan fungsi Lambda, yang berisi logika yang mengevaluasi apakah AWS sumber daya Anda mematuhi aturan. Anda mengaitkan fungsi ini dengan aturan Anda, dan aturan memanggil fungsi baik sebagai respons terhadap perubahan konfigurasi atau secara berkala. Fungsi tersebut kemudian mengevaluasi apakah sumber daya Anda mematuhi aturan Anda, dan mengirimkan hasil evaluasinya ke AWS Config. 

## AWS Kit Pengembangan Aturan (RDK)
<a name="rdk"></a>

 AWS Rule Development Kit (RDK) dirancang untuk mendukung alur kerja “Compliance-as-Code” yang intuitif dan produktif. Ini mengabstraksi sebagian besar angkat berat yang tidak berdiferensiasi yang terkait dengan penerapan AWS Config aturan yang didukung oleh fungsi Lambda khusus, dan menyediakan proses iteratif yang efisien. develop-deploy-monitor

Untuk step-by-step instruksi, lihat Dokumentasi [AWS Rule Development Kit (RDK)](https://aws-config-rdk.readthedocs.io/en/master).

## Contoh AWS Lambda Fungsi untuk AWS Config Aturan (Node.js)
<a name="evaluate-config_develop-rules_nodejs-sample"></a>

AWS Lambda menjalankan fungsi dalam menanggapi peristiwa yang diterbitkan oleh AWS layanan. Fungsi untuk aturan Lambda AWS Config Kustom menerima peristiwa yang diterbitkan oleh AWS Config, dan fungsi tersebut kemudian menggunakan data yang diterimanya dari acara dan diambil dari AWS Config API untuk mengevaluasi kepatuhan aturan. Operasi dalam fungsi untuk aturan Config berbeda tergantung pada apakah ia melakukan evaluasi yang dipicu oleh perubahan konfigurasi atau dipicu secara berkala.

Untuk informasi tentang pola umum dalam AWS Lambda fungsi, lihat [Model Pemrograman](https://docs.aws.amazon.com/lambda/latest/dg/programming-model-v2.html) di *Panduan AWS Lambda Pengembang*.

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

AWS Config akan memanggil fungsi seperti contoh berikut ketika mendeteksi perubahan konfigurasi untuk sumber daya yang berada dalam cakupan aturan khusus.

Jika Anda menggunakan AWS Config konsol untuk membuat aturan yang terkait dengan fungsi seperti contoh ini, pilih **Perubahan konfigurasi** sebagai jenis pemicu. Jika Anda menggunakan AWS Config API atau AWS CLI untuk membuat aturan, tetapkan `MessageType` atribut ke `ConfigurationItemChangeNotification` dan`OversizedConfigurationItemChangeNotification`. Pengaturan ini memungkinkan aturan Anda dipicu setiap kali AWS Config menghasilkan item konfigurasi atau item konfigurasi yang terlalu besar sebagai akibat dari perubahan sumber daya.

Contoh ini mengevaluasi sumber daya Anda dan memeriksa apakah instance cocok dengan jenis sumber daya. `AWS::EC2::Instance` Aturan dipicu saat AWS Config menghasilkan item konfigurasi atau pemberitahuan item konfigurasi berukuran besar. 

```
'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));
    });
};
```

**Operasi Fungsi**

Fungsi melakukan operasi berikut saat runtime:

1. Fungsi berjalan ketika AWS Lambda melewati `event` objek ke `handler` fungsi. Dalam contoh ini, fungsi menerima `callback` parameter opsional, yang digunakan untuk mengembalikan informasi ke pemanggil. AWS Lambda juga melewati `context` objek, yang berisi informasi dan metode yang dapat digunakan fungsi saat berjalan. Perhatikan bahwa dalam versi Lambda yang lebih baru, konteks tidak lagi digunakan.

1. Fungsi memeriksa apakah `messageType` untuk acara tersebut adalah item konfigurasi atau item konfigurasi besar, dan kemudian mengembalikan item konfigurasi. 

1. Handler memanggil `isApplicable` fungsi untuk menentukan apakah sumber daya telah dihapus.
**catatan**  
Aturan pelaporan sumber daya yang dihapus harus mengembalikan hasil evaluasi untuk menghindari evaluasi aturan yang tidak perlu. `NOT_APPLICABLE`

1. Handler memanggil `evaluateChangeNotificationCompliance` fungsi dan meneruskan `configurationItem` dan `ruleParameters` objek yang AWS Config diterbitkan dalam acara tersebut.

   Fungsi pertama mengevaluasi apakah sumber daya adalah instans EC2. Jika sumber daya bukan instans EC2, fungsi mengembalikan nilai kepatuhan. `NOT_APPLICABLE` 

   Fungsi kemudian mengevaluasi apakah `instanceType` atribut dalam item konfigurasi sama dengan nilai `desiredInstanceType` parameter. Jika nilainya sama, fungsi kembali`COMPLIANT`. Jika nilainya tidak sama, fungsi kembali`NON_COMPLIANT`.

1. Handler bersiap untuk mengirim hasil evaluasi AWS Config dengan menginisialisasi objek. `putEvaluationsRequest` Objek ini mencakup `Evaluations` parameter, yang mengidentifikasi hasil kepatuhan, jenis sumber daya, dan ID sumber daya yang dievaluasi. `putEvaluationsRequest`Objek juga menyertakan token hasil dari acara, yang mengidentifikasi aturan dan acara untuk AWS Config. 

1. Handler mengirimkan hasil evaluasi AWS Config dengan meneruskan objek ke `putEvaluations` metode `config` klien.

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

AWS Config akan memanggil fungsi seperti contoh berikut untuk evaluasi berkala. Evaluasi periodik terjadi pada frekuensi yang Anda tentukan saat Anda menentukan aturan di AWS Config.

Jika Anda menggunakan AWS Config konsol untuk membuat aturan yang terkait dengan fungsi seperti contoh ini, pilih **Periodik** sebagai jenis pemicu. Jika Anda menggunakan AWS Config API atau AWS CLI membuat aturan, setel `MessageType` atribut ke`ScheduledNotification`.

Contoh ini memeriksa apakah jumlah total sumber daya tertentu melebihi maksimum yang ditentukan.

```
'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;
}
```

**Operasi Fungsi**

Fungsi melakukan operasi berikut saat runtime:

1. Fungsi berjalan ketika AWS Lambda melewati `event` objek ke `handler` fungsi. Dalam contoh ini, fungsi menerima `callback` parameter opsional, yang digunakan untuk mengembalikan informasi ke pemanggil. AWS Lambda juga melewati `context` objek, yang berisi informasi dan metode yang dapat digunakan fungsi saat berjalan. Perhatikan bahwa dalam versi Lambda yang lebih baru, konteks tidak lagi digunakan.

1. Untuk menghitung sumber daya dari tipe yang ditentukan, handler memanggil `countResourceTypes` fungsi, dan melewati `applicableResourceType` parameter yang diterimanya dari acara tersebut. `countResourceTypes`Fungsi ini memanggil `listDiscoveredResources` metode `config` klien, yang mengembalikan daftar pengidentifikasi untuk sumber daya yang berlaku. Fungsi ini menggunakan panjang daftar ini untuk menentukan jumlah sumber daya yang berlaku, dan mengembalikan hitungan ini ke handler.

1. Handler bersiap untuk mengirim hasil evaluasi AWS Config dengan menginisialisasi objek. `putEvaluationsRequest` Objek ini mencakup `Evaluations` parameter, yang mengidentifikasi hasil kepatuhan dan Akun AWS yang diterbitkan dalam acara tersebut. Anda dapat menggunakan `Evaluations` parameter untuk menerapkan hasilnya ke jenis sumber daya apa pun yang didukung oleh AWS Config. `putEvaluationsRequest`Objek juga menyertakan token hasil dari acara, yang mengidentifikasi aturan dan acara untuk AWS Config.

1. Di dalam `putEvaluationsRequest` objek, handler memanggil `evaluateCompliance` fungsi. Fungsi ini menguji apakah jumlah sumber daya yang berlaku melebihi maksimum yang ditetapkan ke `maxCount` parameter, yang disediakan oleh acara. Jika jumlah sumber daya melebihi maksimum, fungsi kembali`NON_COMPLIANT`. Jika jumlah sumber daya tidak melebihi maksimum, fungsi kembali`COMPLIANT`.

1. Handler mengirimkan hasil evaluasi AWS Config dengan meneruskan objek ke `putEvaluations` metode `config` klien.

------

## Contoh AWS Lambda Fungsi untuk AWS Config Aturan (Python)
<a name="evaluate-config_develop-rules_python-sample"></a>

AWS Lambda menjalankan fungsi dalam menanggapi peristiwa yang diterbitkan oleh AWS layanan. Fungsi untuk aturan Lambda AWS Config Kustom menerima peristiwa yang diterbitkan oleh AWS Config, dan fungsi tersebut kemudian menggunakan data yang diterimanya dari acara dan diambil dari AWS Config API untuk mengevaluasi kepatuhan aturan. Operasi dalam fungsi untuk aturan Config berbeda tergantung pada apakah ia melakukan evaluasi yang dipicu oleh perubahan konfigurasi atau dipicu secara berkala.

Untuk informasi tentang pola umum dalam AWS Lambda fungsi, lihat [Model Pemrograman](https://docs.aws.amazon.com/lambda/latest/dg/programming-model-v2.html) di *Panduan AWS Lambda Pengembang*.

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

AWS Config akan memanggil fungsi seperti contoh berikut ketika mendeteksi perubahan konfigurasi untuk sumber daya yang berada dalam cakupan aturan khusus.

Jika Anda menggunakan AWS Config konsol untuk membuat aturan yang terkait dengan fungsi seperti contoh ini, pilih **Perubahan konfigurasi** sebagai jenis pemicu. Jika Anda menggunakan AWS Config API atau AWS CLI untuk membuat aturan, tetapkan `MessageType` atribut ke `ConfigurationItemChangeNotification` dan`OversizedConfigurationItemChangeNotification`. Pengaturan ini memungkinkan aturan Anda dipicu setiap kali AWS Config menghasilkan item konfigurasi atau item konfigurasi yang terlalu besar sebagai akibat dari perubahan sumber daya.

```
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'])
```

**Operasi Fungsi**

Fungsi melakukan operasi berikut saat runtime:

1. Fungsi berjalan ketika AWS Lambda melewati `event` objek ke `handler` fungsi. Dalam contoh ini, fungsi menerima `callback` parameter opsional, yang digunakan untuk mengembalikan informasi ke pemanggil. AWS Lambda juga melewati `context` objek, yang berisi informasi dan metode yang dapat digunakan fungsi saat berjalan. Perhatikan bahwa dalam versi Lambda yang lebih baru, konteks tidak lagi digunakan.

1. Fungsi memeriksa apakah `messageType` untuk acara tersebut adalah item konfigurasi atau item konfigurasi besar, dan kemudian mengembalikan item konfigurasi. 

1. Handler memanggil `isApplicable` fungsi untuk menentukan apakah sumber daya telah dihapus.
**catatan**  
Aturan pelaporan sumber daya yang dihapus harus mengembalikan hasil evaluasi untuk menghindari evaluasi aturan yang tidak perlu. `NOT_APPLICABLE`

1. Handler memanggil `evaluateChangeNotificationCompliance` fungsi dan meneruskan `configurationItem` dan `ruleParameters` objek yang AWS Config diterbitkan dalam acara tersebut.

   Fungsi pertama mengevaluasi apakah sumber daya adalah instans EC2. Jika sumber daya bukan instans EC2, fungsi mengembalikan nilai kepatuhan. `NOT_APPLICABLE` 

   Fungsi kemudian mengevaluasi apakah `instanceType` atribut dalam item konfigurasi sama dengan nilai `desiredInstanceType` parameter. Jika nilainya sama, fungsi kembali`COMPLIANT`. Jika nilainya tidak sama, fungsi kembali`NON_COMPLIANT`.

1. Handler bersiap untuk mengirim hasil evaluasi AWS Config dengan menginisialisasi objek. `putEvaluationsRequest` Objek ini mencakup `Evaluations` parameter, yang mengidentifikasi hasil kepatuhan, jenis sumber daya, dan ID sumber daya yang dievaluasi. `putEvaluationsRequest`Objek juga menyertakan token hasil dari acara, yang mengidentifikasi aturan dan acara untuk AWS Config. 

1. Handler mengirimkan hasil evaluasi AWS Config dengan meneruskan objek ke `putEvaluations` metode `config` klien.

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

AWS Config akan memanggil fungsi seperti contoh berikut untuk evaluasi berkala. Evaluasi periodik terjadi pada frekuensi yang Anda tentukan saat Anda menentukan aturan di AWS Config.

Jika Anda menggunakan AWS Config konsol untuk membuat aturan yang terkait dengan fungsi seperti contoh ini, pilih **Periodik** sebagai jenis pemicu. Jika Anda menggunakan AWS Config API atau AWS CLI membuat aturan, setel `MessageType` atribut ke`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'])
```

**Operasi Fungsi**

Fungsi melakukan operasi berikut saat runtime:

1. Fungsi berjalan ketika AWS Lambda melewati `event` objek ke `handler` fungsi. Dalam contoh ini, fungsi menerima `callback` parameter opsional, yang digunakan untuk mengembalikan informasi ke pemanggil. AWS Lambda juga melewati `context` objek, yang berisi informasi dan metode yang dapat digunakan fungsi saat berjalan. Perhatikan bahwa dalam versi Lambda yang lebih baru, konteks tidak lagi digunakan.

1. Untuk menghitung sumber daya dari tipe yang ditentukan, handler memanggil `countResourceTypes` fungsi, dan melewati `applicableResourceType` parameter yang diterimanya dari acara tersebut. `countResourceTypes`Fungsi ini memanggil `listDiscoveredResources` metode `config` klien, yang mengembalikan daftar pengidentifikasi untuk sumber daya yang berlaku. Fungsi ini menggunakan panjang daftar ini untuk menentukan jumlah sumber daya yang berlaku, dan mengembalikan hitungan ini ke handler.

1. Handler bersiap untuk mengirim hasil evaluasi AWS Config dengan menginisialisasi objek. `putEvaluationsRequest` Objek ini mencakup `Evaluations` parameter, yang mengidentifikasi hasil kepatuhan dan Akun AWS yang diterbitkan dalam acara tersebut. Anda dapat menggunakan `Evaluations` parameter untuk menerapkan hasilnya ke jenis sumber daya apa pun yang didukung oleh AWS Config. `putEvaluationsRequest`Objek juga menyertakan token hasil dari acara, yang mengidentifikasi aturan dan acara untuk AWS Config.

1. Di dalam `putEvaluationsRequest` objek, handler memanggil `evaluateCompliance` fungsi. Fungsi ini menguji apakah jumlah sumber daya yang berlaku melebihi maksimum yang ditetapkan ke `maxCount` parameter, yang disediakan oleh acara. Jika jumlah sumber daya melebihi maksimum, fungsi kembali`NON_COMPLIANT`. Jika jumlah sumber daya tidak melebihi maksimum, fungsi kembali`COMPLIANT`.

1. Handler mengirimkan hasil evaluasi AWS Config dengan meneruskan objek ke `putEvaluations` metode `config` klien.

------

## Contoh Acara untuk AWS Config Aturan
<a name="evaluate-config_develop-rules_example-events"></a>

Ketika pemicu aturan terjadi, AWS Config memanggil AWS Lambda fungsi aturan dengan menerbitkan peristiwa. Kemudian AWS Lambda mengeksekusi fungsi dengan meneruskan event ke handler fungsi.

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

AWS Config menerbitkan peristiwa ketika mendeteksi perubahan konfigurasi untuk sumber daya yang berada dalam lingkup aturan. Contoh peristiwa berikut menunjukkan bahwa aturan dipicu oleh perubahan konfigurasi untuk instans 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 ]

Beberapa perubahan sumber daya menghasilkan item konfigurasi yang terlalu besar. Contoh peristiwa berikut menunjukkan bahwa aturan dipicu oleh perubahan konfigurasi yang terlalu besar untuk instans 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 menerbitkan acara saat mengevaluasi sumber daya Anda pada frekuensi yang Anda tentukan (seperti setiap 24 jam). Contoh peristiwa berikut menunjukkan bahwa aturan dipicu oleh frekuensi periodik. 

```
{
    "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"
}
```

------

### Atribut Acara
<a name="w2aac20c19c20c13b1b7"></a>

Objek JSON untuk AWS Config acara berisi atribut berikut:

`invokingEvent`  
Peristiwa yang memicu evaluasi untuk suatu aturan. Jika acara dipublikasikan sebagai respons terhadap perubahan konfigurasi sumber daya, nilai untuk atribut ini adalah string yang berisi JSON `configurationItem` atau `configurationItemSummary` (untuk item konfigurasi berukuran besar). Item konfigurasi mewakili status sumber daya pada saat AWS Config mendeteksi perubahan. Untuk contoh item konfigurasi, lihat output yang dihasilkan oleh `get-resource-config-history` AWS CLI perintah di[Melihat Riwayat Konfigurasi](view-manage-resource-console.md#get-config-history-cli).  
Jika acara diterbitkan untuk evaluasi berkala, nilainya adalah string yang berisi objek JSON. Objek tersebut mencakup informasi tentang evaluasi yang dipicu.  
Untuk setiap jenis acara, fungsi harus mengurai string dengan parser JSON untuk dapat mengevaluasi isinya, seperti yang ditunjukkan pada contoh Node.js berikut:  

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

`ruleParameters`  
Pasangan kunci/nilai yang diproses fungsi sebagai bagian dari logika evaluasinya. Anda menentukan parameter saat menggunakan AWS Config konsol untuk membuat aturan Lambda Kustom. Anda juga dapat menentukan parameter dengan `InputParameters` atribut dalam permintaan `PutConfigRule` AWS Config API atau `put-config-rule` AWS CLI perintah.  
Kode JSON untuk parameter terkandung dalam string, sehingga fungsi harus mengurai string dengan parser JSON untuk dapat mengevaluasi isinya, seperti yang ditunjukkan dalam contoh Node.js berikut:  

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

`resultToken`  
Token yang harus diteruskan oleh fungsi AWS Config dengan `PutEvaluations` panggilan.

`eventLeftScope`  
Nilai Boolean yang menunjukkan apakah AWS sumber daya yang akan dievaluasi telah dihapus dari lingkup aturan. Jika nilainya`true`, fungsi menunjukkan bahwa evaluasi dapat diabaikan dengan meneruskan `NOT_APPLICABLE` sebagai nilai untuk `ComplianceType` atribut dalam `PutEvaluations` panggilan.

`executionRoleArn`  
ARN dari peran IAM yang ditugaskan untuk. AWS Config

`configRuleArn`  
ARN yang AWS Config ditugaskan untuk aturan.

`configRuleName`  
Nama yang Anda tetapkan untuk aturan yang menyebabkan AWS Config untuk mempublikasikan acara dan memanggil fungsi.

`configRuleId`  
ID yang AWS Config ditetapkan untuk aturan.

`accountId`  
ID Akun AWS yang memiliki aturan.

`version`  
Nomor versi yang ditetapkan oleh AWS. Versi akan bertambah jika AWS menambahkan atribut ke AWS Config acara. Jika fungsi memerlukan atribut yang hanya dalam peristiwa yang cocok atau melebihi versi tertentu, maka fungsi tersebut dapat memeriksa nilai atribut ini.  
Versi saat ini untuk AWS Config acara adalah 1.0.