KEYCLOAK-16428 Move certificate timestamp validation configuration to CertificateValidatorBuilder (#7634)

This commit is contained in:
Luca Leonardo Scorcia 2021-01-12 14:52:34 -05:00 committed by GitHub
parent 0fecf1546a
commit 553514707e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 13 deletions

View file

@ -109,7 +109,9 @@ public abstract class AbstractX509ClientCertificateAuthenticator implements Auth
.cRLrelativePath(config.getCRLRelativePath())
.oCSPEnabled(config.getOCSPEnabled())
.oCSPResponseCertificate(config.getOCSPResponderCertificate())
.oCSPResponderURI(config.getOCSPResponder());
.oCSPResponderURI(config.getOCSPResponder())
.timestampValidation()
.enabled(config.isCertValidationEnabled());
}
}

View file

@ -385,6 +385,7 @@ public class CertificateValidator {
CRLLoaderImpl _crlLoader;
boolean _ocspEnabled;
OCSPChecker ocspChecker;
boolean _timestampValidationEnabled;
public CertificateValidator() {
@ -396,7 +397,8 @@ public class CertificateValidator {
CRLLoaderImpl crlLoader,
boolean oCSPCheckingEnabled,
OCSPChecker ocspChecker,
KeycloakSession session) {
KeycloakSession session,
boolean timestampValidationEnabled) {
_certChain = certChain;
_keyUsageBits = keyUsageBits;
_extendedKeyUsage = extendedKeyUsage;
@ -406,6 +408,7 @@ public class CertificateValidator {
_ocspEnabled = oCSPCheckingEnabled;
this.ocspChecker = ocspChecker;
this.session = session;
_timestampValidationEnabled = timestampValidationEnabled;
if (ocspChecker == null)
throw new IllegalArgumentException("ocspChecker");
@ -487,10 +490,10 @@ public class CertificateValidator {
return this;
}
public CertificateValidator validateTimestamps(boolean isValidationEnabled) throws GeneralSecurityException {
if (!isValidationEnabled) {
public CertificateValidator validateTimestamps() throws GeneralSecurityException {
if (!_timestampValidationEnabled)
return this;
}
for (int i = 0; i < _certChain.length; i++)
{
X509Certificate x509Certificate = _certChain[i];
@ -510,6 +513,7 @@ public class CertificateValidator {
throw new GeneralSecurityException(message);
}
}
return this;
}
@ -639,6 +643,7 @@ public class CertificateValidator {
boolean _ocspEnabled;
String _responderUri;
X509Certificate _responderCert;
boolean _timestampValidationEnabled;
public CertificateValidatorBuilder() {
_extendedKeyUsage = new LinkedList<>();
@ -807,6 +812,19 @@ public class CertificateValidator {
}
}
public class TimestampValidationBuilder {
CertificateValidatorBuilder _parent;
protected TimestampValidationBuilder(CertificateValidatorBuilder parent) {
_parent = parent;
}
public CertificateValidatorBuilder enabled(boolean timestampValidationEnabled) {
_timestampValidationEnabled = timestampValidationEnabled;
return _parent;
}
}
public CertificateValidatorBuilder session(KeycloakSession session) {
this.session = session;
return this;
@ -824,13 +842,17 @@ public class CertificateValidator {
return new RevocationStatusCheckBuilder(this);
}
public TimestampValidationBuilder timestampValidation() {
return new TimestampValidationBuilder(this);
}
public CertificateValidator build(X509Certificate[] certs) {
if (_crlLoader == null) {
_crlLoader = new CRLFileLoader(session, "");
}
return new CertificateValidator(certs, _keyUsageBits, _extendedKeyUsage,
_crlCheckingEnabled, _crldpEnabled, _crlLoader, _ocspEnabled,
new BouncyCastleOCSPChecker(session, _responderUri, _responderCert), session);
new BouncyCastleOCSPChecker(session, _responderUri, _responderCert), session, _timestampValidationEnabled);
}
}

View file

@ -85,7 +85,7 @@ public class X509ClientCertificateAuthenticator extends AbstractX509ClientCertif
validator.checkRevocationStatus()
.validateKeyUsage()
.validateExtendedKeyUsage()
.validateTimestamps(config.isCertValidationEnabled());
.validateTimestamps();
} catch(Exception e) {
logger.error(e.getMessage(), e);
// TODO use specific locale to load error messages

View file

@ -47,9 +47,12 @@ public class CertificateValidatorTest {
CertificateValidator.CertificateValidatorBuilder builder =
new CertificateValidator.CertificateValidatorBuilder();
CertificateValidator validator = builder.build(new X509Certificate[] { certificate });
CertificateValidator validator = builder
.timestampValidation()
.enabled(true)
.build(new X509Certificate[] { certificate });
try {
validator.validateTimestamps(true);
validator.validateTimestamps();
} catch (Exception ex) {
ex.printStackTrace();
Assert.fail(ex.getMessage());
@ -70,9 +73,12 @@ public class CertificateValidatorTest {
CertificateValidator.CertificateValidatorBuilder builder =
new CertificateValidator.CertificateValidatorBuilder();
CertificateValidator validator = builder.build(new X509Certificate[] { certificate });
CertificateValidator validator = builder
.timestampValidation()
.enabled(true)
.build(new X509Certificate[] { certificate });
try {
validator.validateTimestamps(true);
validator.validateTimestamps();
Assert.fail("certificate validation must fail for certificate is not valid yet");
} catch (Exception ex) {
MatcherAssert.assertThat(ex.getMessage(), Matchers.containsString("not valid yet"));
@ -94,9 +100,12 @@ public class CertificateValidatorTest {
CertificateValidator.CertificateValidatorBuilder builder =
new CertificateValidator.CertificateValidatorBuilder();
CertificateValidator validator = builder.build(new X509Certificate[] { certificate });
CertificateValidator validator = builder
.timestampValidation()
.enabled(true)
.build(new X509Certificate[] { certificate });
try {
validator.validateTimestamps(true);
validator.validateTimestamps();
Assert.fail("certificate validation must fail for certificate has expired");
} catch (Exception ex) {
MatcherAssert.assertThat(ex.getMessage(), Matchers.containsString("has expired"));