使用 AWS SSM 的 SSH 日志记录和会话管理

已发表: 2022-03-11

设置自定义工具或脚本以在 Linux 上保留 SSH 日志可能很乏味且容易出错。

工程师可以使用rootshscreen或其他实用程序来记录用户活动,但如果用户权限设置不正确,熟练的用户可以删除审计日志以掩盖他们的踪迹。 另一种选择是在内核级别设置日志记录,但所需的专业知识并不常见。

值得庆幸的是,有一种方法可以记录用户活动,甚至无需编写单个 Linux 命令! 我们需要这些服务:

  • EC2
  • IAM(身份和访问管理)
  • KMS(密钥管理服务)
  • CloudWatch Logs(和/或 S3)
  • AWS 系统管理器(以前称为 SSM)

让我们看看如何设置它们。

EC2 和 IAM

启动 EC2 实例通常相当容易,但在启动期间必须完成一项关键任务:我们需要将 IAM 角色附加到我们的实例,否则我们将无法实现本文末尾详述的预期结果文章。

我们与 EC2 实例关联的 IAM 角色必须具有内置的AmazonSSMManagedInstanceCore策略,以及此策略(附加为内联或客户管理):

 { "Version": "2012-10-17", "Statement": [ { "Action": [ "logs:CreateLogStream", "logs:DescribeLogStreams", "logs:DescribeLogGroups", "logs:PutLogEvents" ], "Effect": "Allow", "Resource": "*" } ] }

除了 IAM 角色,我们通常使用这个 EC2 实例配置:

  • 操作系统是 Amazon Linux 2,因为默认情况下它安装了 AWS Systems Manager 代理(SSM 代理)。 (Ubuntu 发行版也是如此,这也是一种选择。)
  • 实例类型是 t3.micro(但任何类型都可以)。
  • AWS 分配给 VPC 的默认安全组将起作用,因为我们不需要为此练习打开 SSH 端口。

我们可以开始设置 KMS,而无需等待 EC2 实例启动。

知识管理系统

如果我们希望传送到 CloudWatch 的所有会话日志都以加密方式存储,我们需要一个 KMS 密钥。 让我们转到 KMS 服务并创建一个密钥。

带有面包屑“KMS”、“客户管理的密钥”和“创建密钥”的 AWS 屏幕截图,当前位于第 1 步:“配置密钥”。 “密钥类型”可以设置为“对称”(选中)或“非对称”。在“高级选项”下,“密钥材料来源”设置可以是“KMS”(选中)、“外部”或“自定义密钥存储(CloudHSM)”。
第 1 步:选择对称密钥类型。

具有相同面包屑的 AWS 屏幕截图,现在在第 2 步:“添加标签”。别名字段设置为“cwlg”,可选描述字段留空,可选标签字段未添加任何标签。
第 2 步:命名我们的密钥。

具有相同面包屑的 AWS 屏幕截图,现在在第 3 步:“定义关键管理权限”。第一个字段“关键管理员”有一个空白搜索框,其中包含 10 行结果(第 1 页,共 3 页),其中包含名称、路径和类型列。只有第一行(具有相应的列值“admin”、“/”和“User”)选中了相应的复选框。另一个字段“密钥删除”有一个选项“允许密钥管理员删除此密钥”,它的复选框也被选中。
第 3 步(可选):分配管理员。

我们建议分配一个管理员,以便 AWS 账户根用户以外的用户可以管理密钥,但如果其他人不需要访问,我们可以跳过第 3 步。

在这里,我们选择了 IAM 用户“admin”作为密钥管理员,但我们可以自由选择任何用户或角色。 我们还可以选择禁用管理员的密钥删除权限。

具有相同面包屑的 AWS 屏幕截图,现在在第 4 步:“定义密钥使用权限”。第一个字段“此帐户”具有与第 3 步相同的搜索结果,但没有一个被选中。另一个字段“其他 AWS 账户”没有添加任何内容。
第 4 步:跳过用户分配页面。

我们不会将任何用户分配给此密钥,因为我们希望此密钥仅供 CloudWatch Logs 服务用于 SSH 日志加密和解密操作。

