【问题标题】:What's the best method for passing AWS credentials as user data to an EC2 instance?将 AWS 凭证作为用户数据传递给 EC2 实例的最佳方法是什么?
【发布时间】:2010-10-13 01:18:02
【问题描述】:

我有一个基于 AWS 的作业处理架构,需要 EC2 实例查询 S3 和 SQS。为了让正在运行的实例能够访问 API,凭据以 base64 编码的 shell 脚本的形式作为用户数据 (-f) 发送。例如:

$ cat ec2.sh
...
export AWS_ACCOUNT_NUMBER='1111-1111-1111'
export AWS_ACCESS_KEY_ID='0x0x0x0x0x0x0x0x0x0'
...
$ zip -P 'secret-password' ec2.sh
$ openssl enc -base64 -in ec2.zip

许多实例已启动...

$ ec2run ami-a83fabc0 -n 20 -f ec2.zip

每个实例都使用硬编码到初始化脚本中的“秘密密码”对 ec2.zip 进行解码和解密。虽然它确实有效,但我的方法有两个问题。

  1. 'zip -P' 不是很安全
  2. 密码在实例中是硬编码的(始终是“秘密密码”)

方法和here描述的方法很相似

有没有更优雅或被接受的方法?使用 gpg 加密凭据并将私钥存储在实例上以对其进行解密是我现在正在考虑的一种方法,但我不知道有任何警告。我可以直接使用 AWS 密钥对吗?我是否遗漏了 API 中一些非常明显的部分?

