すべてのプロダクト
Search
ドキュメントセンター

Cloud Config:カスタム関数ルールの定義と実行

最終更新日:Jan 18, 2025

Cloud Config では、Function Compute に基づいてカスタムルールを作成し、関連リソースを監査できます。ルールがトリガーされると、Cloud Config は対応するルール関数を呼び出して関連リソースを評価し、リソースのコンプライアンス評価結果を返します。このトピックでは、カスタム関数ルール入力パラメーターについて説明し、関連する Python コード例を提供します。

カスタム関数ルールの概要

カスタム関数ルールとは、Cloud Config が Function Compute の関数を呼び出すことによって監査を実行するために使用するカスタムルールです。

シナリオ

Cloud Config の定義済みルールテンプレートと条件ルールではリソースコンプライアンス検出の要件を満たせない場合、複雑なシナリオでリソースを監査するための関数コードを記述できます。詳細については、「alibabacloud-config-samples」をご参照ください。

仕組み

次の図は、Function Compute に基づいて作成されたカスタムルールの仕組みを示しています。

image.png

Function Compute に基づいて作成されたカスタムルールの仕組みを以下に示します。

  1. Function Compute で関数が作成されます。

  2. Cloud Config で Function Compute に基づいてカスタムルールが作成され、Cloud Config が自動的に評価をトリガーします。

    説明

    ルールを作成すると、Cloud Config は自動的に評価をトリガーします。

  3. Cloud Config は、サービスロール AliyunServiceRoleForConfig を使用して GetFunction 操作と InvokeFunction 操作を呼び出す権限を取得します。

  4. Cloud Config は InvokeFunction 操作を呼び出して関数を実行し、リソース構成とルール情報を取得します。

  5. 関数はリソースを評価します。

  6. Function Compute は PutEvaluations 操作を呼び出すことによって、リソース評価結果を Cloud Config に返します。

    Cloud Config はリソース評価結果を保存し、Cloud Config コンソールに結果を表示します。Cloud Config コンソールで結果を表示できます。また、非準拠リソースを修復したり、対応するクラウドサービスにリソースデータを配信するように設定したりすることもできます。

関数コード

ルールは、ルール関数に格納されている論理判断コードのスニペットです。Cloud Config はルールに基づいてリソースを監査します。ルールがトリガーされると、Cloud Config は対応するルール関数を呼び出して関連リソースを評価します。この例では、カスタムルール関数のコードには次の主要な関数が含まれています。

  • handler

    handler 関数は、ルールがトリガーされたときに呼び出されるエントリ関数です。Function Compute コンソールで関数を作成するときは、ハンドラ関数を構成する必要があります。詳細については、「ハンドラ」をご参照ください。

    説明

    Cloud Config はイベントハンドラのみをサポートしています。詳細については、「イベントハンドラ」をご参照ください。

  • put_evaluations

    PutEvaluations 操作を呼び出すことによって、リソース評価結果が Cloud Config に返されます。

次の Python コード例を使用してルールを作成できます。


# # !/usr/bin/env python
# # -*- encoding: utf-8 -*-
import json
import logging

from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest


logger = logging.getLogger()
# The compliance evaluation types of resources. 
COMPLIANCE_TYPE_COMPLIANT = 'COMPLIANT'
COMPLIANCE_TYPE_NON_COMPLIANT = 'NON_COMPLIANT'
COMPLIANCE_TYPE_NOT_APPLICABLE = 'NOT_APPLICABLE'
# The types of pushed resource configurations. 
CONFIGURATION_TYPE_COMMON = 'COMMON'
CONFIGURATION_TYPE_OVERSIZE = 'OVERSIZE'
CONFIGURATION_TYPE_NONE = 'NONE'


