@dvc-modules/dds

2.0.15 • Public • Published

Datendrehscheibe

Funktionsweise

Die Datendrehscheibe erlaubt den sicheren Transport von Daten von einem Ort über einen gesicherten Kanal, z.B. ein Netz des Bundes, zu einem anderem Ort.

Der erste Schritt besteht darin die Daten mit einem zufälligem Schlüssel zu verschlüsseln. Dieser Schlüssel wird anschließend selbst mit einem zufälligem Schlüssel verschlüsselt und anschließend asymmetrisch mit dem public key des Empfängers verschlüsselt. Der generierte Schlüssel zur entschlüsselung des Schlüssels wird mit dem private key des Empfängers asymmetrisch verschlüsselt.

Der Resultierende Payload wird nun an den Anfang der Datei geschrieben bevor diese final mit dem eigentlichem Verschlüsselungskey verschlüsselt auf den S3 hochgeladen wird.

Der Empfänger kann nun mithilfe seines Private Keys und dem Public Key des Senders die Daten entschlüsseln.

Alle Komponenten verschicken und empfangen Daten auf diesem Weg. Ein Import sendet an die Übersetzungsschicht, die Übersetzungsschicht sendet an den Export.

Um Zertifikatsrotierung zu gewährleisten werden auch die Public Keys mit einem private key des csp der wiederum mit einem master key signiert wird, zentral abgelegt. Die Aufgabe der Hinterlegung übernimmt eine zentrale Stelle (in diesem Fall das CSP).

Warum ist die Nutzung eines kompatiblen S3-Speichers für den Datenaustausch besser als eine zentrale API?

Die Wahl eines S3-kompatiblen Speichers als Austauschmedium für Dateien bietet erhebliche Vorteile gegenüber einer zentralisierten API, insbesondere in Bezug auf Sicherheit, Skalierbarkeit und Effizienz.


1. Dezentralisierung & Unabhängigkeit

  • Ein S3-kompatibler Speicher ermöglicht die Vermeidung eines zentralisierten API-Gateways, das als Single Point of Failure fungieren könnte.
  • Empfänger oder Sender und Organisationen können ihre eigene Speicherinfrastruktur betreiben, anstatt sich auf einen zentralen Drittanbieter zu verlassen.
  • Daten sind nicht an eine spezifische API oder einen Cloud-Anbieter gebunden, sondern können über beliebige S3-kompatible Lösungen (z. B. AWS S3, MinIO, Wasabi) verwaltet werden.

2. Sicherheit & Datenschutz

  • Ende-zu-Ende-Verschlüsselung:

    • Daten werden vor dem Hochladen verschlüsselt (AES-256).
    • Der Verschlüsselungsschlüssel wird asymmetrisch (RSA) mit dem Empfänger geteilt.
    • Selbst wenn der S3-Speicher kompromittiert wird, bleiben die Daten unlesbar.
  • Minimierung von Angriffspunkten:

    • Eine zentrale API ist ein attraktives Ziel für Angriffe (DDoS, SQL-Injection, Token-Diebstahl).
    • Ein verteiltes S3-Speichersystem eliminiert diesen Schwachpunkt, da kein direkter API-Zugriff erforderlich ist.
  • Datenhoheit & Compliance:

    • Empfänger oder Sender können lokale oder private S3-Implementierungen verwenden, um gesetzliche Vorgaben (z. B. DSGVO, HIPAA) einzuhalten.

3. Skalierbarkeit & Performance

  • Effiziente parallele Übertragung:

    • Daten können direkt an mehrere Empfänger verteilt werden, indem sie einfach in S3 gespeichert und von verschiedenen Clients abgerufen werden.
    • Bei einer zentralen API wäre das oft mit hohem Server-Load und Engpässen verbunden.
  • Weniger Infrastrukturkosten:

    • Ein API-Gateway benötigt hohe Rechenkapazität, um große Dateimengen sicher zu verwalten.
    • S3 ist für große, verteilte Speichersysteme optimiert und kann on-demand skaliert werden.
  • Geografisch verteilte Speicherung:

    • Mit S3 können Daten weltweit repliziert werden.
    • Eine zentrale API könnte in bestimmten Regionen langsam oder unzugänglich sein.
    • Die S3 Instanz kann überall stehen, solange die übersetzende Stelle zugriff hat (z.B. in einem der Netze des Bundes)

