Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,11 @@ public void authenticate(AuthenticationToken authToken, ActionListener<Authentic
assert delegatedRealms != null : "Realm has not been initialized correctly";
X509AuthenticationToken token = (X509AuthenticationToken) authToken;
try {
final BytesKey fingerprint = computeFingerprint(token.credentials()[0]);
final BytesKey fingerprint = computeTokenFingerprint(token);
User user = cache.get(fingerprint);
if (user != null) {
logger.debug((Supplier<?>) () -> new ParameterizedMessage("Using cached authentication for DN [{}], as principal [{}]",
token.dn(), user.principal()));
if (delegatedRealms.hasDelegation()) {
delegatedRealms.resolve(user.principal(), listener);
} else {
Expand Down Expand Up @@ -317,9 +319,13 @@ public void expireAll() {
}
}

private static BytesKey computeFingerprint(X509Certificate certificate) throws CertificateEncodingException {
static BytesKey computeTokenFingerprint(X509AuthenticationToken token) throws CertificateEncodingException {
MessageDigest digest = MessageDigests.sha256();
digest.update(certificate.getEncoded());
byte i = 1;
for (X509Certificate certificate : token.credentials()) {
digest.update(certificate.getEncoded());
digest.update(i++);
}
return new BytesKey(digest.digest());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken;
import org.elasticsearch.xpack.core.security.support.NoOpLogger;
import org.elasticsearch.xpack.core.security.user.User;
import org.elasticsearch.xpack.security.authc.BytesKey;
import org.elasticsearch.xpack.security.authc.support.MockLookupRealm;
import org.elasticsearch.xpack.security.authc.support.UserRoleMapper;
import org.junit.Before;
Expand All @@ -47,6 +48,7 @@
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.sameInstance;
Expand Down Expand Up @@ -433,7 +435,7 @@ public void testDelegatedAuthorization() throws Exception {
assertThat(result.getUser(), sameInstance(lookupUser2));
}

public void testX509AuthenticationToken() throws Exception {
public void testX509AuthenticationTokenOrdered() throws Exception {
X509Certificate[] mockCertChain = new X509Certificate[2];
mockCertChain[0] = mock(X509Certificate.class);
when(mockCertChain[0].getIssuerX500Principal()).thenReturn(new X500Principal("CN=Test, OU=elasticsearch, O=org"));
Expand All @@ -443,6 +445,29 @@ public void testX509AuthenticationToken() throws Exception {
assertThat(e.getMessage(), is("certificates chain array is not ordered"));
}

public void testX509AuthenticationTokenCaching() throws Exception {
X509Certificate[] mockCertChain = new X509Certificate[2];
mockCertChain[0] = mock(X509Certificate.class);
when(mockCertChain[0].getSubjectX500Principal()).thenReturn(new X500Principal("CN=Test, OU=elasticsearch, O=org"));
when(mockCertChain[0].getIssuerX500Principal()).thenReturn(new X500Principal("CN=Test CA, OU=elasticsearch, O=org"));
when(mockCertChain[0].getEncoded()).thenReturn(randomByteArrayOfLength(2));
mockCertChain[1] = mock(X509Certificate.class);
when(mockCertChain[1].getSubjectX500Principal()).thenReturn(new X500Principal("CN=Test CA, OU=elasticsearch, O=org"));
when(mockCertChain[1].getEncoded()).thenReturn(randomByteArrayOfLength(3));
BytesKey cacheKey = PkiRealm.computeTokenFingerprint(new X509AuthenticationToken(mockCertChain));

BytesKey sameCacheKey = PkiRealm
.computeTokenFingerprint(new X509AuthenticationToken(new X509Certificate[] { mockCertChain[0], mockCertChain[1] }));
assertThat(cacheKey, is(sameCacheKey));

BytesKey cacheKeyClient = PkiRealm.computeTokenFingerprint(new X509AuthenticationToken(new X509Certificate[] { mockCertChain[0] }));
assertThat(cacheKey, is(not(cacheKeyClient)));

BytesKey cacheKeyRoot = PkiRealm.computeTokenFingerprint(new X509AuthenticationToken(new X509Certificate[] { mockCertChain[1] }));
assertThat(cacheKey, is(not(cacheKeyRoot)));
assertThat(cacheKeyClient, is(not(cacheKeyRoot)));
}

static X509Certificate readCert(Path path) throws Exception {
try (InputStream in = Files.newInputStream(path)) {
CertificateFactory factory = CertificateFactory.getInstance("X.509");
Expand Down