文档

企业多账号场景下实现不合规资源自动修正

更新时间:

本文为您介绍在多账号的场景下,如何利用资源目录提供的跨账号管理能力以及配置审计的账号组管理能力,实现跨账号不合规资源自动修正。

前提条件

  • 请确保您已开通资源目录。具体操作,请参见开通资源目录

  • 请确保您已开通函数计算。具体操作,请参见开通函数计算服务

    重要

    当您使用函数计算服务运行函数时,会根据函数调用次数、资源使用情况以及公网出流量产生相关费用。更多信息,请参见函数计算计费概述

背景信息

配置审计可以通过运行规则检测不合规资源,并且设置自定义修正将不合规资源进行修正。当企业在多账号场景下需要跨账号的对不合规资源进行修正时,可以结合资源目录提供多级账号和资源关系管理能力来实现。本文以ECS实例是否安装云监控插件为例,实现跨账号的不合规资源检测并自动修正,假设账号A(账号ID:100931896542****)在资源目录中拥有管理员权限(或配置审计委派管理员账号),账号B(账号ID:178366182654****)与账号A为相同资源目录的下成员账号,是待修正不合规资源的所属者。以下步骤介绍如何在账号A中对账号B进行不合规资源检测并修正。

步骤一:资源目录管理员创建角色并添加授权策略

  1. 登录RAM控制台

  2. 创建角色。

    1. 在左侧导航栏,单击身份管理 > 角色

    2. 单击创建角色,在创建角色面板中配置角色创建相关参数。

      1. 选择可信实体类型阿里云账号,单击下一步

      2. 输入角色名称,例如:ConfigCustomRemediationRole选择信任的云账号当前云账号

      3. 单击完成

      4. 单击关闭

  3. 创建权限策略。

    1. 在左侧导航栏,单击权限管理 > 权限策略

    2. 单击创建权限策略,进入创建权限策略编辑页面。

      1. 切换至脚本编辑页签,输入以下权限策略脚本。

        // 扮演该角色实体拥有安装云监控插件权限 
        {
          "Version": "1",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": "cms:InstallMonitoringAgent",
              "Resource": "*"
            },
            {
              "Action": "sts:AssumeRole",
              "Effect": "Allow",
              "Resource": "*"
            }
          ]
        }
      2. 单击继续编辑基础信息,填写权限策略名称,例如ConfigCustomRemediationPolicy

      3. 单击保存

  4. 为角色添加授权。

    1. 在左侧导航栏,单击权限管理 > 授权

    2. 单击新增授权,在新增授权面板中为角色新增授权。

      1. 授权范围选择整个云账号

      2. 授权主体输入框中输入ConfigCustomRemediationRole,并进行选中。

      3. 选择权限中切换至自定义策略页签,在对话框中输入ConfigCustomRemediationPolicy,并进行选中。

      4. 单击确定

  5. 为角色添加信任策略。

    1. 在左侧导航栏,单击身份管理 > 角色

    2. 在角色列表页面搜索角色名称ConfigCustomRemediationRole,单击搜索目标角色名称进入角色配置详情页面。

    3. 切换至信任策略管理页签,单击修改信任策略,将修改策略调整成以下内容。

      // 允许函数计算服务扮演该角色
      { 
        "Statement": [
          {
            "Action": "sts:AssumeRole",
            "Effect": "Allow",
            "Principal": {
              "RAM": [
                "acs:ram::100931896542****:root"
              ]
            }
          },
          {
            "Action": "sts:AssumeRole",
            "Effect": "Allow",
            "Principal": {
              "Service": [
                "fc.aliyuncs.com"
              ]
            }
          }
        ],
        "Version": "1"
      }
    4. 单击确认

步骤二:资源目录成员账号创建角色并添加授权策略

  1. 创建角色并为角色进行授权。

    具体操作,请参见步骤一中的子步骤1~4。

  2. 为角色添加信任策略。

    具体操作,请参见步骤一中子步骤5,并将信任策略调整成以下内容。

    // 允许资源目录管理员100931896542****扮演该角色
    {
      "Statement": [
        {
          "Action": "sts:AssumeRole",
          "Effect": "Allow",
          "Principal": {
            "RAM": [
              "acs:ram::178366182654****:root"
            ]
          }
        },
        {
          "Action": "sts:AssumeRole",
          "Effect": "Allow",
          "Principal": {
            "RAM": [
              "acs:ram::100931896542****:role/configcustomremediationrole"
            ]
          }
        }
      ],
      "Version": "1"
    }