4. Flexibilität & Interoperabilität

  • S3 ist ein offener Standard – viele Anbieter unterstützen ihn (AWS, MinIO, Ceph, DigitalOcean Spaces).
  • Daten können zwischen verschiedenen Cloud-Providern migriert werden, ohne Änderungen am System.
  • Eine API-Lösung wäre an einen bestimmten Anbieter gebunden, was langfristig zu Vendor Lock-in führt.

Fazit

Die Nutzung eines S3-kompatiblen Speichers für den Dateiaustausch ist zukunftssicher, hoch skalierbar und widerstandsfähiger gegenüber Ausfällen – eine zentrale API kann mit diesen Vorteilen nicht konkurrieren.

Transport

Structure in Bucket

/s3-bucket/
├── {import,export}_<filename>       # Encrypted file with metadata
├── s_<filename>.sign    # Digital signature file
File Type Description Contents
Encrypted File Stores the encrypted version of the original file with metadata - AES-256-CBC encrypted file data
- RSA-encrypted AES key
- Initialization Vector (IV)
- Protocol version number
Digital Signature (.sign) Ensures file integrity and authenticity - MD5 hash of the encrypted file
- RSA signature of the hash

🔐 Was wird tatsächlich signiert?

Der Eingangswert für die sign()-Funktion ist:

to <empfänger>:<md5-hash>:<metadata-base64>

🛠 Aufschlüsselung:

  1. to <empfänger> → Stellt sicher, dass die Signatur an einen bestimmten Empfänger gebunden ist.
  2. <md5-hash> → Die Integritätsprüfung des verschlüsselten Files.
  3. <metadata-base64> → Kodiert:
    • Protokollversionsnummer
    • RSA-verschlüsselter AES-Schlüssel
    • Längeninformationen (Größe des Schlüssels und Metadaten)

Diese Struktur stellt sowohl die Datenintegrität als auch die Empfänger-spezifische Authentifizierung sicher.

Format signature

Offset Size Description
0 - 256 256 bytes RSA Signature of MD5 Hash

Format mainfile

Offset Size Description
0 - 2 2 bytes Protocol Version (Identifies encryption scheme)
2 - 6 4 bytes RSA Encrypted AES Key Size (N)
6 - N+6 N bytes RSA Encrypted AES Key (Used for decryption)
N+6 - end Dynamic AES-Encrypted File Data
(defattrs :bg-green {:fill "#a0ffa0"})
(defattrs :bg-yellow {:fill "#ffffa0"})
(defattrs :bg-pink {:fill "#ffb0a0"})
(defattrs :bg-cyan {:fill "#a0fafa"})
(defattrs :bg-purple {:fill "#e4b5f7"})