具有相同面包屑的 AWS 屏幕截图,现在在第 5 步:“审查”。第一个字段“密钥配置”将“密钥类型”列为“对称”,将“密钥规范”列为“SYMMETRIC_DEFAULT”,将“密钥使用”列为“加密和解密”,将“来源”列为“AWS_KMS 。”下一个字段“别名和描述”列出了一个别名“cwlg”,没有描述。下一个字段“标签”不显示任何数据。最后一个字段“密钥策略”包括一个预先填充了 JSON 格式策略的文本框。
第 5 步:查看我们的配置并交换默认密钥策略。

在 Review 页面上,我们需要更改 KMS 生成的密钥策略,因为它不包括 CloudWatch Logs 使用密钥的权限。 我们将用此策略替换它:

 { "Version": "2012-10-17", "Statement": [ { "Sid": "Enable IAM User Permissions", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::ACCOUNT_ID:root" }, "Action": "kms:*", "Resource": "*" }, { "Sid": "Allow access for Key Administrators", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::ACCOUNT_ID:user/USERNAME" }, "Action": [ "kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*", "kms:Put*", "kms:Update*", "kms:Revoke*", "kms:Disable*", "kms:Get*", "kms:Delete*", "kms:TagResource", "kms:UntagResource", "kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion" ], "Resource": "*" }, { "Sid": "Allow access to CloudWatch Log", "Effect": "Allow", "Principal": { "Service": "logs.REGION.amazonaws.com" }, "Action": [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ], "Resource": "*", "Condition": { "ArnLike": { "kms:EncryptionContext:aws:logs:arn": "arn:aws:logs:REGION:ACCOUNT_ID:*" } } } ] }

确保替换所有占位符:

  • ACCOUNT_ID成为我们的 AWS 账户 ID。
  • USERNAME成为在步骤 3 中选择的管理员用户名。如果我们选择退出该步骤,则在此处删除第二个语句块(带有"Sid": "Allow access for Key Administrators" )。
  • REGION成为我们将服务部署到的区域标识符代码(例如us-west-1 )。

有了这个,KMS 准备好了。

CloudWatch 日志组

接下来,我们需要一个 CloudWatch Log 组(和/或一个 S3 存储桶——见下文),SSM 代理可以在其中发送 SSH 会话日志。 让我们创建它。

带有面包屑“CloudWatch”、“CloudWatch Logs”、“日志组”和“创建日志组”的 AWS 屏幕截图。没有多步骤侧边栏。第一个字段“日志组详细信息”具有三个子字段:“日志组名称”(设置为“ssm-session-demo”)、“保留设置”(从下拉列表中设置为“永不过期”)和“KMS 密钥 ARN - 可选”(设置为以“arn:aws:kms”开头的截断值)。第二个字段“标签”没有标签。
创建“CloudWatch Logs”日志组。

请注意 KMS 密钥 ARN 字段:在 KMS 部分的第 5 步中创建密钥后,AWS 会在此处为我们提供所需的值。

(如果我们之前没有将正确的策略与我们的 KMS 密钥相关联,允许 CloudWatch Logs 服务使用该密钥,此时我们将收到与 KMS 密钥相关的错误。)

将 SSH 日志存储在 S3 存储桶中

