当我启动附加了加密卷的实例时,实例立即停止,并显示错误消息“client error on launch”。

上次更新时间:2020 年 9 月 25 日

我启动了附加了加密卷的 Amazon Elastic Compute Cloud (Amazon EC2) 实例,但实例未成功启动 – 实例立即从“待处理”状态变为“已停止”状态。我运行 AWS 命令行界面 (AWS CLI) 命令 describe-instances,并获得了以下错误消息:

....
"StateReason": {
  "Code": "Client.InternalError"
  "Message": "Client.InternalError: Client error on launch"
},
....

如何解决此问题?

简短描述

在以下情况下,附加了加密卷的 EC2 实例会发生此问题:

  • 启动实例的 AWS Key Management Service (AWS KMS) 或 AWS Identity and Access Management (IAM) 用户没有所需的权限。
  • KMS 密钥的使用受 SourceIp 条件密钥的限制。

IAM 用户必须具有 AWS KMS 的权限才能解密客户主密钥 (CMK)。

要允许访问解密 CMK,您必须将密钥策略与 IAM 策略或授权结合使用。仅凭 IAM 策略不足以允许访问 CMK,但您可以将它们与 CMK 的密钥策略结合使用。

默认情况下,KMS 密钥仅授予对根账户的访问权限。向 IAM 用户或角色提供 EC2 完全权限时,AWS KMS 权限必须明确授予对 CMK 密钥策略的访问权限。

解决方法

创建 IAM 策略以允许 IAM 委托人调用 AWS KMS API

1    打开 IAM 控制台,选择策略,然后选择创建策略

2    选择 JSON 选项卡,然后复制并粘贴此策略:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "kms:Decrypt",
                "kms:Encrypt",
                "kms:RevokeGrant",
                "kms:GenerateDataKey",
                "kms:GenerateDataKeyWithoutPlaintext",
                "kms:DescribeKey",
                "kms:CreateGrant",
                "kms:ListGrants"
            ],
            "Resource": "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"
        }
    ]
}

3    选择查看策略

4    在名称中,输入对您有意义的名称,然后选择创建策略

5    选择您在步骤 4 中创建的策略。

6    选择策略使用选项卡,然后选择附加

7    在 名称中,选择要向 CMK 授予权限的 IAM 实体,然后选择附加策略

授予 IAM 委托人对 CMK 的显式访问权限

1    打开 AWS KMS 控制台,然后选择客户托管密钥

2    在 密钥 ID 中,选择您的密钥 ID

3    在密钥用户中,选择添加

4    在名称中,选择 IAM 用户或角色,然后选择添加

注意:如果您使用的是自定义密钥策略而不是默认密钥策略,则 CMK 必须明确授予以下权限:

{
            "Sid": "Allow use of the key",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                "arn:aws:iam::123456789012:role/MyRoleName"
                    "arn:aws:iam::123456789012:user/MyUserName",
                ]
            },
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:DescribeKey"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Allow attachment of persistent resources",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
            "arn:aws:iam::123456789012:role/MyRoleName"
                    "arn:aws:iam::123456789012:user/MyUserName",
                ]
            },
            "Action": [
                "kms:CreateGrant",
                "kms:ListGrants",
                "kms:RevokeGrant"
            ],
            "Resource": "*",
            "Condition": {
                "Bool": {
                    "kms:GrantIsForAWSResource": "true"
                }
            }
        }

使用 IP 地址条件

如果您使用 AWS KMS 保护集成服务中的数据,则在指定 IP 地址条件运算符时或在同一访问策略语句中指定 aws:SourceIp 条件密钥时要小心。将加密的 Amazon Elastic Block Store (Amazon EBS) 卷附加到 Amazon EC2 实例会导致 Amazon EC2 向 AWS KMS 发送请求,以解密卷的加密数据密钥。此请求来自与 EC2 实例关联的 IP 地址,而不是用户的 IP 地址。这意味着如果设置了 SourceIp 条件,则解密请求将被拒绝,并且实例失败。

使用 kms:ViaService 条件密钥。AWS KMS 允许代表您从该服务进行交互。确保委托人有权使用 CMK 和集成服务。有关详细信息,请参阅 kms:ViaService 条件密钥限制

注意:具有登录用户的 EC2 实例无法与此条件进行交互 – 只有代表您的服务才能进行交互。此交互将记录在 AWS CloudTrail 日志中以供您查看。

"userIdentity": {
  "sessionContext": {
    "sessionIssuer": {
      "accountId": "450822418798",
      "principalId": "450822418798:aws:ec2-infrastructure",
      "userName": "aws:ec2-infrastructure",
      "arn": "arn:aws:iam::450822418798:role/aws:ec2-infrastructure",
      "type": "Role"
     },
…
    "eventType": "AwsApiCall",
    "@log_group": "CloudTrail/AllRegionLogGroup",
    "awsRegion": "eu-west-1",
    "requestParameters": {
      "encryptionContext": {
        "aws:ebs:id": "vol-0ca158925aa9c1883"
      }    
},

在此示例中,API 调用的 CloudTrail 条目是针对 AWS KMS 创建的。这是由 Amazon EC2 基础设施调用,而不是从特定的 IP 地址调用。当您向用户添加允许 AWS KMS 与 Amazon EC2 交互的策略时,API 调用即可完成。