# The entry function that orchestrates and processes business logic. 
def handler(event, context):
    """
    Process an event.
    :param event: the event.
    :param context: the context.
    :return: the compliance evaluation result.
    """
    # Check whether the event is valid. You can directly copy the following sample code. 
    evt = validate_event(event)
    if not evt:
        return None
    creds = context.credentials
    rule_parameters = evt.get('ruleParameters')
    result_token = evt.get('resultToken')
    invoking_event = evt.get('invokingEvent')
    ordering_timestamp = evt.get('orderingTimestamp')

    # Obtain the resource configurations. A rule must be set to be triggered upon configuration changes. After a rule that you create is triggered or you manually trigger a rule, Cloud Config invokes the rule function to evaluate associated resources one by one. If the configurations of a resource change, Cloud Config automatically invokes the corresponding rule function to evaluate the resource. 
    configuration_item = invoking_event.get('configurationItem')
    account_id = configuration_item.get('accountId')
    resource_id = configuration_item.get('resourceId')
    resource_type = configuration_item.get('resourceType')
    region_id = configuration_item.get('regionId')

    # Check whether the size of the resource configurations that you want to push is no less than 100 KB. If yes, the GetDiscoveredResource operation is called to query the resource details. 
    configuration_type = invoking_event.get('configurationType')
    if configuration_type and configuration_type == CONFIGURATION_TYPE_OVERSIZE:
        resource_result = get_discovered_resource(creds, resource_id, resource_type, region_id)
        resource_json = json.loads(resource_result)
        configuration_item["configuration"] = resource_json["DiscoveredResourceDetail"]["Configuration"]

    # Evaluate resources. You must implement the evaluation logic based on your business scenario. The following code is only for reference: 
    compliance_type, annotation = evaluate_configuration_item(
        rule_parameters, configuration_item)

    # Specify the compliance evaluation result. The result must use the syntax shown in the following sample: 
    evaluations = [
        {
            'accountId': account_id,
            'complianceResourceId': resource_id,
            'complianceResourceType': resource_type,
            'complianceRegionId': region_id,
            'orderingTimestamp': ordering_timestamp,
            'complianceType': compliance_type,
            'annotation': annotation
        }
    ]

    # Return the compliance evaluation result and write it to Cloud Config. You can directly copy the following sample code. 
    put_evaluations(creds, result_token, evaluations)
    return evaluations


# Evaluate a resource based on the rule information and resource configurations. You must implement the evaluation logic based on the business scenario. The following code is for reference only: 
def evaluate_configuration_item(rule_parameters, configuration_item):
    """
    Evaluate a resource.
    :param rule_parameters: the rule information.
    :param configuration_item: the resource configurations.
    :return: the compliance evaluation result.
    """
    # Initialize the return values.
    compliance_type = COMPLIANCE_TYPE_NON_COMPLIANT
    annotation = None

    # Obtain the complete resource configurations.
    full_configuration = configuration_item['configuration']
    if not full_configuration:
        annotation = 'Configuration is empty.'
        return compliance_type, annotation

    # Convert the configurations to a JSON object.
    configuration = parse_json(full_configuration)
    if not configuration:
        annotation = 'Configuration:{} is invalid.'.format(full_configuration)
        return compliance_type, annotation
    return compliance_type, annotation


def validate_event(event):
    """
    Check whether an event is valid.
    :param event: the event.
    :return: the JSON object.
    """
    if not event:
        logger.error('Event is empty.')
    evt = parse_json(event)
    logger.info('Loading event: %s .' % evt)

    if 'resultToken' not in evt:
        logger.error('ResultToken is empty.')
        return None
    if 'ruleParameters' not in evt:
        logger.error('RuleParameters is empty.')
        return None
    if 'invokingEvent' not in evt:
        logger.error('InvokingEvent is empty.')
        return None
    return evt


def parse_json(content):
    """
    Convert a JSON string into a JSON object.
    :param content: the JSON string.
    :return: the JSON object.
    """
    try:
        return json.loads(content)
    except Exception as e:
        logger.error('Parse content:{} to json error:{}.'.format(content, e))
        return None


