Skip to content

Instantly share code, notes, and snippets.

@kwart
Created May 13, 2022 13:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kwart/a47c100d1f436941ed8d7bc14bd4af00 to your computer and use it in GitHub Desktop.
Save kwart/a47c100d1f436941ed8d7bc14bd4af00 to your computer and use it in GitHub Desktop.
Sample Hazelcast login module that checks SAN information in TLS client certificate.
package com.hazelcast.security.loginimpl;
import java.io.IOException;
import java.security.cert.Certificate;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.List;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.FailedLoginException;
import javax.security.auth.login.LoginException;
import com.hazelcast.security.CertificatesCallback;
import com.hazelcast.security.ClusterLoginModule;
public class SanCheckingLoginModule extends ClusterLoginModule {
public static final Integer GENERAL_NAME_DNS = 2;
private String name;
@Override
public boolean onLogin() throws LoginException {
CertificatesCallback cb = new CertificatesCallback();
try {
callbackHandler.handle(new Callback[] { cb });
} catch (IOException | UnsupportedCallbackException e) {
throw new FailedLoginException("Unable to retrieve Certificates. " + e.getMessage());
}
Certificate[] certs = cb.getCertificates();
if (certs == null || certs.length == 0 || !(certs[0] instanceof X509Certificate)) {
throw new FailedLoginException("No valid X.509 certificate found");
}
X509Certificate clientCert = (X509Certificate) certs[0];
Collection<List<?>> sans;
try {
sans = clientCert.getSubjectAlternativeNames();
} catch (CertificateParsingException e) {
throw new FailedLoginException("Unable to parse SANs");
}
if (sans==null || sans.isEmpty()) {
throw new FailedLoginException("No valid SAN entry found");
}
name = clientCert.getSubjectX500Principal().getName();
if (!isSkipRole()) {
for (List<?> san: sans) {
//TODO implement your own SAN checking and role assignment logic here
//dummy implementation:
if (GENERAL_NAME_DNS.equals(san.get(0))) {
String dnsSan = (String) san.get(1);
if ("xxx.hazelcast.com".equals(dnsSan)) {
addRole("admin");
}
}
}
}
return true;
}
@Override
protected String getName() {
return name;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment