tools/SDKs/.NET SDK

.NET SDK

Connect .NET applications to SikkerKey with a machine identity, then read, export, cache, and monitor permitted secrets.

Updated yesterday

The SikkerKey .NET SDK gives .NET 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

  • .NET 8 or later

  • A SikkerKey vault

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

Network operations are asynchronous and return Task values. Await them from application services, background workers, and request handlers.


#Install the SDK

bash
dotnet add package SikkerKey

To install the version covered by this page:

bash
dotnet add package SikkerKey --version 1.3.0

#Read your first secret

csharp
using SikkerKey;

using var sikkerKey = SikkerKeyClient.Create("vault_...");
var apiKey = await sikkerKey.GetSecretAsync("sk_...");

// Pass apiKey directly to the client or service that needs it.

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


#Choose a machine identity

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

Use a standard machine

csharp
// Select a registered vault.
using var byVault = SikkerKeyClient.Create("vault_...");

// Load a specific identity file.
using var byPath = SikkerKeyClient.Create(
    "/etc/sikkerkey/vaults/vault_.../identity.json");

// Use SIKKERKEY_IDENTITY or select the only registered vault.
using var automatically = SikkerKeyClient.Create();

Automatic selection checks SIKKERKEY_IDENTITY first. If it is not set, the SDK selects the identity when exactly one vault is registered under ~/.sikkerkey/vaults/. Select a vault explicitly when several identities are available.

Set SIKKERKEY_HOME when the application uses a different protected identity directory:

bash
export SIKKERKEY_HOME=/var/lib/sikkerkey

Use an ephemeral machine

csharp
using var sikkerKey = await SikkerKeyClient.BootstrapInMemoryAsync(
    Environment.GetEnvironmentVariable("SIKKERKEY_VAULT_ID")!,
    Environment.GetEnvironmentVariable("SIKKERKEY_ENROLLMENT_TOKEN")!,
    hostname: "checkout-worker",
    name: "Checkout worker");

var apiKey = await sikkerKey.GetSecretAsync("sk_...");

BootstrapInMemoryAsync generates an Ed25519 key pair in memory, registers the ephemeral machine, and returns a ready client. It writes no identity or private key to disk, and the private key disappears when the process exits.

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

Keep enrollment tokens in protected runtime configuration and set the machine lifetime and token use limit for the workload's duration and expected concurrency.


#Read secrets

Read a standard secret

csharp
var apiKey = await sikkerKey.GetSecretAsync("sk_...");

Read a structured secret

csharp
var database = await sikkerKey.GetFieldsAsync("sk_...");

var host = database["host"];
var username = database["username"];
var password = database["password"];

Read one field directly with:

csharp
var password = await sikkerKey.GetFieldAsync(
    "sk_...",
    "password");

GetFieldsAsync returns a Dictionary<string, string>. A non-structured value produces SecretStructureException; a missing field produces FieldNotFoundException with the available field names.


#Discover and export secrets

csharp
var secrets = await sikkerKey.ListSecretsAsync();
var projectSecrets = await sikkerKey.ListSecretsByProjectAsync("proj_...");

foreach (var secret in secrets)
    Console.WriteLine($"{secret.Id}: {secret.Name}");

Each SecretListItem includes the secret ID and name, with optional project and structured-field metadata. Listing returns metadata, not secret values.

Export application configuration

csharp
var allConfiguration = await sikkerKey.ExportAsync();
var projectConfiguration = await sikkerKey.ExportAsync("proj_...");

Export returns a Dictionary<string, string> in one request. Names use uppercase environment-variable format, and structured secrets are flattened into entries such as DATABASE_HOST and DATABASE_PASSWORD.


#Enable encrypted fallback

csharp
using var sikkerKey = SikkerKeyClient
    .Create("vault_...")
    .EnableCache(new CacheOptions
    {
        MaxAge = TimeSpan.FromHours(1),
        OnFallback = (secretId, cachedAt) =>
            logger.LogWarning(
                "Using cached value for {SecretId} from epoch {CachedAt}",
                secretId,
                cachedAt)
    });

