我正在运行一个支持Kerberos认证API的Spring应用程序。
当使用fqdn时,api被成功调用:
$ curl -vvv -u : --negotiate "http://TARGET_HOSTNAME:PORT/api/v1/configuration"
* Trying TARGET_IP...
* TCP_NODELAY set
* Connected to TARGET_HOSTNAME (TARGET_IP) port PORT (#0)
* Server auth using Negotiate with user ''
> GET /api/v1/configuration HTTP/1.1
> Host: TARGET_HOSTNAME:PORT
> Authorization: Negotiate XXXX
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200
< WWW-Authenticate: Negotiate XXXX; Path=/; HttpOnly
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Mon, 25 Oct 2021 17:34:52 GMT
<
{
"msg" : "Ok",
"result" : [ {
"threshold" : 50
} ]
* Connection #0 to host TARGET_HOSTNAME left intact
}* Closing connection 0
然而,当尝试用ip地址调用相同的API时,它失败了:
$ curl -vvv -u : --negotiate "http://TARGET_IP:PORT/api/v1/configuration"
* Trying TARGET_IP...
* TCP_NODELAY set
* Connected to TARGET_IP (TARGET_IP) port PORT (#0)
* gss_init_sec_context() failed: An unsupported mechanism was requested. unknown mech-code 0 for mech unknown.
* Connection #0 to host TARGET_IP left intact
curl: (67) Login denied
* Closing connection 0
这个问题的原因是什么?
调用不需要Kerberos身份验证的api时,使用fqdn和ip地址都可以很好地完成。
klist命令显示为:
$ klist -5
Credentials cache: API:XXX
Principal: USERNAME@REALM
Issued Expires Principal
Oct 26 01:48:41 2021 Oct 26 04:48:39 2021 krbtgt/REALM@REALM
Oct 26 02:27:05 2021 Oct 26 04:48:39 2021 HTTP/TARGET_HOST@REALM
欢迎任何评论或链接。
是keytab的问题。
我不确定我的解释是否准确,但这就是我的理解。
发送Spnego请求时,客户端指定SPN。
本例中spn分别为TARGET_HOST@REALM
和TARGET_IP@REALM
。
处理此请求的服务器,即Spring应用程序,应该有一个包含所有这些spn的keytab。
但是我发现keytab只有一个TARGET_HOST
的本金。
像这样:
$ klist -kt /path/to/keytab
Keytab name: FILE:/path/to/keytab
KVNO Timestamp Principal
---- ----------------- --------------------------------------------------------
3 02/03/20 14:33:39 HTTP/TARGET_HOST@REALM
3 02/03/20 14:33:39 HTTP/TARGET_HOST@REALM
应该包含HTTP/TARGET_IP@REALM
要实现这一点,需要执行以下步骤:
- 用
HTTP/TARGET_IP@REALM
创建新的主体 - 创建一个新的keytab,其中包含新的主体
- 合并现有的和新的keytab
则显示为:
$ klist -kt /path/to/keytab
Keytab name: FILE:/path/to/keytab
KVNO Timestamp Principal
---- ----------------- --------------------------------------------------------
3 02/03/20 14:33:39 HTTP/TARGET_HOST@REALM
3 02/03/20 14:33:39 HTTP/TARGET_HOST@REALM
1 02/03/20 14:33:39 HTTP/TARGET_IP@REALM
然后我用新的keytab重新启动调度程序,这解决了我的问题。