tools/SDKs/Go SDK

Go SDK

Connect Go applications to SikkerKey with a machine identity, then read, export, cache, and monitor the secrets they are permitted to access.

Updated yesterday

The SikkerKey Go SDK gives Go applications secure, read-only access to secrets in your vault. Each client uses a machine identity, so the application can retrieve only the secrets and projects that machine is permitted to access.


#Requirements

  • Go 1.22 or later

  • A SikkerKey vault

  • A machine identity with access to the secrets your application needs

The SDK uses only the Go standard library and adds no third-party runtime dependencies to your application.


#Install the SDK

bash
go get github.com/SikkerKeyOfficial/sikkerkey-go@latest

Import the package with the name sikkerkey in your Go code:

go
import sikkerkey "github.com/SikkerKeyOfficial/sikkerkey-go"

#Read your first secret

go
package main

import (
    "log"

    sikkerkey "github.com/SikkerKeyOfficial/sikkerkey-go"
)

func main() {
    sk, err := sikkerkey.New("vault_..."")
    if err != nil {
        log.Fatal(err)
    }

    apiKey, err := sk.GetSecret("sk_...")
    if err != nil {
        log.Fatal(err)
    }

    _ = apiKey // Pass the value to the client or service that needs it.
}

The SDK loads the identity registered for that vault, signs the request with the machine's Ed25519 private key, and returns the current secret value as a string.

Do not print secret values or include them in application logs.


#Choose a machine identity

Use a standard machine for persistent servers and workstations. Use an ephemeral machine for short-lived workloads that should keep their identity only in memory.

Use a standard machine

After provisioning the machine with the SikkerKey CLI, select its vault:

go
sk, err := sikkerkey.New("vault_...")

You can also load a specific identity file:

go
sk, err := sikkerkey.New("/etc/sikkerkey/identity.json")

For automatic selection, use NewAutoDetect() or pass an empty string to New:

go
sk, err := sikkerkey.NewAutoDetect()

Automatic selection first checks SIKKERKEY_IDENTITY. If it is not set, the SDK selects the identity when exactly one vault is registered on the machine. If several vaults are available, select one explicitly.

By default, identities are stored beneath ~/.sikkerkey/vaults/. Set SIKKERKEY_HOME when the application uses a different protected identity directory:

bash
export SIKKERKEY_HOME=/var/lib/sikkerkey

Use an ephemeral machine

For serverless functions, CI jobs, containers, and other short-lived workloads, create an in-memory identity with an enrollment token:

go
sk, err := sikkerkey.BootstrapInMemory(
    os.Getenv("vault_...""),
    os.Getenv("SIKKERKEY_ENROLLMENT_TOKEN"),
    sikkerkey.BootstrapOptions{
        Hostname: "checkout-worker",
        Name:     "Checkout worker",
    },
)
if err != nil {
    log.Fatal(err)
}

apiKey, err := sk.GetSecret("YOUR_SECRET_ID")

The SDK generates an Ed25519 key pair in memory, registers the ephemeral machine, and returns a ready client. It does not write an identity or private key to disk. The private key disappears when the process exits.

The machine follows the access, hostname rules, use limit, and lifetime configured on the enrollment token. Hostname defaults to the HOSTNAME environment variable and then to serverless. A name pattern configured on the token takes precedence over Name.

Set the ephemeral machine lifetime long enough for the workload to finish, allow enough token uses for concurrent starts, and keep enrollment tokens in protected runtime configuration.


#Read secrets

Read a standard secret

go
apiKey, err := sk.GetSecret("sk_...")
if err != nil {
    return err
}

Read a structured secret

Retrieve every field as a map:

go
database, err := sk.GetFields("sk_...")
if err != nil {
    return err
}

host := database["host"]
username := database["username"]
password := database["password"]

Use GetField when the application needs one field:

go
password, err := sk.GetField("sk_...", "password")

Structured values are returned as strings. The SDK returns an error if the secret is not a supported structured object or if the requested field is missing.


#Discover accessible secrets

List the secret metadata available to the current machine:

go
secrets, err := sk.ListSecrets()
if err != nil {
    return err
}

for _, secret := range secrets {
    log.Printf("available secret: %s (%s)", secret.Name, secret.ID)
}

Limit the list to a project:

go
secrets, err := sk.ListSecretsByProject("proj_...")

Each SecretListItem includes the secret ID and display name. It can also include the owning project and the available structured field names. Listing returns metadata, not secret values.


#Export secrets for application configuration

Export all accessible values in one request:

go
configuration, err := sk.Export("")

Pass a project ID to limit the export:

go
configuration, err := sk.Export("YOUR_PROJECT_ID")

The returned map[string]string uses uppercase environment-style names. Spaces and punctuation become underscores. Structured secrets are flattened into one entry per field, such as DATABASE_HOST and DATABASE_PASSWORD.


#Enable encrypted fallback

Encrypted fallback allows a persistent application to use a previously retrieved value during a temporary network or service interruption. It is disabled until you enable it.

go
sk.EnableCache(sikkerkey.CacheOptions{
    MaxAge: time.Hour,
    OnFallback: func(secretID string, cachedAt time.Time) {
        log.Printf("using cached value for %s from %s", secretID, cachedAt)
    },
})

Successful reads are encrypted locally with AES-256-GCM using a key derived from the machine identity and vault. A zero MaxAge means cached values do not expire automatically. OnFallback is optional and runs only when the SDK serves a cached value.

Fallback is limited to connection failures and temporary gateway or service availability responses. Authentication failures, denied access, missing secrets, rate limits, and other authoritative responses are returned to the application instead of being replaced by an older value.

Cache entries are kept under the vault's identity directory. They are bound to the machine, vault, secret, and creation time, and are rejected if they have been altered or belong to another identity. The cache format is compatible with SikkerKey CLI and the other SikkerKey SDKs.

Encrypted fallback is designed for a host with a persistent, protected identity directory. An ephemeral identity cannot recover its cache key after the process exits.


#Monitor secrets for changes

go
sk.Watch("sk_...", func(event sikkerkey.WatchEvent) {
    switch event.Status {
    case sikkerkey.WatchStatusChanged:
        reloadClient(event.Value, event.Fields)
    case sikkerkey.WatchStatusDeleted:
        log.Printf("secret %s was deleted", event.SecretID)
    case sikkerkey.WatchStatusAccessDenied:
        log.Printf("access to %s was removed", event.SecretID)
    case sikkerkey.WatchStatusError:
        log.Printf("watch failed: %s", event.Error)
    }
})

The SDK checks watched secrets from a background goroutine every 15 seconds by default. A changed event includes the latest value and parsed fields when the secret is structured. Deleted secrets and secrets the machine can no longer access are automatically removed from the watch list.

Callbacks run on the polling goroutine. Send slow or blocking work to another goroutine or worker queue.

Change the interval, stop one watcher, or stop all monitoring:

go
sk.SetPollInterval(30) // seconds; minimum 10
sk.Unwatch("sk_...")
sk.Close()

Closing the watcher does not prevent later secret reads.


#Work with multiple vaults

Create one client for each vault the application uses:

go
production, err := sikkerkey.New("PRODUCTION_VAULT_ID")
staging, err := sikkerkey.New("STAGING_VAULT_ID")

List locally registered vault IDs with:

go
vaultIDs := sikkerkey.ListVaults()

#Inspect the active machine

The client exposes the identity it is using for diagnostics:

go
machineID := sk.MachineID()
machineName := sk.MachineName()
vaultID := sk.VaultID()
apiURL := sk.APIURL()

#Handle errors

HTTP responses and network failures use *sikkerkey.APIError. Inspect its status code when your application needs a different response for authentication, access, missing secrets, or connectivity:

go
value, err := sk.GetSecret("sk_...")
if err != nil {
    var apiErr *sikkerkey.APIError
    if errors.As(err, &apiErr) {
        switch apiErr.StatusCode {
        case 0:
            log.Printf("network failure: %s", apiErr.Message)
        case http.StatusUnauthorized:
            log.Printf("machine authentication failed")
        case http.StatusForbidden:
            log.Printf("machine access was denied")
        case http.StatusNotFound:
            log.Printf("secret was not found")
        default:
            log.Printf("SikkerKey returned HTTP %d", apiErr.StatusCode)
        }
    } else {
        log.Printf("configuration or parsing error: %s", err)
    }
}
_ = value

A status code of 0 represents a DNS, connection, TLS, timeout, or other transport failure. Local identity, key, configuration, and parsing problems are returned as ordinary Go errors with a sikkerkey: prefix and contextual message.

Retries and timeout

Authenticated requests retry transport failures and HTTP 429 or 503 responses up to three times, waiting 1, 2, and 4 seconds. Every retry uses a fresh timestamp and nonce. Each request has a 15-second timeout; other HTTP responses are returned immediately.


#Method reference

Task

Method

Connect with a registered identity

New(vaultOrPath)

Automatically select an identity

NewAutoDetect()

Create an ephemeral identity

BootstrapInMemory(vaultID, token, options)

Read a standard secret

GetSecret(secretID)

Read every structured field

GetFields(secretID)

Read one structured field

GetField(secretID, field)

List accessible secrets

ListSecrets()

List secrets in one project

ListSecretsByProject(projectID)

Export configuration values

Export(projectID)

Enable encrypted fallback

EnableCache(options)

Monitor a secret

Watch(secretID, callback)

Stop monitoring a secret

Unwatch(secretID)

Stop all monitoring

Close()

List local vault identities

ListVaults()


#Source code and license

The Go SDK is open source under the MIT License. Review the source, report an issue, or contribute through the SikkerKeyOfficial GitHub organization.