Skip to content

本文为 SPIRE 官方文档 plugin_server_keymanager_aws_kms 的中文译本,以英文原文为准。

🔗 穿越源码分析:Server 详解 · KeyManager

服务端插件:KeyManager "aws_kms"

aws_kms 密钥管理器(key manager)插件借助 AWS 密钥管理服务(Key Management Service,KMS)来创建、维护并轮换密钥对(以客户主密钥(Customer Master Keys)即 CMK 的形式),并按需签发 SVID,而私钥(private key)始终不会离开 KMS。

配置

该插件接受以下配置项:

键名类型是否必填说明默认值
access_key_idstringAWS KMS 访问权限用于向 KMS 认证的 Access Key Id环境变量 AWS_ACCESS_KEY_ID 的值
secret_access_keystringAWS KMS 访问权限用于向 KMS 认证的 Secret Access Key环境变量 AWS_SECRET_ACCESS_KEY 的值
regionstring密钥将存储在哪个区域(region)
key_identifier_filestring若未设置 key_identifier_value 则必填一个文件路径,用于持久化所生成密钥的相关信息
key_identifier_valuestring若未设置 key_identifier_file 则必填SPIRE server 实例的静态标识符(用于替代 key_identifier_file)
key_policy_filestring一个 JSON 格式的自定义密钥策略(key policy)文件路径""
enable_tag_based_key_discoveryboolean启用基于标签的密钥发现(推荐)。参见基于标签的密钥发现false

服务端实例标识

插件需要一种方式来识别它正在其上运行的具体 server 实例。为此,必须使用 key_identifier_filekey_identifier_value 两者之一。设置**密钥标识文件(Key Identifier File)**会指示插件自动管理 server 的标识符,将 server ID 存储在指定 文件中。这种方式适用于大多数情况。如果配置了_密钥标识文件_而在 server 启动时未 找到该文件,则会以新的、自动生成的 server ID 重新创建该文件。因此,如果该文件丢 失,插件将无法识别它此前管理过的密钥,并会按需重新创建新密钥。

如果你需要对 server 所用的标识符有更多控制,可以使用 key_identifier_value 设置 来为 server 实例指定一个静态标识符。这种设置适用于无法持久化密钥标识文件的场景。

基于标签的密钥发现

推荐。 通过 enable_tag_based_key_discovery = true 启用。

启用基于标签的密钥发现后,插件会使用 AWS Resource Groups Tagging API 来高效地只查找由本插件实例管理的 KMS 密钥。密钥通过以下在创建时打上的 SPIRE 专用标签(tag)来识别:

标签键说明
spire-server-tdSPIRE server 的信任域(trust domain)
spire-server-idserver 实例标识符
spire-active对处于活跃管理状态的密钥设为 true
spire-key-idSPIRE 密钥标识符
spire-last-update最近一次更新的 Unix 时间戳(在创建时设置,并会周期性刷新)

插件在密钥创建时(以及迁移一个已有密钥时)打上 spire-last-update 标签,并周期性地在所有活跃密钥上刷新它。任何 spire-last-update 时间戳早于两周的密钥都会被视为陈旧(stale),被标记为非活跃(spire-active=false),其关联的 KMS 密钥会被安排删除。

从基于别名的发现迁移: 当在一个此前使用基于别名(alias)发现的 server 上启用基于标签的发现时,插件会在启动期间自动检测已有的未打标签的密钥,并为它们打上 SPIRE 标签。无需任何手动迁移步骤。

此模式需要 tag:GetResources 权限(来自 Resource Groups Tagging API)。完整权限列表见 AWS KMS 访问权限

高可用部署中的配置一致性

enable_tag_based_key_discovery 设置应在同一信任域内的所有 SPIRE server 上保持一致。与基于别名的发现一样,每个 server 会周期性地在它所管理的密钥上刷新一个存活信号(liveness signal),并且任何 server 都会回收其信任域内那些存活信号已两周未刷新的密钥(被永久移除的 server 所拥有的密钥正是这样被清理的)。

两种发现模式使用各自独立的存活信号:基于别名的发现刷新别名的 LastUpdatedDate,而基于标签的发现刷新 spire-last-update 标签。server 只会为其当前配置的模式刷新对应的信号。这对回滚(rollback)有如下影响:

  • 在整个集群范围内向前迁移(从基于别名到基于标签)是安全的:密钥会在启动时自动打标签,并从此持续刷新。
  • 在部分节点上从基于标签回滚到基于别名、同时其他 server 仍使用基于标签,只有在两周窗口期内才是安全的。已回滚的 server 会保持其别名新鲜,但停止刷新 spire-last-update,因此两周之后,仍在使用基于标签的 server 会把它正在使用的密钥当作已废弃并安排删除。要安全回滚,需在该窗口期内在信任域的所有 server 上一并修改此设置。

基于别名的密钥发现

注意: 基于别名的密钥发现将在未来某个版本被弃用(deprecated),并在更晚的版本中移除。启用 enable_tag_based_key_discovery 以完成迁移。

默认情况下,插件使用基于别名的密钥发现。插件会为它所管理的客户主密钥分配别名(alias)。别名具有如下形式:alias/SPIRE_SERVER/{TRUST_DOMAIN}/{SERVER_ID}/{KEY_ID}。别名中的 {KEY_ID} 会被编码为 KMS 可接受的字符集

插件会尝试检测并清除陈旧的别名。为便于陈旧别名检测,插件每 6 小时主动更新一次所有别名的 LastUpdatedDate 字段。插件会周期性扫描别名。任何 LastUpdatedDate 早于两周的别名都会连同其关联密钥一起被移除。

插件也会尝试检测并清除陈旧的密钥。插件管理的所有密钥都会被赋予形如 SPIRE_SERVER/{TRUST_DOMAIN}Description。插件会周期性扫描密钥。任何 Description 符合该形式、既未与任何别名关联、且 CreationDate 早于 48 小时的密钥都会被移除。

密钥打标签

插件支持通过 key_tags 配置项为 KMS 密钥打上用户自定义标签。这些标签以键值对形式指定,并会应用到插件创建的所有 KMS 密钥上。

使用密钥打标签时,必须在 IAM 策略中添加 kms:TagResource 权限。没有该权限,密钥创建会失败。

标签约束

  • 标签键长度必须为 1-128 个字符
  • 标签值长度可为 0-256 个字符
  • 最多 50 个标签(AWS KMS 限制)
  • 标签键与值必须使用合法字符:字母、数字、空格,以及以下特殊字符:+ - = . _ : / @
  • 标签键不能以 aws: 开头(AWS 保留)
  • 标签键不能以 spire- 开头(为 SPIRE 管理的标签保留)

标签校验 插件会在配置阶段校验所有用户自定义标签。如果有任何标签违反 AWS KMS 的标签约束,插件将配置失败,并报告一条详细的错误信息,指明具体的校验失败原因。

标签生命周期key_tags 配置块被更新时,只有新创建的密钥才会按新配置打标签。已有密钥的标签不会被更新。

AWS KMS 访问权限

访问 AWS KMS 可以通过设置 access_key_idsecret_access_key 来授予,或者通过确保插件运行在一个绑定了具备特定权限集的 IAM 角色的 EC2 实例上来授予。

该 IAM 角色必须附加一个具备以下权限的策略:

  • kms:CreateAlias
  • kms:CreateKey
  • kms:DescribeKey
  • kms:GetPublicKey
  • kms:ListAliases
  • kms:ScheduleKeyDeletion
  • kms:Sign
  • kms:UpdateAlias
  • kms:DeleteAlias

根据配置的不同,还需要以下额外权限:

权限何时需要
kms:ListKeys使用基于别名的密钥发现(当前默认)
kms:TagResource使用基于标签的密钥发现或 key_tags
tag:GetResources使用基于标签的密钥发现(enable_tag_based_key_discovery = true)

tag:GetResources 属于 Resource Groups Tagging API,而不属于 KMS。它是一项基于身份(identity-based)的权限,必须在 IAM 身份的策略中授予。它无法通过 KMS 密钥策略授予(包括插件生成的默认策略)。

密钥策略

插件可以使用默认密钥策略来生成密钥,也可以加载并使用用户定义的策略。

默认密钥策略

默认密钥策略依赖 SPIRE Server 所担任(assumed)的角色。因此,SPIRE server 必须担任一个角色才能使用默认策略。

json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Allow full access to the SPIRE Server role",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111122223333:role/example-assumed-role-name"
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
             "Sid": "Allow KMS console to display the key and policy",
             "Effect": "Allow",
             "Principal": {
                 "AWS": "arn:aws:iam::111122223333:root"
             },
             "Action": [
                 "kms:Describe*",
                 "kms:List*",
                 "kms:Get*"
             ],
             "Resource": "*"
        }
    ]
}
  • 策略的第一条语句(statement)赋予当前 SPIRE server 所担任的角色对该 CMK 的完全访问权限。
  • 第二条语句允许在 KMS 控制台中显示密钥和策略。

自定义密钥策略

用户也可以定义自定义密钥策略。如果设置了可配置项 key_policy_file,插件会使用该文件中定义的策略来替代默认策略。

插件配置示例

基础配置

hcl
KeyManager "aws_kms" {
    plugin_data {
        region = "us-east-2"
        key_identifier_file = "./key_metadata"
    }
}

启用基于标签的密钥发现的配置(推荐)

hcl
KeyManager "aws_kms" {
    plugin_data {
        region = "us-east-2"
        key_identifier_file = "./key_metadata"
        enable_tag_based_key_discovery = true
    }
}

带标签的配置

hcl
KeyManager "aws_kms" {
    plugin_data {
        region = "us-east-2"
        key_identifier_file = "./key_metadata"
        enable_tag_based_key_discovery = true
        key_tags = {
            Environment = "production"
            Team        = "security"
            Component   = "spire"
        }
    }
}

支持的密钥类型与 TTL

插件支持 SPIRE 支持的所有密钥类型:rsa-2048rsa-4096ec-p256ec-p384