e3db-go: github.com/tozny/e3db-go Index | Examples | Files

package e3db

import "github.com/tozny/e3db-go"

Package e3db provides programmatic access to the e3db API/Innovault service for the secure transmission and storage of arbitrary data encrypted locally using this SDK.

Official documentation for e3db can be found at https://tozny.com/documentation/e3db/

If not using go mod command for your project:

import "github.com/tozny/e3db-go"

Otherwise

import "github.com/tozny/e3db-go/v2"

Code:

package main

// This example interacts with the "feedback" mechanism in the CLI(https://github.com/tozny/e3db/releases). If you run
// this code, it will share text with Tozny in an end-to-end encrypted manner.

import (
    "context"
    "fmt"
    "github.com/tozny/e3db-go/v2"
    "log"
)

func chk(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

func printRecords(recordType string) {
    client, err := e3db.GetDefaultClient()
    chk(err)

    // Query for all records and print them out
    query := e3db.Q{} // queries all records
    if recordType != "" {
        query = e3db.Q{ContentTypes: []string{recordType}}
    }
    cursor := client.Query(context.Background(), query)
    for {
        record, err := cursor.Next()
        if err == e3db.Done {
            break
        } else if err != nil {
            chk(err)
        }
        fmt.Println("\t" + record.Meta.RecordID + " " + record.Meta.Type)
    }
}

func main() {

    // Accessing the default profile.
    // You must run e3db RegisterClient before this will work:
    client, err := e3db.GetDefaultClient()
    chk(err)

    fmt.Println("Current list of records:")
    printRecords("")

    // Create a new "feedback" record; this is the type the CLI uses
    feedbackData := make(map[string]string)
    feedbackData["comment"] = "This is some example feedback!"
    feedbackData["interface"] = "Go Example Code"
    record, err := client.Write(context.Background(), "feedback", feedbackData, nil)
    chk(err)

    // Read back the feedback we just put into the database
    newFeedbackRecord, err := client.Read(context.Background(), record.Meta.RecordID)
    chk(err)
    fmt.Println("Read record id " + record.Meta.RecordID + ": " + newFeedbackRecord.Data["comment"])

    // Fetch the Tozny feedback email address public key and client ID
    feedbackClient, err := client.GetClientInfo(context.Background(), "db1744b9-3fb6-4458-a291-0bc677dba08b")
    chk(err)

    // Share all "feedback" records with that user ID.
    err = client.Share(context.Background(), "feedback", feedbackClient.ClientID)
    chk(err)

    fmt.Println("Current list of records after adding:")
    printRecords("feedback")

    // Delete the record we just created to keep things tidy.
    // Comment out this line if you want to keep it
    err = client.Delete(context.Background(), record.Meta.RecordID, record.Meta.Version)
    chk(err)

    fmt.Println("Current list of records after deleting:")
    printRecords("feedback")
}

Index

Examples

Package Files

client.go config.go crypto.go query.go

Variables

var Done = errors.New("iteration complete")

Done is returned by Next when iteration is complete.

func GenerateKeyPair Uses

func GenerateKeyPair() (string, string, error)

GenerateKeyPair creates a new Curve25519 keypair for cryptographic operations.

func ProfileExists Uses

func ProfileExists(profile string) bool

ProfileExists returns true if a configuration exists for the given profile name.

func SaveConfig Uses

func SaveConfig(profile string, opts *ClientOpts) error

SaveConfig writes an E3DB client configuration to a profile.

func SaveDefaultConfig Uses

func SaveDefaultConfig(opts *ClientOpts) error

SaveDefaultConfig writes an E3DB client configuration to a profile.

type Channel Uses

type Channel struct {
    Application string `json:"application"`
    Type        string `json:"type"`
    Subject     string `json:"subject"`
}

Channel contains information defining the channel to which a client wishes to connect.

type Client Uses

type Client struct {
    Options ClientOpts
    // contains filtered or unexported fields
}

Client is an authenticated connection to the E3DB service, providing access to end-to-end encrypted data stored in the database.

func GetClient Uses

func GetClient(opts ClientOpts) (*Client, error)

GetClient creates an E3DB client given a custom set of options. Use 'GetConfig' to load options from a configuration profile.

func GetDefaultClient Uses

func GetDefaultClient() (*Client, error)

GetDefaultClient loads the default E3DB configuration profile and creates a client using those options.

func (*Client) Backup Uses

func (c *Client) Backup(ctx context.Context, clientID string, registrationToken string) error

Backup backs up the client's credentials to an account with which it's registered.

func (*Client) Delete Uses

func (c *Client) Delete(ctx context.Context, recordID string, version string) error

Delete removes a record, with optional optimistic locking.

func (*Client) GetClientInfo Uses

func (c *Client) GetClientInfo(ctx context.Context, clientID string) (*ClientInfo, error)

GetClientInfo queries the E3DB server for a client's public information given its client UUID.

func (*Client) GetIncomingSharing Uses

func (c *Client) GetIncomingSharing(ctx context.Context) ([]IncomingSharingPolicy, error)

GetIncomingSharing returns a list of writers and types of records that are currently shared with me.

func (*Client) GetOutgoingSharing Uses

func (c *Client) GetOutgoingSharing(ctx context.Context) ([]OutgoingSharingPolicy, error)

GetOutgoingSharing returns a list of readers and types of records that I am currently sharing.

func (*Client) NewEventSource Uses

func (c *Client) NewEventSource(ctx context.Context) (*EventSource, error)

NewEventSource is a factory that creates a new EventSource object for the given client, allowing for incoming events from the e3db server to be ingested by a client application.

func (*Client) Query Uses

func (c *Client) Query(ctx context.Context, q Q) *Cursor

Query executes a database query given a set of search parameters, returning a cursor that can be iterated over to loop through the result set.

func (*Client) Read Uses

func (c *Client) Read(ctx context.Context, recordID string) (*Record, error)

Read reads a record given a record ID, decrypts it, and returns the result.

func (*Client) ReadFields Uses

func (c *Client) ReadFields(ctx context.Context, recordID string, fields []string) (*Record, error)

ReadFields reads a record given a record ID, selecting a subset of fields, and returns a decrypted result.

func (*Client) Share Uses

func (c *Client) Share(ctx context.Context, recordType string, readerID string) error

Share grants another e3db client permission to read records of the specified record type.

func (*Client) Unshare Uses

func (c *Client) Unshare(ctx context.Context, recordType string, readerID string) error

Unshare revokes another e3db client's permission to read records of the given record type.

func (*Client) Update Uses

func (c *Client) Update(ctx context.Context, record *Record) error

Update a record, if the version field matches the version stored by E3DB.

Returns HTTP 409 (Conflict) in error if the record cannot be updated.

func (*Client) Write Uses

func (c *Client) Write(ctx context.Context, recordType string, data map[string]string, plain map[string]string) (*Record, error)

Write writes a new encrypted record to the database. Returns the new record (with the original, unencrypted data)

type ClientDetails Uses

type ClientDetails struct {
    ClientID  string    `json:"client_id"`
    ApiKeyID  string    `json:"api_key_id"`
    ApiSecret string    `json:"api_secret"`
    PublicKey ClientKey `json:"public_key"`
    Name      string    `json:"name"`
}

ClientDetails contains information about a newly-registered E3DB client

func RegisterClient Uses

func RegisterClient(registrationToken string, clientName string, publicKey string, privateKey string, backup bool, apiURL string) (*ClientDetails, error)

RegisterClient creates a new client for a given InnoVault account

Code:

package main

// This program provides a simple example illustrating how to programmatically
// register a client with InnoVault and e3db. In some situations, it's preferable
// to register a client from the server or system that will be using its
// credentials (to ensure that all data is truly encrypted from end-to-end
// with no possibilities of a credential leak). For more detailed information,
// please see the documentation home page: https://tozny.com/documentation/e3db
//
// Author::    Eric Mann (eric@tozny.com)
// Copyright:: Copyright (c) 2017 Tozny, LLC
// License::   Public Domain

import (
    "crypto/rand"
    "encoding/base64"
    "fmt"
    "log"
    "os"

    "github.com/tozny/e3db-go/v2"
)

// randomSecretKey is otherwise private to the client and is used to generate
// a random string ... it's not actually used for cryptographic operations
// in this example.
func randomSecretKey() *[32]byte {
    key := &[32]byte{}
    _, err := rand.Read(key[:])
    if err != nil {
        // we don't expect this to fail
        panic("random number generation failed")
    }

    return key
}

func main() {
    // A registration token is required to set up a client. In this situation,
    // we assume an environment variable called REGISTRATION_TOKEN is set
    token := os.Getenv("REGISTRATION_TOKEN")

    // Clients can either create new cryptographic keypairs, or load in a pre-defined
    // pair of Curve25519 keys. In this situation, we will generate a new keypair.
    public_key, private_key, err := e3db.GenerateKeyPair()

    fmt.Fprintf(os.Stdout, "Public Key:  %s\n", public_key)
    fmt.Fprintf(os.Stdout, "Private Key: %s\n", private_key)

    // Clients must be registered with a name unique to your account to help
    // differentiate between different sets of credentials in the Admin Console.
    // In this example, the name is set at random
    client_name := "client_" + base64.RawURLEncoding.EncodeToString(randomSecretKey()[:8])

    fmt.Fprintf(os.Stdout, "Client Name: %s\n", client_name)

    // Passing all of the data above into the registration routine will create
    // a new client with the system. Remember to keep your private key private!
    client_info, err := e3db.RegisterClient(token, client_name, public_key, "", false, "https://api.e3db.com")
    if err != nil {
        fmt.Fprintf(os.Stderr, "Unhandled error: %s\n", err)
        log.Fatal(err)
    }

    // Optionally, you can automatically back up the credentials of the newly-created
    // client to your InnoVault account (accessible via https://console.tozny.com) by
    // passing your private key and a backup flag when registering. The private key is
    // not sent anywhere, but is used by the newly-created client to sign an encrypted
    // copy of its credentials that is itself stored in e3db for later use.
    //
    // Client credentials are not backed up by default.

    // client_info := e3db.RegisterClient(token, client_name, public_key, private_key, true, "https://api.e3db.com")
    // if err != nil {
    //   fmt.Fprintf(os.Stderr, "Unhandled error: %s\n", err)
    //   log.Fatal(err)
    // }

    fmt.Fprintf(os.Stdout, "Client ID:   %s\n", client_info.ClientID)
    fmt.Fprintf(os.Stdout, "API Key ID:  %s\n", client_info.ApiKeyID)
    fmt.Fprintf(os.Stdout, "API Secret:  %s\n", client_info.ApiSecret)

    // ---------------------------------------------------------
    // Usage
    // ---------------------------------------------------------

    // Once the client is registered, you can use it immediately to create the
    // configuration used to instantiate a Client that can communicate with
    // e3db directly.

    pubBytes, _ := base64.RawURLEncoding.DecodeString(public_key)
    privBytes, _ := base64.RawURLEncoding.DecodeString(private_key)

    config := &e3db.ClientOpts{
        ClientID:    client_info.ClientID,
        ClientEmail: "",
        APIKeyID:    client_info.ApiKeyID,
        APISecret:   client_info.ApiSecret,
        PublicKey:   e3db.MakePublicKey(pubBytes),
        PrivateKey:  e3db.MakePrivateKey(privBytes),
        APIBaseURL:  "https://api.e3db.com",
        Logging:     false,
    }

    // Now create a client using that configuration.
    _, err = e3db.GetClient(*config)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Unhandled error: %s\n", err)
        log.Fatal(err)
    }

    // From this point on, the new client can be used as any other client to read
    // write, delete, and query for records. See the `simple.rb` documentation
    // for more complete examples ...
}

