Ruby on Rails REST API server pre aplikáciu Autogram v mobile. Link na swagger API dokumentáciu.
Autogram v mobile vytvorili freevision s.r.o., Služby Slovensko.Digital s.r.o. a dobrovoľníci pod EUPL-1.2 licenciou. Prevádzkovateľom je Služby Slovensko.Digital s.r.o.. Prípadné issues riešime v GitHub projekte alebo rovno v tomto repozitári. Java komponent AVM service je z veľkej časti vyrobený podľa projektu Autogram, ktorého autormi sú Jakub Ďuraš, Solver IT s.r.o., Slovensko.Digital, CRYSTAL CONSULTING, s.r.o. a ďalší spoluautori.
Projekt sa skladá z viacerých častí:
- Server
- AVM server - Ruby on Rails API server poskytujúci funkcionalitu zdieľania a podpisovania dokumentov.
- AVM service - Java microservice využívajúci Digital Signature Service knižnicu pre elektronické podpisovanie a generovanie vizualizácie dokumentov.
- Mobilná aplikácia
- AVM app Flutter - Flutter aplikácia pre iOS a Android.
- AVM client Dart - Dart API klient pre komunikáciu s AVM serverom.
- eID mSDK Flutter - Flutter wrapper "štátneho" eID mSDK pre komunikáciu s občianskym preukazom.
- Autogram extension - Rozšírenie do prehliadača, ktoré umožňuje podpisovanie priamo na štátnych portáloch.
- Je potrebné si nainštalovať správnu verziu Ruby. To sa najlepšie robí cez RVM alebo Rbenv.
- Aplikácia vyžaduje PostgreSQL databázu.
- Skopírovať
.env.sample
do.env
a nastaviť hodnoty. - Spustiť avm-service.
- Následne v adresári repozitára spustiť:
bundle install
bundle exec rails db:setup
bundle esec rails s
- Je potrebné si vybuildiť Docker image na základe poskytnutého Dockerfile.
- Volume pre šifrované ukladanie podpisovaných súborov v
/app/storage
- Premenné prosredia sú bližšie popísané v
.env.sample
, pričom tieto sú nevyhnutné pre produkčné nasadenie:- PostgreSQL a connection string v
DATABASE_URL
- Adresa AVM Service inštnacie v
AVM_MICROSERVICE_HOST
- Nastavené ENVs
ACTIVE_RECORD_ENCRYPTION_*
- Nastavený ENV
SECRET_KEY_BASE
- Nastavený ENV
RAILS_ENV=production
- PostgreSQL a connection string v
Okrem tohto Rails API sa na serveri nachádza ešte Java microservice avm-service, ktorý sa aj s Digital Signature Service knižnicou stará o samotné podpisovanie dokumentov a ich prípadné zobrazovanie (ak ide napríklad o XML formulár).
AVM server ukladá dokumenty na disk zašifrované kľúčom poskytnutým klientom (či už integráciou alebo priamo aplikáciu z telefónu). Server si kľúč nepamätá, klient ho musí poslať v každom requeste manipulujúcom s dokumentom. Tým pádom je chránené súkromie používateľa, aj keby došlo k úniku dát z disku. Dokument sa maže z disku 24 hodín po jeho vytvorení.
Klient posiela pri vytváraní dokumentu rovnu už aj podpisové parametre, podľa ktorých má byť neskôr vyrobený podpis. Tie sa ukladajú v databáze a spravidla neobsahujú citlivé informácie.
Po vytvorení dokumentu ho môže podpísať každý, kto pozná jeho GUID a šifrovací kľúč. Klient najprv zavolá POST /datatosign
, aby dostal zo servera reťazec na podpísanie, podpíše dokument u seba a následne zavolá POST /sign
aj s podpísanou hodnotou. AVM service na základe týchto dát a dokumentu vytvorí podpísaný dokument a vráti ho klientovi. Vtedy sa zmení aj atribút dokumentu last_signed_at
.
Pri podpisovaní z externého systému sa musí integrácia dopytovať na zmenu podpísaného súboru, aby tak zistila, kedy bol súbor podpísaný používateľom - neexistuje iný automatizovaný spôsob, ako to zistiť.
Ak chce integrácia alebo zariadenie iniciovať podpisovanie cez PUSH notifikácie, musí sa najprv zaregistrovať na serveri aj s verejnou časťou ES256 kľúča, ktorý môžu neskôr používať na pridávanie a odoberanie spárovaných zariadení a integrácií. Notifikácie fungujú cez Firebase Cloud Messaging, takže zariadenie musí serveru poslať aj svoje registration_id
. Notifikácie sú šifrované. zariadenie teda musí serveru zaslať symetrický kľúč, ktorým bude server šifrovať jeho notifikácie (šifrujeme až na serveri, aby bola integrácia jednoduchšia).
Párovanie vykonáva vždy zariadenie. Na server do POST /device-integrations
musí poslať integrationPairingToken
, ktorý získa iným kanálom od integrácie (napríklad už spomínaným QR kódom). Tento token je JWT podpísané kľúčom integrácie s nastaveným claimom aud: "device"
, aby ho nebolo možné použiť na iný účel než párovanie.
V prípade, že používateľ vyberie súbor na podpis zo zariadenia (telefónu) alebo priamo v aplikácii, celá architektúra je o niečo jednoduchšia. Zariadenie pošle dokument s parametrami na server a zapamätá si kľúč a GUID dokumentu. Následne si vypýta vizualizáciu dokumentu, ktorú zobrazí používateľovi. Ak chce používateľ dokument podpísať, zariadenie pošle na server podpisový certifikát a server mu vráti dataToSign
string, ktorý zariadenie a používateľ podpíšu. Výsledok tejto operácie pošle zariadenie opäť na server, ktorý to spojí s pôvodným dokumentom a vráti zariadeniu podpísaný súbor.
- Používateľ si v telefóne vyberie súbor, ktorý chce podpísať (či už cez file explorer, priamo z AVM alebo cez share button z inej aplikácie)
- AVM pošle súbor + podpisové parametre na server endpoint
POST /api/v1/documents
.- Zasiela sa tam súbor + parametre + encryptionKey (symetrický, pre každý dokument sa generuje nový)
- Server tento subor zašifruje, uloží a zabudne encryptionKey. V odpovedi vráti GUID dokumentu.
- AVM zavolá
GET /api/v1/documents/<guid>/visualization
.- Zasiela sa opäť encryptionKey (!) pre tento dokument
- Server dostane encryptionKey, lokálne dešifruje dokument, vyrobí jeho vizualizáciu (HTML/PDF) (v Java microservice v osobitnom kontajneri), a vracia ju AVM.
- AVM zobrazí používateľovi dokument,
- AVM zavolá
POST /api/v1/documents/<guid>/datatosign
- Zasiela sa opäť encryptionKey (!) pre tento dokument a tiež certifikát podpisujúceho.
- Tu sa dá poslať ešte optional parameter “addTimestamp: bool”, ktorý prípadne zmení typ podpisu na “s/bez pečiatky”.
- Server dostane encryptionKey, lokálne dešifruje dokument, zavolá DSS knižnicu (v Java microservice v osobitnom kontajneri), vytvorí údaje potrebné pre podpisovanie (datatosign) a zasiela AVM
- AVM vyvolá podpisovanie (datatosign) a ziska podpísané dáta z eID SDK (občianskemu preukazu sa pošle datatosign, používateľ zadá kódy a karta vráti podpísaný string - tento flow rieši SDK od MV aj obrazovkami)
- AVM zasiela podpísane dáta (signedData) na server
POST /api/v1/documents/<guid>/sign
- Posiela sa encryptionKey + pôvodné dataToSign (aby server zistil, či sa medzitým nezmenili) + signedData
- Server vytvori podpísaný kontajner a zasiela ho naspäť AVM
- Dokument sa prepíše v úložisku (zašifrovaný)
- AVM alebo prípadná integrácia vie zavolať
GET /api/v1/documents/<guid>
na podpísaný súbor s encryptionKey a dostať ho. - Server súbor po 24h zmaže.
V prípade, že má používateľ nainštalované rozšírenie Autogram na štátnych weboch
(Autogram extension), stačí, že priamo na slovensko.sk, financnasprava.sk alebo na ďalších portáloch vyberie podpísať
. Zobrazí sa mu dialóg Autogram extension, kde má na výber podpisovanie cez Autogram lokálne v počítači alebo možnosť podpísať mobilom
. Pri podpise mobilom Autogram extension nahrá podpisovaný dokument (formulár alebo príloha podania) na server a používateľovi zobrazí QR kód s GUID dokumentu a encryptionKey. Používateľ naskenuje QR kód telefónom a v aplikácii Autogram v mobile
sa mu otvorí podpisovaný dokument. Ten podpíše rovnako ako v predchádzajúcom prípade. Autogram extension medzitým polluje na GET /documents/<GUID>
. Keď je dokument podpísaný, polling je úspešný a Autogram extension si stiahne zo servera podpísaný dokument, ktorý potom vráti štátnemu portálu.
- Extension pošle súbor + podpisové parametre na server endpoint
POST /api/v1/documents
.- Zasiela sa tam súbor + parametre + encryptionKey (symetrický, pre každý dokument sa generuje nový)
- Server tento subor zašifruje, uloží a zabudne encryptionKey. V odpovedi vráti GUID dokumentu.
- Extension poskytne iným kanálom (napríklad QR kódom na obrazovke) aplikácii
GUID
aencryptionKey
dokumentu.- Konkrétne náš Autogram extension a aplikácia podporujú link v tvare:
https://<server-hostname>/api/v1/qr-code?guid=<guid>&key=<encryptionKey>
- Konkrétne náš Autogram extension a aplikácia podporujú link v tvare:
- Aplikácia získa z linku
GUID
aencryptionKey
dokumentu a zavoláGET /api/v1/documents/<guid>/visualization
. - Ďalej pokračuje rovnaký flow ako v prvom prípade.
- ...
- Autogram extension polluje
GET /api/v1/documents/<guid>
sIf-Modified-Since
headerom.- ak sa súbor zmenil od času jeho vytvorenia, znamená to, že je podpísaný
- Autogram extension dostane z
GET /api/v1/documents/<guid>
podpísaný súbor. - Autogram extension poskytne podpísaný súbor štátnemu portálu, na ktorom používateľ podpisuje dokument.
- Server súbor po 24h zmaže.