# Return the compliance evaluation result and write it to Cloud Config. You can directly copy the following sample code. 
def put_evaluations(creds, result_token, evaluations):
    """
    Call the Cloud Config API to return the compliance evaluation result and write the result to Cloud Config. 
    :param context: the Function Compute context.
    :param result_token: the result token.
    :param evaluations: the compliance evaluation result.
    :return: None
    """
    # Your account must be assigned a service role of Function Compute to which the AliyunConfigFullAccess policy is attached. 
    client = AcsClient(creds.access_key_id, creds.access_key_secret, region_id='ap-southeast-1')

    # Create a request and specify the parameters. In this example, the domain parameter is set to config.ap-southeast-1.aliyuncs.com. 
    request = CommonRequest()
    request.set_domain('config.ap-southeast-1.aliyuncs.com')
    request.set_version('2019-01-08')
    request.set_action_name('PutEvaluations')
    request.add_body_params('ResultToken', result_token)
    request.add_body_params('Evaluations', evaluations)
    request.add_body_params('SecurityToken', creds.security_token)
    request.set_method('POST')

    try:
        response = client.do_action_with_exception(request)
        logger.info('PutEvaluations with request: {}, response: {}.'.format(request, response))
    except Exception as e:
        logger.error('PutEvaluations error: %s' % e)


# Obtain the details of a resource. You can copy the following sample code based on your business scenario. 
def get_discovered_resource(creds, resource_id, resource_type, region_id):
    """
    Call an API operation to obtain the details of a resource.
    :param context: the Function Compute context.
    :param resource_id: the resource ID.
    :param resource_type: the resource type.
    :param region_id: the ID of the region in which the resource resides.
    :return: the resource details.
    """
    # Your account must be assigned a service role of Function Compute to which the AliyunConfigFullAccess policy is attached. 
    client = AcsClient(creds.access_key_id, creds.access_key_secret, region_id='ap-southeast-1')

    request = CommonRequest()
    request.set_domain('config.ap-southeast-1.aliyuncs.com')
    request.set_version('2020-09-07')
    request.set_action_name('GetDiscoveredResource')
    request.add_query_param('ResourceId', resource_id)
    request.add_query_param('ResourceType', resource_type)
    request.add_query_param('Region', region_id)
    request.add_query_param('SecurityToken', creds.security_token)
    request.set_method('GET')

    try:
        response = client.do_action_with_exception(request)
        resource_result = str(response, encoding='utf-8')
        return resource_result
    except Exception as e:
        logger.error('GetDiscoveredResource error: %s' % e)
重要

構成するルールのconfiguration パラメータで指定されたリソース構成のコアパラメータ名を取得するには、Cloud Config コンソールでコードを確認することをお勧めします。詳細については、「リソース情報の表示」の「手順 6」をご参照ください。

入力パラメータ

Function Compute のルール関数の入力パラメータは、リソース構成とルール情報の 2 つのカテゴリに分類できます。イベントメッセージでは、configurationItem フィールドにリソース構成の入力パラメータが格納され、ruleParameters フィールドにルール関数の入力パラメータが格納されます。Cloud Config が Function Compute に送信するコンテンツは、ルールの [トリガータイプ] によって異なります。

説明