type ClientInfo Uses

type ClientInfo struct {
    ClientID  string    `json:"client_id"`
    PublicKey ClientKey `json:"public_key"`
    Validated bool      `json:"validated"`
}

ClientInfo contains information sent by the E3DB service about a client.

type ClientKey Uses

type ClientKey struct {
    Curve25519 string `json:"curve25519"`
}

ClientKey contains a cryptographic key for use in client operations.

type ClientOpts Uses

type ClientOpts struct {
    ClientID    string
    ClientEmail string
    APIKeyID    string
    APISecret   string
    PublicKey   PublicKey
    PrivateKey  PrivateKey
    APIBaseURL  string
    Logging     bool
}

ClientOpts contains options for configuring an E3DB client.

func DefaultConfig Uses

func DefaultConfig() (*ClientOpts, error)

DefaultConfig loads the default E3DB configuration.

func GetConfig Uses

func GetConfig(profile string) (*ClientOpts, error)

GetConfig loads an E3DB client configuration from a configuration file given the name of the profile.

type Cursor Uses

type Cursor struct {
    // contains filtered or unexported fields
}

Cursor represents an iterator into a recordset returned by 'e3db.Query'.

func (*Cursor) Next Uses

func (c *Cursor) Next() (*Record, error)

Next returns the item at the current iterator position (if one is available).

