[Pitch] VaultCourier

Hi community,

I’d like to pitch VaultCourier to the SSWG Incubation process at a Sandbox level. VaulCourier is a native swift client for interacting with Hashicorp Vault and OpenBao- tools for securely storing, auditing and managing access to secrets, such as API tokens, database credentials, and certificates.

Motivation

As teams and organizations grow, managing secrets securely becomes increasingly complex. Three main challenges often arise:

  • Secret Sprawl: Secrets end up scattered across infrastructure and repositories, making them hard to manage consistently.
  • Lack of Auditability: Large teams often lack visibility into who has access to which secrets, and there's no reliable audit trail to track historical access. In particular, in the context of applications and machines.
  • Difficult Secret Rotation: When secrets are spread everywhere, rotating them quickly in response to a breach becomes a serious operational hurdle.

Tools like Hashicorp Vault and OpenBao provide robust, battle-tested solutions to these issues. However, the Swift ecosystem lacks native support for integrating with these tools. While other languages have dedicated clients, Swift applications—especially server-side—could benefit from direct interaction with Vault. A native Swift client also opens the door for custom orchestration tools built entirely in Swift.

Proposed Solution

I’ve been working for about a year on VaultCourier, a Swift package that serves as a native client for HashiCorp Vault and OpenBao. Built using swift-openapi, it runs on Linux, macOS, and potentially other platforms (if you don’t rely on the swift-openapi-generator). Unless otherwise specified, I’ll refer to both HashiCorp Vault and OpenBao simply as Vault.

VaultCourier currently supports:

  • Key/Value (KV v2) Secret Storage: you can store arbitrary JSON object secrets under named keys.
  • Static and Dynamic Database Credential Generation. This avoid secret sharing by generating unique, short-lived credentials per application.
  • Token and AppRole Authentication: AppRole provides identity-based authentication for applications, allowing fine-grained secret access control and auditability. In the event of a breach, compromised credentials can be rotated quickly, limiting the blast radius.
  • Response Wrapping for Login: adds an extra layer of security by delivering secrets in a one-time-use, time-limited wrapper token.
  • Pkl resource reader. More on this on the detailed design section.

A basic example of usage:

import Foundation
import VaultCourier
import OpenAPIAsyncHTTPClient
import Logging

struct AppSecrets: Decodable, Sendable {
    let apiToken: String
}

// 1. Create a vault client.
let vaultConfiguration = VaultClient.Configuration(
    apiURL: try URL(validatingOpenAPIServerURL: "http://127.0.0.1:8200/v1"),
    backgroundActivityLogger: Logger(label: "my-app")
)

let vaultClient = VaultClient(
    configuration: vaultConfiguration,
    client: Client(
        serverURL: vaultConfiguration.apiURL,
        transport: AsyncHTTPClientTransport()
    ),
    authentication: .token("education")
)
// 2. Authenticate with vault
try await vaultClient.authenticate()

// 3. Read secret
let secret: AppSecrets = try await vaultClient.readKeyValueSecret(key: "dev-eu-central-1")

// Use the secret to start your service or app...

To see more examples in detail please check out the vault-courier-examples repository and the tutorials. In particular, I have written an end-to-end tutorial of integrating VaultCourier into Hummingbird’s Todo example. An equivalent example in Vapor is also planned.
Feedback is welcomed; the API is open to extension and change.

Detailed Design

VaultCourier depends on the following libraries:

As mentioned earlier, a key design decision in VaultCourier is the use of swift-openapi. The client is built in a spec-driven manner, which brings several practical benefits. For example, the generated code is transport-agnostic, making it compatible with both Linux and macOS. It also supports mocking the API, which is useful for development and testing—developers can simulate Vault responses without needing a live Vault instance. VaultCourier includes such a mock client to simplify local development.

Pkl also plays an important role in the project. The OpenAPI specification that VaultCourier uses is written using the org.openapis.v3 Pkl package. Using Pkl helps avoid common mistakes that can occur when hand-writing OpenAPI in JSON or YAML, and it allows for modularizing the spec. This modularity becomes especially useful as OpenBao—the open-source fork of HashiCorp Vault—begins to diverge from Vault upstream. We maintain this specification in a separate repository along with common pkl templates for configuring Vault: vault-courier-pkl.

Pkl is also used at runtime when the Pkl package trait is enabled in VaultCourier. This trait adds custom resource readers that allow Pkl configuration files to reference secrets stored in Vault without exposing them directly. For example, a Pkl config file might look like:

amends "ServerConfig.pkl"

logLevel = "debug"

// Calls a Vault KV endpoint with version 2 of the secret
apiToken = read("vault:secrets/api_token?version=2").text

database {
  hostname = "localhost"
  
  port = 8080
  
  // Calls a Vault database endpoint
  credentials = read("vault:database/static-creds/server_role").text
}

Secrets are read via resource URI schemes—VaultCourier provides an implementation for the “vault” scheme by default, though this can be customized. This setup allows applications to use Pkl as their primary configuration format while securely referencing secrets. A tutorial that extends the Todo app with this feature is available here: Todos App with VaultCourier and Pkl.

Vault and OpenBao support a wide range of authentication methods. VaultCourier currently focuses on AppRole, as it's a cloud-agnostic method that works across diverse environments. With interest and contributions from the community, we’re open to adding support for other authentication methods such as AWS, Google Cloud, Azure, AliCloud, GitHub, and more.

VaultCourier currently supports PostgreSQL vault integration, and with community contributions, support for more databases can be added. See the full list of Vault supported databases; there are plugins for databases already supported in the Swift ecosystem.

I'm looking forward to your feedback!

11 Likes

@jacubit hi! I'm going to kick off the review process hopefully today and will be the review manager!

3 Likes