(defn draw-group-label-header
  [span label]
  (draw-box (text label [:math {:font-size 12}]) {:span span :borders #{} :height 14}))

(defn draw-remotedb-header
  [kind args]
  (draw-column-headers)
  (draw-group-label-header 1 "version")
  (draw-group-label-header 4 "AES Payload Size")
  (draw-group-label-header 2 "AES Payload")
  (next-row 18)

  (draw-box 0x00 :bg-green)
  (draw-box 0x00ff [{:span 4} :bg-yellow])
  (draw-gap "AES Payload" :bg-yellow)
  (draw-gap "Encrypted Data" [:box-last :bg-purple])
)

(draw-remotedb-header 0xffff 9)

(draw-bottom)

Key Distribution und Rotation

Alle Public Keys werden mit dem aktuellem CSP Private Key verschlüsselt im Bucket des CSP (oder einer anderen zentralen Stelle) veröffetlicht. Der aktuelle public des CSP wird im selben Bucket mit dem Master Key verschlüsselt veröffentlicht.

Die Rotation findet über die zentrale Stelle statt, diese Koordiniert auch mit den IDPs und Clients erneuerungen der Keys und Laufzeiten selbiger.

Post Quantum Cryptography

Alle Verschlüsselungsmechanismen können jederzeit ausgetauscht werden. Der Basiscode erlaubt die Nutzung eigener envelope, open und Verschlüsselungsmechanismen. Auf diesem Wege ist auch gewährleistet potenziell den Mechanismus gegen PQC Algorithmen auszutauschen. Die Standardimplentierung greift auf RSA (mindestens 4096 bit) und AES-256 zurück.

Verarbeitung auf der Datendrehscheibe

Referenzimplementierung

Die Translate Komponente ist unter https://gitlab.opencode.de/dvs-modules/dds-modules/translate zu finden.

Erklärung

Die Datendrehscheibe verarbeitet die in den Konfigrationen hinterlegten Mappings und bringt diese mit den Exporten der IDPs zusammen um aus diesen die finalen Daten der Importeure zu erzeugen.

Import von der Datendrehscheibe

Referenzimplementierung

Die Referenzimplementierung des Importes ist unter https://gitlab.opencode.de/dvs-modules/dds-modules/import zu finden.

Für Nutzende

Importe der Datendrehscheibe werden als sortierte reihenbasierte Struktur übermittelt. Dabei werden transitive Abhängigkeiten in der Sortierung zuerst übermittelt. Eine parallele Abarbeitung des Streams ist relativ unproblematisch. Sobald einer der Threads auf den ersten Record trifft, dergestalt einer anderen Natur, muss eine Synchronisierungsphase stattfinden. Sobald alle weiteren Reihen verarbeitet werden, kann mit der Verarbeitung der weiteren Reihen fortgefahren werden.

Für die Entwicklung

Der Import erwartet eine sortierte Reihenbasierte Struktur. Jede Reihe teilt seine Natur über die record property mit. Beispiel:

{ "record": "user", "user": "test1", ... }

Sortiert muss die Struktur in dem Sinne sein, das transitive Abhängigkeiten nicht out of order ausgeliefert werden.

Negativ Beispiel:

In diesem Beispiel wird eine zuordnung einer Gruppe zu früh mitgeteilt, wenn die Gruppe noch gar nicht übermittelt wurde. Dies sorgt bei dem Import im Zielsystem für Fehler.

{ "record": "user", "user": "test1", ... }
{ "record": "mgroup", "user": "test1", ... }
{ "record": "group", "user": "test1", ... }

Positiv Beispiel:

{ "record": "user", "user": "test1", ... }
{ "record": "group", "id": "id", "name": "groupname" }
{ "record": "role", "id": "id", "name": "rolename" }
{ "record": "mgroup", "groupId": "id", "userId": "id" }
{ "record": "mrole", "roleId": "id", "userId": "id" }
{ "record": "mgrole", "roleId": "id", "groupId": "id" }

Export vom IDP

Referenzimplementierung

Die Referenzimplementierung des Exportes ist unter https://gitlab.opencode.de/dvs-modules/dds-modules/export zu finden.

Format

Der Export erwartet eine reihenbasierte Struktur, eine sortierung ist nicht notwendig. Jede Reihe teilt seine Natur über die record property mit.

Beispiel:

{ "record": "user", "user": "test1", ... }
{ "record": "group", "id": "id", "name": "groupname" }
{ "record": "role", "id": "id", "name": "rolename" }
{ "record": "mgroup", "groupId": "id", "userId": "id" }
{ "record": "mrole", "roleId": "id", "userId": "id" }
{ "record": "mgrole", "roleId": "id", "groupId": "id" }

Nutzung

Zuallererst wird die Konfiguration benötigt. Diese kann im root Verzeichnis als .dvcrc Datei abgelegt werden und ist im JSON format.

Einen Teil dieser Konfiguration muss von der zentralen Stelle definiert werden welche die verschiedenen S3 Server konfiguriert und Access Credentials mitteilt.

Als Docker Container (empfohlen)

Import

Für die Referenzimplementierung des Imports benötigen wir in diesem Beispiel eine Konfiguration für eine Keycloak API und darüberhinaus den clients part der von der zentralen Stelle vorgegeben definiert wird. Außerdem definieren wir noch den Namen des Identity Providers der im Keycloak erstellt wurde über die idp Property. Der Beispielimport ordnet so automatisch die Accounts bereits dem IDP zu.

Hier das Beispiel:

{
  "keycloak": {
    "client": {
      "baseUrl": "https://keycloak.de/auth",
      "realmName": "test"
    },
    "credentials": {
      "grantType": "client_credentials",
      "clientId": "admin-cli",
      "clientSecret": "secret"
    }
  },
  "clients": {
    "n1": {
      "name": "test",
      "s3": {
        "bucket": "example",
        "endPoint": "test.wx-one.com",
        "region": "us-east-1",
        "port": 443,
        "useSSL": true,
        "accessKey": "test",
        "secretKey": "test"
      }
    },
    "csp": {
      "name": "csp",
      "s3": {
        "bucket": "test",
        "endPoint": "test.wx-one.com",
        "region": "us-east-1",
        "port": 443,
        "useSSL": true,
        "accessKey": "test",
        "secretKey": "test"
      }
    }
  },
  "idp": "oidc"
}
docker run --rm -v config.json:/home/node/.dvcrc:ro -v master.pub:/home/node/master.pub:ro -v service.pem:/home/node/service.pem:ro -v service.key:/home/node/service.key:ro dvc node import.js

Translate

Der Translate Layer benötigt lediglich die Konfiguration der zentralen Stelle. Die jeweiligen Konfigurationen der Targets werden dynamisch ermittelt.

{
  "clients": {
    "idp": {
      "name": "test",
      "s3": {
        "bucket": "example",
        "endPoint": "test.wx-one.com",
        "region": "us-east-1",
        "port": 443,
        "useSSL": true,
        "accessKey": "test",
        "secretKey": "test"
      }
    },
    "csp": {
      "name": "csp",
      "s3": {
        "bucket": "test",
        "endPoint": "test.wx-one.com",
        "region": "us-east-1",
        "port": 443,
        "useSSL": true,
        "accessKey": "test",
        "secretKey": "test"
      }
    }
  }
}
docker run --rm -v config.json:/home/node/.dvcrc:ro -v master.pub:/home/node/master.pub:ro -v service.pem:/home/node/service.pem:ro -v service.key:/home/node/service.key:ro dvc

Export

Die Referenzimplementierung des Export benötigt die Konfiguration einer Datenbank und die Konfiguration der zentralen Stelle.

{
  "clients": {
    "n1": {
      "name": "test",
      "s3": {
        "bucket": "example",
        "endPoint": "test.wx-one.com",
        "region": "us-east-1",
        "port": 443,
        "useSSL": true,
        "accessKey": "test",
        "secretKey": "test"
      }
    },
    "csp": {
      "name": "csp",
      "s3": {
        "bucket": "test",
        "endPoint": "test.wx-one.com",
        "region": "us-east-1",
        "port": 443,
        "useSSL": true,
        "accessKey": "test",
        "secretKey": "test"
      }
    }
  },
  "database": {
    "user": "keycloak",
    "host": "localhost",
    "database": "keycloak",
    "password": "password",
    "port": 5555
  }
}
docker run --rm -v config.json:/home/node/.dvcrc:ro -v master.pub:/home/node/master.pub:ro -v service.pem:/home/node/service.pem:ro -v service.key:/home/node/service.key:ro dvc node export.js

Direkt

Translate

node translate.js

Import

node import.js

Export

node export.js

Readme

Keywords

none

Package Sidebar

Install

npm i @dvc-modules/dds

Weekly Downloads

4

Version

2.0.15

License

EUPL-1.2

Unpacked Size

66.1 kB

Total Files

11

Last publish

Collaborators

  • wzrdtales