EC2 Image Builder 的安全最佳实践 - EC2 Image Builder
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

EC2 Image Builder 的安全最佳实践

EC2 Image Builder 提供了在您开发和实施自己的安全策略时需要考虑的大量安全功能。以下最佳实践是一般指导原则,并不代表完整安全解决方案。这些最佳实践可能不适合环境或不满足环境要求,请将其视为有用的考虑因素而不是惯例。

  • 不要在 Image Builder 配方中使用过于宽松的安全组。

  • 不要与您不信任的账户共享镜像。

  • 不要公开包含私有或敏感数据的镜像。

  • 在镜像生成期间应用所有可用的 Windows 或 Linux 安全补丁。

我们强烈建议您测试映像,以验证安全状况和适用的安全合规性级别。

适用于 Image Builder 管道的 IMDSv2

当您的 Image Builder 管道运行时,它会发送 HTTP 请求以启动 EC2 实例,Image Builder 使用这些实例来构建和测试您的映像。要配置您的管道用于启动请求的 IMDS 版本,请在 Image Builder 基础架构配置实例元数据设置中设置 httpTokens 参数。

注意

我们建议,将 Image Builder 从管道版本中启动的所有 EC2 实例配置为使用 Imdsv2,这样实例元数据检索请求将需要签名令牌标头。

有关 Image Builder 基础设施配置的更多信息,请参阅 管理 EC2 Image Builder 基础设施配置 有关 Linux Image 的 EC2 实例元数据选项的更多信息,请参阅适用于 Linux 实例的 Amazon EC2 用户指南中的配置实例元数据选项。有关 Windows 映像,请参阅《适用于 Windows 实例的 Amazon EC2 用户指南》中的配置实例元数据选项

需要在构建后进行清理

Image Builder 完成自定义映像的所有构建步骤后,Image Builder 会为测试和映像创建准备构建实例。在关闭构建实例以创建快照之前,Image Builder 会执行以下清理操作以确保映像的安全:

Linux

Image Builder 管道运行清理脚本,以帮助确保最终映像遵循安全最佳实践,并删除任何不应延续到快照中的构建构件或设置。但是,您可以跳过脚本的各个部分,或者完全覆盖用户数据。因此,Image Builder 管道生成的映像不一定符合任何特定的监管标准。

当管道完成其构建期和测试期后,Image Builder 会在创建输出映像之前自动运行以下清理脚本。

重要

如果您在配方中覆盖用户数据,则脚本将无法运行。在这种情况下,请确保在用户数据中包含一个用于创建名为 perform_cleanup 的空文件的命令。Image Builder 会检测到此文件并在创建新映像之前运行清理脚本。

