Przejdź do treści

Raporty retrospektywne

Endpoint POST /v1/reports służy do zlecenia asynchronicznego wygenerowania raportu retrospektywnego. Przyjmuje zlecenie i zwraca 202 Accepted — faktyczne generowanie odbywa się w tle.

Endpoint

POST {kamsoft-api-base}/v1/reports
Content-Type: application/json

Nagłówki

Nagłówek Wymagany Opis
Authorization tak Bearer <access_token> — token OAuth 2.0, podpisany kluczem prywatnym aplikacji
ks-system-identification tak Identyfikator systemu w formacie D.D.NNNNNN.YYYY
Content-Type tak application/json

Struktura żądania

Pole Typ Wymagane Opis
format string tak Format wynikowy: parquet lub csv.
publicKeyPem string (PEM) tak Publiczny klucz RSA integratora do szyfrowania wyniku. Zobacz Szyfrowanie.
runAt DateTime (ISO 8601, UTC) tak Czas wykonania. Wartość w przeszłości lub teraźniejszości oznacza wykonanie natychmiastowe.
storage obiekt tak Docelowe Azure Storage klienta, do którego trafi zaszyfrowany wynik.
reportId string nie* Identyfikator konkretnego raportu. Wymagany jeśli groupId nie jest podany.
groupId string nie* Identyfikator grupy raportów — generuje wszystkie raporty z grupy. Wymagany jeśli reportId nie jest podany.
compression bool nie Włączenie kompresji przed szyfrowaniem. Domyślnie false.
obfuscationToken string nie Token do obfuskacji danych osobowych.
pseudonymizationToken string nie Token do pseudonimizacji danych osobowych.
parameters object nie Parametry specyficzne dla raportu (np. zakres dat, NIP). Zależne od reportId.

* Dokładnie jedno z pól reportId lub groupId musi być podane.

storage

{
  "storage": {
    "type": "AzureBlob",
    "connectionString": "BlobEndpoint=https://<account>.blob.core.windows.net/;SharedAccessSignature=..."
  }
}

Magazyn jest własnością integratora. KAMSOFT zapisuje do niego zaszyfrowany artefakt i nie przechowuje kopii wyniku.

parameters — raporty EOD

Dla raportów kalkulacji kosztów (cost-calculation, product-level-cost-calculation) wymagane parametry:

Klucz Opis
CompanyTaxNo NIP firmy
Year Rok (liczba całkowita)
Month Miesiąc (liczba całkowita, 1–12)

Szyfrowanie

Wynik raportu jest szyfrowany algorytmem hybrydowym RSA/AESG/SHA256 (AES-GCM + RSA-OAEP).

Algorytm

RSA/AESG/SHA256

Dla każdego raportu KAMSOFT:

  1. Generuje losowy klucz AES-256 (32 bajty) i nonce (12 bajtów) — łącznie 44 bajty klucza sesyjnego.
  2. Szyfruje dane raportu algorytmem AES-256-GCM — wynikiem są zaszyfrowane dane i 16-bajtowy tag autentyczności (GCM).
  3. Szyfruje klucz sesyjny (44 bajty) algorytmem RSA-OAEP-SHA256 używając klucza publicznego z pola publicKeyPem.
  4. Zwraca zaszyfrowany klucz sesyjny w odpowiedzi 202 jako pole encryptedSessionKey (base64).
  5. Zapisuje zaszyfrowany plik raportu do Azure Storage klienta.

Format artefaktu w blob storage

Artefakt to czyste dane AES-256-GCM (dane + 16-bajtowy GCM tag na końcu). Klucz i nonce są zwracane osobno w odpowiedzi HTTP — nie są osadzone w pliku.

Segment Rozmiar Zawartość
Zaszyfrowane dane N bajtów Dane raportu zaszyfrowane AES-256-GCM
GCM tag 16 bajtów Tag autentyczności

Generowanie pary kluczy

# Klucz 4096-bit — zalecany
openssl genrsa -out rsr-data.key 4096
openssl rsa -in rsr-data.key -pubout -out rsr-data.pub.pem
  • rsr-data.pub.pem — trafia do pola publicKeyPem w żądaniu (format PEM, BEGIN PUBLIC KEY lub BEGIN RSA PUBLIC KEY).
  • rsr-data.key — przechowywany wyłącznie po stronie integratora do odszyfrowania wyniku.

