Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ target
/secretspec-dotnet/**/obj/

.idea/

.pi/
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- Bitwarden Password Manager provider. `bw://` uses the `bw` CLI for
vault-wide secret storage across all Bitwarden item types.
- The `required` field accepts `at_least_one` and `exactly_one` group tables,
supporting overlapping alternative and mutually exclusive credentials
across `check`, `run`, and SDK resolution.
Expand Down Expand Up @@ -51,6 +53,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [0.16.0] - 2026-07-17

### Added
>>>>>>> upstream/main
- Composed secrets derive read-only values such as connection strings from
other declared secrets using strict `${UPPERCASE_NAME}` templates; names must
match `[A-Z][A-Z0-9_]*`, `$$` produces a literal dollar sign, and ordinary
Expand Down Expand Up @@ -86,6 +89,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [0.15.0] - 2026-07-16

### Added

- Gopass provider (`gopass://`) for GPG-based password manager with git-synced password store.
- `secretspec export` command that resolves every secret for the active profile
and writes them to stdout without running a command, in a chosen `--format`:
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ linkme = "0.3"
jiff = "0.2"
secrecy = { version = "0.10.3", features = ["serde"] }
bitwarden = { version = "2.0.0", features = ["secrets"] }
base64 = "0.22"
rustls = { version = "0.23", default-features = false, features = ["aws_lc_rs"] }
google-cloud-secretmanager-v1 = "1.2"
aws-config = "1"
Expand Down
2 changes: 2 additions & 0 deletions devenv.nix
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
pkgs.cargo-tarpaulin
# installers
pkgs.cargo-dist
# bitwarden-cli for integration testing
pkgs.bitwarden-cli
# Building the secretspec-php-native extension (ext-php-rs) needs php-config +
# the PHP dev headers, and bindgenHook wires libclang/clang system headers so
# ext-php-rs's bindgen step can parse php.h.
Expand Down
6 changes: 5 additions & 1 deletion docs/astro.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ $ secretspec import dotenv://.env.production

## Providers

Secrets can be stored in: keyring (default), dotenv files, environment variables, 1Password, Gopass (0.15+), LastPass, Pass, Proton Pass, Google Cloud Secret Manager, AWS Secrets Manager, HashiCorp Vault, OpenBao (0.17+), Bitwarden Secrets Manager, Azure Key Vault, or Infisical (0.16+).`,
Secrets can be stored in: keyring (default), dotenv files, environment variables, 1Password, Gopass (0.15+), LastPass, Pass, Proton Pass, Google Cloud Secret Manager, AWS Secrets Manager, HashiCorp Vault, OpenBao (0.17+), Bitwarden Password Manager (0.16+), Bitwarden Secrets Manager, Azure Key Vault, or Infisical (0.16+).`,
}),
],
title: "SecretSpec",
Expand Down Expand Up @@ -214,6 +214,10 @@ Secrets can be stored in: keyring (default), dotenv files, environment variables
label: "Vault",
slug: "providers/vault",
},
{
label: "Bitwarden Password Manager (0.16+)",
slug: "providers/bw",
},
{
label: "OpenBao",
slug: "providers/openbao",
Expand Down
1 change: 1 addition & 0 deletions docs/src/content/docs/concepts/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ DATABASE_URL = { description = "Production database", providers = ["prod_vault"]
| [awssm](/providers/awssm/) | AWS Secrets Manager (requires the `awssm` build feature) | ✓ | ✓ | ✓ |
| [vault](/providers/vault/) | HashiCorp Vault (requires the `vault` build feature) | ✓ | ✓ | ✓ |
| [openbao](/providers/openbao/) (0.17+) | OpenBao (requires the `openbao` build feature; 0.16 uses `openbao://` through `vault`) | ✓ | ✓ | ✓ |
| [bw](/providers/bw/) (0.16+) | Bitwarden Password Manager via the `bw` CLI (requires the `bw` build feature) | ✓ | ✓ | ✓ |
| [bws](/providers/bws/) | Bitwarden Secrets Manager (requires the `bws` build feature) | ✓ | ✓ | ✓ |
| [akv](/providers/akv/) | Azure Key Vault (requires the `akv` build feature) | ✓ | ✓ | ✓ |
| [infisical](/providers/infisical/) (0.16+) | Infisical (requires the `infisical` build feature) | ✓ | ✓ | ✓ |
Expand Down
200 changes: 200 additions & 0 deletions docs/src/content/docs/providers/bw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
---
title: Bitwarden Password Manager Provider
description: Bitwarden Password Manager secrets management integration
---

The `bw` provider integrates with Bitwarden Password Manager for secret management with vault-wide access to all item types.

:::note[Version compatibility]
The Bitwarden Password Manager provider is an upcoming SecretSpec 0.16 feature and is not
available in SecretSpec 0.15.
:::

## Prerequisites

- Bitwarden CLI (`bw`)
- Bitwarden account
- Signed in via `bw login` and unlocked with `bw unlock`
- `BW_SESSION` environment variable set

## Configuration

### URI Format

#### Password Manager URIs
```
bw://[collection-id]
bw://[org@collection]
bw://?server=https://vault.company.com
bw://?type=login&field=password
```

- `collection-id`: Target collection ID
- `org@collection`: Organization and collection specification
- `type`: Item type (login, card, identity, sshkey, securenote)
- `field`: Specific field to extract

### Examples

```bash
# Password Manager - Personal vault
$ secretspec set API_KEY --provider bw://

# Password Manager - Organization collection
$ secretspec set DATABASE_URL --provider "bw://myorg@dev-secrets"

# Password Manager - Self-hosted instance
$ secretspec set TOKEN --provider "bw://?server=https://vault.company.com"

# Password Manager - Specific item type and field
$ secretspec get 'MyApp Database' --provider 'bw://?type=login&field=username'
```

## Usage

### Basic Commands

```bash
# Set a secret (Password Manager)
$ secretspec set DATABASE_URL
Enter value for DATABASE_URL: postgresql://localhost/mydb
✓ Secret DATABASE_URL saved to Bitwarden

# Get a secret from existing vault item
$ secretspec get 'MyApp Database' --provider 'bw://?type=login'

# Run with secrets
$ secretspec run -- npm start
```

### Item Type Configuration

The Bitwarden provider supports all Bitwarden item types with smart field detection:

#### Login Items (Default)
```bash
# Get password field (default)
$ secretspec get 'Database Login' --provider 'bw://?type=login'

# Get username field
$ secretspec get 'Database Login' --provider 'bw://?type=login&field=username'

# Get custom field
$ secretspec get 'API Service' --provider 'bw://?type=login&field=api_key'
```

#### Credit Card Items
```bash
# Get API key from custom field (field required)
$ secretspec get 'Stripe Payment' --provider 'bw://?type=card&field=api_key'

# Get card number
$ secretspec get 'Company Card' --provider 'bw://?type=card&field=number'
```

#### SSH Key Items
```bash
# Get private key (default)
$ secretspec get 'Deploy Key' --provider 'bw://?type=sshkey'

# Get passphrase
$ secretspec get 'Deploy Key' --provider 'bw://?type=sshkey&field=passphrase'
```

#### Identity Items
```bash
# Get custom field (field required)
$ secretspec get 'Employee Record' --provider 'bw://?type=identity&field=employee_id'

# Get email field
$ secretspec get 'Personal Identity' --provider 'bw://?type=identity&field=email'
```

#### Secure Note Items
```bash
# Get value from secure note
$ secretspec get 'Legacy Config' --provider 'bw://?type=securenote&field=config_value'
```

### Profile Configuration

```toml
# secretspec.toml
[development]
provider = "bw://dev-secrets"

[production]
provider = "bw://prod-secrets"

```

### Environment Variables

#### Authentication
```bash
# Password Manager session
$ export BW_SESSION="your-session-key"
```

#### Configuration Defaults
```bash
# Set item type and field defaults
$ export BITWARDEN_DEFAULT_TYPE=login
$ export BITWARDEN_DEFAULT_FIELD=password

# Organization settings
$ export BITWARDEN_ORGANIZATION=myorg
$ export BITWARDEN_COLLECTION=dev-secrets

# Use defaults
$ secretspec get DATABASE_PASSWORD --provider bw://
```

### CI/CD Integration

#### Password Manager with Session Key
```bash
# Login and unlock (interactive)
$ bw login
$ bw unlock

# Export session for automation
$ export BW_SESSION="session-key-from-unlock"

# Use in CI/CD
$ secretspec run --provider bw://Production -- deploy
```

### Field Requirements by Item Type

| Item Type | Default Field | Field Required? | Notes |
|--------------|----------------|-----------------|--------------------------|
| Login | `password` | No | Falls back to username |
| SSH Key | `private_key` | No | Standard SSH key field |
| Card | None | **YES** | Must specify field |
| Identity | None | **YES** | Must specify field |
| Secure Note | Smart detect | No | Uses note content/fields |

## Error Handling

The provider includes comprehensive error handling with helpful guidance:

### CLI Installation
```
Bitwarden CLI (bw) is not installed.

To install it:
- npm: npm install -g @bitwarden/cli
- Homebrew: brew install bitwarden-cli
- Download: https://bitwarden.com/help/cli/
```

### Authentication Issues
- Clear distinction between "not logged in" vs "vault locked"
- Step-by-step guidance for `bw login` and `bw unlock`
- Session key setup instructions

### Item Access
- Graceful handling of missing items
- Field validation and suggestions
- Organization/collection permission guidance
1 change: 1 addition & 0 deletions docs/src/content/docs/quick-start.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ $ secretspec config init
awssm: AWS Secrets Manager
vault: HashiCorp Vault secret management
openbao: OpenBao secret management (0.17+)
bw: Bitwarden Password Manager (0.16+)
bws: Bitwarden Secrets Manager
akv: Azure Key Vault
infisical: Infisical secret management (0.16+)
Expand Down
17 changes: 17 additions & 0 deletions docs/src/content/docs/reference/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,22 @@ openbao://127.0.0.1:8200/secret?kv=1&tls=false
**Prerequisites**: OpenBao server, authentication credentials, build with `--features openbao` (0.17+)
**Storage**: KV path `secretspec/{project}/{profile}/{key}` with a `value` field

## Bitwarden Password Manager Provider (0.16+)

**URI**: `bw://[COLLECTION_ID]` - Stores secrets in a Bitwarden Password Manager vault via the `bw` CLI

```bash
bw:// # Personal vault
bw://collection-id # Specific collection
bw://myorg@dev-secrets # Organization collection
bw://?server=https://vault.company.com # Self-hosted server
bw://?type=login&field=username # Default item type and field
```

**Features**: Read/write, all vault item types (logins, cards, identities, SSH keys, secure notes), field selection, `ref = { item, field }` mapping in `secretspec.toml`
**Prerequisites**: Bitwarden CLI (`bw`), signed in and unlocked (`BW_SESSION` env var), build with `--features bw`
**Storage**: One vault item per secret; reads use per-type default fields unless `?field=` or a `ref` mapping selects one

## Bitwarden Secrets Manager Provider

**URI**: `bws://[SERVER_BASE@]PROJECT_UUID` - Stores secrets in Bitwarden Secrets Manager
Expand Down Expand Up @@ -290,6 +306,7 @@ export SECRETSPEC_PROVIDER="dotenv:///config/.env"
| AWSSM | ✅ AWS KMS | Cloud (AWS) | ✅ Yes |
| Vault | ✅ Vault encryption | Vault server | ✅ Yes |
| OpenBao (0.17+) | ✅ OpenBao encryption | OpenBao server | ✅ Yes |
| BW (0.16+) | ✅ End-to-end | Cloud (Bitwarden) or self-hosted | ✅ Yes |
| BWS | ✅ End-to-end | Cloud (Bitwarden) | ✅ Yes |
| AKV | ✅ Azure-managed | Cloud (Azure) | ✅ Yes |
| Infisical | ✅ Infisical-managed | Cloud (Infisical) or self-hosted | ✅ Yes |
5 changes: 4 additions & 1 deletion docs/src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ const providerMetadata: ProviderMetadata[] = [
{ icon: 'apple', slug: 'keyring', label: 'macOS Keychain' },
{ icon: '1password', slug: 'onepassword', label: '1Password' },
{ icon: 'lastpass', slug: 'lastpass', label: 'LastPass' },
{ icon: 'bitwarden', slug: 'bws', label: 'Bitwarden' },
{ icon: 'bitwarden', slug: 'bw', label: 'Bitwarden Password Manager' },
{ icon: 'bitwarden', slug: 'bws', label: 'Bitwarden Secrets Manager' },
{ icon: 'vault', slug: 'vault', label: 'Vault' },
{ slug: 'openbao', label: 'OpenBao (0.17+)' },
{ slug: 'awssm', label: 'AWS Secrets Manager' },
Expand Down Expand Up @@ -141,6 +142,7 @@ $ secretspec init --from dotenv
$ secretspec config init
? Select your preferred provider backend:
<span class="tok-pun">›</span> keyring: Uses system keychain (Recommended)
bw: Bitwarden Password Manager
infisical: Infisical secret management
openbao: OpenBao secret management (0.17+)
<span class="tok-str">✓</span> Saved to ~/.config/secretspec/config.toml
Expand Down Expand Up @@ -209,6 +211,7 @@ $ secretspec run --profile production -- npm start
<pre is:raw class="landing-step-code"><code>$ secretspec config init
? Select your preferred provider backend:
> keyring: Uses system keychain (Recommended)
bw: Bitwarden Password Manager
infisical: Infisical secret management
openbao: OpenBao secret management (0.17+)</code></pre>
</div>
Expand Down
4 changes: 3 additions & 1 deletion secretspec/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ whoami = { workspace = true, optional = true }
linkme.workspace = true
jiff.workspace = true
secrecy.workspace = true
base64 = { workspace = true, optional = true }
bitwarden = { workspace = true, optional = true }
rustls = { workspace = true, optional = true }
google-cloud-secretmanager-v1 = { workspace = true, optional = true }
Expand All @@ -52,7 +53,7 @@ data-encoding.workspace = true
detect-coding-agent.workspace = true

[features]
default = ["cli", "keyring", "gcsm", "awssm", "vault", "openbao", "bws", "akv", "infisical"]
default = ["cli", "keyring", "gcsm", "awssm", "vault", "openbao", "bws", "akv", "infisical", "bw"]
cli = ["dep:toml_edit"]
keyring = ["dep:keyring", "dep:whoami"]
# Compile libdbus from source into the binary instead of linking the system
Expand All @@ -68,4 +69,5 @@ openbao = ["dep:reqwest"]
# name the features it uses rather than inherit them from a sibling.
infisical = ["dep:reqwest", "tokio/sync"]
bws = ["dep:bitwarden", "dep:rustls"]
bw = ["dep:base64"]
akv = ["dep:azure_core", "dep:azure_identity", "dep:azure_security_keyvault_secrets"]
3 changes: 3 additions & 0 deletions secretspec/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ SecretSpec fixes this by separating secret **declaration** from secret **storage
- [AWS Secrets Manager](https://secretspec.dev/providers/awssm)
- [Vault](https://secretspec.dev/providers/vault)
- [OpenBao](https://secretspec.dev/providers/openbao) (0.17+)
- [Bitwarden Password Manager](https://secretspec.dev/providers/bw) (0.16+)
- [Bitwarden Secrets Manager](https://secretspec.dev/providers/bws)
- [Azure Key Vault](https://secretspec.dev/providers/akv)
- [Infisical](https://secretspec.dev/providers/infisical) (0.16+)
Expand Down Expand Up @@ -67,6 +68,7 @@ $ secretspec config init
awssm: AWS Secrets Manager
vault: HashiCorp Vault secret management
openbao: OpenBao secret management (0.17+)
bw: Bitwarden Password Manager (0.16+)
bws: Bitwarden Secrets Manager
akv: Azure Key Vault
infisical: Infisical secret management (0.16+)
Expand Down Expand Up @@ -153,6 +155,7 @@ SecretSpec supports multiple storage backends for secrets:
- **[AWS Secrets Manager](https://secretspec.dev/providers/awssm)** - AWS secret management
- **[Vault](https://secretspec.dev/providers/vault)** - HashiCorp Vault KV engine
- **[OpenBao](https://secretspec.dev/providers/openbao)** (0.17+) - OpenBao KV integration; SecretSpec 0.16 accepts `openbao://` through the Vault provider
- **[Bitwarden Password Manager](https://secretspec.dev/providers/bw)** (0.16+) - Bitwarden Password Manager vault via the `bw` CLI
- **[Bitwarden Secrets Manager](https://secretspec.dev/providers/bws)** - Bitwarden Secrets Manager integration
- **[Azure Key Vault](https://secretspec.dev/providers/akv)** - Azure secret management
- **[Infisical](https://secretspec.dev/providers/infisical)** (0.16+) - Infisical secret management
Expand Down
Loading