Encrypted fallback is opt-in. Successful reads are encrypted locally with AES-256-GCM using a key derived from the machine identity and vault. Omit MaxAge for no automatic expiry. OnFallback runs only when the SDK serves a cached value.

Fallback is limited to network failures, timeouts, and temporary gateway or service availability responses. Authentication failures, denied access, missing secrets, rate limits, and other authoritative responses are returned to the application.

Cache entries are bound to the machine, vault, secret, and creation time. The format is compatible with SikkerKey CLI and the other SikkerKey SDKs. Use it with a persistent, protected identity directory.


#Monitor secrets for changes

csharp
sikkerKey.Watch("sk_...", change =>
{
    switch (change.Status)
    {
        case WatchStatus.Changed:
            ReloadClient(change.Value, change.Fields);
            break;
        case WatchStatus.Deleted:
            logger.LogWarning("Secret {SecretId} was deleted", change.SecretId);
            break;
        case WatchStatus.AccessDenied:
            logger.LogWarning("Access to {SecretId} was removed", change.SecretId);
            break;
        case WatchStatus.Error:
            logger.LogError("Secret update failed: {Error}", change.Error);
            break;
    }
});

The SDK checks watched secrets on a background task every 15 seconds by default. Changed events include the current value and parsed fields when the secret is structured. Deleted and inaccessible secrets are removed from the watch list, and a failed poll is tried again during the next interval.

Callbacks execute as part of the polling task, so hand slow or blocking work to your application's queue or background service.

csharp
sikkerKey.SetPollInterval(30); // seconds; minimum 10
sikkerKey.Unwatch("sk_...");
sikkerKey.Close();

Close stops monitoring while leaving the client available for reads. Dispose releases the HTTP client and polling resources completely; prefer using for the client lifetime.


#Work with vaults and inspect the client

csharp
var vaultIds = SikkerKeyClient.ListVaults();
using var production = SikkerKeyClient.Create("vault_...");
using var staging = SikkerKeyClient.Create("vault_...");

Create a separate client for each vault. The active identity is available through MachineId, MachineName, VaultId, and ApiUrl for application diagnostics.


#Handle errors

csharp
try
{
    var value = await sikkerKey.GetSecretAsync("sk_...");
}
catch (NotFoundException)
{
    HandleMissingSecret();
}
catch (AccessDeniedException)
{
    HandleRemovedAccess();
}
catch (AuthenticationException)
{
    HandleAuthenticationFailure();
}
catch (RateLimitedException)
{
    ScheduleLaterRetry();
}
catch (ApiException error)
{
    RecordServiceError(error.HttpStatus);
}
catch (ConfigurationException)
{
    HandleIdentityConfiguration();
}

All SDK exceptions extend SikkerKeyException. Typed exceptions cover configuration, authentication, access, missing resources, conflicts, rate limits, temporary service availability, invalid structured data, and missing fields. Network failures and timeouts use ApiException with HttpStatus == 0.

Retries and timeout

Authenticated requests retry network failures, timeouts, and HTTP 429 or 503 responses up to three times, waiting 1, 2, and 4 seconds. Every attempt uses a fresh timestamp and nonce. The shared HTTP client has a 15-second timeout.


#Method reference

Task

Method

Connect with a registered identity

SikkerKeyClient.Create(vaultOrPath?)

Create an ephemeral identity

SikkerKeyClient.BootstrapInMemoryAsync(...)

Read a standard secret

GetSecretAsync(secretId)

Read structured fields

GetFieldsAsync / GetFieldAsync

List secrets

ListSecretsAsync / ListSecretsByProjectAsync

Export configuration

ExportAsync(projectId?)

Enable encrypted fallback

EnableCache(options?)

Monitor a secret

Watch(secretId, callback)

Stop monitoring

Unwatch(secretId) / Close()

List local vaults

SikkerKeyClient.ListVaults()

Release the client

Dispose()


#Source code and license

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