Skip to content
Snippets Groups Projects
README.md 7.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • # OSIv2-Postfach-Anbindung für OZG-Cloud-Nachrichten
    
    Jan Zickermann's avatar
    Jan Zickermann committed
    
    
    Senden und Empfangen von Postfach-Nachrichten über die OSI-Postfach-Facade 2.0 (OPF).
    
    Das Maven-Artefakt `osiv2-postach` kann in ein Spring-Boot eingebunden werden.
    Die Spring-Bean `osiPostfachRemoteService` mit dem Interface
    `PostfachRemoteService` kann mit `ozgcloud.osiv2.enabled: true` aktiviert werden.
    
    ## Konfiguration
    
    Um auf die Postfach-Facade zugreifen zu können, muss der Client sich beim Servicekonto anmelden.
    
    Hierzu wird `ozgcloud.osiv2.auth` konfiguriert, wie bspw. hier für Stage-Schleswig-Holstein:
    ```yaml
    client-id: 'OZG-Kopfstelle-SH'
    client-secret: 'changeme'
    scope: default, access_urn:dataport:osi:sh:stage:ozgkopfstelle
    token-uri: 'https://idp.serviceportal-stage.schleswig-holstein.de/webidp2/connect/token'
    resource: 'urn:dataport:osi:postfach:rz2:stage:sh'
    ```
    Für die Postfach-Facade muss zudem die URL, der Tenant, und der SAML-Name-Identifier konfiguriert werden.
    Beim Nachschlagen des Postfachs der Antragsteller*in wird ein Postfach mit übereinstimmenden Tenant präferiert.
    Zudem werden Tenant und SAML-Name-Identifier beim Upload von Anhängen angegeben.
    
    Hierzu wird `ozgcloud.osiv2.api` konfiguriert:
    ```yaml
    url: 'https://api-gateway-stage.dataport.de:443/api/osi_postfach/1.0.0'
    tenant: 'SH'
    name-identifier: 'ozgkopfstelle'
    ```
    <small>(Der Wert von `name-identifier` wird momentan nicht von der Postfach-Facade geprüft.)</small>
    
    
    ## Senden einer Postfach-Nachricht
    
    Der Aufruf `sendMessage(PostfachNachricht)` sendet eine Nachricht an die Antragsteller*in. Jede Nachricht ist stets in Bezug zu einem Vorgang.
    
    1. Mit dem SAML-Name-Identifier der Antragsteller*in wird ein Postfach nachgeschlagen, welches die Nachricht empfangen soll.
    2. Vor dem Senden der Nachricht werden alle Anhänge in die Quarantäne hochgeladen und auf Viren geprüft.
    3. Nach dem erfolgreichen Hochladen der Anhänge wird die Nachricht an das Postfach gesendet.
    
    ```mermaid
    %% Senden einer Nachricht
      sequenceDiagram
        participant N as nachrichten-manager
        participant A as file-manager
        participant B as Client
        participant C as OPF
        activate N
        N->>B: OsiPostfachRemoteService::sendMessage
    
        activate B
        Note left of B: (1) Nachschlagen einer Empfänger-Postfach-Adresse
        B->>C: POST /MailboxDirectory/v1/Lookup
        activate C
        C-->>B: {mailboxId}
        deactivate C
        Note left of B: (2) Hochladen der Anhänge
    
        B->>A: GRPC findBinaryFilesMetaData
    
        A-->>B: {Liste an Anhang-Metadaten}
    
        loop Für jeden Anhang
          B->>A: GRPC GetBinaryFileContent
    
          loop Für jeden Daten-Chunk
    
            B->>C: POST /Quarantine/v1/Upload/Chunked (chunk)
            activate C
    
          B->>C: POST /Quarantine/v1/Upload/Chunked (empty chunk)
    
        end
        loop Regelmäßiges Polling bis alle Anhänge geprüft sind
    
          loop Für jeden Anhang
    
            B->>C: GET /Quarantine/v1/Upload/{guid}
    
            activate C
            C-->>B: 
            deactivate C
    
        Note left of B: (3) Nachricht senden
    
        B->>C: POST /MessageExchange/v1/Send/{mailboxId}
    
        C-->>B: 
        deactivate C
        B-->>N: 
        deactivate B
        deactivate N
    ```
    
    ## Empfangen von Postfach-Nachrichten
    
    Der Aufruf `getAllMessages()` holt alle Nachrichten, die an das OZG-Cloud-Postfach gerichtet sind ab.
    
    1. Es wird eine Liste an Nachrichten-Kennungen abgerufen.
    2. Für jede Nachricht wird die Nachricht abgerufen und die Anhänge heruntergeladen.
    3. Ein Stream an Nachrichten wird zurückgegeben. Anhand der Vorgangs-Kennung lässt sich jede Nachricht stets einem Vorgang zugordnen.
    
    %% Empfangen von Nachrichten
    
      sequenceDiagram
        participant N as nachrichten-manager
        participant A as file-manager
        participant B as Client
        participant C as OPF
        activate N
    
        N->>B: OsiPostfachRemoteService::getAllMessages
    
        B->>C: GET /MessageExchange/v1/Receive
    
        C-->>B: {Liste an Nachrichten-Kennungen (max 100)}
    
        loop Für jede Nachrichten-Kennung (messageId)
          Note left of B: (1) Nachricht abrufen
          B->>C: GET /MessageExchange/v1/Receive/{messageId}
    
          C-->>B: {Nachricht mit Anhang-Metadaten}
    
          Note left of B: (2) Herunterladen der Anhänge
          loop Für jeden Anhang
            B->>C: GET /MessageExchange/v1/Receive/{messageId}/Attachment/{attachmentId}
    
            B->>A: GRPC UploadBinaryFileAsStream
    
          Note left of B: (3) Bereitstellung der Postfach-Nachricht
          B-->>N: {Postfach-Nachricht als Stream-Element}
    
    Der nachrichten-manager erhält beim Aufruf von `getAllMessages` einen Stream von Postfach-Nachrichten. Nach der erfolgreichen Verarbeitung einer Nachricht sollte er `deleteMessage` aufrufen:
    
    
    ```mermaid
    %% Empfangen einer Nachricht
      sequenceDiagram
        participant N as nachrichten-manager
        participant B as Client
        participant C as OPF
    
        activate N
        N->>B: OsiPostfachRemoteService::deleteMessage
    
        B->>C: GET /MessageExchange/v1/Delete/{messageId}
    
        C->>B: 
        deactivate C
        B-->>N: 
        deactivate B
        deactivate N
    ```
    
    
    ## Client-Authentifizierung beim Servicekonto
    
    Die Client-Authentifizierung beim Authentication-Server (Servicekonto) erfolgt über den OAuth2-Client-Credentials-Flow (siehe [RFC 6749, Sec. 1.3.4](https://www.rfc-editor.org/rfc/rfc6749#section-1.3.4))
    mit `client_id` und `client_secret` in Verbindung mit einem Resource-URI-Parameter (siehe [RFC 8707](https://datatracker.ietf.org/doc/html/rfc8707)), der den Zugriff des Clients auf den Resource-Server (Postfach-Facade) einschränkt. 
    
    
    Der Resource-Server liest die Resource-URI aus dem `aud`-Claim (siehe [RFC 9068, Sec. 3](https://datatracker.ietf.org/doc/html/rfc9068#section-3) und [ServicePortal-Dokumentation](https://idp.serviceportal-stage.hamburg.de/doc/external/articles/OIDC/OIDC-Protokoll.html)).
    
    
    ### Beispiel:
    
    ```bash
    curl -v --output auth_response.json \
         -H "Content-Type: application/x-www-form-urlencoded" \
         --data-urlencode "grant_type=client_credentials" \
    
         --data-urlencode "client_id=OZG-Kopfstelle-SH" \
    
         --data-urlencode "client_secret=${SH_STAGE_CLIENT_SECRET}" \
         --data-urlencode "scope=default access_urn:dataport:osi:sh:stage:ozgkopfstelle" \
         --data-urlencode "resource=urn:dataport:osi:postfach:rz2:stage:sh" \
         https://idp.serviceportal-stage.schleswig-holstein.de/webidp2/connect/token
    ```
    
    **Beobachtungen:**
    - <small>Mit einem ungültigen `resource`-Parameter kommt ein `invalid_target`-Fehler bei der Token-Erstellung.</small>
    - <small>Ohne `resource`-Parameter (d.h. ohne `aud`-Claim) kommt `401 Unauthorized` von der Postfach-Facade.</small>
    - <small>Ohne `default`-Scope kommt ein `invalid_target`-Fehler bei der Token-Erstellung</small>
    
    - <small>Ohne `access_urn:dataport:osi:sh:stage:ozgkopfstelle`-Scope kommt ein `Internal Server Error 500` von der Postfach-Facade.</small>