Storage Connector
This section aims to describe how you can build a storage provider connector for the Axone protocol. We will implement here a simple storage proxy using the Axone SDK and expose it over HTTP.
Functional Specification
The storage proxy will allow the following features:
Authentication: Given an authentication verifiable credential, the proxy will authenticate the identity;Read: Allow or not read access to a stored resource based on the governance rules of both the storage service & the requested resource;Store: Allow or not to store a resource based on the governance rules of the storage service, issuing a verifiable credential expressing the publication of the stored resource;
Proxy implementation
To instantiate the proxy we'll need first some element to provide.
In order to issue credentials verifiable on-chain, the storage service must have a set of keys to provide cryptographic proofs, let's create them:
key, err := keys.NewKeyFromMnemonic(mnemonic)It'll need also to establish a connection with the Axone blockchain to be able to interact with it, let's create a client for that purpose:
dataverseClient, err := dataverse.NewQueryClient(
context.Background(),
nodeGrpcAddr, // The gRPC address of an Axone node
dataverseAddr, // The address of the dataverse smart contract
grpc.WithTransportCredentials(insecure.NewCredentials()), // Use insecure credentials for demo purposes
)For the management of verifiable credentials the proxy will need to resolve JSON-LD contexts, let's create a resolver for that purpose:
We now have all the elements to instantiate the proxy:
Expose over HTTP
At this point we have a fully functional storage proxy, but it is not available through any communication protocol, let's expose it over HTTP.
We'll expose an API with three endpoints:
POST /authenticate: Authenticate an identity given a verifiable credential and return a JWT token that must be used to access other endpoints;GET /{resourceID}: Read a resource given its DID, the JWT token must be provided in theAuthorizationheader as a bearer token;POST /{resourceID}: Store a resource given its DID, the JWT token must be provided in theAuthorizationheader as a bearer token;
Full source
Until now we saw only separate snippets for pedagogic purpose, let's see what it looks like when we put everything together in a single main.go:
Don't take this implementation as production-grade, it suffers from many issues. It is only a starting point to build your own storage connector.
Last updated