Operator-Webservice

Überblick

Ein RESTful-Webservice (auch RESTful-Web-API genannt) ist ein Webservice, der unter Verwendung von HTTP(S) und den Prinzipien von REST (Representational State Transfer) implementiert wird. REST erfordert die explizite Verwendung von HTTP-Methoden in einer Weise, die mit der Protokolldefinition übereinstimmt. Dieses grundlegende REST-Designprinzip stellt eine Eins-zu-Eins-Zuordnung zwischen Erstellen, Lesen, Aktualisieren und Löschen (CRUD-Operationen) und HTTP-Methoden her. Gemäß dieser Zuordnung:

  • POST: wird verwendet, um eine Ressource auf dem Server zu erstellen
  • GET: wird verwendet, um eine Ressource abzurufen
  • PUT: wird verwendet, um den Zustand einer Ressource zu ändern oder sie zu aktualisieren
  • DELETE: wird verwendet, um eine Ressource zu entfernen oder zu löschen

Der PKI-Webservice basiert hauptsächlich auf zwei Ressourcen:

  • Profile
  • ITS-Stationen

In den verschiedenen PKI-Bereitstellungen ist der Webservice in der Regel durch eine OpenId-Connect-Schicht für die Authentifizierung geschützt. Auch wenn dieser Teil streng genommen nicht die REST-API ist, beschreibt der nächste Abschnitt, wie man ein Authentifizierungstoken erhält und wie man es verwendet. Anschließend werden die verschiedenen Anfragen zu den Ressourcen beschrieben.

Authentifizierung

Für den Zugang muss eine HTTP(S)-Anfrage gesendet werden:

  • mit der Methode POST,
  • an die OpenId-Connect-Service-URL (wird zusammen mit diesem Dokument bereitgestellt, kann sich von der Basis-URL des Operator-Webservices unterscheiden),
  • mit einem URL-kodierten Formular mit folgenden Feldern:
    • scope festgelegt auf openid,
    • grant_type festgelegt auf password,
    • client_id und client_secret (ebenfalls zusammen mit diesem Dokument bereitgestellt),
    • username und password eines registrierten Kontos.

Wenn die Anfrage akzeptiert wird, wird eine HTTP-Antwort mit dem Statuscode 200 empfangen. Die Antwort enthält einen Payload im JSON-Format mit einem Feld access_token. In den folgenden Anfragen an den REST-Webservice muss ein HTTP-Header hinzugefügt werden: Authorization: Bearer <access_token>, wobei <access_token> der in der Antwort gefundene Wert ist.

Selbstverständlich ist in den weiteren Abschnitten der HTTP-Header Authorization implizit: Er wird nicht erwähnt, muss aber in jeder Anfrage vorhanden sein.

Beispiel

In dieser Situation:

  • OpenId-Connect-Zugangspunkt: https://keycloak.int.c-its-pki.eu/realms/atos-l0/protocol/openid-connect/token
  • Client-ID: operator, Client-Secret: 97793a4b-ae56-494c-9f4c-2f395cc35ab1
  • Benutzername: myuser, Passwort: Password#1234

Die folgende Anfrage muss gesendet werden (mit dem Befehlszeilenwerkzeug HTTPie), wobei diese Antwort empfangen wird (die Werte von access_token, id_token und refresh_token wurden gekürzt):

$ http https://keycloak.int.c-its-pki.eu/realms/atos-l0/protocol/openid-connect/token "scope=openid" "grant_type=password" "client_id=operator" "client_secret=97793a4b-ae56-494c-9f4c-2f395cc35ab1" "username=myuser" "password=Password#1234" -fv
POST /realms/atos-l0/protocol/openid-connect/token HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 141
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Host: keycloak.c-its-pki.eu
User-Agent: HTTPie/1.0.3

scope=openid&grant_type=password&client_id=operator&client_secret=97793a4b-ae56-494c-9f4c-2f395cc35ab1&username=myuser&password=Password%231234

HTTP/1.1 200 OK
Cache-Control: no-store
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/json
Date: Tue, 13 Oct 2020 13:41:32 GMT
Pragma: no-cache
Referrer-Policy: no-referrer
Server: openresty/1.15.8.1
Set-Cookie: KEYCLOAK_LOCALE=; Version=1; Comment=Expiring cookie; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Max-Age=0; Path=/realms/atos-l0/; HttpOnly
Set-Cookie: KC_RESTART=; Version=1; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Max-Age=0; Path=/realms/atos-l0/; HttpOnly
Strict-Transport-Security: max-age=15724800; includeSubDomains
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block

{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAi[...]D7ewWLjhSTJXsfA",
    "expires_in": 300,
    "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldU[...]GzivenB7aTf_8kg",
    "not-before-policy": 0,
    "refresh_expires_in": 1800,
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiA[...]5CDElob-7TUf7hs",
    "scope": "openid profile email",
    "session_state": "ffd527d8-76b7-4b5c-b955-870043c15f93",
    "token_type": "bearer"
}

Um dann das Token zu verwenden und die Liste der Profile abzurufen, mit der Operator-Basis-URL unter https://0.atos-op.l0.c-its-pki.eu:

$ http https://0.atos-op.l0.c-its-pki.eu/v1/profiles "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAi[...]D7ewWLjhSTJXsfA"
HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/json
Date: Tue, 13 Oct 2020 14:28:02 GMT
Expires: 0
Pragma: no-cache
Server: openresty/1.15.8.1
Set-Cookie: JSESSIONID=64D45A954860CCC37CA9C846C83F30F5; Path=/; Secure; HttpOnly
Strict-Transport-Security: max-age=15724800; includeSubDomains
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Xss-Protection: 1; mode=block

[
    {
        "assuranceLevel": 0,
        "atPreloadingDuration": 90,
        "atPreloadingUnit": "DAYS",
        "atValidityDuration": 7,
        "atValidityUnit": "DAYS",
        "confidenceLevel": 0,
        "ecValidityDuration": 3,
        "ecValidityUnit": "YEARS",
        "editAllowed": true,
        "groupId": "atos-l0.Atos",
        "id": "3f621d8e-f7a1-427f-bb34-b3c02e07d96c",
        "name": "TestProfile",
        "permissions": [
            {
                "opaque": false,
                "psid": 36,
                "ssp": "AQAA"
            }
        ],
        "privacyPolicy": "OPTIONAL"
    }
]

CSRF-Token

GET-Anfragen: Kein CSRF-Token erforderlich, diesen Schritt überspringen. POST/PUT/DELETE-Anfragen: Erfordern dasselbe CSRF-Token als Header und als Cookie-Header. Fügen Sie die folgenden Header mit einem beliebigen Zufallswert hinzu:

"X-XSRF-TOKEN: MyRandomValue007"
"Cookie: XSRF-TOKEN=MyRandomValue007"

Profil

Profilformat

Im JSON-Format ist ein Profil ein Objekt mit folgenden Feldern:

  • id (string): Kennung des Profils (schreibgeschützt).
  • name (string): Name des Profils. Dieser Name wird bei der Registrierung von ITS-Stationen verwendet.
  • ecValidityDuration (number): Die maximale EC-Gültigkeitsdauer. Der Wert muss positiv sein.
  • ecValidityUnit (string): Die Einheit des Feldes ecValidityDuration. Möglich: "SECONDS", "MINUTES", "HOURS", "DAYS" oder "YEARS".
  • atValidityDuration (number): Die maximale AT-Gültigkeitsdauer. Der Wert muss positiv sein.
  • atValidityUnit (string): Die Einheit des Feldes atValidityDuration. Möglich: "SECONDS", "MINUTES", "HOURS", "DAYS" oder "YEARS".
  • atPreloadingDuration (number): Der maximale Zeitraum zwischen dem Empfang der Anfrage und dem Gültigkeitsbeginn des angeforderten AT. Der Wert muss positiv sein.
  • atPreloadingUnit (string): Die Einheit des Feldes atPreloadingDuration. Möglich: "SECONDS", "MINUTES", "HOURS", "DAYS" oder "YEARS".
  • assuranceLevel (number): Definiert den Assurance-Level-Teil der maximalen Subject Assurance. Der Wert muss zwischen 0 und 7 liegen.
  • confidenceLevel (number): Definiert den Confidence-Level-Teil der maximalen Subject Assurance. Der Wert muss zwischen 0 und 3 liegen.
  • privacyPolicy (string): Das akzeptable Format (verschlüsselt oder nicht) der abgetrennten Signatur in der AT-Anfrage. Möglich: "OPTIONAL", "WITHOUT_PRIVACY" oder "WITH_PRIVACY".
  • permissions (array of objects): Ein Array von PSID/SSP, die ein ITS exakt anfordern kann. Jedes Objekt ist definiert durch:
    • psid (number): Die PSID (Dezimalformat).
    • ssp (string): Die SSP, in Base64.
    • opaque (boolean): true wenn die SSP als opaque definiert ist, false wenn sie als Bitmaske definiert ist.
  • itsLimit (number): Maximale Anzahl von Stationen, die mit diesem Profil registriert werden können. -1 für unbegrenzte Anzahl.
  • itsCount (number): Aktuelle Anzahl der mit diesem Profil registrierten Stationen (schreibgeschützt).
  • groupId (string): Die Sicherheitsgruppe des Profils. Kann aus den zugänglichen Gruppen des authentifizierten Benutzers gewählt werden (Format: <realm>.<group>).
  • editAllowed (boolean): true wenn das Profil bearbeitet werden kann (schreibgeschützt).

Beispiel:

{
    "id": "d4989cf0-4145-41b1-b96b-2e484f1c2e09",
    "name": "DefaultProfile",
    "ecValidityDuration": 3,
    "ecValidityUnit": "YEARS",
    "atValidityDuration": 7,
    "atValidityUnit": "DAYS",
    "atPreloadingDuration": 30,
    "atPreloadingUnit": "DAYS",
    "assuranceLevel": 0,
    "confidenceLevel": 0,
    "privacyPolicy": "OPTIONAL",
    "groupId": "atos-l0.Atos",
    "itsLimit": -1,
    "itsCount": 52,
    "permissions": [
        {
            "psid": 36,
            "ssp": "Af/8",
            "opaque": false
        },
        {
            "psid": 37,
            "ssp": "AQAAAA==",
            "opaque": false
        }
    ],
    "editAllowed": true
}

Profil speichern

  • Anfrage: POST /v1/profiles
  • Anfragekörper: Ein Profil im JSON-Format (ohne die schreibgeschützten Felder)
  • Antwort:
  • 201: Profil erstellt. Der Header Location enthält den vollständigen Pfad zur erstellten Ressource. Der Body enthält das neu erstellte Profil.
  • 400: Ein Fehler ist aufgetreten. Der Body enthält eine Struktur mit einer Fehlerbeschreibung:
    • id (string): ein Code-Identifikator des Fehlers.
    • description (string): menschenlesbare Beschreibung des Fehlers.
    • params (object): Parameter im Zusammenhang mit dem Fehler.
  • Sonstiges: siehe HTTP-Standard.

Profil abrufen

  • Anfrage: GET /v1/profiles/{id}
  • Parameter:
  • {id}: Die ID des Profils
  • Antwort:
  • 200: Das Profil wurde abgerufen. Der Body enthält das angeforderte Profil im JSON-Format.
  • 400: Ein Fehler ist aufgetreten. Der Body enthält eine Struktur mit einer Fehlerbeschreibung:
    • id (string): ein Code-Identifikator des Fehlers.
    • description (string): menschenlesbare Beschreibung des Fehlers.
    • params (object): Parameter im Zusammenhang mit dem Fehler.
  • Sonstiges: siehe HTTP-Standard.

Alle Profile auflisten

  • Anfrage: GET /v1/profiles/
  • Antwort:
  • 200: Die Profile wurden abgerufen. Der Body enthält die Liste der Profile im JSON-Format.
  • 400: Ein Fehler ist aufgetreten. Der Body enthält eine Struktur mit einer Fehlerbeschreibung:
    • id (string): ein Code-Identifikator des Fehlers.
    • description (string): menschenlesbare Beschreibung des Fehlers.
    • params (object): Parameter im Zusammenhang mit dem Fehler.
  • Sonstiges: siehe HTTP-Standard.

Profil aktualisieren

  • Anfrage: PUT /v1/profiles/{id}
  • Parameter:
  • {id}: Die ID des Profils
  • Anfragekörper: Der neue Profilwert im JSON-Format (ohne die schreibgeschützten Felder)
  • Antwort:
  • 200: Das Profil wurde aktualisiert. Der Body enthält das gespeicherte Profil im JSON-Format.
  • 400: Ein Fehler ist aufgetreten. Der Body enthält eine Struktur mit einer Fehlerbeschreibung:
    • id (string): ein Code-Identifikator des Fehlers.
    • description (string): menschenlesbare Beschreibung des Fehlers.
    • params (object): Parameter im Zusammenhang mit dem Fehler.
  • Sonstiges: siehe HTTP-Standard.

Profil löschen

  • Anfrage: DELETE /v1/profiles/{id}
  • Parameter:
  • {id}: Die ID des Profils
  • Antwort:
  • 200: Das Profil wurde gelöscht.
  • 400: Ein Fehler ist aufgetreten. Der Body enthält eine Struktur mit einer Fehlerbeschreibung:
    • id (string): ein Code-Identifikator des Fehlers.
    • description (string): menschenlesbare Beschreibung des Fehlers.
    • params (object): Parameter im Zusammenhang mit dem Fehler.
  • Sonstiges: siehe HTTP-Standard.

ITS-Stationen

ITS-Stationsformat

Im JSON-Format ist eine ITS-Station ein Objekt mit folgenden Feldern:

  • id (string): Kennung der ITS-Station (schreibgeschützt).
  • prefixId (string): Erster Teil der kanonischen ID der ITS-Station, in ASCII. Kann leer sein, wenn serialId nicht leer ist.
  • serialId (string): Letzter Teil der kanonischen ID der ITS-Station, in Base64. Kann leer sein, wenn prefixId nicht leer ist.
  • canonicalName (string): Menschenlesbare Darstellung der kanonischen ID der ITS-Station (schreibgeschützt).
  • canonicalId (string): Base64-Darstellung der kanonischen ID der ITS-Station (schreibgeschützt).
  • technicalPublicKey (string): Der technische öffentliche Schlüssel, im X.509-Public-Key-Format, in Base64.
  • status (string): Der Status der ITS-Station. Möglich: "REGISTERED", "ACTIVATED", "SUSPENDED" oder "DEACTIVATED".
  • profile (string): Der Name (nicht die ID) des Profils der ITS-Station.
  • tags (list of string): Tags, die der ITS-Station zugeordnet sind.
  • ecNumber (number): Gesamtzahl der von der ITS-Station angeforderten EC (schreibgeschützt).

Beispiel:

{
    "id": "4a5e179f-1e72-453a-8923-c85a9a8c1d0a",
    "prefixId": "ITS-STATION",
    "serialId": "AAE=",
    "canonicalName": "ITS-STATION.0001",
    "canonicalId": "SVRTLVNUQVRJT04AAQ==",
    "technicalPublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWpBjhoHafQvkZjE6VlmSuv6YWidgFR4Ohisrs5GoVdE1YI5prKz3ckJzaoZwnRgB74mpcEJEeJjftS64FBPoOQ==",
    "status": "ACTIVATED",
    "profile": "DefaultProfile",
    "tags": [
        "PREPRODUCTION"
    ],
    "ecNumber": 1
}

