Skip to content
Snippets Groups Projects
Commit b417d509 authored by David Schwarzmann's avatar David Schwarzmann
Browse files

docs: Apply more comments and write some more texts

parent 4a3021fd
No related branches found
No related tags found
1 merge request!3docs(event-log): Start documenting the event log and interaction with signed JWTs
......@@ -7,6 +7,10 @@ liefert die API ein Array von JSON Web Token (JWT) gemäß [RFC 7519](https://da
JWT ist einen Security-Event-Token (SET) gemäß [RFC 8417](https://datatracker.ietf.org/doc/html/rfc8417). Wie mit den
Security-Event-Token (SET) umgegangen wird, wird in diesem Abschnitt beschrieben.
## Hintergrund
> Hier sollte begründet werden, warum ein solches signiertes Format sinnvoll ist (Nachweis bei Streitfällen, etc.).
## Events
Das folgende Statusdiagramm zeigt die Status und Ereignisse einer Einreichung. Die Status sind als orange Ovale
......@@ -15,10 +19,10 @@ empfangenden System erstellt und signiert.
![Statusdiagramm](/images/status/status.svg)
Das Akzeptieren oder Zurückweisen von Einreichungen oder Antworten passiert auf einer rein technischen Ebene und trifft
Das Akzeptieren oder Zurückweisen von Einreichungen auf einer rein technischen Ebene und trifft
keine Aussage über die fachliche Korrektheit der Einreichungen. Gründe für technische Rückweisungen wären beispielsweise
Probleme bei der Entschlüsselung oder Validierungsfehler der Datenstrukturen. In der folgenden Tabelle sind die Ereignisse,
ihre Beschreibungen und die Autoren aufgeführt und beschrieben.
Probleme bei der Entschlüsselung oder Validierungsfehler der Datenstrukturen. In der folgenden Tabelle sind die möglichen
Ereignisse, ihre Beschreibungen und die Autoren aufgeführt und beschrieben.
| Event | Autor | Bedeutung |
|-----------------------------------------------------------------|---------------------|-------------------------------|
......@@ -48,7 +52,7 @@ entsprechen und über folgende Header-Attribute verfügen:
| `alg` | `PS512` | Zur Signaturerstellung wird der Signaturalgorithmus RSASSA-PSS mit SHA-512 und MGF1 mit SHA-512 verwendet. Vorgabe gemäß [BSI TR-02102](https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Publikationen/TechnischeRichtlinien/TR02102/BSI-TR-02102.html) in der Version 2021-01 (Stand 24. März 2021). |
| `kid` | Key-ID des zugehörigen Public Keys | Die Key-ID des Public Key, mit dem die Signatur des JWT geprüft werden kann. |
Im Payload des signierten SET MÜSSEN die folgenden [standardisierten Felder](https://www.iana.org/assignments/jwt/jwt.xhtml)
In der Payload des signierten SET MÜSSEN die folgenden [standardisierten Felder](https://www.iana.org/assignments/jwt/jwt.xhtml)
gesetzt sein:
| Feld | Inhalt | Erläuterung |
......@@ -57,8 +61,8 @@ gesetzt sein:
| iat | Timestamp (UNIX-Format) | Zeitpunkt der Ausstellung des SET. |
| jti | UUID des Token | Die JWT ID ist eine eindeutige ID des SET bzw. JWT. Es wird eine zufällige UUID verwendet. |
| sub | URI, die den Gegenstand des SET identifiziert | Das Subject eines SET ist eine Kombination aus dem Schlüsselwort `submission` und der Id `submissionId` der Resource. |
| events | JSON-Objekt der Events in diesem Event-Token | Das Objekt "events" beschreibt eine oder mehrere Ereignisse zu einem logischen Sachverhalt bzw. Gesamtereignis, wie bspw. der Versendung einer Einreichung wurde durch den Sender. Dieses Objekt beinhaltet immer zwingend eine URI, die das jeweilige Gesamtereignis eindeutig identifiziert. Das Objekt der URI des Gesamtereignisses ist aktuell leer, kann aber zukünftig weitere Details zu einem Gesamtereignis enthalten. |
| txn | URI, die den Vorgang identifiziert | Als "Transaction Identifier" wird die Vorgangsreferenz `caseId` angegeben |
| events | JSON-Objekt der Events in diesem Event-Token | Das Objekt "events" beschreibt eine oder mehrere Ereignisse zu einem logischen Sachverhalt bzw. Gesamtereignis, wie bspw. der Versendung einer Einreichung durch den Sender. Dieses Objekt beinhaltet immer zwingend eine URI, die das jeweilige Gesamtereignis eindeutig identifiziert. Das Objekt der URI des Gesamtereignisses ist aktuell leer, kann aber zukünftig weitere Details zu einem Gesamtereignis enthalten. |
| txn | URI, die den Vorgang identifiziert | Als "Transaction Identifier" wird die Vorgangsreferenz `caseId` angegeben. |
:::note SET Beispiel
......@@ -94,7 +98,9 @@ UUID keyId = UUID.fromString(securityEventToken.getHeader().getKeyID());
validateTokenStructure(securityEventToken);
verifySignature(securityEventToken, keyId); // Abhängig von der Quelle
verifyZustelldienstSignature(securityEventToken, keyId)
// bzw.
verifyClientSignature(securityEventToken, keyId);
```
```java
......@@ -103,7 +109,7 @@ boolean validateTokenStructure(SignedJWT securityEventToken) {
validateHeader(signedJWT.getHeader());
validatePayload(signedJWT.getJWTClaimsSet());
} catch (ParseException e) {
throw new SecurityEventTokenValidationException("The payload of the SET could not get parsed properly.");
throw new RuntimeException("The payload of the SET could not get parsed properly.");
}
}
......@@ -122,7 +128,7 @@ private void validatePayload(JWTClaimsSet payload) throws ParseException {
validateTrueOrElseThrow(payload.getClaim("events") != null, "The claim events is missing in the payload of the SET.");
validateTrueOrElseThrow(payload.getJSONObjectClaim("events").keySet().size() == 1, "Only exactly one event is allowed.");
String uuidPattern = "\\b[0-9a-fA-F]{8}\\b-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-\\b[0-9a-fA-F]{12}\\b";
String uuidPattern = "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}";
String subject = payload.getStringClaim("sub");
validateTrueOrElseThrow(subject.matches("(submission|case|reply):" + uuidPattern), "The provided subject does not match the allowed pattern.");
......@@ -133,7 +139,7 @@ private void validatePayload(JWTClaimsSet payload) throws ParseException {
private void validateTrueOrElseThrow(boolean expression, String msg) {
if (!expression) {
throw new SecurityEventTokenValidationException(msg);
throw new RuntimeException(msg);
}
}
```
......@@ -192,6 +198,80 @@ boolean verifyZustelldienstSignature(SignedJWT securityEventToken, String keyId)
}
```
### :construction: Signaturprüfung eines vom Senders/Subscriber ausgestellten SET
### Signaturprüfung eines vom empfangenden System ausgestellten SET
Um die Signatur eines SET zu überprüfen, welches von einem empfangenden System ausgestellt wurde, ist es notwendig, auf den
verwendeten Schlüssel zugreifen zu können. Die Schlüssel eines empfangenden Systems sind über die Destination in Form eines
JSON Web Key (JWK) Sets öffentlich verfügbar. Welche Schritte notwendig sind und wie die Prüfung letztendlich durchgeführt
wird, wird im Folgenden anhand eines Beispiels beschrieben.
Als Ausgangslage dient das Token mit dem folgenden Header und der entsprechenden Payload. Aus dem Header wird die `kid`
benötigt, sowie die `submissionId` aus dem Payload. Konkret sind das hier
- kid: `dd0409e5-410e-4d98-85b6-f81a40b8d980`
- submissionId: `F65FEAB2-4883-4DFF-85FB-169448545D9F`
```json title="SET Header"
{
"typ": "secevent+jwt"
"alg": "PS512",
"kid": "dd0409e5-410e-4d98-85b6-f81a40b8d980",
}
```
```json title="SET Payload"
{
"iss": "https://api.fitko.de/fit-connect/",
"iat": 1622796532,
"jti": "0BF6DBF6-CE7E-44A3-889F-82FE74C3E715",
"sub": "submission:F65FEAB2-4883-4DFF-85FB-169448545D9F",
"events": {
"https://schema.fitko.de/fit-connect/events/accept-submission": {}
},
"txn": "case:F73D30C6-8894-4444-8687-00AE756FEA90"
}
```
Mit der `submissionId` kann über einen HTTP Request die `destinationId` aus der Repräsentation einer Submission gelesen
werden. Hier ist das konkret der Wert `92f2f581-c89d-44a5-b834-1fe3f6fa48d5`.
```http title="Abfrage der Submission"
GET /submissions/F65FEAB2-4883-4DFF-85FB-169448545D9F
{
"destinationId": "92f2f581-c89d-44a5-b834-1fe3f6fa48d5",
// ...
}
```
Über diese kann dann das JWK Set der zugehörigen Destination über einen HTTP Request abgefragt werden. In dem Attribut
`publicKeys` ist das JWK Set abgelegt. In den darin enthaltenen Schlüsseln kann dann der Schlüssel mit `kid` von oben
gesucht und für die Verifikation genutzt werden.
```http title="Abfrage der Destination"
GET /submissions/92f2f581-c89d-44a5-b834-1fe3f6fa48d5
{
"publicKeys": {
"keys": [
// ...
]
},
// ...
}
```
Die Verifikation mit dem Schlüssel ist dann ziemlich geradlinig. Es wird noch überprüft, ob der Schlüssel den passenden
Algorithmus hat und dann die eigentliche Verifikation über die Methode der Bibliothek durchgeführt.
```java
boolean verifyClientSignature(SignedJWT securityEventToken, String keyId) {
JWK publicKey = getKeyForSET(securityEventToken, keyId);
if (publicKey.getAlgorithm() != JWSAlgorithm.PS512) {
throw new RuntimeException("The key specified for signature verification doesn't use/specify PS512 as algorithm.")
}
JWSVerifier jwsVerifier = new RSASSAVerifier(publicKey.toRSAKey());
return signedJWT.verify(jwsVerifier);
}
```
TBD
......@@ -26,32 +26,7 @@ der darunterliegenden Tabelle beschrieben sind.
| `rejected` | Die Einreichung wurde durch den Empfänger zurückgewiesen. |
| `accepted` | Die Einreichung wurde durch den Empfänger akzeptiert. |
## Status über die Einreichung abfragen
Der Status kann über zwei Wege in zwei verschiedenen Formen abgerufen werden. Einerseits wird der Status in einer Einreichung
abgespeichert und ist in der Antwort von `GET /submissions/<uuid>` im Feld `currentStatus` enthalten. Der Wert darin
entspricht dem Wert aus obiger Tabelle.
```json {10}
{
"destinationId": "879ee109-a690-4db8-ab32-424284184d7d",
"submissionId": "ce75a6b8-d72f-4b94-b09e-af6be35dbc2ae",
"caseId": "e89e107e-ed79-40e6-ad34-4e770f9df26d",
"attachments": [
...
],
"encryptedMetadata": "ey...Yfiz5g",
"encryptedData": "eyJlbmMiO...iz5g",
"currentStatus": "submitted",
"serviceType": {
...
}
}
```
## Status über den Event Log abfragen
Alternativ kann der Status über `GET /submissions/<uuid>/events` abgefragt werden. Hierbei wird der Event Log der Einreichung
Der Status wird über `GET /submissions/<uuid>/events` abgefragt. Hierbei wird der Event Log der Einreichung
zurückgeliefert, der die verschiedenen Statusübergänge bzw. abgelegten Ereignisse beinhaltet. Das Ergebnis könnte wie folgt aussehen:
```json
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment