Basic Question:
我可以在我的Java中使用为其他地方的ldap服务生成的服务票证来使用kerminster对ldap服务进行身份验证并形成LdapContent以进行进一步操作吗?
Goal
我想为在Unix机器上运行的Java服务实现无密码身份验证,以连接到Active目录Ldap,以对目录对象执行各种CRUD操作.
Note:由于各种原因,我无法使用keytab文件,稍后我想扩展它以使用gGMA,使其纯粹进行无密码身份验证.我所说的"少密码"是指我想避免DC上的显式密码管理,对于在Unix上运行的Java服务,它必须是无密码的
我的 idea :
- 使用可以成功generate a service ticket换ldap的Windows Agent Service
- 对服务票证(base64)进行编码并将其提供给Java服务(安全地)
- Java然后可以将其decode并使用它到authenticate到ldap并形成LdapContext for further usage
- Java服务和Windows代理服务之间的通信是安全的,Java服务可以定期要求Windows服务生成ldap服务票证.
- 现在有了这个,100
- 目前密码信息仅为Windows代理服务.
- 后来当我集成gGMA时,就连Windows代理端的密码要求都没有了,就达到了我的目标!
首先,我想验证这在理论上是否可行.
到目前为止我都try 了什么?
使用Express.NET C#库生成ldap服务票证
此C#生成ldap服务票证:
private static async Task<string> GenerateLDAPServiceTicketForUser(string userName, string password, string domain, string ldapSPN)
{
KerberosClient client = new KerberosClient();
await client.Authenticate(new KerberosPasswordCredential(userName, password, domain));
KrbApReq ticket = await client.GetServiceTicket(ldapSPN);
if (null != ticket)
{
ReadOnlyMemory<byte> memory = ticket.EncodeApplication();
byte[] ticketBytes = memory.ToArray();
return Convert.ToBase64String(ticketBytes);
} else
{
throw new Exception("Ticket is null...Service Ticket could not be generated...");
}
}
提供给该函数的输入是:
**username**: Administrator
**domain**: helix.lab
**ldapSPN**: ldap/WIN-FMCLF26TASJ.Helix.Lab
**password**: <my-password>
这成功生成base64编码的服务票证.
现在,我正在try 在我的Java应用程序中使用相同的功能来连接helix.lab的ldap服务并执行ldap操作.此收件箱只是演示了如何使用已经的服务票证连接到AD ldap服务(并证明我在Java服务端无密码连接的假设)
这是我的Java代码:
初始化
System.setProperty("java.security.krb5.conf", "/etc/krb5.conf");
System.setProperty("sun.security.krb5.debug", "true");
System.setProperty("sun.security.jgss.debug", "true");
解码Base 64门票并形成KerberosTicket
String base64Ticket = "<my base 64 encoded ticket>";
byte[] ticketBytes = Base64.getDecoder().decode(base64Ticket);
byte[] sessionKey = new byte[] {0x00, 0x01, 0x02};
Date authTime = new Date(System.currentTimeMillis());
Date startTime = new Date(System.currentTimeMillis());
Date endTime = new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000);
Date renewTill = new Date(System.currentTimeMillis() + 48 * 60 * 60 * 1000);;
KerberosTicket ticket = new KerberosTicket(ticketBytes,
new KerberosPrincipal("Administrator@HELIX.LAB"),
new KerberosPrincipal("ldap/WIN-FMCLF26TASJ.Helix.Lab"),
sessionKey, 18, null, authTime, startTime, endTime, renewTill, null);
Subject subject = new Subject();
subject.getPrivateCredentials().add(ticket);
连接到LDAP
Subject.doAs(subject, new PrivilegedAction<Void>() {
@Override
public Void run() {
connectToLdap();
return null;
}
});
实现connect ToLdap:
String ldapURL = "ldap://WIN-FMCLF26TASJ.helix.lab:389";
Hashtable<String, Object> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapURL);
env.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
env.put(Context.SECURITY_PRINCIPAL, "ldap/WIN-FMCLF26TASJ.Helix.Lab@HELIX.LAB");
try {
LdapContext ctx = new InitialLdapContext(env, null);
// Do ldap operations....
} catch(Exception e) {
}
我的DC上的setspn -l命令给出以下输出(ldap的多个条目):
ldap/WIN-FMCLF26TASJ/HELIX
ldap/b57bcf7f-d8b5-4e38-a2d2-f6833fe3d617._msdcs.Helix.lab
ldap/WIN-FMCLF26TASJ.Helix.lab/HELIX
ldap/WIN-FMCLF26TASJ
ldap/WIN-FMCLF26TASJ.Helix.lab
ldap/WIN-FMCLF26TASJ.Helix.lab/Helix.lab
其中我使用的是:ldap/WIN-FMCLF26TASJ.Helix.lab,我认为这更有意义.
当我运行Java代码时:我收到以下错误:
Java config name: /etc/krb5.conf
Loading krb5 profile at /etc/krb5.conf
Loaded from Java config
Search Subject for Kerberos V5 INIT cred (<<DEF>>,
sun.security.jgss.krb5.Krb5InitCredential)
找到了管理员@HELIX.LAB的门票,前往ldap/WIN-FMCLF 26 TASJ. HSEARCH.lab@HELIX.LAB,将于2024年4月23日星期二14:01:51 IST到期
Error occurred: GSSAPI exception: javax.naming.AuthenticationException: GSSAPI [Root
exception is javax.security.sasl.SaslException: GSS initiate failed [Caused by
GSSException: No valid credentials provided (Mechanism level: Identifier doesn't match
expected value (906))]]
这条线表示什么?
找到了管理员@HELIX.LAB的门票,前往ldap/WIN-FMCLF 26 TASJ. HSEARCH.lab@HELIX.LAB,将于2024年4月23日星期二14:01:51 IST到期
为什么身份验证失败?我做错了什么或者我错过了什么来理解? 任何其他方法或建议都可能对我有所帮助,但想了解这里出了什么问题以及如何纠正它?
更新 :
这是门票在https://lapo.it/asn1js上解码后的样子
Update 2 : Service Ticket retrieved from AP-REQ
更新 3 :
Upon adding the valid ticket and its cipher, getting following error:
Java config name: /etc/krb5.conf
Loading krb5 profile at /etc/krb5.conf
Loaded from Java config
Search Subject for Kerberos V5 INIT cred (<<DEF>>, sun.security.jgss.krb5.Krb5InitCredential)
Found ticket for Admininstrator@HELIX.LAB to go to ldap/WIN-FMCLF26TASJ.Helix.Lab@HELIX.LAB expiring on Wed Apr 24 13:17:10 IST 2024
Entered Krb5Context.initSecContext with state=STATE_NEW
Found ticket for Admininstrator@HELIX.LAB to go to ldap/WIN-FMCLF26TASJ.Helix.Lab@HELIX.LAB expiring on Wed Apr 24 13:17:10 IST 2024
Service ticket not found in the subject
>>> serviceCredsSingle: cross-realm authentication
>>> serviceCredsSingle: obtaining credentials from WIN-FMCLF26TASJ.Helix.Lab to HELIX.LAB
>>> Credentials acquireServiceCreds: main loop: [0] tempService=krbtgt/HELIX.LAB@WIN-FMCLF26TASJ.Helix.Lab
>>> Credentials serviceCredsSingle: same realm
Using builtin default etypes for default_tgs_enctypes
default etypes for default_tgs_enctypes: 18 17 20 19.
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> Credentials serviceCredsSingle: same realm
Using builtin default etypes for default_tgs_enctypes
default etypes for default_tgs_enctypes: 18 17 20 19.
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> Credentials acquireServiceCreds: no tgt; searching thru capath
>>> Credentials acquireServiceCreds: inner loop: [1] tempService=krbtgt/Helix.Lab@WIN-FMCLF26TASJ.Helix.Lab
>>> Credentials serviceCredsSingle: same realm
Using builtin default etypes for default_tgs_enctypes
default etypes for default_tgs_enctypes: 18 17 20 19.
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> Credentials serviceCredsSingle: same realm
Using builtin default etypes for default_tgs_enctypes
default etypes for default_tgs_enctypes: 18 17 20 19.
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> Credentials acquireServiceCreds: inner loop: [2] tempService=krbtgt/Lab@WIN-FMCLF26TASJ.Helix.Lab
>>> Credentials serviceCredsSingle: same realm
Using builtin default etypes for default_tgs_enctypes
default etypes for default_tgs_enctypes: 18 17 20 19.
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> Credentials serviceCredsSingle: same realm
Using builtin default etypes for default_tgs_enctypes
default etypes for default_tgs_enctypes: 18 17 20 19.
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> Credentials acquireServiceCreds: inner loop: [3] tempService=krbtgt/LAB@WIN-FMCLF26TASJ.Helix.Lab
>>> Credentials serviceCredsSingle: same realm
Using builtin default etypes for default_tgs_enctypes
default etypes for default_tgs_enctypes: 18 17 20 19.
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> Credentials serviceCredsSingle: same realm
Using builtin default etypes for default_tgs_enctypes
default etypes for default_tgs_enctypes: 18 17 20 19.
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> Credentials acquireServiceCreds: no tgt; cannot get creds
>>> serviceCredsSingle: cross-realm authentication
>>> serviceCredsSingle: obtaining credentials from WIN-FMCLF26TASJ.Helix.Lab to HELIX.LAB
>>> Credentials acquireServiceCreds: main loop: [0] tempService=krbtgt/HELIX.LAB@WIN-FMCLF26TASJ.Helix.Lab
>>> Credentials serviceCredsSingle: same realm
Using builtin default etypes for default_tgs_enctypes
default etypes for default_tgs_enctypes: 18 17 20 19.
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> Credentials serviceCredsSingle: same realm
Using builtin default etypes for default_tgs_enctypes
default etypes for default_tgs_enctypes: 18 17 20 19.
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> Credentials acquireServiceCreds: no tgt; searching thru capath
>>> Credentials acquireServiceCreds: inner loop: [1] tempService=krbtgt/Helix.Lab@WIN-FMCLF26TASJ.Helix.Lab
>>> Credentials serviceCredsSingle: same realm
Using builtin default etypes for default_tgs_enctypes
default etypes for default_tgs_enctypes: 18 17 20 19.
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> Credentials serviceCredsSingle: same realm
Using builtin default etypes for default_tgs_enctypes
default etypes for default_tgs_enctypes: 18 17 20 19.
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> Credentials acquireServiceCreds: inner loop: [2] tempService=krbtgt/Lab@WIN-FMCLF26TASJ.Helix.Lab
>>> Credentials serviceCredsSingle: same realm
Using builtin default etypes for default_tgs_enctypes
default etypes for default_tgs_enctypes: 18 17 20 19.
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> Credentials serviceCredsSingle: same realm
Using builtin default etypes for default_tgs_enctypes
default etypes for default_tgs_enctypes: 18 17 20 19.
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> Credentials acquireServiceCreds: inner loop: [3] tempService=krbtgt/LAB@WIN-FMCLF26TASJ.Helix.Lab
>>> Credentials serviceCredsSingle: same realm
Using builtin default etypes for default_tgs_enctypes
default etypes for default_tgs_enctypes: 18 17 20 19.
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> Credentials serviceCredsSingle: same realm
Using builtin default etypes for default_tgs_enctypes
default etypes for default_tgs_enctypes: 18 17 20 19.
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> Credentials acquireServiceCreds: no tgt; cannot get creds
KrbException: Fail to create credential. (63) - No service creds
at java.security.jgss/sun.security.krb5.internal.CredentialsUtil.serviceCredsSingle(CredentialsUtil.java:458)
at java.security.jgss/sun.security.krb5.internal.CredentialsUtil.serviceCreds(CredentialsUtil.java:340)
at java.security.jgss/sun.security.krb5.internal.CredentialsUtil.serviceCreds(CredentialsUtil.java:314)
at java.security.jgss/sun.security.krb5.internal.CredentialsUtil.acquireServiceCreds(CredentialsUtil.java:169)
at java.security.jgss/sun.security.krb5.Credentials.acquireServiceCreds(Credentials.java:490)
at java.security.jgss/sun.security.jgss.krb5.Krb5Context.initSecContext(Krb5Context.java:697)
at java.security.jgss/sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:266)