1
0
mirror of https://github.com/pcvolkmer/mv64e-rest-to-kafka-gateway synced 2025-09-13 01:02:51 +00:00

feat: custom HTTP basic user-names

This commit is contained in:
2025-09-09 21:01:18 +02:00
parent b19f7fd2fe
commit 84ee8cbde7
2 changed files with 44 additions and 12 deletions

View File

@@ -41,7 +41,7 @@ Die Anwendung lässt sich auch mit Umgebungsvariablen konfigurieren.
* `LISTEN`: Adresse und Port für eingehende HTTP-Requests. Standardwert: `[::]:3000` - Port `3000` auf allen
Adressen (IPv4 und IPv6)
* `SECURITY_TOKEN`: Verpflichtende Angabe es Tokens als *bcrypt*-Hash
* `SECURITY_TOKEN`: Verpflichtende Angabe des Benutzernamens und *bcrypt*-Hash des Passworts
* `KAFKA_BOOTSTRAP_SERVERS`: Zu verwendende Kafka-Bootstrap-Server als kommagetrennte Liste
* `KAFKA_TOPIC`: Zu verwendendes Topic zum Warten auf neue Anfragen. Standardwert: `etl-processor_input`
@@ -72,17 +72,23 @@ wird.
### Authentifizierung
Requests müssen einen HTTP-Header `authorization` für HTTP-Basic enthalten. Hier ist es erforderlich, dass der
Benutzername `token` gewählt wird.
Es ist hierzu erforderlich, die erforderliche Umgebungsvariable `SECURITY_TOKEN` zu setzen. Dies kann z.B. mit
*htpasswd* erzeugt werden:
Requests müssen einen HTTP-Header `authorization` für HTTP-Basic enthalten.
Dazu muss die erforderliche Umgebungsvariable `SECURITY_TOKEN` gesetzt sein.
Der erforderliche Wert kann z.B. mit *htpasswd* erzeugt werden - `token` ist hier der gewählte Benutzername - es kann
jedoch ein beliebiger Benutzername verwendet werden:
```
htpasswd -Bn token
```
Der hintere Teil (hinter `token:`) entspricht dem *bcrypt*-Hash des Tokens.
Der vordere Teil der Ausgabe ist der Benutzername, der hintere Teil (im Beispiel hinter `token:`) entspricht dem
*bcrypt*-Hash des Tokens, welches als HTTP-Basic-Passwort erwartet wird.
Ein Beispiel für die Angabe `SECURITY_TOKEN` ist für den Benutzernamen `token` und das Passwort `very-secret`:
`token:$2y$05$LIIFF4Rbi3iRVA4UIqxzPeTJ0NOn/cV2hDnSKFftAMzbEZRa42xSG`
Zur Kompatibilität mit älteren Versionen kann (nur) bei Wahl des Benutzernamens `token` der Teil `token:`
bei der Angabe entfallen: `$2y$05$LIIFF4Rbi3iRVA4UIqxzPeTJ0NOn/cV2hDnSKFftAMzbEZRa42xSG`
### Beispiele für HTTP-Requests und resultierende Kafka-Records
@@ -146,8 +152,10 @@ Resultierender Kafka-Record:
Es werden keine weiteren patientenbezogenen Daten übermittelt.
In optionaler Verbindung mit [Key-Based-Retention](https://github.com/pcvolkmer/mv64e-etl-processor#key-based-retention) wird
In optionaler Verbindung mit [Key-Based-Retention](https://github.com/pcvolkmer/mv64e-etl-processor#key-based-retention)
wird
lediglich der letzte und aktuelle Record, hier die Information ohne Consent-Zustimmung, in Kafka vorgehalten.
Trifft dieser Kafka-Record im [ETL-Prozessor](https://github.com/pcvolkmer/mv64e-etl-processor) ein, so wird dort ebenfalls eine
Trifft dieser Kafka-Record im [ETL-Prozessor](https://github.com/pcvolkmer/mv64e-etl-processor) ein, so wird dort
ebenfalls eine
Löschanfrage ausgelöst, da keine Modellvorhaben Metadaten enthalten sind.

View File

@@ -9,9 +9,17 @@ pub fn check_basic_auth(auth_header: &str, expected_token: &str) -> bool {
&& let Ok(auth) = BASE64_STANDARD.decode(split.last().unwrap_or(&""))
&& let Ok(auth) = String::from_utf8(auth)
{
let split_token = expected_token.split(':').collect::<Vec<_>>();
let expected_username = if split_token.len() == 2 {
split_token.first().unwrap_or(&"token")
} else {
&"token"
};
let expected_token = split_token.get(1).unwrap_or(&expected_token);
let split = auth.split(':').collect::<Vec<_>>();
if split.len() == 2
&& split.first() == Some(&"token")
&& split.first() == Some(expected_username)
&& let Some(&token) = split.last()
&& let Ok(true) = bcrypt::verify(token, expected_token)
{
@@ -48,7 +56,7 @@ mod tests {
}
#[test]
fn should_reject_basic_auth_without_wrong_token() {
fn should_reject_basic_auth_without_valid_token() {
assert!(!check_basic_auth(
"Basic dG9rZW46MTIzNDU2Nzg5",
EXPECTED_TOKEN
@@ -56,10 +64,26 @@ mod tests {
}
#[test]
fn should_accept_basic_auth_without_correct_token() {
fn should_accept_basic_auth_with_valid_token() {
assert!(check_basic_auth(
"Basic dG9rZW46dmVyeS1zZWNyZXQ=",
EXPECTED_TOKEN
));
}
#[test]
fn should_accept_basic_auth_with_custom_username() {
assert!(check_basic_auth(
"Basic Y3VzdG9tdXNlcjp2ZXJ5LXNlY3JldA==",
&format!("customuser:{EXPECTED_TOKEN}")
));
}
#[test]
fn should_reject_basic_auth_without_correct_custom_username() {
assert!(!check_basic_auth(
"Basic Y3VzdG9tdXNlcjp2ZXJ5LXNlY3JldA==",
&format!("otheruser:{EXPECTED_TOKEN}")
));
}
}