为了使用 S3 存储活动日志而不是 CloudWatch Logs,我们需要将这些权限作为单独的策略添加到我们的 EC2 实例配置文件(或手动将它们与我们可能需要关联的其他权限组合):

 { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject" ], "Resource": "arn:aws:s3:::BUCKET_NAME/*" }, { "Effect": "Allow", "Action": [ "s3:GetEncryptionConfiguration" ], "Resource": "*" }, { "Effect": "Allow", "Action": "kms:GenerateDataKey", "Resource": "*" } ] }

在上面的代码段中,请务必替换BUCKET_NAME占位符。

既然我们已经设置了存储日志的位置(CloudWatch Logs、S3 存储桶或两者兼而有之),我们就可以利用 SSH 会话了。

AWS Systems Manager 会话管理器

这是最后一个关键步骤,我们在其中配置对 Linux 机器的安全访问以进行 SSH 会话监控和日志记录。 我们将从会话管理器仪表板开始。

AWS Session Manager 控制面板的屏幕截图,其中包含“工作原理”、“为什么使用 Session Manager?”、“开始使用”、“更多资源”和右上角的“开始会话”部分。后一部分有一个橙色的“开始会话”按钮和一个白色的“配置首选项”按钮。
第 1 步:开始使用仪表板。

在仪表板上,单击右上角“开始会话”框中的白色“配置首选项”按钮以启用会话日志记录。

在 Preferences 页面上,我们将找到多个可以探索的部分,但我们的重点将是将 SSH 会话日志流式传输到 CloudWatch 或 S3,以使我们能够快速查看 Linux 机器中发生的情况。

标题为“CloudWatch 日志记录”的 AWS 部分的屏幕截图。它的第一个设置,也称为“CloudWatch 日志记录”,有一个标记为 Enable 的复选框已选中。下一个设置“选择您的首选日志记录选项”选择了“流会话日志(推荐)”而不是“上传会话日志”。下一个设置“强制加密”有一个标记为“仅允许加密的 CloudWatch 日志组”的复选框已选中。最终设置“CloudWatch 日志组”选择了“从列表中选择日志组名称”而不是“在文本框中输入日志组”。在它下面是一个列表“CloudWatch 日志组”,其中选择了“ssm-session-demo”。它有相应的列“加密”(设置为“加密”)、“过期事件”(设置为“永不过期”)、“度量过滤器”(设置为 0)、“存储的字节数”(设置为 0)和“创建时间”时间戳。
步骤 2a:启用 CloudWatch 日志记录。

在“CloudWatch 日志记录”部分之后,有一个“S3 日志记录”部分,我们可以在其中选择存储桶。

标题为“S3 日志记录”的 AWS 部分的屏幕截图。它的第一个设置“向 S3 发送会话日志”有一个标记为“启用”的复选框,该复选框已被选中。它的下一个设置“强制加密”有一个标记为“仅允许加密的 S3 存储桶”的复选框已选中。它的下一个设置“选择 S3 存储桶”选择了“从列表中选择存储桶名称”而不是“在文本框中输入存储桶名称”。在其下方,从下拉列表中选择“ssm-session-demo”。最后一个字段“S3 密钥前缀 - 可选”为空白。
步骤 2b:启用 S3 日志记录。

配置 SSH 日志记录后,我们可以通过 SSH 连接到我们的 Linux 机器并执行一些命令来查看活动是否被捕获。

所以,让我们开始一个会话。 在同一页面上,我们将找到一个“会话”选项卡,我们可以在其中开始会话。 单击“开始会话”按钮将为我们提供一个 EC2 机器列表,我们可以在这些机器上启动会话:

带有面包屑的 AWS 屏幕截图 AWS Systems Manager、Session Manager 和 Start a session。 “目标实例”搜索框没有填写任何查询,只有一个结果,“实例名称”设置为“SSM Demo”。
第 3 步:选择我们的 EC2 实例以启动 SSH 会话。

如果我们没有在列表中看到我们的 EC2 Linux 实例,我们应该检查它是否处于运行状态并具有与它相关联的 IAM 权限,如前所述。

处理 SSM 代理“不支持流式日志”错误

如果我们收到错误消息说安装在我们的 EC2 机器上的 SSM 代理版本不支持流式 CloudWatch 日志,请不要担心。 有一种无痛的方法可以解决这个问题。

红色背景上带有白色文本的 AWS 错误消息的屏幕截图。消息旁边有一个带圆圈的 X,“此实例上安装的 SSM 代理版本不支持将日志流式传输到 CloudWatch。请将 SSM 代理更新到最新版本,或者在您的首选项中禁用流式日志选项。”
潜在的“过时的 SSM 代理版本”错误。

要更新 SSM 代理,我们需要导航到AWS Systems Manager服务左侧面板中的Run Command

AWS Systems Manager Run Command 控制面板的屏幕截图,其中包含“工作原理”、“功能和优势”、“用例和博客文章”、“文档”以及右上角的“管理您的实例”部分。该部分仅包含一个橙色的“运行命令”按钮。
第 1 步:从“运行命令”仪表板开始。

到达那里后,我们可以单击橙色的“运行命令”按钮,进入一个新页面,我们可以在其中填写一些参数。

带有面包屑的 AWS 屏幕截图 AWS Systems Manager、Run Command 和 Run a command。标有“命令文档”的搜索框列出了 10 行(超过 5 页的第 4 页),其中选择了一个名为“AWS-UpdateSSMAgent”的行。它的“所有者”列中有“Amazon”,“平台类型”列中有“Windows、Linux”。底部的“文档版本”字段从下拉列表中选择了“1(默认)”。
第 2 步:选择命令文档。

我们首先从列表中选择AWS-UpdateSSMAgent

标题为“目标”的 AWS 部分的屏幕截图。第一个字段,也称为“目标”,具有“指定实例标签”、“手动选择实例”(选中)和“选择资源组”选项。底部是一个没有查询的“Instances”搜索框,其唯一的结果是“SSM Demo”,已选中。行中对应的实例 ID 被复制到“实例”正上方带有 X 的框中。
第 3 步:选择具有需要更新的 SSM 代理的 EC2 实例。

选择后,我们将向下滚动,直到看到“目标”部分。 在那里,我们需要选择要更新 SSM 代理的 EC2 实例,然后在最后点击“运行”按钮。 这会将我们发送到可以监控更新进度的页面。

带有面包屑“AWS Systems Manager”、“Run Command”和“Command ID”(后跟 GUID)的 AWS 屏幕截图。第一部分“命令状态”显示成功指标,下一部分“目标和输出”的唯一一行也显示了成功指标,其中列出了之前的单个实例。底部还有两个未展开的部分,“命令描述”和“命令参数”。
第 4 步:监控我们的更新进度。

代理更新不应超过五分钟。 一旦完成,我们应该能够在会话管理器中创建一个会话。

此时,我们应该启动了一个 SSH 会话。

终端上方带有会话 ID 和实例 ID 的 AWS 屏幕截图。提示符是“sh-4.2$”,输入了命令“whoami”和“pwd”,分别输出“ssm-user”和“/usr/bin”。
通过 AWS Systems Manager Session Manager 使用 SSM 代理的 SSH 会话。

执行几个命令后,让我们导航到 CloudWatch Logs 日志组(或我们的 S3 存储桶,未显示)并确认正在记录活动。

带有面包屑“CloudWatch”、“CloudWatch Logs”、“日志组”、“ssm-session-demo”和上一步的会话 ID 的 AWS 屏幕截图。唯一的部分是一个搜索框“日志事件”,其中的行都有一个时间戳和一个 JSON 格式的消息。其中一个被扩展以显示其漂亮的 JSON 打印,并且右侧有一个白色按钮,标记为“复制”。
记录在 CloudWatch Logs 中的 SSH 日志事件。

我们现在有了一个启用静态加密的设置,记录在我们的 Linux 机器中触发的每个命令。

事实上,每个命令都可能超出我们的预期:会话期间提供或生成的任何秘密都将记录在 CloudWatch 或 S3 中,任何拥有所需权限的人都可以看到。 为了防止这种情况,我们可以使用stty -echo; read passwd; stty echo; stty -echo; read passwd; stty echo; 对于我们需要在会话期间提供的每个秘密。

一个很棒的 SSM/SSH AWS 日志记录解决方案,有一些小注意事项

会话管理器是一个有用的工具,可以在无需打开端口 22 的情况下远程访问我们在 AWS 中的虚拟机。事实上,如果我们使用端口转发或直接 SSH 连接,我们无法以这种方式生成 SSH 日志,因为会话管理器文档说明。

尽管如此,将会话管理器与会话记录相结合是控制和监视虚拟机内活动的强大解决方案。 此外,我们不收取使用 Session Manager 服务的费用。 我们只需为我们的 EC2 实例和 CloudWatch Logs 或用于存储日志的 S3 存储桶付费。

对于喜欢视频教程的读者,我在 YouTube 上更彻底地介绍了一个非常相似的过程。


进一步阅读 Toptal 工程博客:

  • 案例研究:为什么我将 AWS 云基础设施用于我的产品