{"value":"### **1. 前言**\n\n企业在上云过程中,随着不同业务负载逐步迁移至云上,在设计云安全基线过程中,不仅需要设定企业整体范围的统一安全基线标准,同时也需要考虑到不同业务部门的特定安全需求。面对大量云业务负载跨多个 Organizations、多个账户,如何快速有效执行日常安全基线检查,这对于大多数企业信息安全团队会是一个挑战。同时,在大量 Account 中进行资源统计和配置查询是非常繁琐的工作,通常会利用 MSP 和云管平台等来进行,但是对于没有接入上述平台的云端环境或需要进行快速、复杂查询的情况,就可以借助 Steampipe Amazon Web Services plugin 来简化操作了。本文我们将会介绍利用开源即时查询工具 Steampipe 在亚马逊云科技服务快速构建云端安全基线检查方案。\n\n具体来说,本方案基于 Steampipe 配置方案,适用于多个 Amazon Organizations,每个 Organizations 中有大量 Account 使用 AssumeRole+MFA 的方式以特定 Account 中的 user 对 Organizations 中的 Account 进行访问的环境。这种 IAM 和 Account 配置是企业 Amazon 环境中常见的配置方式,其他账号配置方式可基于此配置模板进行修改匹配。\n\n基于 Steampipe 引擎 可以使用 SQL 语句来对多个 Organizations 和大量 Account 的环境进行有效、复杂的资源统计和配置查询。\n\n相对于很多沉重复杂的商用云管和安全产品,Steampipe 具有不需要对 account 环境进行变更配置,轻量化部署可以便利的任何位置直接运行,PostgreSQL 标准数据接口提供了更多扩展可能等优点,是“小而美“的云 CMDB 和安全基线检查方案,非常适合作为”敏捷运维“的基础工具栈使用。\n\n### **2. 前置准备:**\n\nSteampipe 可以部署在个人电脑终端 wsl 环境和 Linux 运维工作站中 也可以配合 instance role 部署在 EC2实例中,以下以常用的 WSL 环境为例,其他 Linux 环境大同小异。配置 Steampipe 前需要确保以下内容就绪:\n\n1. 安装 awscli,或者手工创建 Amazon credentials 和 config 文件。参考:\n[https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.h### 三级标题tml](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)\n \n2. 安装 Amazon-vault。参考:[https://github.com/99designs/aws-vault](https://github.com/99designs/aws-vault)\n\n3. 安装最新版本的 Steampipe。参考:[https://Steampipe.io/downloads](https://steampipe.io/downloads)\n\n4. 安装 Amazon plugin 和其他所需 plugin。参考[https://hub.Steampipe.io/plugins/turbot/aws](https://hub.steampipe.io/plugins/turbot/aws), (安装plugin如需要使用镜像库和基于文件的安装方式,参考\n[https://Steampipe.io/docs/using-Steampipe/managing-plugins )](https://steampipe.io/docs/using-Steampipe/managing-plugins)\n \n5. 准备好访问云端环境所需的 credential(AKSK, MFA_serial, role_arn)信息,Account id list 等基本环境信息,所使用的 role 应具备查询所需要的权限,如“ReadOnlyAccess”\n\n### **3. 配置步骤**\n\nOrganization 环境下复杂 OU 和 account 结构的 steampipe connection 配置是非常繁琐枯燥的工作,笔者编写了一个自动化小工具帮助快速完成这一配置,可以从[https://github.com/happy240/steampipe-conn-generator-for-aws-organization](https://github.com/happy240/steampipe-conn-generator-for-aws-organization) 获取。以下是详细的配置逻辑:\n\n#### **3.1 配置 Amazon-vault credential profile**\n\n```\naws-vault add <profile name>\n```\n\n![image.png](https://dev-media.amazoncloud.cn/50cda86ffa7e4586b9fee02281410736_image.png)\n\n根据提示输入 AKSK 等信息。\n\n说明: 可以使用 Amazon-vault list 查看已配置的 profile 列表,也可以在~/.aws/config中找到,并进一步修改 profile 的配置信息。\n\n#### **3.2 配置 Amazon config文件增加 MFA 信息**\n\n在~/.aws/config文件,找到对应的 profile 增加 MFA 信息,示例配置以中国区域为例。 如果在 Global 区域配置,注意修改 Amazon-cn 为 Amazon。\n\n```\n[profile <profile name>]\nMFA_serial=arn:aws-cn:iam::<Account1 id>:MFA/<MFA id>\n```\n\n![image.png](https://dev-media.amazoncloud.cn/c40484ea7b3f45a6acb7b9a7872cfea7_image.png)\n\n#### **3.3 配置 Amazon credentials 文件引用 Amazon-vault profile**\n\n在~/.aws/credentials文件中为每一个需要查询的 Amazon Account增加一条记录。\n\n注意:\n\n- profile 名称可以直接使用 Account id,也可以使用便于分辨的名称\n- 保险起见,Amazon-vault 路径应设置为绝对路径,而不是使用 PATH环境变量,避免环境变量设置错误造成无法获取 credential 的情况。\n- 对于中国区环境 Amazon-vault 指令带有–region 参数。\n\n```\n[Account1]\ncredential_process=aws-vault exec -j <profile name> --region=cn-north-1\n[Account2]\nsource_profile=orgprefix_Account1\nrole_arn=arn:aws-cn:iam::<Account2 id>:role/<role id>\n[Account3]\nsource_profile=orgprefix_Account1\nrole_arn=arn:aws-cn:iam::<Account3 id>:role/<role id>\n```\n\n#### **3.4 配置 Steampipe aws plugin connection 文件\n**\n在~/.Steampipe/config/aws.spc文件中为每一个 Amazon Account增加一条记录。\n\n注意:\n\n\n- connection 名称务必根据 Organizations 等分组信息增加统一前缀,方便后续配置 aggregation。\n- 在中国区域,regions 参数不能使用*通配符, 否则会错误调用 Global region的 API。\n- 可以为不同 region 设置不同的 connection profile 方便进行不同区域的查询或提高查询性能。\n\n```\nconnection \"orgprefix_Account1\" {\nplugin = \"aws\"\nprofile = \"Account1\"\nregions = [\"cn-north-1\",\"cn-northwest-1\"]\n}\nconnection \"orgprefix_Account2\" {\nplugin = \"aws\"\nprofile = \"Account2\"\nregions = [\"cn-north-1\",\"cn-northwest-1\"]\n}\nconnection \"orgprefix_Account3\" {\nplugin = \"aws\"\nprofile = \"Account3\"\nregions = [\"cn-north-1\",\"cn-northwest-1\"]\n}\n\n```\n\n#### **3.5 根据需要配置 aggregation connection**\n\n在~/.Steampipe/config/aws.spc 文件中,根据查询需要,将要合并至一起查询的 account connection 配置为 aggregation。例如:\n\n```\nconnection \"orgprefix_all\" {\ntype = \"aggregator\"\nplugin = \"aws\"\nconnections = [\"orgprefix_*\"]\n}\n```\n\n保存~/.Steampipe/config/aws.spc 文件。\n\n### **4. 查询步骤**\n\n#### **4.1 输入 MFA 并缓存 session 信息\n**\n注意:Steampipe 目前无法直接提示输入 MFA,因此如果使用了 MFA,应在查询前通过 Amazon-vault 提前获取并缓存 session token,否则在未提前验证或 session 过期(默认 session 超时时间是1小时)的情况下,Steampipe 查询会因为提示输入 MFA 卡死,需要重开 shell。\n\n```\naws-vault exec -j <profile name> --region cn-north-1\n```\n\n根据提示输入 MFA 信息。\n\n注意: 如果需要较长时间进行查询操作 可以最长使用”-d 12h”参数执行 Amazon-vault exec:\n\n```\naws-vault exec -j <profile name> -d 12h --region cn-north-1\n```\n\n如需要提前刷新 session token:\n\n```\naws-vault rotate <profile name>\n```\n\n#### 4.2 Steampipe 进行查询\n\n使用 Steampipe 查询,以下举例几个常用的资源查询语句:\n\n```\n# 启动交互式查 \nSteampipe query\n# 统计每个Account中的ec2数 \nselect Account_id,count(*) as countalb from orgprefix_all.aws_ec2_instance\ngroup by Account_id\n# 统计每个Account中的ALB数 \nselect Account_id,count(*) as countalb from\norgprefix_all.aws_ec2_application_load_balancer group by Account_id\n# 统计每个Account中的VPC数 \nselect Account_id,count(*) as countalb from orgprefix_all.aws_vpc group by\nAccount_id\n\n```\n\n#### **4.3 输出到 csv**\n\n将查询结果输出到.csv文件。\n\n```\nSteampipe query \"<sql query>\" --output csv > <filename>.csv\n```\n\n#### **4.4 可视化和合规扫描**\n\n根据需要获取 Steampipe Amazon Compliance Mod 和 Amazon Insights Mod,参考:\n\n[https://hub.steampipe.io/mods/turbot/aws_compliance](https://hub.steampipe.io/mods/turbot/aws_compliance)\n\n[https://hub.steampipe.io/mods/turbot/aws_insights](https://hub.steampipe.io/mods/turbot/aws_insights)\n\n进入对应 Mod 目录,执行’steampipe dashboard’即可启动可视化面板\n\n![image.png](https://dev-media.amazoncloud.cn/de3a60d58e354b128caaa63d385eb9ab_image.png)\n\n\n![image.png](https://dev-media.amazoncloud.cn/ab150bd7da0b4fceba1beae9e3928aa3_image.png)\n\n### **5. 查询示例**\n\n以下是一些场景示例设计及对应的查询语句,建议结合实际安全基线设定灵活组合使用。\n\n#### **示例1: 查询一组账户开通的特定资源数量**\n\n前置条件:已配置 connection aggregator ‘org_all’,以下语句统计 aggregator connection 中每个 account 中的 ALB 数量。\n\n\n```\nselect account_id,count(*) as countalb from\norg_all.aws_ec2_application_load_balancer group by account_id\n\nselect\nload_balancer_arns,count(*)\nfrom\norg_all.aws_ec2_target_group\ncross join jsonb_array_elements(target_health_descriptions) as target\ngroup by load_balancer_arns\n\nselect account_id,count(*) as counteip from account_all.aws_vpc_eip group by\naccount_id\n\nselect group_id,ip_permission -> 'FromPort' as OpenPort from\naccount_all.aws_vpc_security_group cross join\njsonb_array_elements(ip_permissions) as ip_permission where (ip_permission -\n>> 'FromPort'='80' and ip_permission ->> 'ToPort'='80') or (ip_permission -\n>> 'FromPort'='443' and ip_permission ->> 'ToPort'='443') or (ip_permission\n->> 'FromPort'='8080' and ip_permission ->> 'ToPort'='8080') or\n(ip_permission ->> 'FromPort'='8081' and ip_permission ->> 'ToPort'='8081')\nor (ip_permission ->> 'FromPort'='3128' and ip_permission ->>\n'ToPort'='3128') or (ip_permission ->> 'FromPort'='9080' and ip_permission -\n>> 'ToPort'='9080')\n```\n\n#### **示例2:查询开放 web 端口的 EIP**\n\n```\nselect eip.*,sg ->> 'GroupId' as sgid,websg.OpenPort from (select\naccount_id,instance_id,network_interface_id,private_ip_address,public_ip\nfrom account_all.aws_vpc_eip) as eip inner join (select\nnetwork_interface_id,groups from account_all.aws_ec2_network_interface) as\neni on eip.network_interface_id=eni.network_interface_id cross join\njsonb_array_elements(eni.groups) as sg inner join (select\ngroup_id,ip_permission -> 'FromPort' as OpenPort from\naccount_all.aws_vpc_security_group cross join\njsonb_array_elements(ip_permissions) as ip_permission where (ip_permission -\n>> 'FromPort'='80' and ip_permission ->> 'ToPort'='80') or (ip_permission -\n>> 'FromPort'='443' and ip_permission ->> 'ToPort'='443') or (ip_permission\n->> 'FromPort'='8080' and ip_permission ->> 'ToPort'='8080') or\n(ip_permission ->> 'FromPort'='8081' and ip_permission ->> 'ToPort'='8081')\nor (ip_permission ->> 'FromPort'='3128' and ip_permission ->>\n'ToPort'='3128') or (ip_permission ->> 'FromPort'='9080' and ip_permission -\n>> 'ToPort'='9080')) as websg on sg ->> 'GroupId'=websg.group_id\n\n```\n\n#### **示例3:查询开放 web 端口的 NLB\n**\n```\nselect nlb.account_id, nlb.name,nlb.arn from\naccount_all.aws_ec2_network_load_balancer as nlb inner join\n(select load_balancer_arn,port from\naccount_all.aws_ec2_load_balancer_listener where port in\n(80,443,8080,8081,3128,9080)) as listener on\nnlb.arn=listener.load_balancer_arn\n```\n\n#### **示例4:查询特定账户所使用 Amazon OpenSearch 版本**\n\n```\nselect account_id, arn, domain_id, domain_name, elasticsearch_version,\nenabled, endpoint from account_all.aws_elasticsearch_domain\n```\n\n#### **示例5:查询&过滤特定机型**\n\n```\nselect account_id, instance_id, instance_type, instance_state from\naccount_all.aws_ec2_instance where instance_type not like 'a1%' and\ninstance_type not like 'c5%' and instance_type not like 'c6%' and\ninstance_type not like 'd3%' and instance_type not like 'dl%' and\ninstance_type not like 'g4%' and instance_type not like 'g5%' and\ninstance_type not like 'hpc6%' and instance_type not like 'i3en%' and\ninstance_type not like 'im4gn%' and instance_type not like 'inf1%' and\ninstance_type not like 'is4gen%' and instance_type not like 'm5%' and\ninstance_type not like 'm6%' and instance_type not like 'p3dn%' and\ninstance_type not like 'p4%' and instance_type not like 'r5%' and\ninstance_type not like 'r6%' and instance_type not like 't3%' and\ninstance_type not like 't4%' and instance_type not like 'vt1%' and\ninstance_type not like 'x2gd%' and instance_type not like 'z1d%'\n```\n\n#### **示例6:查询特定实例 AMI 信息**\n\n```\nselect instance.account_id,instance.instance_id,ami.*,instance.tags from\naccount_all.aws_ec2_instance as instance left outer join (select\naccount_id,image_id,name,platform_details,description from\naccount_all.aws_ec2_ami_shared where owner_id='141808717104') as ami on\ninstance.account_id=ami.account_id and instance.image_id=ami.image_id\n\n```\n\n#### **示例7:查询特定实例 SSM 托管状态\n**\n```\nselect ec2.account_id as account_id, ec2.instance_id, mi.computer_name,\nmi.platform_name, mi.platform_version, ec2.instance_type,\nec2.instance_state, mi.agent_version, mi.is_latest_version, mi.ping_status,\nec2.launch_time from (select\naccount_id,instance_id,instance_state,instance_type,launch_time from\naccount_all.aws_ec2_instance) as ec2 left outer join (select\naccount_id,agent_version,computer_name,instance_id,is_latest_version,ping_st\natus,platform_name,platform_version from\naccount_all.aws_ssm_managed_instance) as mi on\nec2.instance_id=mi.instance_id order by account_id\n```\n\n####** 示例8:查询 ENI 与 RDS 关联情况**\n\n```\nselect i.*,r.* from (select rdsinstance.*,rdsinstanceip.ip from (select\naccount_id, db_instance_identifier, arn, endpoint_address, engine,\nengine_version, vpc_id, subnets from account_all.aws_rds_db_instance) as\nrdsinstance join (select domain,ip from net.net_dns_record where domain in\n(select endpoint_address from account_all.aws_rds_db_instance) and type =\n'A' and target is null) as rdsinstanceip on\nrdsinstance.endpoint_address=rdsinstanceip.domain) as r join (select\naccount_id,network_interface_id,private_ip_address,association_public_ip\nfrom account_all.aws_ec2_network_interface where\nattached_instance_owner_id='amazon-rds') as i on r.account_id=i.account_id\nand (r.ip=i.private_ip_address or r.ip=i.association_public_ip)\n```\n\n#### **示例9:查询未使用的 ENI**\n\n```\nselect\naccount_id,network_interface_id,description,private_ip_address,association_p\nublic_ip from account_all.aws_ec2_network_interface where status!='in-use'\n```\n\n### **6. 结尾**\n\n至此,我们介绍了一个云原生的轻量级安全基线检查方案,涉及该方案的前置准备、部署过程以及使用步骤。同时,附上基于 Steampipe 的常用安全基线检查查询语句示例,以供读者参考,进一步结合自身实际场景组合执行日常安全基线检查。\n\n### **7. 参考资料**\n\n更多关于 Steampipe connection 和查询的信息,请参考:\n\n[https://aws.amazon.com/cn/blogs/opensource/querying-aws-at-scale-across-apis-regions-and-accounts/](https://aws.amazon.com/cn/blogs/opensource/querying-aws-at-scale-across-apis-regions-and-accounts/)\n\n### **本篇作者\n**\n![image.png](https://dev-media.amazoncloud.cn/45a3b306fa9d48469ea2c26d25a729c0_image.png)\n\n#### **霍延峰**\n\n拥有超过18年的 IT 从业经历,包括 ERP 系统前端和后端开发人员、 OA 系统和基础架构运维、企业软件系统架构、数据库管理员和商业智能工程师、虚拟化和私有云工程师、公有云解决方案架构师。他热衷于使用新技术来解决客户的实际问题,在云架构和应用现代化、DevOps、数据科学和其他领域具有独特的见解。他从2016年开始为使用 Amazon 的 ECCOM 客户提供帮助,并陪伴数十家客户的 Amazon 迁移旅程,以及 ECCOM 自身从传统网络系统集成商到 Amazon 的现代 MSP 服务提供商的转型过程。\n\n![image.png](https://dev-media.amazoncloud.cn/b9d94acb8333467cbe7f866644b82238_image.png)\n\n#### **陈琪**\n\n亚马逊云科技合作伙伴解决方案架构师,超过十年 IT 从业经验,涉及产品研发、方案咨询、产品管理等多个环节。长期从事企业信息化架构设计与方案咨询,具有丰富的企业数字化转型实践经验,尤其在安全、数据分析、网络等领域具有深刻认知及丰富实践。现负责亚马逊云科技合作伙伴的方案设计与能力构建。\n\n\n\n\n\n","render":"<h3><a id=\"1__0\"></a><strong>1. 前言</strong></h3>\n<p>企业在上云过程中,随着不同业务负载逐步迁移至云上,在设计云安全基线过程中,不仅需要设定企业整体范围的统一安全基线标准,同时也需要考虑到不同业务部门的特定安全需求。面对大量云业务负载跨多个 Organizations、多个账户,如何快速有效执行日常安全基线检查,这对于大多数企业信息安全团队会是一个挑战。同时,在大量 Account 中进行资源统计和配置查询是非常繁琐的工作,通常会利用 MSP 和云管平台等来进行,但是对于没有接入上述平台的云端环境或需要进行快速、复杂查询的情况,就可以借助 Steampipe Amazon Web Services plugin 来简化操作了。本文我们将会介绍利用开源即时查询工具 Steampipe 在亚马逊云科技服务快速构建云端安全基线检查方案。</p>\n<p>具体来说,本方案基于 Steampipe 配置方案,适用于多个 Amazon Organizations,每个 Organizations 中有大量 Account 使用 AssumeRole+MFA 的方式以特定 Account 中的 user 对 Organizations 中的 Account 进行访问的环境。这种 IAM 和 Account 配置是企业 Amazon 环境中常见的配置方式,其他账号配置方式可基于此配置模板进行修改匹配。</p>\n<p>基于 Steampipe 引擎 可以使用 SQL 语句来对多个 Organizations 和大量 Account 的环境进行有效、复杂的资源统计和配置查询。</p>\n<p>相对于很多沉重复杂的商用云管和安全产品,Steampipe 具有不需要对 account 环境进行变更配置,轻量化部署可以便利的任何位置直接运行,PostgreSQL 标准数据接口提供了更多扩展可能等优点,是“小而美“的云 CMDB 和安全基线检查方案,非常适合作为”敏捷运维“的基础工具栈使用。</p>\n<h3><a id=\"2__10\"></a><strong>2. 前置准备:</strong></h3>\n<p>Steampipe 可以部署在个人电脑终端 wsl 环境和 Linux 运维工作站中 也可以配合 instance role 部署在 EC2实例中,以下以常用的 WSL 环境为例,其他 Linux 环境大同小异。配置 Steampipe 前需要确保以下内容就绪:</p>\n<ol>\n<li>\n<p>安装 awscli,或者手工创建 Amazon credentials 和 config 文件。参考:<br />\n<a href=\"https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html\" target=\"_blank\">https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.h### 三级标题tml</a></p>\n</li>\n<li>\n<p>安装 Amazon-vault。参考:<a href=\"https://github.com/99designs/aws-vault\" target=\"_blank\">https://github.com/99designs/aws-vault</a></p>\n</li>\n<li>\n<p>安装最新版本的 Steampipe。参考:<a href=\"https://steampipe.io/downloads\" target=\"_blank\">https://Steampipe.io/downloads</a></p>\n</li>\n<li>\n<p>安装 Amazon plugin 和其他所需 plugin。参考<a href=\"https://hub.steampipe.io/plugins/turbot/aws\" target=\"_blank\">https://hub.Steampipe.io/plugins/turbot/aws</a>, (安装plugin如需要使用镜像库和基于文件的安装方式,参考<br />\n<a href=\"https://steampipe.io/docs/using-Steampipe/managing-plugins\" target=\"_blank\">https://Steampipe.io/docs/using-Steampipe/managing-plugins )</a></p>\n</li>\n<li>\n<p>准备好访问云端环境所需的 credential(AKSK, MFA_serial, role_arn)信息,Account id list 等基本环境信息,所使用的 role 应具备查询所需要的权限,如“ReadOnlyAccess”</p>\n</li>\n</ol>\n<h3><a id=\"3__26\"></a><strong>3. 配置步骤</strong></h3>\n<p>Organization 环境下复杂 OU 和 account 结构的 steampipe connection 配置是非常繁琐枯燥的工作,笔者编写了一个自动化小工具帮助快速完成这一配置,可以从<a href=\"https://github.com/happy240/steampipe-conn-generator-for-aws-organization\" target=\"_blank\">https://github.com/happy240/steampipe-conn-generator-for-aws-organization</a> 获取。以下是详细的配置逻辑:</p>\n<h4><a id=\"31__Amazonvault_credential_profile_30\"></a><strong>3.1 配置 Amazon-vault credential profile</strong></h4>\n<pre><code class=\"lang-\">aws-vault add <profile name>\n</code></pre>\n<p><img src=\"https://dev-media.amazoncloud.cn/50cda86ffa7e4586b9fee02281410736_image.png\" alt=\"image.png\" /></p>\n<p>根据提示输入 AKSK 等信息。</p>\n<p>说明: 可以使用 Amazon-vault list 查看已配置的 profile 列表,也可以在~/.aws/config中找到,并进一步修改 profile 的配置信息。</p>\n<h4><a id=\"32__Amazon_config_MFA__42\"></a><strong>3.2 配置 Amazon config文件增加 MFA 信息</strong></h4>\n<p>在~/.aws/config文件,找到对应的 profile 增加 MFA 信息,示例配置以中国区域为例。 如果在 Global 区域配置,注意修改 Amazon-cn 为 Amazon。</p>\n<pre><code class=\"lang-\">[profile <profile name>]\nMFA_serial=arn:aws-cn:iam::<Account1 id>:MFA/<MFA id>\n</code></pre>\n<p><img src=\"https://dev-media.amazoncloud.cn/c40484ea7b3f45a6acb7b9a7872cfea7_image.png\" alt=\"image.png\" /></p>\n<h4><a id=\"33__Amazon_credentials__Amazonvault_profile_53\"></a><strong>3.3 配置 Amazon credentials 文件引用 Amazon-vault profile</strong></h4>\n<p>在~/.aws/credentials文件中为每一个需要查询的 Amazon Account增加一条记录。</p>\n<p>注意:</p>\n<ul>\n<li>profile 名称可以直接使用 Account id,也可以使用便于分辨的名称</li>\n<li>保险起见,Amazon-vault 路径应设置为绝对路径,而不是使用 PATH环境变量,避免环境变量设置错误造成无法获取 credential 的情况。</li>\n<li>对于中国区环境 Amazon-vault 指令带有–region 参数。</li>\n</ul>\n<pre><code class=\"lang-\">[Account1]\ncredential_process=aws-vault exec -j <profile name> --region=cn-north-1\n[Account2]\nsource_profile=orgprefix_Account1\nrole_arn=arn:aws-cn:iam::<Account2 id>:role/<role id>\n[Account3]\nsource_profile=orgprefix_Account1\nrole_arn=arn:aws-cn:iam::<Account3 id>:role/<role id>\n</code></pre>\n<h4><a id=\"34__Steampipe_aws_plugin_connection__74\"></a>**3.4 配置 Steampipe aws plugin connection 文件</h4>\n<p>**<br />\n在~/.Steampipe/config/aws.spc文件中为每一个 Amazon Account增加一条记录。</p>\n<p>注意:</p>\n<ul>\n<li>connection 名称务必根据 Organizations 等分组信息增加统一前缀,方便后续配置 aggregation。</li>\n<li>在中国区域,regions 参数不能使用*通配符, 否则会错误调用 Global region的 API。</li>\n<li>可以为不同 region 设置不同的 connection profile 方便进行不同区域的查询或提高查询性能。</li>\n</ul>\n<pre><code class=\"lang-\">connection "orgprefix_Account1" {\nplugin = "aws"\nprofile = "Account1"\nregions = ["cn-north-1","cn-northwest-1"]\n}\nconnection "orgprefix_Account2" {\nplugin = "aws"\nprofile = "Account2"\nregions = ["cn-north-1","cn-northwest-1"]\n}\nconnection "orgprefix_Account3" {\nplugin = "aws"\nprofile = "Account3"\nregions = ["cn-north-1","cn-northwest-1"]\n}\n\n</code></pre>\n<h4><a id=\"35__aggregation_connection_104\"></a><strong>3.5 根据需要配置 aggregation connection</strong></h4>\n<p>在~/.Steampipe/config/aws.spc 文件中,根据查询需要,将要合并至一起查询的 account connection 配置为 aggregation。例如:</p>\n<pre><code class=\"lang-\">connection "orgprefix_all" {\ntype = "aggregator"\nplugin = "aws"\nconnections = ["orgprefix_*"]\n}\n</code></pre>\n<p>保存~/.Steampipe/config/aws.spc 文件。</p>\n<h3><a id=\"4__118\"></a><strong>4. 查询步骤</strong></h3>\n<h4><a id=\"41__MFA__session__120\"></a>**4.1 输入 MFA 并缓存 session 信息</h4>\n<p>**<br />\n注意:Steampipe 目前无法直接提示输入 MFA,因此如果使用了 MFA,应在查询前通过 Amazon-vault 提前获取并缓存 session token,否则在未提前验证或 session 过期(默认 session 超时时间是1小时)的情况下,Steampipe 查询会因为提示输入 MFA 卡死,需要重开 shell。</p>\n<pre><code class=\"lang-\">aws-vault exec -j <profile name> --region cn-north-1\n</code></pre>\n<p>根据提示输入 MFA 信息。</p>\n<p>注意: 如果需要较长时间进行查询操作 可以最长使用”-d 12h”参数执行 Amazon-vault exec:</p>\n<pre><code class=\"lang-\">aws-vault exec -j <profile name> -d 12h --region cn-north-1\n</code></pre>\n<p>如需要提前刷新 session token:</p>\n<pre><code class=\"lang-\">aws-vault rotate <profile name>\n</code></pre>\n<h4><a id=\"42_Steampipe__142\"></a>4.2 Steampipe 进行查询</h4>\n<p>使用 Steampipe 查询,以下举例几个常用的资源查询语句:</p>\n<pre><code class=\"lang-\"># 启动交互式查 \nSteampipe query\n# 统计每个Account中的ec2数 \nselect Account_id,count(*) as countalb from orgprefix_all.aws_ec2_instance\ngroup by Account_id\n# 统计每个Account中的ALB数 \nselect Account_id,count(*) as countalb from\norgprefix_all.aws_ec2_application_load_balancer group by Account_id\n# 统计每个Account中的VPC数 \nselect Account_id,count(*) as countalb from orgprefix_all.aws_vpc group by\nAccount_id\n\n</code></pre>\n<h4><a id=\"43__csv_161\"></a><strong>4.3 输出到 csv</strong></h4>\n<p>将查询结果输出到.csv文件。</p>\n<pre><code class=\"lang-\">Steampipe query "<sql query>" --output csv > <filename>.csv\n</code></pre>\n<h4><a id=\"44__169\"></a><strong>4.4 可视化和合规扫描</strong></h4>\n<p>根据需要获取 Steampipe Amazon Compliance Mod 和 Amazon Insights Mod,参考:</p>\n<p><a href=\"https://hub.steampipe.io/mods/turbot/aws_compliance\" target=\"_blank\">https://hub.steampipe.io/mods/turbot/aws_compliance</a></p>\n<p><a href=\"https://hub.steampipe.io/mods/turbot/aws_insights\" target=\"_blank\">https://hub.steampipe.io/mods/turbot/aws_insights</a></p>\n<p>进入对应 Mod 目录,执行’steampipe dashboard’即可启动可视化面板</p>\n<p><img src=\"https://dev-media.amazoncloud.cn/de3a60d58e354b128caaa63d385eb9ab_image.png\" alt=\"image.png\" /></p>\n<p><img src=\"https://dev-media.amazoncloud.cn/ab150bd7da0b4fceba1beae9e3928aa3_image.png\" alt=\"image.png\" /></p>\n<h3><a id=\"5__184\"></a><strong>5. 查询示例</strong></h3>\n<p>以下是一些场景示例设计及对应的查询语句,建议结合实际安全基线设定灵活组合使用。</p>\n<h4><a id=\"1__188\"></a><strong>示例1: 查询一组账户开通的特定资源数量</strong></h4>\n<p>前置条件:已配置 connection aggregator ‘org_all’,以下语句统计 aggregator connection 中每个 account 中的 ALB 数量。</p>\n<pre><code class=\"lang-\">select account_id,count(*) as countalb from\norg_all.aws_ec2_application_load_balancer group by account_id\n\nselect\nload_balancer_arns,count(*)\nfrom\norg_all.aws_ec2_target_group\ncross join jsonb_array_elements(target_health_descriptions) as target\ngroup by load_balancer_arns\n\nselect account_id,count(*) as counteip from account_all.aws_vpc_eip group by\naccount_id\n\nselect group_id,ip_permission -> 'FromPort' as OpenPort from\naccount_all.aws_vpc_security_group cross join\njsonb_array_elements(ip_permissions) as ip_permission where (ip_permission -\n>> 'FromPort'='80' and ip_permission ->> 'ToPort'='80') or (ip_permission -\n>> 'FromPort'='443' and ip_permission ->> 'ToPort'='443') or (ip_permission\n->> 'FromPort'='8080' and ip_permission ->> 'ToPort'='8080') or\n(ip_permission ->> 'FromPort'='8081' and ip_permission ->> 'ToPort'='8081')\nor (ip_permission ->> 'FromPort'='3128' and ip_permission ->>\n'ToPort'='3128') or (ip_permission ->> 'FromPort'='9080' and ip_permission -\n>> 'ToPort'='9080')\n</code></pre>\n<h4><a id=\"2_web__EIP_219\"></a><strong>示例2:查询开放 web 端口的 EIP</strong></h4>\n<pre><code class=\"lang-\">select eip.*,sg ->> 'GroupId' as sgid,websg.OpenPort from (select\naccount_id,instance_id,network_interface_id,private_ip_address,public_ip\nfrom account_all.aws_vpc_eip) as eip inner join (select\nnetwork_interface_id,groups from account_all.aws_ec2_network_interface) as\neni on eip.network_interface_id=eni.network_interface_id cross join\njsonb_array_elements(eni.groups) as sg inner join (select\ngroup_id,ip_permission -> 'FromPort' as OpenPort from\naccount_all.aws_vpc_security_group cross join\njsonb_array_elements(ip_permissions) as ip_permission where (ip_permission -\n>> 'FromPort'='80' and ip_permission ->> 'ToPort'='80') or (ip_permission -\n>> 'FromPort'='443' and ip_permission ->> 'ToPort'='443') or (ip_permission\n->> 'FromPort'='8080' and ip_permission ->> 'ToPort'='8080') or\n(ip_permission ->> 'FromPort'='8081' and ip_permission ->> 'ToPort'='8081')\nor (ip_permission ->> 'FromPort'='3128' and ip_permission ->>\n'ToPort'='3128') or (ip_permission ->> 'FromPort'='9080' and ip_permission -\n>> 'ToPort'='9080')) as websg on sg ->> 'GroupId'=websg.group_id\n\n</code></pre>\n<h4><a id=\"3_web__NLB_241\"></a>**示例3:查询开放 web 端口的 NLB</h4>\n<p>**</p>\n<pre><code class=\"lang-\">select nlb.account_id, nlb.name,nlb.arn from\naccount_all.aws_ec2_network_load_balancer as nlb inner join\n(select load_balancer_arn,port from\naccount_all.aws_ec2_load_balancer_listener where port in\n(80,443,8080,8081,3128,9080)) as listener on\nnlb.arn=listener.load_balancer_arn\n</code></pre>\n<h4><a id=\"4_Amazon_OpenSearch__252\"></a><strong>示例4:查询特定账户所使用 Amazon OpenSearch 版本</strong></h4>\n<pre><code class=\"lang-\">select account_id, arn, domain_id, domain_name, elasticsearch_version,\nenabled, endpoint from account_all.aws_elasticsearch_domain\n</code></pre>\n<h4><a id=\"5_259\"></a><strong>示例5:查询&过滤特定机型</strong></h4>\n<pre><code class=\"lang-\">select account_id, instance_id, instance_type, instance_state from\naccount_all.aws_ec2_instance where instance_type not like 'a1%' and\ninstance_type not like 'c5%' and instance_type not like 'c6%' and\ninstance_type not like 'd3%' and instance_type not like 'dl%' and\ninstance_type not like 'g4%' and instance_type not like 'g5%' and\ninstance_type not like 'hpc6%' and instance_type not like 'i3en%' and\ninstance_type not like 'im4gn%' and instance_type not like 'inf1%' and\ninstance_type not like 'is4gen%' and instance_type not like 'm5%' and\ninstance_type not like 'm6%' and instance_type not like 'p3dn%' and\ninstance_type not like 'p4%' and instance_type not like 'r5%' and\ninstance_type not like 'r6%' and instance_type not like 't3%' and\ninstance_type not like 't4%' and instance_type not like 'vt1%' and\ninstance_type not like 'x2gd%' and instance_type not like 'z1d%'\n</code></pre>\n<h4><a id=\"6_AMI__277\"></a><strong>示例6:查询特定实例 AMI 信息</strong></h4>\n<pre><code class=\"lang-\">select instance.account_id,instance.instance_id,ami.*,instance.tags from\naccount_all.aws_ec2_instance as instance left outer join (select\naccount_id,image_id,name,platform_details,description from\naccount_all.aws_ec2_ami_shared where owner_id='141808717104') as ami on\ninstance.account_id=ami.account_id and instance.image_id=ami.image_id\n\n</code></pre>\n<h4><a id=\"7_SSM__288\"></a>**示例7:查询特定实例 SSM 托管状态</h4>\n<p>**</p>\n<pre><code class=\"lang-\">select ec2.account_id as account_id, ec2.instance_id, mi.computer_name,\nmi.platform_name, mi.platform_version, ec2.instance_type,\nec2.instance_state, mi.agent_version, mi.is_latest_version, mi.ping_status,\nec2.launch_time from (select\naccount_id,instance_id,instance_state,instance_type,launch_time from\naccount_all.aws_ec2_instance) as ec2 left outer join (select\naccount_id,agent_version,computer_name,instance_id,is_latest_version,ping_st\natus,platform_name,platform_version from\naccount_all.aws_ssm_managed_instance) as mi on\nec2.instance_id=mi.instance_id order by account_id\n</code></pre>\n<p>####** 示例8:查询 ENI 与 RDS 关联情况**</p>\n<pre><code class=\"lang-\">select i.*,r.* from (select rdsinstance.*,rdsinstanceip.ip from (select\naccount_id, db_instance_identifier, arn, endpoint_address, engine,\nengine_version, vpc_id, subnets from account_all.aws_rds_db_instance) as\nrdsinstance join (select domain,ip from net.net_dns_record where domain in\n(select endpoint_address from account_all.aws_rds_db_instance) and type =\n'A' and target is null) as rdsinstanceip on\nrdsinstance.endpoint_address=rdsinstanceip.domain) as r join (select\naccount_id,network_interface_id,private_ip_address,association_public_ip\nfrom account_all.aws_ec2_network_interface where\nattached_instance_owner_id='amazon-rds') as i on r.account_id=i.account_id\nand (r.ip=i.private_ip_address or r.ip=i.association_public_ip)\n</code></pre>\n<h4><a id=\"9_ENI_319\"></a><strong>示例9:查询未使用的 ENI</strong></h4>\n<pre><code class=\"lang-\">select\naccount_id,network_interface_id,description,private_ip_address,association_p\nublic_ip from account_all.aws_ec2_network_interface where status!='in-use'\n</code></pre>\n<h3><a id=\"6__327\"></a><strong>6. 结尾</strong></h3>\n<p>至此,我们介绍了一个云原生的轻量级安全基线检查方案,涉及该方案的前置准备、部署过程以及使用步骤。同时,附上基于 Steampipe 的常用安全基线检查查询语句示例,以供读者参考,进一步结合自身实际场景组合执行日常安全基线检查。</p>\n<h3><a id=\"7__331\"></a><strong>7. 参考资料</strong></h3>\n<p>更多关于 Steampipe connection 和查询的信息,请参考:</p>\n<p><a href=\"https://aws.amazon.com/cn/blogs/opensource/querying-aws-at-scale-across-apis-regions-and-accounts/\" target=\"_blank\">https://aws.amazon.com/cn/blogs/opensource/querying-aws-at-scale-across-apis-regions-and-accounts/</a></p>\n<h3><a id=\"_337\"></a>**本篇作者</h3>\n<p>**<br />\n<img src=\"https://dev-media.amazoncloud.cn/45a3b306fa9d48469ea2c26d25a729c0_image.png\" alt=\"image.png\" /></p>\n<h4><a id=\"_341\"></a><strong>霍延峰</strong></h4>\n<p>拥有超过18年的 IT 从业经历,包括 ERP 系统前端和后端开发人员、 OA 系统和基础架构运维、企业软件系统架构、数据库管理员和商业智能工程师、虚拟化和私有云工程师、公有云解决方案架构师。他热衷于使用新技术来解决客户的实际问题,在云架构和应用现代化、DevOps、数据科学和其他领域具有独特的见解。他从2016年开始为使用 Amazon 的 ECCOM 客户提供帮助,并陪伴数十家客户的 Amazon 迁移旅程,以及 ECCOM 自身从传统网络系统集成商到 Amazon 的现代 MSP 服务提供商的转型过程。</p>\n<p><img src=\"https://dev-media.amazoncloud.cn/b9d94acb8333467cbe7f866644b82238_image.png\" alt=\"image.png\" /></p>\n<h4><a id=\"_347\"></a><strong>陈琪</strong></h4>\n<p>亚马逊云科技合作伙伴解决方案架构师,超过十年 IT 从业经验,涉及产品研发、方案咨询、产品管理等多个环节。长期从事企业信息化架构设计与方案咨询,具有丰富的企业数字化转型实践经验,尤其在安全、数据分析、网络等领域具有深刻认知及丰富实践。现负责亚马逊云科技合作伙伴的方案设计与能力构建。</p>\n"}