當您基于函數計算新建自定義規則時,如果規則被觸發,配置審計會運行規則對應的函數對資源進行檢測,并提供資源合規評估結果。本文通過Python示例為您介紹函數規則的函數代碼和函數入參。
什么是自定義函數規則
自定義函數規則是配置審計通過函數計算服務的函數來承載規則代碼的自定義規則。
應用場景
當配置審計預置的規則模板和條件規則均不能滿足檢測資源合規性的需求時,您可以通過編寫函數代碼,完成復雜場景的合規檢測。更多場景和代碼示例,請參見自定義函數規則示例庫。
運行原理
基于函數計算創建自定義規則的運行原理如下圖所示。
基于函數計算創建自定義規則運行原理的說明如下:
在函數計算中創建函數。
在配置審計中基于函數計算創建自定義規則,并自動觸發評估。
說明當您創建規則后,配置審計會自動觸發一次評估。
配置審計通過配置審計服務關聯角色(AliyunServiceRoleForConfig)獲取GetFunction和InvokeFunction接口的權限。
配置審計調用InvokeFunction接口執行函數,獲取資源配置和規則信息。
函數執行對資源的評估。
函數計算通過PutEvaluations接口將資源評估結果返回給配置審計。
配置審計對資源評估結果進行保存并在控制臺展示,以便查看。您還可以對不合規資源進行修正,或設置將資源數據投遞到對應云服務。
函數代碼
規則的本質是一段邏輯判斷代碼,這段代碼存放在新建的函數中。在配置審計對資源的持續審計中,通過觸發該函數的執行來實現對資源的評估。本函數代碼主要有兩個函數,具體如下:
handler
handler
為入口函數,即自定義規則觸發時調用的函數。當您在函數計算控制臺上新建函數時,需要設置Handler。關于Handler的更多信息,請參見請求處理程序(Handler)。說明配置審計僅支持事件請求處理程序(Event Handler)。
put_evaluations
通過PutEvaluations接口將資源評估結果返回給配置審計。
函數代碼的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()
# 資源的合規類型。
COMPLIANCE_TYPE_COMPLIANT = 'COMPLIANT'
COMPLIANCE_TYPE_NON_COMPLIANT = 'NON_COMPLIANT'
COMPLIANCE_TYPE_NOT_APPLICABLE = 'NOT_APPLICABLE'
# 資源配置的推送類型。
CONFIGURATION_TYPE_COMMON = 'COMMON'
CONFIGURATION_TYPE_OVERSIZE = 'OVERSIZE'
CONFIGURATION_TYPE_NONE = 'NONE'
# 入口函數,完成業務邏輯編排和處理。
def handler(event, context):
"""
處理函數
:param event:事件
:param context:上下文
:return:評估結果
"""
# 校驗Event,代碼可直接復制。
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')
# 資源的配置信息。規則觸發機制需要設置為配置變更。當您新建規則或手動執行規則時,配置審計會逐個調用函數觸發對所有資源的評估。如果資源配置發生變更,配置審計根據變更的資源信息自動調用函數觸發一次資源評估。
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')
# 判斷當前推送的資源配置信息是否大于等于配置(100 KB),如果是,則需要調用GetDiscoveredResource查詢資源詳情。
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"]
# 對資源進行評估,需要根據實際業務自行實現評估邏輯,以下代碼僅供參考。
compliance_type, annotation = evaluate_configuration_item(
rule_parameters, configuration_item)
# 設置評估結果,格式需符合以下示例要求。
evaluations = [
{
'accountId': account_id,
'complianceResourceId': resource_id,
'complianceResourceType': resource_type,
'complianceRegionId': region_id,
'orderingTimestamp': ordering_timestamp,
'complianceType': compliance_type,
'annotation': annotation
}
]
# 返回評估結果并寫入配置審計,代碼可直接復制。
put_evaluations(creds, result_token, evaluations)
return evaluations
# 根據規則信息和資源配置進行評估。需要根據實際業務自行實現評估邏輯,以下代碼僅供參考。
def evaluate_configuration_item(rule_parameters, configuration_item):
"""
評估邏輯
:param rule_parameters:規則信息
:param configuration_item:資源配置
:return:評估類型
"""
# 初始化返回值
compliance_type = COMPLIANCE_TYPE_NON_COMPLIANT
annotation = None
# 獲取資源配置完整信息
full_configuration = configuration_item['configuration']
if not full_configuration:
annotation = 'Configuration is empty.'
return compliance_type, annotation
# 轉換為JSON
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):
"""
校驗Event
:param event:Event
:return:JSON對象
"""
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):
"""
JSON類型轉換
:param content:JSON字符串
:return:JSON對象
"""
try:
return json.loads(content)
except Exception as e:
logger.error('Parse content:{} to json error:{}.'.format(content, e))
return None
# 返回評估結果,并寫入配置審計,代碼可直接復制。
def put_evaluations(creds, result_token, evaluations):
"""
調用API返回并寫入評估結果。
:param context:函數計算上下文
:param result_token:回調令牌
:param evaluations:評估結果
:return: None
"""
# 需具備權限AliyunConfigFullAccess的函數計算FC的服務角色。
client = AcsClient(creds.access_key_id, creds.access_key_secret, region_id='cn-shanghai')
# 新建Request,并設置參數,Domain為config.cn-shanghai.aliyuncs.com。
request = CommonRequest()
request.set_domain('config.cn-shanghai.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)
# 獲取資源詳情,代碼可直接復制。
def get_discovered_resource(creds, resource_id, resource_type, region_id):
"""
調用API獲取資源配置詳情
:param context:函數計算上下文
:param resource_id:資源ID
:param resource_type:資源類型
:param region_id:資源所屬地域ID
:return: 資源詳情
"""
# 需具備權限AliyunConfigFullAccess的函數計算FC的服務角色。
client = AcsClient(creds.access_key_id, creds.access_key_secret, region_id='cn-shanghai')
request = CommonRequest()
request.set_domain('config.cn-shanghai.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)
函數入參
函數計算的函數入參包括資源配置和規則信息兩部分。資源配置信息保存在configurationItem
中,規則的入參信息保存在ruleParameters
中。配置審計向函數計算推送的內容因規則的觸發機制而不同,具體如下:
關于如何從函數計算中獲取函數入參,請參見查看調用日志。
當規則的觸發機制僅設置為周期執行時,配置審計不會推送資源配置信息至函數計算。
當新創建規則初次執行、規則周期自動執行和規則手動觸發執行時,配置審計只會推送一條不包含資源配置信息的記錄,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****" }
當規則的觸發機制包括配置變更時,配置審計會推送資源配置信息至函數計算。
當新創建規則初次執行、規則周期自動執行和規則手動觸發執行時,配置審計會將資源配置信息逐條推送至函數計算。當新增資源或已有資源發生變化時,配置審計僅將變更的單個資源配置信息推送至函數計算,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****" }
當推送的資源配置信息大于等于100 KB時,配置審計只推送資源的摘要信息,不包含資源配置的
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 | 資源的配置信息。包括:資源所屬的阿里云賬號ID、資源的ARN、資源所屬的可用區、資源所屬的地域、資源的詳細配置、配置審計發現資源變更事件并生成日志的時間戳、新建資源的時間戳、資源狀態、資源ID、資源名稱、資源類型和標簽。 |
configurationType | 資源配置的推送類型。取值:
| |
規則信息 | orderingTimestamp | 評估執行的開始時間戳。 |
invokingEvent | 調用事件。 | |
accountId | 調用事件的賬號ID。 | |
messageType | 消息類型。取值:
| |
notificationCreationTimestamp | 規則觸發時的時間戳。 | |
ruleParameters | 自定義規則的入參。包括:規則入參名稱和期望值。 | |
resultToken | 函數計算中的回調令牌。 |