Function Compute からルール関数の入力パラメータを取得する方法の詳細については、「ロギングの構成」をご参照ください。

  • [トリガー] パラメータが [定期実行] に設定されている場合、Cloud Config はリソース構成を Function Compute に送信しません。

    新しいルールが初めて実行されたとき、ルールが定期的に自動実行されたとき、またはルールが手動で実行されたとき、Cloud Config はリソース構成を含まないレコードのみを Function Compute に送信します。次のサンプルコードは JSON の例を示しています。

    {
        "orderingTimestamp": 1716365226714,
        "invokingEvent": {
            "accountId": 120886317861****,
            "messageType": "ScheduledNotification",
            "notificationCreationTimestamp": 1716365226714,
            "configurationType": "NONE"
        },
        "ruleParameters": {
            "CpuCount": "2"
        },
        "resultToken": "HLQr3BZx/C+DLjwudFcYdXxZFPF2HnGqlg1uHceZ5kDEFeQF2K5LZGofyhn+GE4NP5VgkwANUH3qcdeSjWwODk1ymtmLWLzFV4JForVWYIKdbwwhbDBOgVwF7Ov9c3uVCNz/KpxNElwhTzMkZB95U1vmLs4vUYXuB/Txw4jiCYBYZZnVumhwXWswTLvAhIe5Y451FckObyM3I47AaB+4KtDW3I5q8O+Kx7eSYkqqGTawmJEYjvWXz9CHHMLFtNYyJX54a35mpVdxFSvgeXYDJTStxqb+d9UH/162fZh7T78OHxpQZgl8bcXzZhml****"
    }
  • [トリガー] パラメータが [構成の変更] に設定されている場合、Cloud Config はリソース構成を Function Compute に送信します。

    新しいルールが初めて実行されたとき、ルールが定期的に自動実行されたとき、またはルールが手動で実行されたとき、Cloud Config はリソース構成を 1 つずつ Function Compute に送信します。新しいリソースが追加されたとき、または既存のリソースが変更されたとき、Cloud Config は変更された単一のリソースの構成のみを Function Compute に送信します。次のサンプルコードは JSON の例を示しています。

    {
        "orderingTimestamp":1695786337959,
        "invokingEvent":{
            "accountId":120886317861****,
            "messageType":"Manual",
            "notificationCreationTimestamp":1695786337959,
            "configurationType":"COMMON",
            "configurationItem":{
                "accountId":120886317861****,
                "arn":"acs:ecs:ap-southeast-1:120886317861****:instance/i-t4n0vr6x7v54jdbu****",
                "availabilityZone":"ap-southeast-1a",
                "regionId":"ap-southeast-1",
                "configuration":"{\\"ResourceGroupId\\":\\"\\",\\"Memory\\":4096,\\"InstanceChargeType\\":\\"PostPaid\\",\\"Cpu\\":2,\\"OSName\\":\\"Alibaba Cloud Linux  3.2104 LTS 64\xe4\xbd\x8d\\",\\"InstanceNetworkType\\":\\"vpc\\",\\"InnerIpAddress\\":{\\"IpAddress\\":[]},\\"ExpiredTime\\":\\"2099-12-31T15:59Z\\",\\"ImageId\\":\\"aliyun_3_x64_20G_alibase_20230727.vhd\\",\\"EipAddress\\":{\\"AllocationId\\":\\"\\",\\"IpAddress\\":\\"\\",\\"InternetChargeType\\":\\"\\"},\\"ImageOptions\\":{},\\"VlanId\\":\\"\\",\\"HostName\\":\\"iZt4n0vr6x7v54jdbuk****\\",\\"Status\\":\\"Running\\",\\"HibernationOptions\\":{\\"Configured\\":false},\\"MetadataOptions\\":{\\"HttpTokens\\":\\"\\",\\"HttpEndpoint\\":\\"\\"},\\"InstanceId\\":\\"i-t4n0vr6x7v54jdbu****\\",\\"StoppedMode\\":\\"Not-applicable\\",\\"CpuOptions\\":{\\"ThreadsPerCore\\":2,\\"Numa\\":\\"ON\\",\\"CoreCount\\":1},\\"StartTime\\":\\"2023-08-18T09:02Z\\",\\"DeletionProtection\\":false,\\"VpcAttributes\\":{\\"PrivateIpAddress\\":{\\"IpAddress\\":[\\"192.168.XX.XX\\"]},\\"VpcId\\":\\"vpc-t4nmwd0l9a7aj09yr****\\",\\"VSwitchId\\":\\"vsw-t4njclm0dlz2szayi****\\",\\"NatIpAddress\\":\\"\\"},\\"SecurityGroupIds\\":{\\"SecurityGroupId\\":[\\"sg-t4n5pulxj2lvechw****\\"]},\\"InternetChargeType\\":\\"PayByTraffic\\",\\"InstanceName\\":\\"zs-test-peer****\\",\\"DeploymentSetId\\":\\"\\",\\"InternetMaxBandwidthOut\\":0,\\"SerialNumber\\":\\"8c3fadf7-2ea1-4486-84ce-7784aeb7****\\",\\"OSType\\":\\"linux\\",\\"CreationTime\\":\\"2023-08-18T09:02Z\\",\\"AutoReleaseTime\\":\\"\\",\\"Description\\":\\"\\",\\"InstanceTypeFamily\\":\\"ecs.c7\\",\\"DedicatedInstanceAttribute\\":{\\"Tenancy\\":\\"\\",\\"Affinity\\":\\"\\"},\\"PublicIpAddress\\":{\\"IpAddress\\":[]},\\"GPUSpec\\":\\"\\",\\"NetworkInterfaces\\":{\\"NetworkInterface\\":[{\\"Type\\":\\"Primary\\",\\"PrimaryIpAddress\\":\\"192.168.XX.XX\\",\\"MacAddress\\":\\"00:16:3e:04:XX:XX\\",\\"NetworkInterfaceId\\":\\"eni-t4n16tmnpp794y1o****\\",\\"PrivateIpSets\\":{\\"PrivateIpSet\\":[{\\"PrivateIpAddress\\":\\"192.168.XX.XX\\",\\"Primary\\":true}]}}]},\\"SpotPriceLimit\\":0.0,\\"SaleCycle\\":\\"\\",\\"DeviceAvailable\\":true,\\"InstanceType\\":\\"ecs.c7.large\\",\\"OSNameEn\\":\\"Alibaba Cloud Linux  3.2104 LTS 64 bit\\",\\"SpotStrategy\\":\\"NoSpot\\",\\"IoOptimized\\":true,\\"ZoneId\\":\\"ap-southeast-1a\\",\\"ClusterId\\":\\"\\",\\"EcsCapacityReservationAttr\\":{\\"CapacityReservationPreference\\":\\"\\",\\"CapacityReservationId\\":\\"\\"},\\"DedicatedHostAttribute\\":{\\"DedicatedHostId\\":\\"\\",\\"DedicatedHostName\\":\\"\\",\\"DedicatedHostClusterId\\":\\"\\"},\\"GPUAmount\\":0,\\"OperationLocks\\":{\\"LockReason\\":[]},\\"InternetMaxBandwidthIn\\":-1,\\"Recyclable\\":false,\\"RegionId\\":\\"ap-southeast-1\\",\\"CreditSpecification\\":\\"\\"}",
                "captureTime":1695786337959,
                "resourceCreateTime":1692349320000,
                "resourceId":"i-t4n0vr6x7v54jdbu****",
                "resourceName":"zs-test-peer****",
                "resourceGroupId":"rg-acfmw3ty5y7****",
                "resourceType":"ACS::ECS::Instance",
                "tags":"{}"
            }
        },
        "ruleParameters":{
            "CpuCount":"2"
        },
        "resultToken":"HLQr3BZx/C+DLjwudFcYdXxZFPF2HnGqlg1uHceZ5kDEFeQF2K5LZGofyhn+GE4NP5VgkwANUH3qcdeSjWwODk1ymtmLWLzFV4JForVWYIKdbwwhbDBOgVwF7Ov9c3uVCNz/KpxNElwhTzMkZB95U1vmLs4vUYXuB/Txw4jiCYBYZZnVumhwXWswTLvAhIe5Y451FckObyM3I47AaB+4KtDW3I5q8O+Kx7eSYkqqGTawmJEYjvWXz9CHHMLFtNYyJX54a35mpVdxFSvgeXYDJTStxqb+d9UH/162fZh7T78OHxpQZgl8bcXzZhml****"
    }

    Cloud Config が送信するリソース構成ファイルの値が 100 KB 以上の場合、Cloud Config はリソース構成ファイルの configuration フィールドを除く、リソースの概要情報のみを送信します。次のサンプルコードは JSON の例を示しています。

    説明

    GetDiscoveredResource 操作を呼び出すことで、完全なリソース構成を取得できます。

    {
        "orderingTimestamp":1695786337959,
        "invokingEvent":{
            "accountId":120886317861****,
            "messageType":"Manual",
            "notificationCreationTimestamp":1695786337959,
            "configurationType":"OVERSIZE",
            "configurationItem":{
                "accountId":120886317861****,
                "arn":"acs:ecs:ap-southeast-1:120886317861****:instance/i-t4n0vr6x7v54jdbu****",
                "availabilityZone":"ap-southeast-1a",
                "regionId":"ap-southeast-1",
                "captureTime":1695786337959,
                "resourceCreateTime":1692349320000,
                "resourceId":"i-t4n0vr6x7v54jdbu****",
                "resourceName":"zs-test-peer****",
                "resourceGroupId":"rg-acfmw3ty5y7****",
                "resourceType":"ACS::ECS::Instance",
                "tags":"{}"
            }
        },
        "ruleParameters":{
            "CpuCount":"2"
        },
        "resultToken":"HLQr3BZx/C+DLjwudFcYdXxZFPF2HnGqlg1uHceZ5kDEFeQF2K5LZGofyhn+GE4NP5VgkwANUH3qcdeSjWwODk1ymtmLWLzFV4JForVWYIKdbwwhbDBOgVwF7Ov9c3uVCNz/KpxNElwhTzMkZB95U1vmLs4vUYXuB/Txw4jiCYBYZZnVumhwXWswTLvAhIe5Y451FckObyM3I47AaB+4KtDW3I5q8O+Kx7eSYkqqGTawmJEYjvWXz9CHHMLFtNYyJX54a35mpVdxFSvgeXYDJTStxqb+d9UH/162fZh7T78OHxpQZgl8bcXzZhml****"
    }