#!/bin/bash if [[ ! -f {{workingDirectory}}/perform_cleanup ]]; then echo "Skipping cleanup" exit 0 else sudo rm -f {{workingDirectory}}/perform_cleanup fi function cleanup() { FILES=("$@") for FILE in "${FILES[@]}"; do if [[ -f "$FILE" ]]; then echo "Deleting $FILE"; sudo shred -zuf $FILE; fi; if [[ -f $FILE ]]; then echo "Failed to delete '$FILE'. Failing." exit 1 fi; done }; # Clean up for cloud-init files CLOUD_INIT_FILES=( "/etc/sudoers.d/90-cloud-init-users" "/etc/locale.conf" "/var/log/cloud-init.log" "/var/log/cloud-init-output.log" ) if [[ -f {{workingDirectory}}/skip_cleanup_cloudinit_files ]]; then echo "Skipping cleanup of cloud init files" else echo "Cleaning up cloud init files" cleanup "${CLOUD_INIT_FILES[@]}" if [[ $( sudo find /var/lib/cloud -type f | sudo wc -l ) -gt 0 ]]; then echo "Deleting files within /var/lib/cloud/*" sudo find /var/lib/cloud -type f -exec shred -zuf {} \; fi; if [[ $( sudo ls /var/lib/cloud | sudo wc -l ) -gt 0 ]]; then echo "Deleting /var/lib/cloud/*" sudo rm -rf /var/lib/cloud/* || true fi; fi; # Clean up for temporary instance files INSTANCE_FILES=( "/etc/.updated" "/etc/aliases.db" "/etc/hostname" "/var/lib/misc/postfix.aliasesdb-stamp" "/var/lib/postfix/master.lock" "/var/spool/postfix/pid/master.pid" "/var/.updated" "/var/cache/yum/x86_64/2/.gpgkeyschecked.yum" ) if [[ -f {{workingDirectory}}/skip_cleanup_instance_files ]]; then echo "Skipping cleanup of instance files" else echo "Cleaning up instance files" cleanup "${INSTANCE_FILES[@]}" fi; # Clean up for ssh files SSH_FILES=( "/etc/ssh/ssh_host_rsa_key" "/etc/ssh/ssh_host_rsa_key.pub" "/etc/ssh/ssh_host_ecdsa_key" "/etc/ssh/ssh_host_ecdsa_key.pub" "/etc/ssh/ssh_host_ed25519_key" "/etc/ssh/ssh_host_ed25519_key.pub" "/root/.ssh/authorized_keys" ) if [[ -f {{workingDirectory}}/skip_cleanup_ssh_files ]]; then echo "Skipping cleanup of ssh files" else echo "Cleaning up ssh files" cleanup "${SSH_FILES[@]}" USERS=$(ls /home/) for user in $USERS; do echo Deleting /home/"$user"/.ssh/authorized_keys; sudo find /home/"$user"/.ssh/authorized_keys -type f -exec shred -zuf {} \; done for user in $USERS; do if [[ -f /home/"$user"/.ssh/authorized_keys ]]; then echo Failed to delete /home/"$user"/.ssh/authorized_keys; exit 1 fi; done; fi; # Clean up for instance log files INSTANCE_LOG_FILES=( "/var/log/audit/audit.log" "/var/log/boot.log" "/var/log/dmesg" "/var/log/cron" ) if [[ -f {{workingDirectory}}/skip_cleanup_instance_log_files ]]; then echo "Skipping cleanup of instance log files" else echo "Cleaning up instance log files" cleanup "${INSTANCE_LOG_FILES[@]}" fi; # Clean up for TOE files if [[ -f {{workingDirectory}}/skip_cleanup_toe_files ]]; then echo "Skipping cleanup of TOE files" else echo "Cleaning TOE files" if [[ $( sudo find {{workingDirectory}}/TOE_* -type f | sudo wc -l) -gt 0 ]]; then echo "Deleting files within {{workingDirectory}}/TOE_*" sudo find {{workingDirectory}}/TOE_* -type f -exec shred -zuf {} \; fi if [[ $( sudo find {{workingDirectory}}/TOE_* -type f | sudo wc -l) -gt 0 ]]; then echo "Failed to delete {{workingDirectory}}/TOE_*" exit 1 fi if [[ $( sudo find {{workingDirectory}}/TOE_* -type d | sudo wc -l) -gt 0 ]]; then echo "Deleting {{workingDirectory}}/TOE_*" sudo rm -rf {{workingDirectory}}/TOE_* fi if [[ $( sudo find {{workingDirectory}}/TOE_* -type d | sudo wc -l) -gt 0 ]]; then echo "Failed to delete {{workingDirectory}}/TOE_*" exit 1 fi fi # Clean up for ssm log files if [[ -f {{workingDirectory}}/skip_cleanup_ssm_log_files ]]; then echo "Skipping cleanup of ssm log files" else echo "Cleaning up ssm log files" if [[ $( sudo find /var/log/amazon/ssm -type f | sudo wc -l) -gt 0 ]]; then echo "Deleting files within /var/log/amazon/ssm/*" sudo find /var/log/amazon/ssm -type f -exec shred -zuf {} \; fi if [[ $( sudo find /var/log/amazon/ssm -type f | sudo wc -l) -gt 0 ]]; then echo "Failed to delete /var/log/amazon/ssm" exit 1 fi if [[ -d "/var/log/amazon/ssm" ]]; then echo "Deleting /var/log/amazon/ssm/*" sudo rm -rf /var/log/amazon/ssm fi if [[ -d "/var/log/amazon/ssm" ]]; then echo "Failed to delete /var/log/amazon/ssm" exit 1 fi fi if [[ $( sudo find /var/log/sa/sa* -type f | sudo wc -l ) -gt 0 ]]; then echo "Deleting /var/log/sa/sa*" sudo shred -zuf /var/log/sa/sa* fi if [[ $( sudo find /var/log/sa/sa* -type f | sudo wc -l ) -gt 0 ]]; then echo "Failed to delete /var/log/sa/sa*" exit 1 fi if [[ $( sudo find /var/lib/dhclient/dhclient*.lease -type f | sudo wc -l ) -gt 0 ]]; then echo "Deleting /var/lib/dhclient/dhclient*.lease" sudo shred -zuf /var/lib/dhclient/dhclient*.lease fi if [[ $( sudo find /var/lib/dhclient/dhclient*.lease -type f | sudo wc -l ) -gt 0 ]]; then echo "Failed to delete /var/lib/dhclient/dhclient*.lease" exit 1 fi if [[ $( sudo find /var/tmp -type f | sudo wc -l) -gt 0 ]]; then echo "Deleting files within /var/tmp/*" sudo find /var/tmp -type f -exec shred -zuf {} \; fi if [[ $( sudo find /var/tmp -type f | sudo wc -l) -gt 0 ]]; then echo "Failed to delete /var/tmp" exit 1 fi if [[ $( sudo ls /var/tmp | sudo wc -l ) -gt 0 ]]; then echo "Deleting /var/tmp/*" sudo rm -rf /var/tmp/* fi # Shredding is not guaranteed to work well on rolling logs if [[ -f "/var/lib/rsyslog/imjournal.state" ]]; then echo "Deleting /var/lib/rsyslog/imjournal.state" sudo shred -zuf /var/lib/rsyslog/imjournal.state sudo rm -f /var/lib/rsyslog/imjournal.state fi if [[ $( sudo ls /var/log/journal/ | sudo wc -l ) -gt 0 ]]; then echo "Deleting /var/log/journal/*" sudo find /var/log/journal/ -type f -exec shred -zuf {} \; sudo rm -rf /var/log/journal/* fi sudo touch /etc/machine-id
Windows

Image Builder 管道在自定义 Windows 映像后,将运行 Microsoft Sysprep 实用程序。这些操作遵循了强化和清理图像 Amazon 的最佳实践。

覆盖 Linux 清理脚本

Image Builder 创建的映像在默认情况下是安全的,并遵循我们的安全最佳实践。但是,一些更高级的使用案例可能需要您跳过内置清理脚本的一个或多个部分。如果您确实需要跳过一些清理部分,我们强烈建议您测试输出 AMI,以确保映像的安全。

重要

跳过清理脚本中的一些部分可能会导致敏感信息(例如所有者帐户详细信息或 SSH 密钥)被包含在最终映像中,并被包含在从该映像启动的任何实例中。在不同的可用区、区域或账户中启动时,您也可能会遇到问题。

下表概述了清理脚本的各个部分,这些部分中删除的文件,以及可用于标记 Image Builder 应跳过的某个部分的文件名。要跳过清理脚本的特定部分,您可以使用 CreateFile 组件操作模块或用户数据中的命令(如果已覆盖)来创建一个空文件,其名称在跳过部分文件名列中指定。

注意

为跳过清理脚本的某一部分而创建的文件不应包含文件扩展名。例如,如果您想跳过脚本的 CLOUD_INIT_FILES 部分,但创建了一个名为 skip_cleanup_cloudinit_files.txt 的文件,那么 Image Builder 将无法识别要跳过的文件。

输入

清理部分

文件已删除

跳过部分文件名

CLOUD_INIT_FILES

/etc/sudoers.d/90-cloud-init-users

/etc/locale.conf

/var/log/cloud-init.log

/var/log/cloud-init-output.log

skip_cleanup_cloudinit_files

INSTANCE_FILES

/etc/.updated

/etc/aliases.db

/etc/hostname

/var/lib/misc/postfix.aliasesdb-stamp

/var/lib/postfix/master.lock

/var/spool/postfix/pid/master.pid

/var/.updated

/var/cache/yum/x86_64/2/.gpgkeyschecked.yum

skip_cleanup_instance_files

SSH_FILES

/etc/ssh/ssh_host_rsa_key

/etc/ssh/ssh_host_rsa_key.pub

/etc/ssh/ssh_host_ecdsa_key

/etc/ssh/ssh_host_ecdsa_key.pub

/etc/ssh/ssh_host_ed25519_key

/etc/ssh/ssh_host_ed25519_key.pub

/root/.ssh/authorized_keys

/home/<all users>/.ssh/authorized_keys;

skip_cleanup_ssh_files

INSTANCE_LOG_FILES

/var/log/audit/audit.log

/var/log/boot.log

/var/log/dmesg

/var/log/cron

skip_cleanup_instance_log_files

TOE_FILES

{{workingDirectory}}/TOE_*

skip_cleanup_toe_files

SSM_LOG_FILES

/var/log/amazon/ssm/*

skip_cleanup_ssm_log_files