ITS-Station speichern

  • Anfrage: POST /v1/its
  • Anfragekörper: Eine ITS-Station im JSON-Format (ohne die schreibgeschützten Felder)
  • Antwort:
  • 201: ITS-Station erstellt. Der Header Location enthält den vollständigen Pfad zur erstellten Ressource. Der Body enthält die neu erstellte ITS-Station.
  • 400: Ein Fehler ist aufgetreten. Der Body enthält eine Struktur mit einer Fehlerbeschreibung:
    • id (string): ein Code-Identifikator des Fehlers.
    • description (string): menschenlesbare Beschreibung des Fehlers.
    • params (object): Parameter im Zusammenhang mit dem Fehler.
  • Sonstiges: siehe HTTP-Standard.

ITS-Station abrufen

  • Anfrage: GET /v1/its/{id}
  • Parameter:
  • {id}: Die ID der ITS-Station
  • Antwort:
  • 200: Die ITS-Station wurde abgerufen. Der Body enthält die angeforderte ITS-Station im JSON-Format.
  • 400: Ein Fehler ist aufgetreten. Der Body enthält eine Struktur mit einer Fehlerbeschreibung:
    • id (string): ein Code-Identifikator des Fehlers.
    • description (string): menschenlesbare Beschreibung des Fehlers.
    • params (object): Parameter im Zusammenhang mit dem Fehler.
  • Sonstiges: siehe HTTP-Standard.

Alle ITS-Stationen auflisten

  • Anfrage: GET /v1/its/?size={size}&page={page}
  • Parameter:
  • {size}: Maximale Anzahl der zurückgegebenen ITS-Stationen. Optional, Standard ist 20.
  • {page}: Seitennummer. Optional, Standard ist 0.
  • Antwort:
  • 200: Die ITS-Stationen wurden abgerufen. Der Body enthält die angeforderten ITS-Stationen und einige Metadaten zu Seiten im JSON-Format:
    • content (list of objects): die Liste der auf der angeforderten Seite gefundenen ITS-Stationen.
    • number (number): Nummer der aktuellen Seite.
    • numberOfElements (number): Anzahl der ITS-Stationen auf dieser Seite.
    • size (number): Maximale Größe einer Seite.
    • sort (null): nicht verwendet, immer null.
    • first (boolean): true wenn es die erste Seite ist, false andernfalls.
    • last (boolean): true wenn es die letzte Seite ist, false andernfalls.
    • totalPages (number): Gesamtanzahl der Seiten.
    • totalElements (number): Gesamtanzahl der gefundenen ITS-Stationen.
  • 400: Ein Fehler ist aufgetreten. Der Body enthält eine Struktur mit einer Fehlerbeschreibung:
    • id (string): ein Code-Identifikator des Fehlers.
    • description (string): menschenlesbare Beschreibung des Fehlers.
    • params (object): Parameter im Zusammenhang mit dem Fehler.
  • Sonstiges: siehe HTTP-Standard.

ITS-Station aktualisieren

  • Anfrage: PUT /v1/its/{id}
  • Parameter:
  • {id}: Die ID der ITS-Station
  • Anfragekörper: Der neue Stationswert im JSON-Format (ohne die schreibgeschützten Felder)
  • Antwort:
  • 200: Die ITS-Station wurde aktualisiert. Der Body enthält die gespeicherte Station im JSON-Format.
  • 400: Ein Fehler ist aufgetreten. Der Body enthält eine Struktur mit einer Fehlerbeschreibung:
    • id (string): ein Code-Identifikator des Fehlers.
    • description (string): menschenlesbare Beschreibung des Fehlers.
    • params (object): Parameter im Zusammenhang mit dem Fehler.
  • Sonstiges: siehe HTTP-Standard.

ITS-Station löschen

  • Anfrage: DELETE /v1/its/{id}
  • Parameter:
  • {id}: Die ID der ITS-Station
  • Antwort:
  • 200: Die ITS-Station wurde gelöscht.
  • 400: Ein Fehler ist aufgetreten. Der Body enthält eine Struktur mit einer Fehlerbeschreibung:
    • id (string): ein Code-Identifikator des Fehlers.
    • description (string): menschenlesbare Beschreibung des Fehlers.
    • params (object): Parameter im Zusammenhang mit dem Fehler.
  • Sonstiges: siehe HTTP-Standard.