-
Notifications
You must be signed in to change notification settings - Fork 5
Calling the GOSQAS backend
The new GOSQAS backend is implemented with Azure Functions. This wiki page describes how to interact with this backend via TypeScript.
Note, there is a test deployment of this backend, but any provenance data published to this endpoint will be destroyed prior to release of GOSQAS 2.0.
The base URL of the test deployment is https://gosqasbe.azurewebsites.net/api
.
All data stored in the GOSQAS backend is encrypted with an AES-CBC key (128-, 192- and 256-bit key lengths are all supported). The device key is passed as a URL parameter to all the endpoints listed below. The device key is Base-58 encoded for use as a URL parameter.
Here is some example code for generating and encoding a 128-bit device key in Typescript using the WebCrypto API (also available in NodeJS) and the @urlpack/base58 package.
import {encode as base58encode } from '@urlpack/base58'
export async function makeDeviceKey(): Promise<Uint8Array> {
const key = await crypto.subtle.generateKey({
name: "AES-CBC",
length: 128
}, true, ['encrypt', 'decrypt']);
const buffer = await crypto.subtle.exportKey("raw", key);
return new Uint8Array(buffer).slice();
}
function encodeDeviceKey(key: Uint8Array): string {
return base58encode(key);
}
GOSQAS will store any valid JSON as provenance record. GOSQAS accepts JSON5 encoded records, but converts all provided data to standard JSON before encrypting and storing.
GOSQAS can optionally store multiple attachments for each provenance record. Attachments are encrypted and stored separately from the provenance record itself.
Note, GOSQAS stores the content type of the encrypted attachment as a metadata field, which is stored in the clear.
GOSQAS automatically timestamps all provenance records and attachments when they are submitted to the system.
Relative URL: /api/provenance/{deviceKey}
HTTP Verb: GET
This endpoint retrieves the decrypted provenance records for a given device. As described above, the device key is a base58 encoded AES-CBC key. The endpoint returns an array of JSON encoded objects with the following structure:
{
record: any, // whatever you passed to postProvenance
attachments?: string[], // array of attachment IDs, may be empty or undefined
timestamp: number // UTC epoch milliseconds when the record was submitted to GOSQAS
}
Sample TS code to invoke getProvenance via fetch:
// method takes the base58 encoded device key
async function getProvenance(deviceKey: string) {
const response = await fetch(`${baseUrl}/provenance/${deviceKey}`, {
method: "GET",
});
return await response.json() as { record: any, attachments?: string[], timestamp: number }[];
}
Relative URL: /attachment/{deviceKey}/{attachmentID}
HTTP Verb: GET
This endpoint retrieves a single provenance attachment for a given device.
In addition to the device key URL parameter, this endpoint requires an attachmentID parameter.
This value is returned in the attachments
array of a provenance record described above.
The attachment is returned unencrypted as a blob with the content type that was specified when the record was created.
Sample TS code to invoke getAttachment via fetch:
async function getAttachment(deviceKey: string, attachmentID: string) {
const response = await fetch(`${baseUrl}/attachment/${deviceKey}/${attachmentID}`, {
method: "GET",
});
return await response.blob();
}
Relative URL: /api/provenance/{deviceKey}
HTTP Verb: POST
This endpoint accepts a single provenance record for a given device, encrypts it and then stores it for future retrieval.
The provenance record is encoded as multipart/form-data
to enable submission of binary attachments.
The FormData submitted to this endpoint must have the following structure:
- provenanceRecord: a single form field containing a JSON (or JSON5) stringified object
- attachment: zero or more binary Blobs
This endpoint will encrypt the provided record and all the attachments using the key provided. It returns the records string identifier as well as an optional array of strings containing the identifier for each attachment provided.
Sample TS code to invoke getAttachment via fetch:
async function postProvenance(deviceKey: string, record: any, attachments: readonly Blob[]) {
const formData = new FormData();
formData.append("provenanceRecord", JSON.stringify(record));
for (const blob of attachments) {
formData.append("attachment", blob);
}
const response = await fetch(`${baseUrl}/provenance/${deviceKey}`, {
method: "POST",
body: formData,
});
return await response.json() as { record: string, attachments?: string[] };
}