type Event Uses

type Event struct {
    Time        time.Time         `json:"time"`
    Application string            `json:"application"`
    Type        string            `json:"type"`
    Action      string            `json:"action"`
    Subject     string            `json:"subject"`
    Producer    string            `json:"producer"`
    Context     map[string]string `json:"context"`
}

Event is an object representing the JSON blob dispatched from e3db in response to serverside events.

type EventSource Uses

type EventSource struct {
    // contains filtered or unexported fields
}

EventSource represents an open socket to the e3db Event source.

func (*EventSource) Close Uses

func (c *EventSource) Close() error

Close the underlying websocket connection.

func (*EventSource) Events Uses

func (c *EventSource) Events() <-chan Event

Events produces a one-way version of the event-bearing channel.

func (*EventSource) Subscribe Uses

func (c *EventSource) Subscribe(channel Channel)

Subscribe to a specific event stream.

func (*EventSource) Unsubscribe Uses

func (c *EventSource) Unsubscribe(channel Channel)

Unsubscribe from a specific event stream.

type IncomingSharingPolicy Uses

type IncomingSharingPolicy struct {
    WriterID   string `json:"writer_id"`
    Type       string `json:"record_type"`
    WriterName string `json:"writer_name"`
}

IncomingSharingPolicy contains information about who has shared what type of records with me.

type Meta Uses

type Meta struct {
    RecordID     string            `json:"record_id,omitempty"`
    WriterID     string            `json:"writer_id"`
    UserID       string            `json:"user_id"`
    Type         string            `json:"type"`
    Plain        map[string]string `json:"plain"`
    Created      time.Time         `json:"created"`
    LastModified time.Time         `json:"last_modified"`
    Version      string            `json:"version,omitempty"`
}

Meta contains meta-information about an E3DB record, such as who wrote it, when it was written, and the type of the data stored.

type OutgoingSharingPolicy Uses

type OutgoingSharingPolicy struct {
    ReaderID   string `json:"reader_id"`
    Type       string `json:"record_type"`
    ReaderName string `json:"reader_name"`
}

OutgoingSharingPolicy contains information about who and what types of records I have shared with.

type PrivateKey Uses

type PrivateKey *[privateKeySize]byte

PrivateKey is an alias of a 32-byte array representing the private key component.

func MakePrivateKey Uses

func MakePrivateKey(b []byte) PrivateKey

MakePrivateKey converts a byte array to a PrivateKey type.

type PublicKey Uses

type PublicKey *[publicKeySize]byte

PublicKey is an alias of a 32-byte array representing the public key component.

func MakePublicKey Uses

func MakePublicKey(b []byte) PublicKey

MakePublicKey converts a byte array to a PublicKey type.

type Q Uses

type Q struct {
    Count       int  `json:"count"`                  //The maximum number of records to return.
    IncludeData bool `json:"include_data,omitempty"` //If true, include record data with results.

    WriterIDs         []string          `json:"writer_ids,omitempty"`    //If not empty, limit results to records written by the given set of IDs.
    UserIDs           []string          `json:"user_ids,omitempty"`      //If not null, limit results to records about given set of IDs.
    RecordIDs         []string          `json:"record_ids,omitempty"`    //If not empty, limit results to the records specified.
    ContentTypes      []string          `json:"content_types,omitempty"` //If not empty, limit results to records of the given types.
    AfterIndex        int               `json:"after_index,omitempty"`   //If greater than 0, limit results to the records appearing "after" the given index.
    Plain             map[string]string `json:"plain,omitempty"`
    IncludeAllWriters bool              `json:"include_all_writers,omitempty"` //If true, include all records shared with this client.
}

Q contains options for querying a set of records in the database.

type Record Uses

type Record struct {
    Meta Meta              `json:"meta"`
    Data map[string]string `json:"data"`
}

Record contains a plaintext 'Meta' object containing record metadata, along with decrypted fields in 'Data'. All data will be encrypted before it is stored in the E3DB service.

Package e3db imports 22 packages (graph). Updated 2018-11-28. Refresh now. Tools for package owners.