【问题讨论】:

    标签: encryption amazon-s3 amazon-ec2 amazon-web-services


    【解决方案1】:

    您可以将凭据存储在机器上(或转移、使用然后删除它们。)

    您可以通过安全通道传输凭据(例如,使用 scp 和非交互式身份验证,例如密钥对),这样您就不需要执行任何自定义加密(只需确保将权限正确设置为 @987654324 @ 始终在密钥文件上,例如设置主文件的权限并使用scp -p)

    如果以上内容不能回答您的问题,请提供更具体的详细信息。您的设置是什么以及您要实现的目标。是否要从一个中心位置在多个节点上启动 EC2 操作? SSH 在多个节点和中心位置之间是否可用?等等。


    编辑

    您是否考虑过 parameterizing your AMI,要求实例化您的 AMI 的人员首先使用其 AWS 密钥填充用户数据 (ec2-run-instances -f user-data-file)?然后,您的 AMI 可以从 http://169.254.169.254/1.0/user-data 动态检索这些每个实例的参数。


    更新

    好的,下面是迄今为止讨论的各种方法的安全性比较:

    1. 存储在 AMI user-data 未加密时的数据安全
      • 任何 管理登录 AMI 并有权访问telnetcurlwget 等的用户都可以访问明文数据(可以访问明文http://169.254.169.254/1.0/user-data)
      • 您容易受到代理请求攻击(例如,攻击者要求 AMI 上可能运行或未运行的 Apache 获取并转发明文 http://169.254.169.254/1.0/user-data
    2. 存储在 AMI user-data 中并使用易于获取的密钥加密(或解密)时的数据安全性
      • 容易获得的密钥(密码)可能包括:
        • 密钥硬编码在 ABI 内的脚本中(攻击者可以在其中获取 ABI)
        • 密钥硬编码在 AMI 本身的脚本中,任何设法登录 AMI 的用户都可以读取该脚本
        • 任何其他容易获得的信息,例如公钥等。
        • 任何私钥(其公钥可能很容易获得)
      • 给定一个易于获得的密钥(密码),第 1 点中确定的相同问题同样适用,即:
        • 任何用户可以访问解密的数据,他们可以访问 AMI 并有权访问telnetcurlwget 等(可以访问明文@ 987654338@)
        • 您容易受到代理请求攻击(例如,攻击者要求 AMI 上可能运行或未运行的 Apache 获取并转发加密的 http://169.254.169.254/1.0/user-data,然后使用易于获得的密钥进行解密)
    3. 存储在 AMI user-data 中并使用不易获得的密钥加密时的数据安全性
      • 平均
      • 任何管理登录 AMI 并有权访问telnetcurlwget 等的用户都可以访问加密数据(可以访问加密的http://169.254.169.254/1.0/user-data )
        • 然后可以使用暴力攻击尝试解密加密数据
    4. 数据存储在 AMI 上的安全位置时的安全性(加密没有附加价值)
      • 更高
      • 数据只能由一个用户访问,即需要数据才能操作的用户
        • 例如用户拥有的文件:掩码为 0600 或 0400 的用户
      • 攻击者必须能够冒充特定用户才能访问数据
        • 额外的安全层,例如拒绝用户直接登录(必须通过root 进行交互式模拟)提高了安全性

    因此,涉及 AMI user-data 的任何方法都不是最安全的,因为访问机器上的任何用户(最弱点)会危及数据。

    如果 S3 凭证仅在有限的时间段内需要(即仅在部署过程中),则可以缓解这种情况,如果 AWS 允许您覆盖或删除 user-data 的内容完成后(但情况似乎并非如此。)如果可能的话,另一种方法是在部署过程期间创建临时 S3 凭据(在部署过程之后从user-data 泄露这些凭据已完成且凭证已在 AWS 中失效,不再构成安全威胁。)

    如果上述不适用(例如,已部署节点无限期需要 S3 凭据)或不可能(例如,不能仅为部署颁发临时 S3 凭据),那么最好的方法仍然是硬着头皮,scp 将凭据传递给多个节点,可能是并行的,具有正确的所有权和权限。

    【讨论】:

    • 我不想在实例中捆绑凭证,因为我希望我的 AMI 用户使用他们自己的 AWS 凭证。实例启动后,它将连接到启动实例的用户指定的 S3 存储桶和 SQS 队列。 SCP 在少数机器上工作正常,但不是 10 或 100。对于循环?嗯
    • 好的,所以您正在向任意数量的用户提供 AMI,每个用户都必须提供自己的 AWS 凭证才能连接到(您的?他们的?)S3 区域?跨度>
    • Vlad,“参数化您的 AMI”一文几乎就是我现在正在做的事情。实际上,blogs.oracle.com/ec2/entry/… 更接近。问题是我的用户数据是敏感的(AWS 凭据),密码必须包含在 AMI 中。
    • 您可以通过防火墙或黑洞 169.254.169.254 IP 地址使除 root 以外的任何人都无法访问用户数据。 root 可以重新获得访问权限,但普通用户不能。
    • 现在可以通过在 IAM 中创建角色并将其分配给实例来使用 InstanceProfile 凭证。 SDK 会在需要时自动下载凭据。
    【解决方案2】:

    我写了一篇文章,研究了将机密安全地传递给 EC2 实例的各种方法以及每种方法的优缺点。

    http://www.shlomoswidler.com/2009/08/how-to-keep-your-aws-credentials-on-ec2/

    【讨论】:

      【解决方案3】:

      最好的方法是使用instance profiles。基本思路是:

      • 创建实例配置文件
      • 创建新的 IAM 角色
      • 将策略分配给之前创建的角色,例如:

        { “陈述”: [ { “席德”:“Stmt1369049349504”, "动作": "sqs:", “效果”:“允许”, “资源”:“” } ] }

      • 将角色和实例配置文件关联在一起。

      • 当您启动一个新的 EC2 实例时,请确保您提供实例配置文件名称。

      如果一切正常,并且您用于从 EC2 实例中连接到 AWS 服务的库支持从实例元数据中检索凭证,您的代码将能够使用 AWS 服务。

      来自 boto-user 邮件列表的完整示例:

      首先,您必须创建一个 JSON 策略文档,该文档表示 IAM 角色应有权访问哪些服务和资源。例如,此策略授予存储桶“my_bucket”的所有 S3 操作。您可以使用适合您的应用程序的任何策略。

      BUCKET_POLICY = """{
        "Statement":[{
          "Effect":"Allow",
          "Action":["s3:*"],
          "Resource":["arn:aws:s3:::my_bucket"]}]}"""
      

      接下来,您需要在 IAM 中创建一个实例配置文件。

      import boto
      c = boto.connect_iam()
      instance_profile = c.create_instance_profile('myinstanceprofile')
      

      拥有实例配置文件后,您需要创建角色、将角色添加到实例配置文件并将策略与角色相关联。

      role = c.create_role('myrole')
      c.add_role_to_instance_profile('myinstanceprofile', 'myrole')
      c.put_role_policy('myrole', 'mypolicy', BUCKET_POLICY)
      

      现在,您可以在启动实例时使用该实例配置文件:

      ec2 = boto.connect_ec2()
      ec2.run_instances('ami-xxxxxxx', ..., instance_profile_name='myinstanceprofile')
      

      【讨论】:

      • boto 不是为了方便 API 访问 AWS 而创建的 python 模块吗?您将如何以独立于语言的方式(即在云模板中)执行此操作?
      【解决方案4】:

      我想指出,不再需要向您的 EC2 实例提供任何凭据。使用 IAM,您可以为您的 EC2 实例创建角色。在这些角色中,您可以设置细粒度的策略,例如,允许您的 EC2 实例从特定 S3 存储桶获取特定对象,仅此而已。您可以在 AWS 文档中阅读有关 IAM 角色的更多信息:

      http://docs.aws.amazon.com/IAM/latest/UserGuide/WorkingWithRoles.html

      【讨论】:

      • 任何成功登录 AMI 的用户都可以使用 IAM 角色授权。您需要安全地将每个非 root 服务容器化并限制网络访问。
      • 当然可以,但这并不是 IAM 授权所独有的。 API 凭证也是如此。您应该使用一个系统,您将 IAM 用户需要的内容列入白名单:您可以稍后进行更改。
      【解决方案5】:

      就像其他人在这里已经指出的那样,您实际上并不需要通过使用 IAM 角色来存储 EC2 实例的 AWS 凭证 - https://aws.amazon.com/blogs/security/a-safer-way-to-distribute-aws-credentials-to-ec2/。 我要补充一点,您也可以使用相同的方法为您的 EC2 实例安全地存储 NON-AWS 凭证,例如,如果您有一些想要保持安全的数据库凭证。您将非 aws 凭证保存在 S3 Bukcet 上,并使用 IAM 角色访问该存储桶。 你可以在这里找到更多详细信息 - https://aws.amazon.com/blogs/security/using-iam-roles-to-distribute-non-aws-credentials-to-your-ec2-instances/

      【讨论】:

        猜你喜欢
        • 2016-07-21
        • 2020-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多