Lorsqu'une règle de fonction personnalisée est déclenchée, Cloud Config invoque la fonction associée dans Function Compute pour évaluer vos ressources et renvoyer un résultat de conformité. Cette rubrique décrit la structure du code de fonction et les paramètres d'entrée à l'aide d'un exemple Python.
Règle de fonction personnalisée
Une règle de fonction personnalisée utilise une fonction Function Compute pour définir et exécuter sa logique d'évaluation.
Scénarios
Si les règles gérées et les règles conditionnelles ne satisfont pas vos exigences de conformité, créez des fonctions personnalisées pour des évaluations complexes. Des scénarios supplémentaires et des exemples de code sont disponibles dans la bibliothèque d'exemples de règles de fonction personnalisée.
Mécanisme
La figure suivante illustre le flux d'exécution d'une règle de fonction personnalisée.

Étapes d'exécution :
Créez une fonction dans Function Compute.
-
Créez une règle personnalisée basée sur cette fonction dans Cloud Config. Une évaluation est automatiquement déclenchée.
RemarqueCloud Config déclenche automatiquement une évaluation après la création de la règle.
Cloud Config utilise son rôle lié au service (AliyunServiceRoleForConfig) pour obtenir les autorisations nécessaires aux opérations API GetFunction et InvokeFunction.
Cloud Config appelle l'opération API InvokeFunction pour exécuter la fonction et transmet l'élément de configuration ainsi que les informations de règle.
La fonction évalue la ressource.
-
La fonction appelle l'opération API PutEvaluations pour renvoyer le résultat de l'évaluation de conformité à Cloud Config.
Cloud Config enregistre et affiche le résultat dans la console. Vous pouvez ensuite corriger les ressources non conformes ou transmettre les données à d'autres services Alibaba Cloud.
Code de fonction
Une règle correspond à une logique d'évaluation stockée dans une fonction. Cloud Config invoque cette fonction lors de l'audit. Le code de fonction se compose de deux parties :
-
handlerLe
handlerest la fonction d'entrée invoquée lorsque la règle se déclenche. Spécifiez le gestionnaire lors de la création d'une fonction dans la console Function Compute. Consultez la rubrique Handlers.RemarqueCloud Config prend uniquement en charge les gestionnaires d'événements.
-
put_evaluationsCette fonction appelle l'opération API PutEvaluations pour soumettre le résultat de l'évaluation de conformité à Cloud Config.
Le code suivant fournit un exemple 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 type of a resource.
COMPLIANCE_TYPE_COMPLIANT = 'COMPLIANT'
COMPLIANCE_TYPE_NON_COMPLIANT = 'NON_COMPLIANT'
COMPLIANCE_TYPE_NOT_APPLICABLE = 'NOT_APPLICABLE'
# The delivery type of a resource configuration.
CONFIGURATION_TYPE_COMMON = 'COMMON'
CONFIGURATION_TYPE_OVERSIZE = 'OVERSIZE'
CONFIGURATION_TYPE_NONE = 'NONE'
# The entry function that orchestrates and processes the business logic.
def handler(event, context):
"""
The handler function.
:param event: The event.
:param context: The context.
:return: The evaluation result.
"""
# Validate the event. You can copy this code block.
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')
# The configuration of the resource. The trigger of the rule must be set to Configuration Change. When you create or manually run a rule, Cloud Config invokes the function to evaluate all resources one by one. If the configuration of a resource changes, Cloud Config automatically invokes the function to evaluate the resource based on the change information.
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 delivered resource configuration is greater than or equal to 100 KB. If it is, you must call the GetDiscoveredResource operation 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 the resource. You must implement the evaluation logic based on your business requirements. The following code is for reference only.
compliance_type, annotation = evaluate_configuration_item(
rule_parameters, configuration_item)
# Set the evaluation result. The format must comply with the following example.
evaluations = [
{
'accountId': account_id,
'complianceResourceId': resource_id,
'complianceResourceType': resource_type,
'complianceRegionId': region_id,
'orderingTimestamp': ordering_timestamp,
'complianceType': compliance_type,
'annotation': annotation
}
]
# Submit the evaluation result to Cloud Config. You can copy this code block.
put_evaluations(creds, result_token, evaluations)
return evaluations
# Evaluate the resource based on the rule information and resource configuration. You must implement the evaluation logic based on your business requirements. The following code is for reference only.
def evaluate_configuration_item(rule_parameters, configuration_item):
"""
The evaluation logic.
:param rule_parameters: The rule information.
:param configuration_item: The resource configuration.
:return: The compliance type.
"""
# Initialize the return value.
compliance_type = COMPLIANCE_TYPE_NON_COMPLIANT
annotation = None
# Obtain the full resource configuration.
full_configuration = configuration_item['configuration']
if not full_configuration:
annotation = 'Configuration is empty.'
return compliance_type, annotation
# Convert the configuration to the JSON format.
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):
"""
Validate the event.
:param event: The event.
:return: A 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 data to the JSON format.
:param content: A JSON string.
:return: A JSON object.
"""
try:
return json.loads(content)
except Exception as e:
logger.error('Parse content:{} to json error:{}.'.format(content, e))
return None
# Submit the evaluation result to Cloud Config. You can copy this code block.
def put_evaluations(creds, result_token, evaluations):
"""
Call an API operation to return and write the evaluation result.
:param creds: The credentials of the function.
:param result_token: The result token.
:param evaluations: The evaluation results.
:return: None
"""
# The service-linked role for Function Compute must have the AliyunConfigFullAccess policy attached.
client = AcsClient(creds.access_key_id, creds.access_key_secret, region_id='ap-southeast-1')
# Create a request and set its parameters. The domain name is 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)
# Retrieve the full resource details. You can copy this code block.
def get_discovered_resource(creds, resource_id, resource_type, region_id):
"""
Call an API operation to obtain the resource configuration details.
:param creds: The credentials of the function.
: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.
"""
# The service-linked role for Function Compute must have the AliyunConfigFullAccess policy 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)
Consultez le champ configuration de l'élément de configuration dans la console Cloud Config pour identifier les noms de paramètres de votre règle. Reportez-vous à l'étape Étape 6 de la rubrique View resource information.
Entrées de fonction
Les paramètres d'entrée de fonction se composent d'un élément de configuration et d'informations de règle. Le contenu envoyé à Function Compute varie selon le Trigger de la règle.
Pour obtenir les paramètres d'entrée de fonction dans Function Compute, consultez la section View invocation logs.
-
Si le Trigger de la règle est défini sur Periodic uniquement, Cloud Config n'envoie pas d'éléments de configuration à Function Compute.
Lors de la première exécution d'une règle, d'une exécution planifiée ou manuelle, Cloud Config envoie un seul enregistrement sans élément de configuration. Exemple :
{ "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****" } -
Si le Trigger de la règle inclut Configuration Changes, Cloud Config envoie l'élément de configuration à Function Compute.
Lors de la première exécution, d'une exécution planifiée ou manuelle, Cloud Config envoie les éléments de configuration un par un. Lorsqu'une ressource est créée ou modifiée, Cloud Config envoie uniquement l'élément de configuration concerné. Exemple :
{ "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****" }Si un élément de configuration atteint ou dépasse 100 Ko, Cloud Config envoie uniquement un résumé de ressource sans le champ
configuration. Exemple :RemarquePour obtenir la configuration complète de la ressource, appelez l'opération API 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****" }
Le tableau suivant répertorie les principaux paramètres d'entrée de fonction par catégorie.
|
Catégorie |
Paramètre |
Description |
|
Élément de configuration |
configurationItem |
Objet JSON représentant l'état de configuration de la ressource à un instant donné, incluant l'ID de ressource, le type, la région, l'horodatage de création, les tags et la configuration complète. |
|
configurationType |
Type de livraison de l'élément de configuration. Valeurs possibles :
|
|
|
Informations de règle |
orderingTimestamp |
Horodatage du début de l'évaluation. |
|
invokingEvent |
Événement d'appel. |
|
|
accountId |
ID du compte associé à l'événement d'appel. |
|
|
messageType |
Type de message. Valeurs possibles :
|
|
|
notificationCreationTimestamp |
Horodatage du déclenchement de la règle. |
|
|
ruleParameters |
Paramètres d'entrée de la règle personnalisée, incluant les noms de paramètres et les valeurs attendues. |
|
|
resultToken |
Jeton requis lors de la soumission des résultats d'évaluation via l'opération API PutEvaluations. |