Skip to content

Commit 0f6835c

Browse files
authored
Merge pull request #2982 from nordic-institute/XRDDEV-2921
Xrddev 2921
2 parents a904043 + b85417e commit 0f6835c

File tree

85 files changed

+1223
-1055
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+1223
-1055
lines changed

src/addons/messagelog/messagelog-addon/src/main/java/org/niis/xroad/proxy/core/messagelog/AbstractTimestampRequest.java

Lines changed: 85 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,22 @@
2525
*/
2626
package org.niis.xroad.proxy.core.messagelog;
2727

28-
import ee.ria.xroad.common.CodedException;
2928
import ee.ria.xroad.common.messagelog.MessageLogProperties;
3029

3130
import jakarta.xml.bind.JAXBException;
3231
import lombok.Getter;
3332
import lombok.RequiredArgsConstructor;
3433
import lombok.extern.slf4j.Slf4j;
3534
import org.apache.xml.security.signature.XMLSignatureException;
35+
import org.bouncycastle.asn1.ASN1Encoding;
3636
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
3737
import org.bouncycastle.cms.CMSException;
38-
import org.bouncycastle.operator.OperatorCreationException;
3938
import org.bouncycastle.tsp.TSPException;
4039
import org.bouncycastle.tsp.TimeStampRequest;
4140
import org.bouncycastle.tsp.TimeStampRequestGenerator;
4241
import org.bouncycastle.tsp.TimeStampResponse;
4342
import org.bouncycastle.tsp.TimeStampToken;
43+
import org.niis.xroad.common.core.exception.ErrorCode;
4444
import org.niis.xroad.common.core.exception.XrdRuntimeException;
4545
import org.niis.xroad.globalconf.GlobalConfProvider;
4646
import org.niis.xroad.globalconf.impl.signature.TimestampVerifier;
@@ -51,11 +51,18 @@
5151
import java.io.InputStream;
5252
import java.security.cert.CertificateEncodingException;
5353
import java.security.cert.X509Certificate;
54+
import java.util.HashMap;
5455
import java.util.List;
56+
import java.util.Map;
5557

56-
import static ee.ria.xroad.common.ErrorCodes.X_INTERNAL_ERROR;
5758
import static ee.ria.xroad.common.crypto.Digests.calculateDigest;
5859
import static ee.ria.xroad.common.crypto.Digests.getAlgorithmIdentifier;
60+
import static org.niis.xroad.common.core.exception.ErrorCode.ADDING_SIGNATURE_TO_TS_TOKEN_FAILED;
61+
import static org.niis.xroad.common.core.exception.ErrorCode.CALCULATING_MESSAGE_DIGEST_FAILED;
62+
import static org.niis.xroad.common.core.exception.ErrorCode.TIMESTAMPING_FAILED;
63+
import static org.niis.xroad.common.core.exception.ErrorCode.TIMESTAMP_RESPONSE_VALIDATION_FAILED;
64+
import static org.niis.xroad.common.core.exception.ErrorCode.TIMESTAMP_TOKEN_ENCODING_FAILED;
65+
import static org.niis.xroad.common.core.exception.ErrorCode.TSP_CERTIFICATE_NOT_FOUND;
5966
import static org.niis.xroad.proxy.core.messagelog.TimestamperUtil.addSignerCertificate;
6067
import static org.niis.xroad.proxy.core.messagelog.TimestamperUtil.getTimestampResponse;
6168

@@ -89,62 +96,115 @@ public static class TsRequest {
8996

9097
protected Timestamper.TimestampResult makeTsRequest(TimeStampRequest tsRequest, List<String> tspUrls) {
9198
log.debug("tspUrls: {}", tspUrls);
99+
Map<String, Exception> errorsByUrl = new HashMap<>();
92100
for (String url : tspUrls) {
93101
try {
94102
log.debug("Sending time-stamp request to {}", url);
95103

96-
TsRequest req = new TsRequest(TimestamperUtil.makeTsRequest(tsRequest, url), url);
104+
TsRequest req = new TsRequest(getTsRequestInputStream(tsRequest, url), url);
97105

98106
TimeStampResponse tsResponse = getTimestampResponse(req.getInputStream());
99107
log.info("tsresponse {}", tsResponse);
100108

101109
verify(tsRequest, tsResponse);
102110

103-
return result(tsResponse, url);
111+
Timestamper.TimestampResult result = result(tsResponse, url);
112+
result.setErrorsByUrl(errorsByUrl);
113+
return result;
104114

105115
} catch (Exception ex) {
106116
log.error("Failed to get time stamp from " + url, ex);
117+
errorsByUrl.put(url, ex);
107118
}
108119
}
109120

110-
// All the URLs failed. Throw exception.
111-
throw XrdRuntimeException.systemInternalError("Failed to get time stamp from any time-stamping providers");
121+
Timestamper.TimestampFailed timestampFailed = new Timestamper.TimestampFailed(logRecords,
122+
XrdRuntimeException.systemException(TIMESTAMPING_FAILED)
123+
.details("Failed to get time stamp from any time-stamping providers")
124+
.build()
125+
);
126+
timestampFailed.setErrorsByUrl(errorsByUrl);
127+
return timestampFailed;
112128
}
113129

114-
private TimeStampRequest createTimestampRequest(byte[] data) throws IOException {
130+
private static InputStream getTsRequestInputStream(TimeStampRequest tsRequest, String url) {
131+
try {
132+
return TimestamperUtil.makeTsRequest(tsRequest, url);
133+
} catch (IOException e) {
134+
throw XrdRuntimeException.systemException(ErrorCode.TIMESTAMP_PROVIDER_CONNECTION_FAILED)
135+
.details("Could not get response from TSP")
136+
.build();
137+
}
138+
}
139+
140+
private TimeStampRequest createTimestampRequest(byte[] data) {
115141
TimeStampRequestGenerator reqgen = new TimeStampRequestGenerator();
116142

117143
var tsaHashAlg = MessageLogProperties.getHashAlg();
118144

119145
log.trace("Creating time-stamp request (algorithm: {})", tsaHashAlg);
120146

121-
byte[] digest = calculateDigest(tsaHashAlg, data);
147+
byte[] digest;
148+
try {
149+
digest = calculateDigest(tsaHashAlg, data);
150+
} catch (IOException e) {
151+
throw XrdRuntimeException.systemException(CALCULATING_MESSAGE_DIGEST_FAILED)
152+
.cause(e)
153+
.build();
154+
}
122155

123-
ASN1ObjectIdentifier algorithm =
124-
getAlgorithmIdentifier(tsaHashAlg).getAlgorithm();
156+
ASN1ObjectIdentifier algorithm = getAlgorithmIdentifier(tsaHashAlg).getAlgorithm();
125157

126158
return reqgen.generate(algorithm, digest);
127159
}
128160

129-
protected byte[] getTimestampDer(TimeStampResponse tsResponse)
130-
throws CertificateEncodingException, IOException, TSPException, CMSException {
131-
X509Certificate signerCertificate =
132-
TimestampVerifier.getSignerCertificate(
133-
tsResponse.getTimeStampToken(),
134-
globalConfProvider.getTspCertificates());
161+
protected byte[] getTimestampDer(TimeStampResponse tsResponse) {
162+
X509Certificate signerCertificate = getSignerCertificate(tsResponse);
163+
TimeStampToken token = getTimeStampToken(tsResponse, signerCertificate);
164+
try {
165+
return token.getEncoded(ASN1Encoding.DER);
166+
} catch (IOException e) {
167+
throw XrdRuntimeException.systemException(TIMESTAMP_TOKEN_ENCODING_FAILED)
168+
.details("Timestamp token der encoding failed")
169+
.cause(e)
170+
.build();
171+
}
172+
}
173+
174+
private X509Certificate getSignerCertificate(TimeStampResponse tsResponse) {
175+
X509Certificate signerCertificate;
176+
signerCertificate = TimestampVerifier.getSignerCertificate(
177+
tsResponse.getTimeStampToken(),
178+
globalConfProvider.getTspCertificates());
135179
if (signerCertificate == null) {
136-
throw new CodedException(X_INTERNAL_ERROR,
137-
"Could not find signer certificate");
180+
throw XrdRuntimeException.systemException(TSP_CERTIFICATE_NOT_FOUND)
181+
.details("Could not find signer certificate")
182+
.build();
138183
}
184+
return signerCertificate;
185+
}
139186

140-
TimeStampToken token =
141-
addSignerCertificate(tsResponse, signerCertificate);
142-
return token.getEncoded();
187+
private static TimeStampToken getTimeStampToken(TimeStampResponse tsResponse, X509Certificate signerCertificate) {
188+
try {
189+
return addSignerCertificate(tsResponse, signerCertificate);
190+
} catch (CMSException | TSPException | CertificateEncodingException | IOException e) {
191+
throw XrdRuntimeException.systemException(ADDING_SIGNATURE_TO_TS_TOKEN_FAILED)
192+
.details("Adding signer certificate to timestamp token failed")
193+
.cause(e)
194+
.build();
195+
}
143196
}
144197

145-
protected void verify(TimeStampRequest request, TimeStampResponse response)
146-
throws TSPException, CertificateEncodingException, IOException, OperatorCreationException, CMSException {
147-
response.validate(request);
198+
protected void verify(TimeStampRequest request, TimeStampResponse response) {
199+
try {
200+
response.validate(request);
201+
} catch (TSPException e) {
202+
throw XrdRuntimeException.systemException(TIMESTAMP_RESPONSE_VALIDATION_FAILED)
203+
.details("Timestamp response validation against the request failed")
204+
.metadataItems(e.getMessage())
205+
.cause(e)
206+
.build();
207+
}
148208

149209
TimeStampToken token = response.getTimeStampToken();
150210
TimestampVerifier.verify(token, globalConfProvider.getTspCertificates());

src/addons/messagelog/messagelog-addon/src/main/java/org/niis/xroad/proxy/core/messagelog/BatchTimestampRequest.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,18 @@
3232
import org.bouncycastle.cms.CMSException;
3333
import org.bouncycastle.tsp.TSPException;
3434
import org.bouncycastle.tsp.TimeStampResponse;
35+
import org.niis.xroad.common.core.exception.XrdRuntimeException;
3536
import org.niis.xroad.globalconf.GlobalConfProvider;
3637

3738
import java.io.IOException;
3839
import java.security.cert.CertificateEncodingException;
40+
import java.util.Arrays;
3941

4042
import static ee.ria.xroad.common.util.EncoderUtils.decodeBase64;
4143
import static ee.ria.xroad.common.util.MessageFileNames.SIGNATURE;
4244
import static ee.ria.xroad.common.util.MessageFileNames.TS_HASH_CHAIN;
4345
import static java.nio.charset.StandardCharsets.UTF_8;
46+
import static org.niis.xroad.common.core.exception.ErrorCode.FAILED_TO_BUILD_SIGNATURE_HASH_CHAIN;
4447

4548
class BatchTimestampRequest extends AbstractTimestampRequest {
4649

@@ -57,10 +60,17 @@ class BatchTimestampRequest extends AbstractTimestampRequest {
5760
}
5861

5962
@Override
60-
byte[] getRequestData() throws JAXBException, IOException {
61-
HashChainBuilder hcBuilder = buildHashChain(signatureHashes);
62-
hashChainResult = hcBuilder.getHashChainResult(TS_HASH_CHAIN);
63-
hashChains = hcBuilder.getHashChains(SIGNATURE);
63+
byte[] getRequestData() {
64+
try {
65+
HashChainBuilder hcBuilder = buildHashChain(signatureHashes);
66+
hashChainResult = hcBuilder.getHashChainResult(TS_HASH_CHAIN);
67+
hashChains = hcBuilder.getHashChains(SIGNATURE);
68+
} catch (IOException | JAXBException e) {
69+
throw XrdRuntimeException.systemException(FAILED_TO_BUILD_SIGNATURE_HASH_CHAIN)
70+
.details("Failed to build hash chain for log records " + Arrays.toString(logRecords))
71+
.cause(e)
72+
.build();
73+
}
6474
return hashChainResult.getBytes(UTF_8);
6575
}
6676

src/addons/messagelog/messagelog-addon/src/main/java/org/niis/xroad/proxy/core/messagelog/LogManager.java

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
package org.niis.xroad.proxy.core.messagelog;
2727

2828
import ee.ria.xroad.common.CodedException;
29-
import ee.ria.xroad.common.DiagnosticsErrorCodes;
29+
import ee.ria.xroad.common.DiagnosticStatus;
30+
import ee.ria.xroad.common.DiagnosticsStatus;
3031
import ee.ria.xroad.common.DiagnosticsUtils;
3132
import ee.ria.xroad.common.message.AttachmentStream;
3233
import ee.ria.xroad.common.messagelog.AbstractLogManager;
@@ -44,9 +45,9 @@
4445
import jakarta.xml.soap.SOAPException;
4546
import lombok.extern.slf4j.Slf4j;
4647
import org.apache.commons.io.input.BoundedInputStream;
48+
import org.niis.xroad.common.core.exception.ErrorCode;
4749
import org.niis.xroad.common.core.exception.XrdRuntimeException;
4850
import org.niis.xroad.globalconf.GlobalConfProvider;
49-
import org.niis.xroad.globalconf.status.DiagnosticsStatus;
5051
import org.niis.xroad.serverconf.ServerConfProvider;
5152

5253
import java.io.IOException;
@@ -61,7 +62,6 @@
6162
import java.util.concurrent.ScheduledFuture;
6263

6364
import static ee.ria.xroad.common.ErrorCodes.X_LOGGING_FAILED_X;
64-
import static ee.ria.xroad.common.ErrorCodes.X_MLOG_TIMESTAMPER_FAILED;
6565
import static ee.ria.xroad.common.crypto.Digests.calculateDigest;
6666
import static ee.ria.xroad.common.messagelog.MessageLogProperties.getAcceptableTimestampFailurePeriodSeconds;
6767
import static ee.ria.xroad.common.messagelog.MessageLogProperties.getHashAlg;
@@ -70,6 +70,8 @@
7070
import static ee.ria.xroad.common.util.EncoderUtils.encodeBase64;
7171
import static java.nio.charset.StandardCharsets.UTF_8;
7272
import static java.util.concurrent.TimeUnit.SECONDS;
73+
import static org.niis.xroad.common.core.exception.ErrorCode.NO_TIMESTAMPING_PROVIDER_FOUND;
74+
import static org.niis.xroad.common.core.exception.ErrorCode.TIMESTAMPING_FAILED;
7375

7476
/**
7577
* Message log manager. Sets up the whole logging system components.
@@ -194,7 +196,7 @@ private TimestampRecord timestampImmediately(MessageRecord logRecord) {
194196
case Timestamper.TimestampFailed ttf:
195197
Exception e = ttf.getCause();
196198
log.error("Timestamping failed", e);
197-
putStatusMapFailures(e);
199+
putStatusMapFailures(ttf);
198200
throw XrdRuntimeException.systemException(e);
199201
default:
200202
throw XrdRuntimeException.systemInternalError("Unexpected result from Timestamper: " + result.getClass());
@@ -312,25 +314,19 @@ static TimestampRecord saveTimestampRecord(Timestamper.TimestampSucceeded messag
312314
* @param url url of timestamper which stamped successfully
313315
*/
314316
static void putStatusMapSuccess(String url) {
315-
statusMap.put(url, new DiagnosticsStatus(DiagnosticsErrorCodes.RETURN_SUCCESS, TimeUtils.offsetDateTimeNow()));
317+
statusMap.put(url, new DiagnosticsStatus(DiagnosticStatus.OK, TimeUtils.offsetDateTimeNow()));
316318
}
317319

318-
/**
319-
* Put failure state into statusMap (used for diagnostics).
320-
* Timestamping ({@link AbstractTimestampRequest} attempts to use all TSAs, and failure means that
321-
* all were tried and failed, so all TSAs will be marked with failed status
322-
*
323-
* @param e exception which is used to determine diagnostics error code
324-
*/
325-
void putStatusMapFailures(Exception e) {
326-
int errorCode = DiagnosticsUtils.getErrorCode(e);
327-
for (String tspUrl : serverConfProvider.getTspUrl()) {
328-
statusMap.put(tspUrl,
329-
new DiagnosticsStatus(errorCode, TimeUtils.offsetDateTimeNow(), tspUrl));
330-
}
320+
void putStatusMapFailures(Timestamper.TimestampFailed timestampFailedResult) {
321+
timestampFailedResult.getErrorsByUrl().forEach((tspUrl, ex) -> {
322+
ErrorCode errorCode = DiagnosticsUtils.getErrorCode(ex);
323+
DiagnosticsStatus diagnosticsStatus =
324+
new DiagnosticsStatus(DiagnosticStatus.ERROR, TimeUtils.offsetDateTimeNow(), tspUrl, errorCode);
325+
diagnosticsStatus.setErrorCodeMetadata(DiagnosticsUtils.getErrorCodeMetadata(ex));
326+
statusMap.put(tspUrl, diagnosticsStatus);
327+
});
331328
}
332329

333-
334330
private static TimestampRecord createTimestampRecord(Timestamper.TimestampSucceeded message) {
335331
TimestampRecord timestampRecord = new TimestampRecord();
336332
timestampRecord.setTime(new Date().getTime());
@@ -353,7 +349,7 @@ void setTimestampingStatus(SetTimestampingStatusMessage statusMessage) {
353349
}
354350

355351
/**
356-
* Only externally use this method from tests. Otherwise send message to this actor.
352+
* Only externally use this method from tests. Otherwise, send message to this actor.
357353
*/
358354
void setTimestampSucceeded() {
359355
if (timestampFailed != null) {
@@ -371,8 +367,9 @@ void setTimestampFailed(Instant atTime) {
371367

372368
private void verifyCanLogMessage(boolean shouldTimestampImmediately) {
373369
if (serverConfProvider.getTspUrl().isEmpty()) {
374-
throw new CodedException(X_MLOG_TIMESTAMPER_FAILED,
375-
"Cannot time-stamp messages: no timestamping services configured");
370+
throw XrdRuntimeException.systemException(NO_TIMESTAMPING_PROVIDER_FOUND)
371+
.details("Cannot time-stamp messages: no timestamping services configured")
372+
.build();
376373
}
377374

378375
if (!shouldTimestampImmediately) {
@@ -384,7 +381,9 @@ private void verifyCanLogMessage(boolean shouldTimestampImmediately) {
384381

385382
if (isTimestampFailed()) {
386383
if (TimeUtils.now().minusSeconds(period).isAfter(timestampFailed)) {
387-
throw new CodedException(X_MLOG_TIMESTAMPER_FAILED, "Cannot time-stamp messages");
384+
throw XrdRuntimeException.systemException(TIMESTAMPING_FAILED)
385+
.details("Cannot time-stamp messages")
386+
.build();
388387
}
389388
}
390389
}

src/addons/messagelog/messagelog-addon/src/main/java/org/niis/xroad/proxy/core/messagelog/LogRecordManager.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import lombok.extern.slf4j.Slf4j;
4444
import org.hibernate.Session;
4545
import org.hibernate.query.MutationQuery;
46+
import org.niis.xroad.common.core.exception.ErrorCode;
4647
import org.niis.xroad.common.core.exception.XrdRuntimeException;
4748

4849
import java.sql.Connection;
@@ -182,12 +183,19 @@ static void updateMessageRecordSignature(MessageRecord messageRecord, String old
182183
*/
183184
static void saveTimestampRecord(TimestampRecord timestampRecord, Long[]
184185
timestampedLogRecords, String[] hashChains) {
185-
doInTransaction(session -> {
186-
timestampRecord.setId(getNextRecordId(session));
187-
save(session, timestampRecord);
188-
setMessageRecordsTimestamped(session, timestampedLogRecords, timestampRecord, hashChains);
189-
return null;
190-
});
186+
try {
187+
doInTransaction(session -> {
188+
timestampRecord.setId(getNextRecordId(session));
189+
save(session, timestampRecord);
190+
setMessageRecordsTimestamped(session, timestampedLogRecords, timestampRecord, hashChains);
191+
return null;
192+
});
193+
} catch (Exception e) {
194+
throw XrdRuntimeException.systemException(ErrorCode.TIMESTAMP_RECORD_SAVE_FAILURE)
195+
.details("Failed to save timestamp record to database")
196+
.cause(e)
197+
.build();
198+
}
191199
}
192200

193201
/**
@@ -265,7 +273,7 @@ private static void setMessageRecordsTimestamped(Long[] messageRecords, Timestam
265273
}
266274

267275
private static AbstractLogRecordEntity getLogRecord(Session session, Long number) {
268-
return session.get(AbstractLogRecordEntity.class, number);
276+
return session.find(AbstractLogRecordEntity.class, number);
269277
}
270278

271279
private static MessageRecordEntity getMessageRecord(Session session, String queryId, ClientId clientId,

src/addons/messagelog/messagelog-addon/src/main/java/org/niis/xroad/proxy/core/messagelog/MessageLogDatabaseCtx.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ public static DatabaseCtx get() {
5050
* @param <T> the type of result.
5151
* @param callback the callback.
5252
* @return the result.
53-
* @throws Exception if an error occurs.
5453
*/
5554
public static <T> T doInTransaction(TransactionCallback<T> callback) {
5655
return CTX.doInTransaction(callback);

0 commit comments

Comments
 (0)