Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅
中国的 Amazon Web Services 服务入门
(PDF)。
本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
Image Builder 的安全最佳实践
EC2Image Builder 提供了许多安全功能,供您在制定和实施自己的安全策略时考虑。以下最佳实践是一般指导原则,并不代表完整安全解决方案。这些最佳实践可能不适合环境或不满足环境要求,请将其视为有用的考虑因素而不是惯例。
-
不要在 Image Builder 配方中使用过于宽松的安全组。
-
不要与您不信任的账户共享镜像。
-
不要公开包含私有或敏感数据的镜像。
-
在镜像生成期间应用所有可用的 Windows 或 Linux 安全补丁。
-
定期为您的 macOS 配方应用托管AMI更新,并创建新映像以启动安装了最新安全补丁的实例。
我们强烈建议您测试映像,以验证安全状况和适用的安全合规性级别。
IMDSv2适用于 Image Builder 管道
当您的 Image Builder 管道运行时,它会发送HTTP请求以启动EC2实例,Image Builder 使用这些实例来构建和测试您的映像。要配置您的管道用于启动请求的版本IMDS,请在 Image Builder 基础架构配置实例元数据设置中设置httpTokens
参数。
我们建议您将 Image Builder 从管道版本启动的所有EC2实例配置为使用,IMDSv2以便实例元数据检索请求需要签名的令牌标头。
有关 Image Builder 基础设施配置的更多信息,请参阅 管理 Image Builder 基础设施配置 有关 Linux 映像的EC2实例元数据选项的更多信息,请参阅 Amazon EC2 用户指南中的配置实例元数据选项。对于 Windows 映像,请参阅亚马逊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 的最佳实践。
- macOS
-
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 rm -f $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 rm -f {} \;
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 rm -f {} \;
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"
"/var/log/amazon/ec2/ec2-macos-init.log"
"/var/log/amazon/ec2/ena-ethernet.log"
"/var/log/amazon/ec2/system-monitoring.log"
)
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 rm -f {} \;
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 rm -f {} \;
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 rm -f /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 rm -f /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 rm -f {} \;
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 rm -f /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 rm -f {} \;
sudo rm -rf /var/log/journal/*
fi
sudo touch /etc/machine-id
覆盖 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
|