Skip to content

Add resilient OCSP certificate revocation checker#99

Open
madislm wants to merge 31 commits intoweb-eid:WE2-1030-use-platform-ocspfrom
madislm:AUT-2514
Open

Add resilient OCSP certificate revocation checker#99
madislm wants to merge 31 commits intoweb-eid:WE2-1030-use-platform-ocspfrom
madislm:AUT-2514

Conversation

@madislm
Copy link
Copy Markdown

@madislm madislm commented Feb 2, 2026

AUT-2514

Signed-off-by: Madis Jaagup Laurson madisjaagup.laurson@nortal.com

@madislm madislm force-pushed the AUT-2514 branch 2 times, most recently from 0e6161a to e927de2 Compare February 2, 2026 09:16
@madislm madislm force-pushed the AUT-2514 branch 5 times, most recently from e96286a to a324e96 Compare February 10, 2026 08:29
@mrts mrts force-pushed the WE2-1030-use-platform-ocsp branch from 10a405b to 74e7af2 Compare February 20, 2026 16:55
@madislm madislm force-pushed the AUT-2514 branch 2 times, most recently from 9cdcc89 to ef4ae35 Compare February 27, 2026 09:35
@mrts mrts force-pushed the WE2-1030-use-platform-ocsp branch from 74e7af2 to f55d636 Compare March 6, 2026 18:37
Comment thread src/main/java/eu/webeid/ocsp/service/FallbackOcspService.java Outdated
Comment thread src/main/java/eu/webeid/ocsp/service/OcspService.java Outdated
Comment thread src/main/java/eu/webeid/ocsp/OcspCertificateRevocationChecker.java Outdated
Comment thread src/main/java/eu/webeid/ocsp/protocol/OcspResponseValidator.java Outdated
Comment thread src/main/java/eu/webeid/ocsp/protocol/IssuerCommonName.java Outdated
Comment thread src/main/java/eu/webeid/ocsp/protocol/IssuerCommonName.java Outdated
Comment thread src/main/java/eu/webeid/ocsp/exceptions/OCSPClientException.java Outdated
Comment thread src/main/java/eu/webeid/ocsp/exceptions/OCSPClientException.java Outdated
Comment thread src/main/java/eu/webeid/ocsp/service/AiaOcspService.java Outdated
Comment thread src/main/java/eu/webeid/ocsp/service/FallbackOcspServiceConfiguration.java Outdated
Comment thread src/main/java/eu/webeid/ocsp/service/FallbackOcspServiceConfiguration.java Outdated
Comment thread src/main/java/eu/webeid/ocsp/OcspCertificateRevocationChecker.java Outdated
Comment thread src/main/java/eu/webeid/ocsp/protocol/IssuerDistinguishedName.java Outdated
*/
package eu.webeid.security.validator.revocationcheck;

import eu.webeid.resilientocsp.ResilientOcspCertificateRevocationChecker;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid depending on resilientocsp here, this creates a cyclic dependency between two separate libraries.

// Users must not be able to modify this value.
.ignoreExceptions(ResilientUserCertificateRevokedException.class)
.build();
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move the helpers from RevocationInfo here:

Suggested change
}
}
private static RevocationInfo withOcspResponse(RevocationInfo revocationInfo, byte[] ocspResponse) {
return revocationInfo.withAdditionalOcspResponseAttribute(RevocationInfo.KEY_OCSP_RESPONSE, ocspResponse);
}
private static RevocationInfo withHttpStatusCode(RevocationInfo revocationInfo, Integer statusCode) {
return revocationInfo.withAdditionalOcspResponseAttribute(RevocationInfo.KEY_HTTP_STATUS_CODE, statusCode);
}
private static RevocationInfo withCircuitBreakerStatistics(RevocationInfo revocationInfo, CircuitBreakerStatistics circuitBreakerStatistics) {
return revocationInfo.withAdditionalOcspResponseAttribute(RevocationInfo.KEY_CIRCUIT_BREAKER_STATISTICS, circuitBreakerStatistics);
}

if (result.isSuccess()) {
RevocationInfo revocationInfo = result.get();
if (revocationInfoList.isEmpty()) {
revocationInfo = revocationInfo.withCircuitBreakerStatistics(circuitBreakerStatistics);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the local helper instead:

Suggested change
revocationInfo = revocationInfo.withCircuitBreakerStatistics(circuitBreakerStatistics);
revocationInfo = withCircuitBreakerStatistics(revocationInfo, circuitBreakerStatistics);

Comment on lines +46 to +57

public RevocationInfo withCircuitBreakerStatistics(ResilientOcspCertificateRevocationChecker.CircuitBreakerStatistics circuitBreakerStatistics) {
return withAdditionalField(KEY_CIRCUIT_BREAKER_STATISTICS, circuitBreakerStatistics);
}

public RevocationInfo withOcspResponse(byte[] ocspResponse) {
return withAdditionalField(KEY_OCSP_RESPONSE, ocspResponse);
}

public RevocationInfo withHttpStatusCode(Integer statusCode) {
return withAdditionalField(KEY_HTTP_STATUS_CODE, statusCode);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As circuit breaker is not conceptually part of the base library, it is best to move these methods to ResilientOcspCertificateRevocationChecker.

Suggested change
public RevocationInfo withCircuitBreakerStatistics(ResilientOcspCertificateRevocationChecker.CircuitBreakerStatistics circuitBreakerStatistics) {
return withAdditionalField(KEY_CIRCUIT_BREAKER_STATISTICS, circuitBreakerStatistics);
}
public RevocationInfo withOcspResponse(byte[] ocspResponse) {
return withAdditionalField(KEY_OCSP_RESPONSE, ocspResponse);
}
public RevocationInfo withHttpStatusCode(Integer statusCode) {
return withAdditionalField(KEY_HTTP_STATUS_CODE, statusCode);
}

}

} No newline at end of file
private RevocationInfo withAdditionalField(String key, Object value) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice helper!

if (value == null) {
return this;
}
Map<String, Object> newOcspResponseAttributes = new HashMap<>(ocspResponseAttributes);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ocspResponseAttributes can be null, so null check is needed here:

Suggested change
Map<String, Object> newOcspResponseAttributes = new HashMap<>(ocspResponseAttributes);
Map<String, Object> newOcspResponseAttributes = ocspResponseAttributes != null
? new HashMap<>(ocspResponseAttributes)
: new HashMap<>();

new HashMap<>(null) throws NullPointerException.

CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker(primaryService.getAccessLocation().toASCIIString());

Optional<FallbackOcspService> firstFallbackServiceOpt = primaryService.getFallbackService();
if (firstFallbackServiceOpt.isEmpty()) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a comment here is needed to clarify that without a configured fallback the primary service is used directly:

Suggested change
if (firstFallbackServiceOpt.isEmpty()) {
if (firstFallbackServiceOpt.isEmpty()) {
// Without a configured fallback, use the primary service directly without retry or circuit-breaker.

As this is may be non-obvious, maybe add this to the class-level Javadoc as well:

  /**
   * OCSP revocation checker that falls back to configured fallback OCSP responders when the primary OCSP service fails.
   *
   * <p>Retry and circuit-breaker handling are applied only when a fallback OCSP service is configured for the
   * certificate issuer. If no fallback is configured, validation is handled by the primary OCSP service directly.
   */

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants