Skip to content

Commit 2299541

Browse files
committed
AUT-2623 Fix and improve tests
1 parent 3714891 commit 2299541

File tree

2 files changed

+75
-9
lines changed

2 files changed

+75
-9
lines changed

src/test/java/eu/webeid/ocsp/protocol/OcspResponseValidatorTest.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424

2525
import eu.webeid.ocsp.OcspCertificateRevocationChecker;
2626
import eu.webeid.ocsp.exceptions.UserCertificateOCSPCheckFailedException;
27+
import eu.webeid.ocsp.exceptions.UserCertificateRevokedException;
28+
import eu.webeid.ocsp.exceptions.UserCertificateUnknownException;
29+
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
30+
import org.bouncycastle.cert.ocsp.OCSPResp;
2731
import org.bouncycastle.cert.ocsp.SingleResp;
2832
import org.junit.jupiter.api.Test;
2933

@@ -33,7 +37,9 @@
3337
import java.time.temporal.ChronoUnit;
3438
import java.util.Date;
3539

40+
import static eu.webeid.ocsp.OcspCertificateRevocationCheckerTest.getOcspResponseBytesFromResources;
3641
import static eu.webeid.ocsp.protocol.OcspResponseValidator.validateCertificateStatusUpdateTime;
42+
import static eu.webeid.ocsp.protocol.OcspResponseValidator.validateSubjectCertificateStatus;
3743
import static org.assertj.core.api.Assertions.assertThatCode;
3844
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
3945
import static org.mockito.Mockito.mock;
@@ -118,8 +124,32 @@ void whenNextUpdateHalfHourBeforeNow_thenThrows() {
118124
+ " (OCSP responder: https://example.org)");
119125
}
120126

127+
@Test
128+
void whenRejectUnknownOcspResponseStatusIsFalse_ThenUnknownStatusThrowsUserCertificateRevokedException() throws Exception {
129+
SingleResp unknownCertStatus = getUnknownCertStatusResponse();
130+
assertThatExceptionOfType(UserCertificateRevokedException.class)
131+
.isThrownBy(() ->
132+
validateSubjectCertificateStatus(unknownCertStatus, OCSP_URL, false))
133+
.withMessage("User certificate has been revoked: Unknown status (OCSP responder: https://example.org)");
134+
}
135+
136+
@Test
137+
void whenRejectUnknownOcspResponseStatusIsTrue_ThenUnknownStatusThrowsUserCertificateUnknownException() throws Exception {
138+
SingleResp unknownCertStatus = getUnknownCertStatusResponse();
139+
assertThatExceptionOfType(UserCertificateUnknownException.class)
140+
.isThrownBy(() ->
141+
validateSubjectCertificateStatus(unknownCertStatus, OCSP_URL, true))
142+
.withMessage("User certificate status is unknown: Unknown status (OCSP responder: https://example.org)");
143+
}
144+
121145
private static Date getThisUpdateWithinAgeLimit(Instant now) {
122146
return Date.from(now.minus(THIS_UPDATE_AGE.minusSeconds(1)));
123147
}
124148

149+
private static SingleResp getUnknownCertStatusResponse() throws Exception {
150+
final OCSPResp ocspRespUnknown = new OCSPResp(getOcspResponseBytesFromResources("ocsp_response_unknown.der"));
151+
final BasicOCSPResp basicResponse = (BasicOCSPResp) ocspRespUnknown.getResponseObject();
152+
return basicResponse.getResponses()[0];
153+
}
154+
125155
}

src/test/java/eu/webeid/resilientocsp/ResilientOcspCertificateRevocationCheckerTest.java

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
3737
import io.github.resilience4j.retry.RetryConfig;
3838
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
39+
import org.bouncycastle.cert.ocsp.CertificateStatus;
3940
import org.bouncycastle.cert.ocsp.OCSPResp;
4041
import org.bouncycastle.cert.ocsp.RevokedStatus;
4142
import org.bouncycastle.cert.ocsp.SingleResp;
@@ -72,13 +73,16 @@ public class ResilientOcspCertificateRevocationCheckerTest {
7273

7374
private X509Certificate estEid2018Cert;
7475
private X509Certificate testEsteid2018CA;
76+
7577
private OCSPResp ocspRespGood;
78+
private OCSPResp ocspRespRevoked;
7679

7780
@BeforeEach
7881
void setUp() throws Exception {
7982
estEid2018Cert = getJaakKristjanEsteid2018Cert();
8083
testEsteid2018CA = getTestEsteid2018CA();
8184
ocspRespGood = new OCSPResp(getOcspResponseBytesFromResources("ocsp_response.der"));
85+
ocspRespRevoked = new OCSPResp(getOcspResponseBytesFromResources("ocsp_response_revoked.der"));
8286
}
8387

8488
@Test
@@ -133,8 +137,6 @@ void whenMultipleValidationCalls_thenPreviousResultsAreNotModified() throws Exce
133137

134138
@Test
135139
void whenFirstFallbackReturnsRevoked_thenRevocationPropagatesWithoutSecondFallback() throws Exception {
136-
OCSPResp ocspRespRevoked = new OCSPResp(getOcspResponseBytesFromResources("ocsp_response_revoked.der"));
137-
138140
OcspClient ocspClient = mock(OcspClient.class);
139141
when(ocspClient.request(eq(PRIMARY_URI), any()))
140142
.thenThrow(new OCSPClientException("Primary OCSP service unavailable"));
@@ -152,6 +154,25 @@ void whenFirstFallbackReturnsRevoked_thenRevocationPropagatesWithoutSecondFallba
152154
verify(ocspClient, never()).request(eq(SECOND_FALLBACK_URI), any());
153155
}
154156

157+
@Test
158+
void whenMaxAttemptsIsOneAndAllCallsFail_thenRevocationInfoListShouldHaveThreeElements() throws Exception {
159+
OcspClient ocspClient = mock(OcspClient.class);
160+
when(ocspClient.request(eq(PRIMARY_URI), any()))
161+
.thenThrow(new OCSPClientException());
162+
when(ocspClient.request(eq(FALLBACK_URI), any()))
163+
.thenThrow(new OCSPClientException());
164+
when(ocspClient.request(eq(SECOND_FALLBACK_URI), any()))
165+
.thenThrow(new OCSPClientException());
166+
167+
RetryConfig retryConfig = RetryConfig.custom()
168+
.maxAttempts(1)
169+
.build();
170+
171+
ResilientOcspCertificateRevocationChecker checker = buildChecker(ocspClient, retryConfig, false);
172+
ResilientUserCertificateOCSPCheckFailedException ex = assertThrows(ResilientUserCertificateOCSPCheckFailedException.class, () -> checker.validateCertificateNotRevoked(estEid2018Cert, testEsteid2018CA));
173+
assertThat(ex.getValidationInfo().revocationInfoList().size()).isEqualTo(3);
174+
}
175+
155176
@Test
156177
void whenMaxAttemptsIsTwoAndAllCallsFail_thenRevocationInfoListShouldHaveFourElements() throws Exception {
157178
OcspClient ocspClient = mock(OcspClient.class);
@@ -179,6 +200,10 @@ void whenMaxAttemptsIsTwoAndFirstCallFails_thenTwoCallsToPrimaryShouldBeRecorded
179200
when(ocspClient.request(eq(PRIMARY_URI), any()))
180201
.thenThrow(new OCSPClientException("Primary OCSP service unavailable (call1)"))
181202
.thenReturn(ocspRespGood);
203+
when(ocspClient.request(eq(FALLBACK_URI), any()))
204+
.thenReturn(ocspRespRevoked);
205+
when(ocspClient.request(eq(SECOND_FALLBACK_URI), any()))
206+
.thenReturn(ocspRespRevoked);
182207

183208
RetryConfig retryConfig = RetryConfig.custom()
184209
.maxAttempts(2)
@@ -206,36 +231,41 @@ void whenFirstCallSucceeds_thenRevocationInfoListShouldHaveOneElementAndItShould
206231
OcspClient ocspClient = mock(OcspClient.class);
207232
when(ocspClient.request(eq(PRIMARY_URI), any()))
208233
.thenReturn(ocspRespGood);
234+
when(ocspClient.request(eq(FALLBACK_URI), any()))
235+
.thenReturn(ocspRespRevoked);
236+
when(ocspClient.request(eq(SECOND_FALLBACK_URI), any()))
237+
.thenReturn(ocspRespRevoked);
209238

210239
ResilientOcspCertificateRevocationChecker checker = buildChecker(ocspClient, null, false);
211240

212241
List<RevocationInfo> revocationInfoList = checker.validateCertificateNotRevoked(estEid2018Cert, testEsteid2018CA);
213242
assertThat(revocationInfoList.size()).isEqualTo(1);
214243
Map<String, Object> responseAttributes = revocationInfoList.get(0).ocspResponseAttributes();
215244
OCSPResp ocspResp = (OCSPResp) responseAttributes.get("OCSP_RESPONSE");
216-
final BasicOCSPResp basicResponse = (BasicOCSPResp) ocspResp.getResponseObject();
217-
final SingleResp certStatusResponse = basicResponse.getResponses()[0];
218-
assertThat(certStatusResponse.getCertStatus()).isEqualTo(org.bouncycastle.cert.ocsp.CertificateStatus.GOOD);
245+
CertificateStatus status = getCertificateStatus(ocspResp);
246+
assertThat(status).isEqualTo(org.bouncycastle.cert.ocsp.CertificateStatus.GOOD);
219247
}
220248

221249
@Test
222250
@Disabled("Primary supplier has allowThisUpdateInPast disabled and that is checked before revocation, " +
223251
"which results in ResilientUserCertificateOCSPCheckFailedException")
224252
void whenFirstCallResultsInRevoked_thenRevocationInfoListShouldHaveOneElementAndItShouldHaveRevokedStatus() throws Exception {
225253
OcspClient ocspClient = mock(OcspClient.class);
226-
OCSPResp ocspRespRevoked = new OCSPResp(getOcspResponseBytesFromResources("ocsp_response_revoked.der"));
227254
when(ocspClient.request(eq(PRIMARY_URI), any()))
228255
.thenReturn(ocspRespRevoked);
256+
when(ocspClient.request(eq(FALLBACK_URI), any()))
257+
.thenReturn(ocspRespGood);
258+
when(ocspClient.request(eq(SECOND_FALLBACK_URI), any()))
259+
.thenReturn(ocspRespGood);
229260

230261
ResilientOcspCertificateRevocationChecker checker = buildChecker(ocspClient, null, false);
231262
ResilientUserCertificateRevokedException ex = assertThrows(ResilientUserCertificateRevokedException.class, () -> checker.validateCertificateNotRevoked(estEid2018Cert, testEsteid2018CA));
232263
List<RevocationInfo> revocationInfoList = ex.getValidationInfo().revocationInfoList();
233264
assertThat(revocationInfoList.size()).isEqualTo(1);
234265
Map<String, Object> responseAttributes = ex.getValidationInfo().revocationInfoList().get(0).ocspResponseAttributes();
235266
OCSPResp ocspResp = (OCSPResp) responseAttributes.get("OCSP_RESPONSE");
236-
final BasicOCSPResp basicResponse = (BasicOCSPResp) ocspResp.getResponseObject();
237-
final SingleResp certStatusResponse = basicResponse.getResponses()[0];
238-
assertThat(certStatusResponse.getCertStatus()).isInstanceOf(RevokedStatus.class);
267+
CertificateStatus status = getCertificateStatus(ocspResp);
268+
assertThat(status).isInstanceOf(RevokedStatus.class);
239269
}
240270

241271
private ResilientOcspCertificateRevocationChecker buildChecker(OcspClient ocspClient, RetryConfig retryConfig, boolean rejectUnknownOcspResponseStatus) throws Exception {
@@ -266,4 +296,10 @@ private ResilientOcspCertificateRevocationChecker buildChecker(OcspClient ocspCl
266296
rejectUnknownOcspResponseStatus
267297
);
268298
}
299+
300+
private CertificateStatus getCertificateStatus(OCSPResp ocspResp) throws Exception {
301+
final BasicOCSPResp basicResponse = (BasicOCSPResp) ocspResp.getResponseObject();
302+
final SingleResp certStatusResponse = basicResponse.getResponses()[0];
303+
return certStatusResponse.getCertStatus();
304+
}
269305
}

0 commit comments

Comments
 (0)