Skip to content

本文为 SPIRE 官方文档 plugin_server_nodeattestor_azure_msi.md 的中文译本,以英文原文为准。 🔗 穿越源码分析:Server 详解 · NodeAttestor

Server 插件:NodeAttestor "azure_msi"

必须与 Agent 侧 azure_msi 插件配合使用

azure_msi 插件用于对运行在 Microsoft Azure 中、且启用了托管服务标识(Managed Service Identity,MSI)的节点进行认证。agent 节点会获取一个经签名的 MSI 令牌并将其传递给 server。server 校验该签名 MSI 令牌,并从中提取 Tenant ID 和 Principal ID 来构成 agent 的 SPIFFE ID。SPIFFE ID 的格式为:

xml
spiffe://<trust_domain>/spire/agent/azure_msi/<tenant_id>/<principal_id>

server 本身无需运行在 Azure 中即可执行节点认证或解析 selector。

Configuration(配置)

ConfigurationRequiredDescriptionDefault
tenants必填一个租户(tenant)映射,以 tenant ID 为键,列出被授权进行认证的租户。未指定租户对应的令牌将被拒绝。
agent_path_template可选Agent SPIFFE ID 的 URL 路径部分格式,以 text/template 格式描述。"/{{ .PluginName }}/{{ .TenantID }}/{{ .PrincipalID }}"

主配置中的每个租户支持以下配置:

ConfigurationRequiredDescriptionDefault
resource_id可选该租户 MSI 令牌的资源 ID(或受众 audience)。资源 ID 不同的令牌将被拒绝。https://management.azure.com/
subscription_id可选该租户所在的订阅(subscription)
app_id可选应用 id(application id)
app_secret可选应用密钥(application secret)

需要特别注意的是,resource ID 必须是一个众所周知的 Azure 服务,或是 Azure AD 中一个已注册应用的 app ID。对于自己不认识的资源,Azure 不会签发 MSI 令牌。

向 Azure 认证(Authenticating to Azure)

本插件需要凭据(credentials)来向 Azure 进行认证,以便查询被认证节点的属性并生成 selector。

默认情况下,插件会尝试通过 DefaultAzureCredential API 使用应用默认凭据(application default credential)。DefaultAzureCredential API 会按以下顺序依次尝试各种机制进行认证——环境变量、工作负载标识(Workload Identity)、托管标识(Managed Identity),一旦某种方式成功即停止。当使用 Workload Identity 或 Managed Identity 时,插件必须能够获取所配置 tenant ID 的凭据,否则使用该认证器的节点认证将会失败。

或者,也可以将插件配置为使用某个在租户内注册的应用的静态凭据(subscription_idapp_idapp_secret)。

出于向后兼容的原因,认证配置目前并非必需,但在未来的版本中它将成为必需项。

Sample Configurations(示例配置)

默认 Resource ID 与应用认证(App Authentication)

hcl
    NodeAttestor "azure_msi" {
        plugin_data {
            tenants = {
                "00000000-1111-2222-3333-444444444444" = {
                    subscription_id = SUBSCRIPTION_ID
                    app_id = APP_ID
                    app_secret = APP_SECRET
                }
            }
        }
    }
}

自定义 Resource ID 与 MSI 认证(MSI Authentication)

hcl
    NodeAttestor "azure_msi" {
        plugin_data {
            tenants = {
                "00000000-1111-2222-3333-444444444444" = {
                    resource_id = "http://example.org/app/"
                }
            }
        }
    }

Selectors(选择器)

插件生成以下 selector。

SelectorExampleDescription
Subscription IDsubscription-id:d5b40d61-272e-48da-beb9-05f295c42bd6节点所属的订阅(subscription)
Virtual Machine Namevm-name:frontend:blog虚拟机名称(例如 blog),以其资源组(resource group,例如 frontend)限定
Network Security Groupnetwork-security-group:frontend:webservers网络安全组名称(例如 webservers),以其资源组(例如 frontend)限定
Virtual Networkvirtual-network:frontend:vnet虚拟网络名称(例如 vnet),以其资源组(例如 frontend)限定
Virtual Network Subnetvirtual-network-subnet:frontend:vnet:default虚拟网络子网名称(例如 default),以其虚拟网络和资源组限定

所有 selector 的类型均为 azure_msi

Agent 路径模板(Agent Path Template)

Agent 路径模板(agent path template)是一种自定义 agent SPIFFE ID 生成格式的方式。模板格式化器采用 Golang text/template 约定,可以引用插件提供的值,或 MSI 访问令牌中的值。关于模板引擎的详情,见模板引擎文档

一些有用的值包括:

ValueDescription
.PluginName插件名称
.TenantIDAzure 租户标识符
.PrincipalID对某个特定 application ID 而言唯一的标识符

Security Considerations(安全考量)

Azure 托管服务标识(Managed Service Identity)令牌是本认证器用于证明节点身份的凭据,默认情况下节点上运行的任何进程都可访问它。因此,节点上的非 agent 代码有可能向 SPIRE Server 完成认证,从而获取该节点被授权运行的任意工作负载身份(workload identity)。

尽管许多运维人员会选择配置系统以阻止对 Managed Service Identity 令牌的访问,但 SPIRE 项目无法保证这一安全态势。为缓解相关风险,azure_msi 节点认证器实现了首次使用即信任(Trust On First Use,简称 TOFU)语义。对于任意给定节点,认证只能发生一次,后续的认证尝试都将被拒绝。

非 agent 代码仍有可能先于 SPIRE Agent 完成节点认证;不过这种情况很容易被迅速发现,因为此时 SPIRE Agent 将无法启动,并且 SPIRE Agent 和 SPIRE Server 都会记录该事件。此类情况应作为可能的安全事件加以调查。