签名密钥
正如之前讨论的,NKEY 就是身份标识,如果有人获取了账户或运营商的 NKEY,他们就能像你一样执行所有操作。
NATS 提供了策略来帮助你处理私钥泄露的情况。
首要且最重要的防御措施是签名密钥。签名密钥允许你拥有多个相同类型(运营商或账户)的 NKEY 身份,这些身份与标准的颁发者 NKEY 具有同等的信任度。
签名密钥背后的概念是,你可以为运营商或账户颁发一个列出多个 NKEY 的 JWT。通常,颁发者会与发布 JWT 的实体的主题相匹配。有了签名密钥,只要 JWT 是由颁发者的主题或其签名密钥之一签名的,该 JWT 就被认为是有效的。这使得你可以更严密地保护运营商或账户的私钥,同时允许使用替代的私钥来为账户、用户或激活令牌签名。
如果出现问题,例如某个签名密钥意外泄露,你可以从实体中移除被盗用的签名密钥,添加一个新的密钥,重新颁发给该实体。当验证 JWT 时,如果签名密钥缺失,操作将被拒绝。你还需要负责重新颁发所有使用被盗用签名密钥签名的 JWT(账户、用户、激活令牌)。
这实际上是一个强有力的手段。你可以通过拥有大量签名密钥,然后轮换这些密钥,以便在发生泄露时能够轻松处理分发问题,从而稍微缓解这个过程。在未来的版本中,我们将提供一个撤销流程,你可以通过唯一的 JWT ID(JTI)使单个 JWT 失效。但目前,你只能使用这个"大锤"。
安全流程越严格,复杂性就越高。因此,nsc 不跟踪公钥或私钥签名密钥。因为这些身份标识在使用时假定是手动操作的。这意味着用户必须更仔细地跟踪和管理自己的私钥。
让我们来熟悉一下工作流程。我们将要:
创建一个有签名密钥的运营商
创建一个有签名密钥的账户
使用运营商的签名密钥为该账户签名
使用账户的签名密钥创建一个用户
所有签名密钥操作都围绕全局的 nsc 标志 -K 或 --private-key 进行。每当你想要修改一个实体时,都必须提供父级密钥以便对 JWT 进行签名。通常情况下这是自动完成的,但在使用签名密钥时,你需要手动提供该标志。
创建运营商:
nsc add operator O2[ OK ] generated and stored operator key "OABX3STBZZRBHMWMIMVHNQVNUG2O3D54BMZXX5LMBYKSAPDSHIWPMMFY"
[ OK ] added operator "O2"要添加签名密钥,我们首先要用 nsc 生成一个:
在生产环境中,私钥应保存到一个文件中,并始终从受保护的文件中引用。
现在我们将编辑运营商,使用 --sk 标志添加一个签名密钥,并提供生成的运营商公钥(以 O 开头的那个):
检查我们的成果:
现在让我们创建一个名为 A 的账户,并使用生成的运营商签名密钥的私钥为其签名。要使用该密钥签名,请指定 -K 标志以及私钥或私钥的路径:
让我们生成一个账户签名密钥,再次使用 nk:
让我们添加签名密钥到这个账户,并记住使用运营商签名密钥为账户签名:
让我们查看一下账户
我们可以看到签名密钥 ADUQTJD4TF4O6LTTHCKDKSHKGBN2NECCHHMWFREPKNO6MPA7ZETFEEF7 已被添加到账户中。同时,颁发者是运营商的签名密钥(通过 -K 指定)。
现在让我们创建一个用户,并使用以 ADUQTJD4TF4O 开头的账户签名密钥为其签名。
检查用户
正如预期的那样,颁发者现在是我们之前生成的签名密钥。为了将用户映射到实际账户,JWT 中添加了一个 Issuer Account 字段,用于标识账户 A 的公钥。
作用域签名密钥
作用域签名密钥简化了用户权限管理。以前,如果你想限制用户的权限,必须为每个用户指定权限。有了作用域签名密钥,你可以将一个签名密钥与一组权限关联起来。此配置存在于账户 JWT 上,并通过 nsc edit signing-key 命令进行管理。你可以根据需要添加任意多个作用域签名密钥。
要为用户授予一组权限,只需使用具有所需权限集的签名密钥为用户签名即可。以及不得在用户配置中分配任何权限。
连接后,nats-server 会将与该签名密钥关联的权限分配给用户。如果你更新了与签名密钥关联的权限,服务器将立即更新使用该密钥签名的用户的权限。
生成签名密钥
添加一个服务到账户
由于签名密钥在账户内具有唯一的角色名称,后续可以更容易地引用它。
要查看用户的权限,请输入 nsc describe user - 你将在报告中看到该用户是作用域内的,并且拥有列出的权限。你可以使用 nsc edit signing-key 检查和修改作用域权限 - 将更新推送到账户将重新分配用户权限。
模板函数
自 NATS 2.9.0 起可用
尽管作用域签名密钥非常有用并能提高安全性(通过限制特定签名密钥的范围),但在多用户设置中,设置的权限可能过于僵化。例如,给定两个用户 pam 和 joe,我们可能希望允许他们订阅自己命名空间下的主题来处理请求,例如 pam.> 和 joe.>。这些用户之间的权限结构是相同的,但它们的具体主题不同,这些主题进一步根据该用户的某些属性进行了作用域划分。
模板函数可用于在作用域签名密钥中声明结构,但利用基本模板功能,使得使用该签名密钥创建的每个用户都具有用户特定的主题。
以下模板函数在创建用户时将展开。
{{name()}}- 扩展为用户的名称,例如pam{{subject()}}- 扩展为用户公钥 NKEY 值,例如UAC...{{account-name()}}- 扩展为签名账户的名称,例如sales{{account-subject()}}- 扩展为账户公钥 NKEY 值,例如AXU...{{tag(key)}}- 扩展与签名密钥关联的key:value标签
例如,给定一个具有模板化 --allow-sub 主题的作用域签名密钥:
我们可以在不同的团队中创建两个用户。
每个用户最终的 --allow-sub 权限将扩展为:
和
最后更新于