步骤三:创建自定义修正函数

  1. 登录函数计算控制台

  2. 创建服务。

    1. 在左侧导航栏,单击服务及函数

    2. 单击创建服务,唤出创建服务面板。

      1. 填写服务名称,例如:ConfigRemediationService

      2. 选择服务角色ConfigCustomRemediationRole

      3. 单击确定

  3. 创建自定义修正函数。

    1. 在函数管理页面左侧导航栏选择函数管理

    2. 单击创建函数,进入创建函数配置页面。

      1. 函数创建方式使用内置运行时创建

      2. 基本设置中填写函数名称,例如:ConfigRemediationFunction请求处理程序类型选择处理事件请求

      3. 函数代码配置中运行环境选择Python 3.9代码上传方式选择使用示例代码

      4. 单击创建,进入函数详情页。

      5. 函数代码页签中输入以下资源修正函数代码。

        #!/usr/bin/env python
        # -*- encoding: utf-8 -*-
        import json
        from aliyunsdkcore.client import AcsClient
        from aliyunsdkcore.acs_exception.exceptions import ClientException
        from aliyunsdkcore.acs_exception.exceptions import ServerException
        from aliyunsdkcore.request import CommonRequest
        from aliyunsdkcore.auth.credentials import StsTokenCredential
        from aliyunsdksts.request.v20150401.AssumeRoleRequest import AssumeRoleRequest
        import logging
        
        logger = logging.getLogger()
        
        # 此处示例代码针对ECS实例未开启云监控插件进行修正,对于不同的业务场景用户可以自定义修正逻辑
        def handler(event, context):
            get_resources_non_compliant(event, context)
        
        def get_resources_non_compliant(event, context):
            resources = parse_json(event)
            for resource in resources:
                remediation(resource, context)
        
        def parse_json(content):
            """
            Parse string to json object
            :param content: json string content
            :return: Json object
            """
            try:
                return json.loads(content)
            except Exception as e:
                logger.error('Parse content:{} to json error:{}.'.format(content, e))
                return None
        
        def remediation(resource, context):
            logger.info(resource)
            region_id = resource['regionId']
            account_id = resource['accountId']
            resource_id = resource['resourceId']
            resource_type = resource['resourceType']
            config_rule_id = resource['configRuleId']
            if resource_type == 'ACS::ECS::Instance':
                logger.info("process account_id: {}, resource_id: {}, config_rule_id: {}".format(
                    account_id, resource_id, config_rule_id))
                install_monitoring_agent(context, account_id, region_id, resource_id)
        
        def install_monitoring_agent(context, account_id, resource_region_id, resource_id):
            logger.info("start install agent {}: {}".format(resource_region_id, resource_id))
        
            token = assume_role_and_get_token(context, account_id, resource_region_id)
            client = AcsClient(token['Credentials']['AccessKeyId'], token['Credentials']['AccessKeySecret'],
                               region_id=resource_region_id)
            request = CommonRequest()
            request.set_accept_format('json')
            request.set_domain(f'metrics.{resource_region_id}.aliyuncs.com')
            request.set_method('POST')
            request.set_protocol_type('https') # https | http
            request.set_version('2019-01-01')
            request.set_action_name('InstallMonitoringAgent')
            request.add_query_param('InstanceIds.1', resource_id)
            request.add_query_param('Force', "true")
            request.add_query_param('SecurityToken', token['Credentials']['SecurityToken'])
        
            response = client.do_action_with_exception(request)
            logger.info(response)
        
        # 通过扮演获取临时token,注意该方法一般只需替换为实际需要扮演的角色名称即可
        def assume_role_and_get_token(context, account_id, region_id):
            creds = context.credentials
            logger.info('assume_role_and_get_token begin.')
            credentials = StsTokenCredential(creds.access_key_id, creds.access_key_secret, creds.security_token)
            client = AcsClient(credential=credentials)
        
            request = AssumeRoleRequest()
            request.set_domain(f'sts-vpc.{region_id}.aliyuncs.com')
            request.set_accept_format('json')
        
            request.set_RoleArn(f'acs:ram::{account_id}:role/configcustomremediationrole')
            request.set_RoleSessionName("ConfigCustomRemediationRole")
            response = client.do_action_with_exception(request)
            logger.info('assume_role_and_get_token response : {}.'.format(response))
        
            token = json.loads(response)
            logger.info('assume_role_and_get_token: {}, assume role: {}.'.format(context.credentials, token))
            return token

步骤四:创建规则并配置自定义修正

  1. 登录配置审计控制台

  2. 创建账号组,将账号A和账号B加入至相同账号组中。

    具体操作,请参见新建账号组

  3. 在配置审计控制台左上角切换账号组至上一步创建的账号组。

  4. 创建规则,具体创建过程可参考基于模板创建规则

    1. 选择创建方式页面,先选择基于模板创建,搜索运行中的ECS实例安装了云监控插件规则并且选中,单击下一步

    2. 设置基本属性页面,填写规则名称风险等级触发机制描述信息,然后单击下一步

    3. 设置生效范围页面,保持默认配置,单击下一步

    4. 设置修正页面,打开设置修正开关,选择自定义修正,选择触发方式自动触发,然后选择函数ARN为步骤三所创建的函数,最后单击提交

      说明

      如果自定义修正函数还在测试过程中,可以暂时将触发方式调整为手动触发,以便于调试观察,当调试完成之后可以将触发方式切换为自动触发

步骤五:执行自定义修正并校验修正结果

  1. 规则页面,单击目标规则对应修正模板列的修正详情

  2. 修正详情页签,单击修正详情正后方的执行手动修正

    执行结果列表区域,您可以查看修正执行结果。对于修正失败的资源,您还可以查看失败原因。

    说明

    修正详情页签,单击修正模板正后方的函数ARN,进入函数计算控制台的目标函数的函数代码页签。

相关文档