Odszyfrowanie wyniku

Schemat deszyfrowania:

  1. Z odpowiedzi 202 odczytaj pole encryptedSessionKey (base64) i zapisz je.
  2. Odszyfruj encryptedSessionKey kluczem prywatnym RSA (OAEP-SHA256) — otrzymujesz 44 bajty: pierwsze 32 B to klucz AES, kolejne 12 B to nonce.
  3. Pobierz zaszyfrowany plik z Azure Blob Storage.
  4. Odszyfruj plik AES-256-GCM używając klucza i nonce z kroku 2 (weryfikacja tagu GCM jest obowiązkowa — odrzuć artefakt jeśli tag nie pasuje).

Do kroków 2–4 możesz użyć gotowego skryptu decrypt_report.py:

# Instalacja zależności
pip install cryptography

# Zapisanie klucza AES z odpowiedzi endpointu
curl -s -X POST https://<host>/v1/reports \
    -H "Authorization: Bearer <token>" \
    -H "ks-system-identification: 1.2.123456.2026" \
    -H "Content-Type: application/json" \
    -d @request.json | python3 -c "import sys,json; print(json.load(sys.stdin)['encryptedSessionKey'])" > aes_key.b64

# Pobranie zaszyfrowanego pliku z blob storage
az storage blob download \
    --connection-string "<sas-connection-string>" \
    --container-name rsr-output \
    --name <ścieżka-do-pliku> \
    --file report.enc

# Odszyfrowanie
python3 decrypt_report.py \
    --private-key rsr-data.key \
    --aes-key aes_key.b64 \
    --input report.enc \
    --output report.parquet

Klucze jednorazowe

Generuj nową parę RSA na każde zlecenie. Nie używaj ponownie kluczy z poprzednich żądań ani certyfikatu uwierzytelniającego do szyfrowania danych.

Przykład żądania

POST /v1/reports HTTP/1.1
Host: api.kamsoft.example
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIs...
ks-system-identification: 1.2.123456.2026
Content-Type: application/json

{
  "format": "parquet",
  "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A...\n-----END PUBLIC KEY-----",
  "runAt": "2026-05-01T02:00:00Z",
  "storage": {
    "type": "AzureBlob",
    "connectionString": "BlobEndpoint=https://integratorstorage.blob.core.windows.net/;SharedAccessSignature=sv=2024-11-04&..."
  },
  "reportId": "cost-calculation",
  "parameters": {
    "CompanyTaxNo": "1234567890",
    "Year": "2026",
    "Month": "4"
  }
}

Odpowiedź 202 Accepted:

{
  "executionId": "<guid>",
  "encryptedSessionKey": "<base64>"
}
  • executionId — identyfikator zlecenia do celów diagnostycznych.
  • encryptedSessionKey — klucz sesyjny AES zaszyfrowany kluczem publicznym RSA z pola publicKeyPem. Zachowaj go — jest potrzebny do odszyfrowania pliku po jego pojawieniu się w storageConfig.

Kody odpowiedzi

Kod Znaczenie
202 Accepted Zlecenie przyjęte.
400 Bad Request Błędne body, brakujący publicKeyPem, niepoprawny zakres dat.
401 Unauthorized Brak lub nieważny token Bearer.
403 Forbidden Brak nadanego pola eksploatacji RSR.
429 Too Many Requests Przekroczony limit bramki — zastosuj backoff wg Retry-After.
5xx Awaria po stronie KAMSOFT.

Cykl życia zlecenia

sequenceDiagram
    participant I as Integrator
    participant K as KAMSOFT API
    participant S as Azure Storage (integratora)

    I->>I: Generuje parę kluczy RSA
    I->>K: POST /v1/reports (publicKeyPem)
    K-->>I: 202 Accepted + encryptedSessionKey
    I->>I: Zapisuje encryptedSessionKey
    K->>K: Generuje raport
    K->>K: Szyfruje dane AES-256-GCM
    K->>S: Zapisuje zaszyfrowany plik
    I->>S: Pobiera zaszyfrowany plik
    I->>I: Odszyfrowuje encryptedSessionKey kluczem prywatnym RSA
    I->>I: Odszyfrowuje plik AES-256-GCM