Keycloak¶
若要使用`Keycloak<https://www.keycloak.org/>`__ 配合 NetHSM,既能在 NetHSM 中安全地存储私钥,又能让 Keycloak 签署访问令牌并解密 JWE,您需要按照以下步骤安装并配置`此密钥提供程序<https://github.com/Nitrokey/nethsm-keycloak>`__:
AI 披露¶
该服务提供商是在人工智能的大力协助下开发和审核的。
Prepare the NetHSM¶
请按以下步骤准备 NetHSM。有关详细说明,请参阅`管理部分<../administration.html>`__。
如果 NetHSM 使用的是自签名证书,请记录其指纹:
echo | openssl s_client -connect $NETHSM_HOST 2>/dev/null \ | openssl x509 -fingerprint -sha256 -noout
`创建一个专门用于 Keycloak 的“操作员”用户<../administration.html#user-management>`__。
Keycloak 扩展*会发现* 中的密钥,但不会创建这些密钥。`请手动创建所需的密钥<../operation.html#key-management>`__:
密钥 ID 必须以该领域将声明的前缀开头。请选择合适的命名方案,例如``kc-<realm>-<purpose>-<year>``(例如``kc-staff-sig-rs256-2026``、
kc-partners-sig-es256-2026、kc-customers-enc-oaep-2026)。该 ID 将作为``kid`` 由 Keycloak 发布。未来的密钥轮换是通过添加新 ID 来实现的,因此我们建议将年份作为密钥 ID 的一部分。机制 决定了该密钥可用于哪些 JOSE 算法:
NetHSM key type and mechanism
JOSE algorithms served
RSA+RSA_Signature_PKCS1RS256、RS384、RS512——不依赖哈希算法,因此一个密钥即可覆盖这三种算法
RSA+``RSA_Signature_PSS_SHA256`` /_SHA384/_SHA512PS256 / PS384 / PS512 —— 这些名称仅指算法
EC_P256/EC_P384/EC_P521+``ECDSA_Signature``ES256 / ES384 / ES512 — 曲线决定了算法
Curve25519+EdDSA_SignatureEdDSA
RSA+``RSA_Decryption_OAEP_SHA1`` /_SHA256RSA-OAEP / RSA-OAEP-256,用于解密传入的 JWE
安装¶
下载 Keycloak NetHSM 提供程序`的 JAR 文件<https://github.com/Nitrokey/nethsm-keycloak/releases>`__,将其保存到 Keycloak 的提供程序文件夹中,例如``/opt/keycloak/providers/``
重建提供商注册表:/opt/keycloak/bin/kc.sh build
配置¶
设置既可以通过``conf/keycloak.conf`` 指定,也可以通过环境变量指定。这两种形式表示相同的设置;环境变量具有优先级,因此非机密值可以保存在文件中,仅在运行时注入密码短语。
使用``conf/keycloak.conf``¶
spi-keys--nethsm--url=https://nethsm.internal:8443/api/v1
spi-keys--nethsm--username=keycloak
spi-keys--nethsm--passphrase=<passphrase>
spi-keys--nethsm--tls-fingerprints=aabbcc...
Using environment variables¶
在容器部署中更推荐这种方式,因为密码短语可以从 Docker 或 Kubernetes 密钥中获取,而无需写入文件。
KC_SPI_KEYS__NETHSM__URL=https://nethsm.internal:8443/api/v1
KC_SPI_KEYS__NETHSM__USERNAME=keycloak
KC_SPI_KEYS__NETHSM__PASSPHRASE="<passphrase>"
KC_SPI_KEYS__NETHSM__TLS_FINGERPRINTS=aabbcc...
备注
环境变量名称是根据配置键机械生成的:在键名前添加`KC_` ,转换为大写,并将所有`-` 替换为`_` 。双下划线源自键的结构`spi-<spi-name>--<provider-id>--<option>` ,其中对于此扩展而言,SPI为`keys` ,提供者为`nethsm` ,以及选项名称。
See also all available configuration options.
Restart Keycloak¶
连接配置文件仅在提供商工厂初始化时被读取。请重启 Keycloak。
Confirm the server configuration¶
在配置任何领域之前,请检查启动日志。这样可以区分连接或凭据问题与领域配置问题。
成功时:
NetHSM key provider ready: 1 instance(s), user 'keycloak',
discovery cache PT5M, on-unavailable fail
Otherwise:
Log message |
Cause |
|---|---|
没有提示信息,或者出现一条调试信息,指出提供程序处于非活动状态 |
|
|
地址错误、被防火墙阻止、证书 PIN 不匹配,或者 NetHSM 处于锁定状态或未配置状态 |
|
Wrong username or passphrase |
将提供商添加到领域中¶
在管理控制台中,进入*领域设置 → 密钥 → 提供商* ,选择**添加提供商** ,并选择``nethsm``。
Field |
含义 |
|---|---|
Key use |
|
Key ID prefix |
ID 以该字符串开头的每个 NetHSM 密钥均由该领域发布 |
Algorithm |
发布这些密钥所依据的算法 |
Priority |
参见`将优先级设置为大于 100`_ |
Enabled / Active |
若要使密钥生效,这两项都必须开启 |
一个组件发布一种算法,这与 Keycloak 的内置密钥提供程序相类似。因此,需要同时支持 RS256 和 ES256 的领域将包含两个组件。对于前缀下无法支持所选算法的密钥,系统会将其跳过,因此一个前缀可以安全地匹配一组混合的密钥。
小心
请勿将两个组件使用不同的算法指向同一个密钥。否则,两者都会在相同的``kid`` 下发布一个 JWKS 条目。
将优先级设置为大于 100¶
重要
一个新创建的域包含四个生成的密钥提供者——rsa-generated、rsa-enc-generated、hmac-generated 以及``aes-generated``——它们的优先级均为**100** 。NetHSM 组件的优先级必须更高,否则 Keycloak 将继续使用生成的软件密钥进行签名,且配置看似正常。
NetHSM 的默认值为``200``,这是一个合理的设置。
为该领域选择算法¶
将*中的“领域设置”→“令牌”→“默认签名算法”* 设置为组件上配置的算法。如果领域请求的算法是组件未发布的,Keycloak 将回退到使用生成的密钥,且不会报告错误。
验证¶
List the published keys:
curl -s https://<keycloak-host>/realms/<realm>/protocol/openid-connect/certs
kid 的值应为 NetHSM 密钥 ID。
最终的验证依据是生成的令牌。请求一个令牌并解析其头部信息:
curl -s \
-d "client_id=<client>" \
-d "client_secret=<secret>" \
-d "grant_type=client_credentials" \
https://$NETHSM_HOST/realms/<realm>/protocol/openid-connect/token \
| python3 -c 'import sys, json, base64
header = json.load(sys.stdin)["access_token"].split(".")[0]
print(json.loads(base64.urlsafe_b64decode(header + "==")))'
如果``kid`` 是 NetHSM 的密钥 ID,则该签名是在 HSM 内部生成的。您还可以同时查看 NetHSM 的日志,其中应会显示相应的调用记录。
Further Details¶
You find further details here.