次の表は、入力パラメータのタイプと主要なパラメータを示しています。

カテゴリ

パラメータ

説明

リソース構成

configurationItem

リソースの構成。次の構成が含まれます。リソースが属する Alibaba Cloud アカウントの ID、リソースの Alibaba Cloud Resource Name(ARN)、リソースが存在するゾーンの ID、リソースが存在するリージョンの ID、リソースの詳細構成、Cloud Config がリソース変更イベントを検出してログを生成したタイムスタンプ、リソースが作成されたタイムスタンプ、リソースステータス、リソース ID、リソース名、リソースタイプ、およびタグ。

configurationType

プッシュされた構成のタイプ。有効な値:

  • COMMON: configurationItem のサイズが 100 KB 未満の場合、リソース構成は想定どおりにプッシュされます。

  • OVERSIZE: configurationItem のサイズが 100 KB 以上の場合、GetDiscoveredResource 操作が呼び出され、リソースの詳細がクエリされます。

ルール情報

orderingTimestamp

評価実行の開始タイムスタンプ。

invokingEvent

呼び出しイベント。

accountId

呼び出しイベントのアカウント ID。

messageType

メッセータイプ。有効な値:

  • Manual: ルールは手動でトリガーされます。

  • ConfigurationItemChangeNotification: ルールは構成の変更によってトリガーされます。

  • ScheduledNotification: ルールは定期的にトリガーされます。

notificationCreationTimestamp

ルールがトリガーされたタイムスタンプ。

ruleParameters

カスタムルールの入力パラメータ。カスタムルールの入力パラメータの名前と期待値を指定する必要があります。

resultToken

Function Compute の結果トークン。