Table of Contents

Quick Start

# Install via Homebrew
brew tap SCGIS-Wales/homebrew-tap https://github.com/SCGIS-Wales/homebrew-tap.git
brew install dcert

# Analyze a live HTTPS endpoint (bare hostname or full URL)
dcert api.example.com
dcert https://www.google.com

# Read PEM from a pipe
cat certificate.pem | dcert

# Check certificate expiry (CI/CD gate)
dcert https://your-api.com --expiry-warn 30

# Convert PFX to PEM
dcert convert pfx-to-pem client.pfx --password secret --output-dir ./certs

# Verify a private key matches a certificate
dcert verify-key cert.pem --key private.key

# Auto-discover and verify all cert/key pairs in a directory
dcert verify-key

# Create a new CSR with RSA 4096 key
dcert csr create --cn api.example.com --org "My Corp" --country GB

# Validate a CSR for compliance
dcert csr validate my-cert.csr

# Issue a TLS certificate from HashiCorp Vault PKI
dcert vault issue --cn www.example.com --role my-role

# Renew a certificate stored in Vault KV
dcert vault renew secret/certs/www-example-com --role my-role

Installation

Homebrew (recommended — macOS and Linux)

Homebrew is the recommended installation method. On Linux it builds from source, which avoids glibc compatibility issues and works on Ubuntu 22.04 and later.

brew tap SCGIS-Wales/homebrew-tap https://github.com/SCGIS-Wales/homebrew-tap.git
brew install dcert

Note: If you don't have Homebrew on Linux, install it first:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Prebuilt binaries

Download from the Releases page. Each release includes dcert (CLI) and dcert-mcp (MCP server). Prebuilt Linux binaries require Ubuntu 22.04 (glibc 2.35) or later.

curl -L https://github.com/SCGIS-Wales/dcert/releases/latest/download/dcert-x86_64-unknown-linux-gnu.tar.gz | tar xz
chmod +x dcert dcert-mcp
sudo mv dcert dcert-mcp /usr/local/bin/

Windows

Install with Chocolatey:

choco install dcert

Or pip install dcert (the win_amd64 wheel bundles dcert.exe and dcert-mcp.exe), or download the dcert-x86_64-pc-windows-msvc.zip archive from the Releases page and add the extracted .exe files to your PATH.

Note: the Windows build links a vendored OpenSSL that has no system trust store. If certificate verification fails because no CA roots are found, set SSL_CERT_FILE to a CA bundle (e.g. one exported from your organization or a cacert.pem).

Build from source

git clone https://github.com/SCGIS-Wales/dcert.git
cd dcert
cargo build --release
# Binaries: target/release/dcert and target/release/dcert-mcp

Docker

docker pull ghcr.io/scgis-wales/dcert:main

# CLI
docker run --rm ghcr.io/scgis-wales/dcert:main https://www.google.com

# Local PEM file
docker run --rm -v "$PWD:/data" ghcr.io/scgis-wales/dcert:main /data/cert.pem

# MCP server
docker run --rm -i --entrypoint dcert-mcp ghcr.io/scgis-wales/dcert:main

Commands

dcert uses subcommands to organize its features. The check subcommand is the default and can be omitted:

dcert <targets> [OPTIONS]              # Certificate analysis (default, same as 'dcert check')
dcert csr create [OPTIONS]             # Create a CSR and private key
dcert csr validate <CSR_FILE>          # Validate a CSR for compliance
dcert convert <MODE> [OPTIONS]         # Format conversion (PFX/PEM/keystore/truststore)
dcert verify-key <target> --key <KEY>  # Key-certificate matching (single pair)
dcert verify-key [--dir <DIR>]         # Auto-discover and verify all cert/key pairs
dcert vault issue [OPTIONS]            # Issue a TLS certificate from Vault PKI
dcert vault sign [OPTIONS]             # Sign a CSR using Vault PKI
dcert vault revoke [OPTIONS]           # Revoke a certificate in Vault PKI
dcert vault list [OPTIONS]             # List certificates issued by Vault PKI
dcert vault store [OPTIONS] <PATH>     # Store cert+key in Vault KV
dcert vault validate <PATH>            # Validate a certificate in Vault KV
dcert vault renew <PATH> [OPTIONS]     # Renew a certificate in Vault KV

dcert [check] -- Certificate Analysis (default)

Analyze TLS certificates from PEM files or HTTPS endpoints. The check keyword is optional -- dcert https://example.com and dcert check https://example.com are equivalent.

# Fetch and analyze certificates from HTTPS
dcert https://www.google.com

# Bare hostname (auto-prepends https://)
dcert api.example.com

# Analyze a local PEM file
dcert certificate.pem

# Read PEM data from stdin (pipe)
cat certificate.pem | dcert
echo "<base64-pem>" | base64 --decode | dcert
cat certificate.pem | dcert -

# Multiple targets
dcert https://www.google.com https://github.com cert.pem

# Pipe target names from stdin (one per line)
echo -e "https://google.com\nhttps://github.com" | dcert -

# JSON or YAML output
dcert https://example.com --format json
dcert https://example.com --format yaml

# SHA-256 fingerprints and certificate extensions
dcert https://example.com --fingerprint --extensions

# Expiry warning (exit code 1 if expiring within 30 days)
dcert https://example.com --expiry-warn 30

# OCSP revocation check
dcert https://example.com --check-revocation

# Compare certificates between two targets
dcert --diff https://staging.example.com https://prod.example.com

# Monitor certificates every 60 seconds
dcert --watch 60 https://example.com

# Export certificate chain to PEM file
dcert https://www.google.com --export-pem chain.pem

# Export excluding expired certificates
dcert https://www.google.com --export-pem chain.pem --exclude-expired

# Sort by expiry date
dcert certificates.pem --sort-expiry asc

# Only show expired certificates
dcert certificates.pem --expired-only

# Compliance report (CA/B Forum Baseline Requirements)
dcert https://example.com --compliance
dcert certificate.pem --compliance

# Compliance report in JSON (for CI/CD)
dcert https://example.com --compliance --format json

Root CA Trust Classification

Every check reports whether the certificate chain anchors to a publicly trusted root CA, a private PKI, or is self-signed — answering "is this issued by a real public CA, or a private/self-signed one?" This runs by default.

# Classification appears in the "Root CA trust" block (pretty) and the
# "root_trust" object (JSON/YAML)
dcert https://www.google.com
dcert https://example.com --format json   # see .root_trust

# Skip it (byte-stable legacy output)
dcert https://example.com --no-trust-check

The classification is one of:

Classification Meaning
publicly_trusted Chain verifies up to a root in the embedded Mozilla/CCADB root set
private_pki Chain terminates in a private (non-public) root CA
self_signed A single self-signed certificate, not issued by any CA
incomplete Chain neither reaches a public root nor presents a self-signed root (an issuer is missing) — try --resolve-issuers

How "publicly trusted" is defined. The authoritative source is the Mozilla/CCADB root set, embedded at build time via the webpki-root-certs crate. CCADB is the shared database behind the Mozilla, Microsoft, Apple and Google root programs, so DigiCert, Amazon/AWS, Google Trust Services, Microsoft and Apple public TLS roots, GlobalSign, Sectigo, Let's Encrypt, etc. are all included. Classification is a local cryptographic verification — no network is used — so it stays fast across 50+ certificates with no per-host timeouts. A private root that merely shares a Distinguished Name with a public one cannot produce a false positive, because the signature must validate against an embedded public key. Certificate expiry is ignored for this verdict (dcert reports expiry separately).

Each certificate that is itself a recognized public root carries an is_public_root: true attribute in JSON/YAML (usually absent, since servers don't send the root).

Optional network probe (--resolve-issuers). For incomplete or private_pki results you can follow the certificate's AIA "CA Issuers" URLs to fetch missing issuer certificates — completing the chain (which can flip an incomplete result to publicly_trusted) and confirming whether a private CA backend is reachable (private_backend_reachable). It is off by default.

# Complete a chain whose server omitted the intermediate
dcert https://example.com --resolve-issuers

# Keep the timeout short when probing many private CAs
dcert - --resolve-issuers --issuer-timeout 2 < hosts.txt

--resolve-issuers honours the standard forward-proxy environment variables (http_proxy/https_proxy/no_proxy, see Proxy and Timeout Configuration) and uses the short --issuer-timeout (default 2s) so large batches fail fast. Unlike the OCSP path, it intentionally does not block private/internal IPs — private-PKI AIA endpoints legitimately live on internal hosts, which is exactly what this flag exists to reach. It is gated behind this explicit opt-in.

Refreshing the public root set. --refresh-public-roots fetches the latest Mozilla/CCADB bundle from https://curl.se/ca/cacert.pem (over the proxy layer) and unions it into the embedded set for that run, so coverage can stay current between releases.

TLS Options

# Require TLS 1.3
dcert --min-tls 1.3 https://example.com

# Force TLS 1.2 only
dcert --min-tls 1.2 --max-tls 1.2 https://example.com

# Specific TLS 1.2 ciphers
dcert --cipher-list "ECDHE+AESGCM:CHACHA20" --max-tls 1.2 https://example.com

# TLS 1.3 cipher suites
dcert --cipher-suites "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256" https://example.com

# HTTP/2 ALPN negotiation
dcert --http-protocol http2 https://example.com

# SNI override
dcert https://10.0.0.1 --sni api.example.com

# Connect to a specific IP while validating the hostname (like curl --connect-to).
# Keep the hostname in the URL — it is used for SNI and certificate validation —
# and dcert dials the given IP instead of resolving DNS. Useful for probing one
# backend behind a load balancer, or a host that does not resolve from here.
dcert https://api.example.com --connect-to 10.0.0.5

# Skip TLS verification (self-signed certs)
dcert https://localhost:8443 --no-verify

# Inspect the certificate of a STARTTLS service (SMTP/IMAP/POP3/FTP)
dcert mail.example.com:587 --starttls smtp
dcert imap.example.com:143 --starttls imap

# Show the negotiated cipher suite in IANA or OpenSSL notation
dcert https://example.com --ciphers iana

mTLS (Mutual TLS)

# Client certificate with PEM files
dcert https://api.internal.com --client-cert client.pem --client-key client-key.pem

# Client certificate with PKCS12/PFX
dcert https://api.internal.com --pkcs12 client.pfx --cert-password secret

# Custom CA bundle (overrides system CAs)
dcert https://internal.server --ca-cert corporate-ca.pem

# Combine mTLS with custom CA
dcert https://api.internal.com --client-cert client.pem --client-key client-key.pem --ca-cert corporate-ca.pem

When the server demands a client certificate and you didn't supply one:

[mTLS REQUIRED] This server requires client certificate authentication.
  Re-run with --client-cert <pem> --client-key <pem>  or  --pkcs12 <p12> --cert-password ...
  The server's certificate chain is shown below for reference.

dcert detects the tlsv13 alert certificate required (and the equivalent legacy alerts), captures the server's certificate chain from inside the TLS handshake — so you can still inspect the server identity even though the handshake aborted — and exits with code 6.

HTTP Options

# Custom headers and method
dcert https://api.example.com --method POST --header "Authorization:Bearer token"

# POST with inline data
dcert https://api.example.com -d '{"key":"value"}' --header "Content-Type:application/json"

# POST with data from file
dcert https://api.example.com --data-file body.json

# Custom timeout
dcert https://slow-server.example.com --timeout 30 --read-timeout 15

Full Options Reference

dcert [check] [OPTIONS] [TARGETS]...

Arguments:
  [TARGETS]...                         PEM file(s), HTTPS URL(s), bare hostnames, or '-' for stdin
                                       Omit targets to read PEM data from a pipe

Options:
  -f, --format <FORMAT>                Output format [pretty, json, yaml] (default: pretty)
      --expired-only                   Show only expired certificates
      --export-pem <FILE>              Export fetched PEM chain to a file
      --exclude-expired                Exclude expired certs from export
      --sort-expiry <ORDER>            Sort by expiry [asc, desc]
      --method <METHOD>                HTTP method [get, post, head, options] (default: get)
      --header <KEY:VALUE>             Custom HTTP headers (repeatable)
  -d, --data <DATA>                    Request body (implies POST)
      --data-file <FILE>               Request body from file (implies POST)
      --http-protocol <PROTO>          HTTP protocol [http1-1, http2] (default: http1-1)
      --min-tls <VERSION>              Minimum TLS version [1.2, 1.3]
      --max-tls <VERSION>              Maximum TLS version [1.2, 1.3]
      --cipher-list <STRING>           Allowed TLS 1.2 ciphers (OpenSSL format)
      --cipher-suites <SUITES>         Allowed TLS 1.3 cipher suites (colon-separated)
      --ciphers <NOTATION>             Show the negotiated cipher suite in [iana, openssl] notation
      --starttls <PROTOCOL>            Upgrade a plaintext connection before TLS
                                       [smtp, imap, pop3, ftp]
      --no-verify                      Disable TLS verification (insecure)
      --timeout <SECONDS>              Connection timeout (default: 10)
      --read-timeout <SECONDS>         Read timeout (default: 5)
      --sni <HOSTNAME>                 Override SNI hostname
      --connect-to <IP>                Dial this IP instead of resolving DNS
                                       (hostname still used for SNI/validation)
      --fingerprint                    Show SHA-256 fingerprints
      --extensions                     Show certificate extensions
      --expiry-warn <DAYS>             Warn if expiring within N days (exit code 1)
      --diff                           Compare certificates between two targets
      --watch <SECONDS>                Re-check at interval
      --compliance                      Run compliance checks (CA/B Forum, DigiCert, X9)
      --check-revocation               Check OCSP revocation status
      --no-trust-check                 Skip root-CA trust classification (on by default)
      --resolve-issuers                Follow AIA "CA Issuers" URLs over the network to
                                       complete a chain / probe a private CA backend (off by default)
      --issuer-timeout <SECONDS>       Short timeout for issuer/refresh fetches (default: 2)
      --refresh-public-roots           Refresh the embedded Mozilla/CCADB root set from
                                       https://curl.se/ca/cacert.pem for this run
      --debug                          Verbose OSI-layer diagnostics on stderr
      --client-cert <PATH>             Client certificate PEM for mTLS
      --client-key <PATH>              Client private key PEM for mTLS
      --pkcs12 <PATH>                  PKCS12/PFX file for mTLS (alternative to --client-cert/--client-key)
      --cert-password <PASS>           PKCS12 password (env: DCERT_CERT_PASSWORD)
      --ca-cert <PATH>                 Custom CA bundle PEM (overrides system CAs)
  -h, --help                           Print help
  -V, --version                        Print version

Exit Codes

Code Meaning
0 Success -- all certificates valid
1 Expiry warning -- certificate(s) expiring within --expiry-warn threshold
2 Error -- connection failure, file not found, or processing error
3 TLS verification failed
4 Certificate expired
5 Certificate revoked (OCSP)
6 Client certificate error (invalid, unreadable, wrong password) — also returned when the server requires mTLS but no --client-cert / --pkcs12 was supplied
7 Key mismatch (private key doesn't match certificate)

dcert csr -- CSR Creation & Validation

Create PKCS#10 Certificate Signing Requests (CSRs) and validate existing CSRs for compliance with CA/B Forum Baseline Requirements, DigiCert, and X9 standards.

Create a CSR

# RSA 4096 (default) — guided interactive mode (omit --cn)
dcert csr create

# RSA 4096 with subject fields
dcert csr create --cn api.example.com --org "My Corp" --country GB

# ECDSA P-256 (recommended modern) with multiple SANs
dcert csr create --cn www.example.com --key-algo ecdsa-p256 \
  --san DNS:www.example.com --san DNS:example.com --san IP:10.0.0.1

# Encrypted private key
dcert csr create --cn secure.example.com --encrypt-key --key-password "$(read -sp 'Password: ' p && echo $p)"

# Custom output paths and JSON output
dcert csr create --cn api.example.com --csr-out api.csr --key-out api.key --format json

# OU metadata identifiers (for internal/private PKI)
dcert csr create --cn app.internal.corp --ou "AppId:my-service-123" --ou "Team:Platform"

Validate a CSR

# Pretty compliance report
dcert csr validate my-cert.csr

# JSON output (for CI/CD pipelines)
dcert csr validate my-cert.csr --format json

# Treat warnings as errors (--strict is a deprecated alias)
dcert csr validate my-cert.csr --warnings-as-errors

Key Algorithm Options

Algorithm Flag Description
RSA 4096 --key-algo rsa-4096 Default. Strong, widely compatible.
RSA 2048 --key-algo rsa-2048 Minimum accepted by CAs.
ECDSA P-256 --key-algo ecdsa-p256 Recommended modern choice. Faster, equivalent to RSA 3072.
ECDSA P-384 --key-algo ecdsa-p384 High-security requirements.
Ed25519 --key-algo ed25519 Modern EdDSA. Compact signatures, high performance. Requires OpenSSL 3.x.

Compliance Checks

The validator checks against CA/B Forum Baseline Requirements, DigiCert, and X9 standards:

  • Key size: Minimum RSA 2048-bit / ECDSA P-256
  • Signature algorithm: SHA-256+ required, SHA-1 rejected
  • Subject Alternative Names: Required for all modern certificates
  • OU deprecation: Warning for publicly-trusted CAs (CA/B Forum Ballot SC47v2, Sep 2022)
  • Country code: ISO 3166-1 alpha-2 validation
  • CN in SAN: CN should be included in SANs per RFC 6125

Full Options Reference

dcert csr create [OPTIONS]

Options:
      --cn <NAME>          Common Name (FQDN). Omit for interactive mode.
      --org <NAME>         Organization (O)
      --ou <NAME>          Organizational Unit (repeatable, supports metadata e.g., "AppId:xxx")
      --country <CODE>     Two-letter country code (e.g., GB, US)
      --state <NAME>       State or province (ST)
      --locality <NAME>    City or locality (L)
      --email <EMAIL>      Email address
      --san <TYPE:VALUE>   Subject Alternative Name (repeatable, e.g., DNS:www.example.com, IP:10.0.0.1)
      --key-algo <ALGO>    Key algorithm [rsa-4096, rsa-2048, ecdsa-p256, ecdsa-p384, ed25519] (default: rsa-4096)
      --encrypt-key        Encrypt the private key (AES-256-CBC, PKCS#8)
      --key-password <PW>  Password for key encryption (env: DCERT_KEY_PASSWORD)
      --csr-out <FILE>     Output CSR file path (default: <cn>.csr)
      --key-out <FILE>     Output key file path (default: <cn>.key)
  -f, --format <FORMAT>    Output format [pretty, json, yaml] (default: pretty)

dcert csr validate [OPTIONS] <CSR_FILE>

Arguments:
  <CSR_FILE>              PEM-encoded CSR file to validate

Options:
      --warnings-as-errors  Treat warnings as errors (alias: --strict)
  -f, --format <FORMAT>   Output format [pretty, json, yaml] (default: pretty)

dcert convert -- Format Conversion

Convert between certificate formats. Four modes are available:

pfx-to-pem

Extract certificate, key, and CA chain from a PKCS12/PFX file into separate PEM files.

dcert convert pfx-to-pem server.pfx --password secret --output-dir ./certs
# Produces: ./certs/cert.pem, ./certs/key.pem, ./certs/ca.pem (if CA certs present)

pem-to-pfx

Bundle PEM certificate and private key into a PKCS12/PFX file.

dcert convert pem-to-pfx --cert server.pem --key server-key.pem --output server.pfx --password secret

# Include CA chain
dcert convert pem-to-pfx --cert server.pem --key server-key.pem --ca ca-chain.pem --output server.pfx --password secret

create-keystore

Create a PKCS12 keystore from PEM certificate and key (Java-compatible since JDK 9, where PKCS12 is the default keystore type).

dcert convert create-keystore --cert server.pem --key server-key.pem --output keystore.p12 --password changeit --alias myserver

# Print a beginner primer about keystores before creating one (useful when
# handing instructions to external partners)
dcert convert create-keystore --explain --cert server.pem --key server-key.pem --output keystore.p12 --password changeit

dcert warns if the cert PEM contains only a leaf with no intermediates (Java clients usually need the full chain), or if the first cert is a CA rather than the leaf (wrong order).

To convert to JKS format if needed:

keytool -importkeystore -srckeystore keystore.p12 -srcstoretype PKCS12 -destkeystore keystore.jks -deststoretype JKS

create-truststore

Create a PKCS12 truststore from CA certificate PEM files. By default dcert rejects leaf (server) certificates — a truststore should hold trust anchors (CAs), not the server's own cert. The error message points to --allow-non-ca if you really need to override.

# Standard truststore from CA chain
dcert convert create-truststore ca1.pem ca2.pem --output truststore.p12 --password changeit

# Beginner primer (six-line explanation of truststores + CA rotation)
dcert convert create-truststore --explain ca1.pem --output truststore.p12

# Override the leaf-rejection guard (advanced, rarely correct)
dcert convert create-truststore --allow-non-ca cert-with-leaf.pem --output truststore.p12

# Machine-readable JSON output (for scripts and the MCP layer)
dcert convert --format json create-truststore ca1.pem --output truststore.p12

The pretty default output prints a pre-flight table with each cert's role ([ROOT] / [INTERMEDIATE] / [LEAF]), expiry, and SHA-256 fingerprint, plus warnings for duplicates, expired CAs, and CA-rotation cases (two CAs with the same subject CN but different fingerprints).


dcert verify-key -- Key Matching

Verify that a private key matches a certificate. Works with PEM files and HTTPS endpoints. When run without arguments, auto-discovers matching cert/key pairs in the current directory.

# Verify a specific pair
dcert verify-key cert.pem --key private.key

# Verify against an HTTPS endpoint
dcert verify-key https://example.com --key private.key

# Auto-discover all cert/key pairs in the current directory
dcert verify-key

# Auto-discover in a specific directory
dcert verify-key --dir /etc/ssl/certs

# JSON output
dcert verify-key cert.pem --key private.key --format json
dcert verify-key --format json

Auto-discovery scans for .crt and .pem files that have a matching .key file with the same base name (e.g. server.crt + server.key, app.pem + app.key). Files without a matching key are skipped.

Returns key type, key size, certificate subject, and whether the key matches. Exit code 7 on mismatch.


dcert vault -- HashiCorp Vault PKI

Issue, sign, revoke, list, store, validate, and renew TLS certificates using HashiCorp Vault's PKI Secrets Engine. Supports interactive wizard mode (omit required args) or fully non-interactive CLI usage.

Prerequisites

Set these environment variables before using vault commands:

Variable Required Description
VAULT_ADDR Yes Vault server URL (e.g., https://vault.example.com:8200)
VAULT_TOKEN No* Vault authentication token (for --auth-method token)
VAULT_CACERT No Custom CA certificate PEM file for Vault TLS
VAULT_CAPATH No Directory of CA PEM files for Vault TLS
VAULT_SKIP_VERIFY No Set to 1 to skip TLS verification (insecure)
SSL_CERT_FILE No Fallback CA cert file (used if VAULT_CACERT is not set)
SSL_CERT_DIR No Fallback CA cert directory (used if VAULT_CAPATH is not set)
DCERT_LDAP_USERNAME / DCERT_LDAP_PASSWORD No Credentials for --auth-method ldap
DCERT_APPROLE_ROLE_ID / DCERT_APPROLE_SECRET_ID No Credentials for --auth-method approle

* Token is discovered in order: VAULT_TOKEN env var, then ~/.vault-token file.

Authentication Methods

By default dcert authenticates with a Vault token. LDAP and AppRole logins are also supported via --auth-method:

# LDAP login (credentials via flags or DCERT_LDAP_USERNAME / DCERT_LDAP_PASSWORD)
dcert vault --auth-method ldap --ldap-username alice issue --cn www.example.com --role my-role

# AppRole login (credentials via flags or DCERT_APPROLE_ROLE_ID / DCERT_APPROLE_SECRET_ID)
dcert vault --auth-method approle \
  --approle-role-id "$ROLE_ID" --approle-secret-id "$SECRET_ID" \
  issue --cn www.example.com --role my-role

TLS configuration: By default, dcert uses your system's native CA store. For corporate Vault servers using internal CAs, set VAULT_CACERT or SSL_CERT_FILE to point to your CA bundle. Use --debug to diagnose TLS issues:

# Use a custom CA certificate
export VAULT_CACERT=/path/to/corporate-ca.pem
dcert vault issue --cn www.example.com --role my-role

# Or via CLI flag
dcert vault --vault-cacert /path/to/ca.pem issue --cn www.example.com --role my-role

# Debug TLS connectivity issues
dcert vault --debug issue --cn www.example.com --role my-role

# Skip TLS verification (insecure, for testing only)
dcert vault --skip-verify issue --cn www.example.com --role my-role

Role Discovery

If --role is not provided, dcert looks up your token's policies (vault token lookup-self) and extracts role names from policies that follow a dotted naming convention (prefix.rolename.permission). The second segment is used as the role name. If multiple roles are found, you are prompted to select one.

Issue a Certificate

Vault generates a new private key and certificate via the PKI engine.

# Interactive wizard (guided step-by-step)
dcert vault issue

# Non-interactive with all options
dcert vault issue --cn www.example.com --role my-role \
  --san "DNS:*.example.com" --ip-san 10.0.0.1 --ttl 8760h

# Output as PFX instead of PEM
dcert vault issue --cn www.example.com --role my-role --pfx-password secret

# Issue and store in Vault KV
dcert vault issue --cn www.example.com --role my-role \
  --store-path secret/company/project/certs/www-example-com

# Custom PKI mount point
dcert vault issue --cn www.example.com --role my-role --mount pki_intermediate

Sign a CSR

Submit an existing CSR to Vault PKI for signing (no private key is generated).

# Interactive wizard
dcert vault sign

# Non-interactive
dcert vault sign --csr-file server.csr --role my-role --ttl 8760h

# Override CN from CSR
dcert vault sign --csr-file server.csr --role my-role --cn override.example.com

# Sign with IP SANs
dcert vault sign --csr-file server.csr --role my-role --ip-san 10.0.0.1 --ip-san 192.168.1.1

Revoke a Certificate

# Revoke by serial number
dcert vault revoke --serial "1a:2b:3c:4d:5e"

# Revoke by PEM certificate file
dcert vault revoke --cert-file server.crt

List Certificates

# List all issued certificates (serial numbers only)
dcert vault list

# Fetch and display details for each certificate
dcert vault list --show-details

# Filter by status
dcert vault list --show-details --expired-only
dcert vault list --show-details --valid-only

# Export to JSON, CSV, or Excel
dcert vault list --show-details --export certs.json
dcert vault list --show-details --export certs.csv
dcert vault list --show-details --export certs.xlsx

# JSON output
dcert vault list --show-details --format json

Store in Vault KV

Store a local certificate and private key in Vault KV (v1 by default, v2 with --kv-version 2).

dcert vault store --cert-file server.crt --key-file server.key \
  secret/company/project/certs/www-example-com

# Use KV v2
dcert vault store --cert-file server.crt --key-file server.key \
  --kv-version 2 secret/company/project/certs/www-example-com

# Custom key names in KV
dcert vault store --cert-file server.crt --key-file server.key \
  --cert-key tls_cert --key-key tls_key \
  secret/company/project/certs/www-example-com

Validate from Vault KV

Read a certificate and key from Vault KV, validate them, and display certificate details (same output as dcert check). Also verifies the private key matches the certificate.

dcert vault validate secret/company/project/certs/www-example-com

# Custom key names
dcert vault validate secret/company/project/certs/www-example-com \
  --cert-key tls_cert --key-key tls_key

# JSON output
dcert vault validate secret/company/project/certs/www-example-com --format json

Renew a Certificate

Read an existing certificate from Vault KV, extract its CN and SANs, issue a new certificate with the same parameters, and overwrite the KV entry. Optionally override SANs or IP SANs.

dcert vault renew secret/company/project/certs/www-example-com --role my-role

# Custom TTL and mount
dcert vault renew secret/company/project/certs/www-example-com \
  --role my-role --ttl 2160h --mount pki_intermediate

# Override SANs on renew
dcert vault renew secret/company/project/certs/www-example-com --role my-role \
  --san app.example.com --ip-san 10.0.0.1

Permission Errors

All Vault API calls produce clear, actionable error messages on permission denial:

Error: Permission denied by Vault.

  Endpoint: POST vault_intermediate/issue/my-role
  Required: create capability on "vault_intermediate/issue/my-role"

  Ask your Vault administrator to add this policy to your token:
    path "vault_intermediate/issue/my-role" {
      capabilities = ["create"]
    }

Full Options Reference

dcert vault [GLOBAL OPTIONS] <SUBCOMMAND> [OPTIONS]

Global Vault Options:
      --skip-verify              Skip TLS verification (insecure). Also: VAULT_SKIP_VERIFY=1
      --vault-cacert <PATH>      Custom CA certificate PEM file. Also: VAULT_CACERT env var
      --auth-method <METHOD>     Vault auth method [token, ldap, approle] (default: token)
      --ldap-username <USER>     LDAP username (env: DCERT_LDAP_USERNAME)
      --ldap-password <PASS>     LDAP password (env: DCERT_LDAP_PASSWORD)
      --ldap-mount <MOUNT>       LDAP auth mount (default: ldap)
      --approle-role-id <ID>     AppRole role ID (env: DCERT_APPROLE_ROLE_ID)
      --approle-secret-id <ID>   AppRole secret ID (env: DCERT_APPROLE_SECRET_ID)
      --approle-mount <MOUNT>    AppRole auth mount (default: approle)
      --debug                    Show verbose TLS and API diagnostics

dcert vault issue [OPTIONS]
      --cn <NAME>           Common Name. Omit for interactive wizard.
      --san <SAN>           Subject Alternative Names (repeatable)
      --ip-san <IP>         IP SANs (repeatable)
      --ttl <TTL>           Certificate TTL (default: 8760h)
      --role <ROLE>         Vault PKI role name
      --mount <MOUNT>       Vault PKI mount point (default: vault_intermediate)
      --output <NAME>       Output file base name (default: sanitised CN)
  -f, --format <FORMAT>     Output format [pretty, json, yaml]
      --pfx-password <PW>   Output as PFX instead of PEM (env: DCERT_CERT_PASSWORD)
      --store-path <PATH>   Store cert+key in Vault KV after issuance
      --kv-version <1|2>    Vault KV version for --store-path (default: 1)

dcert vault sign [OPTIONS]
      --csr-file <FILE>     CSR PEM file. Omit for interactive wizard.
      --cn <NAME>           Override CN from CSR
      --san <SAN>           Additional SANs (repeatable)
      --ip-san <IP>         IP SANs (repeatable)
      --ttl <TTL>           Certificate TTL (default: 8760h)
      --role <ROLE>         Vault PKI role name
      --mount <MOUNT>       PKI mount point (default: vault_intermediate)
      --output <NAME>       Output file base name
  -f, --format <FORMAT>     Output format [pretty, json, yaml]
      --pfx-password <PW>   Output as PFX instead of PEM (env: DCERT_CERT_PASSWORD)
      --store-path <PATH>   Store certificate in Vault KV after signing
      --kv-version <1|2>    Vault KV version for --store-path (default: 1)

dcert vault revoke [OPTIONS]
      --serial <SERIAL>     Certificate serial number (hex, colon or hyphen-separated)
      --cert-file <FILE>    PEM certificate file to revoke
      --mount <MOUNT>       PKI mount point (default: vault_intermediate)

dcert vault list [OPTIONS]
      --mount <MOUNT>       PKI mount point (default: vault_intermediate)
  -f, --format <FORMAT>     Output format [pretty, json, yaml]
      --show-details        Fetch details for each certificate
      --expired-only        Show only expired certificates
      --valid-only          Show only valid certificates
      --export <FILE>       Export to JSON, CSV, or XLSX file

dcert vault store [OPTIONS] <PATH>
      --cert-file <FILE>    Local PEM certificate file (required)
      --key-file <FILE>     Local PEM private key file (required)
      --cert-key <NAME>     KV key name for certificate (default: cert)
      --key-key <NAME>      KV key name for private key (default: key)
      --kv-version <1|2>    Vault KV version (default: 1)

dcert vault validate [OPTIONS] <PATH>
      --cert-key <NAME>     KV key name for certificate (default: cert)
      --key-key <NAME>      KV key name for private key (default: key)
      --kv-version <1|2>    Vault KV version (default: 1)
  -f, --format <FORMAT>     Output format [pretty, json, yaml]

dcert vault renew [OPTIONS] <PATH>
      --role <ROLE>         PKI role name for issuing new certificate
      --mount <MOUNT>       PKI mount point (default: vault_intermediate)
      --ttl <TTL>           TTL for new certificate (default: 8760h)
      --cert-key <NAME>     KV key name for certificate (default: cert)
      --key-key <NAME>      KV key name for private key (default: key)
      --kv-version <1|2>    Vault KV version (default: 1)
      --san <SAN>           Override SANs from existing cert (repeatable)
      --ip-san <IP>         Override IP SANs from existing cert (repeatable)
  -f, --format <FORMAT>     Output format [pretty, json, yaml]

MCP Server (AI IDE Integration)

dcert-mcp is a Model Context Protocol server that exposes dcert's capabilities as tools for AI-powered IDEs. It supports two transport modes: stdio (default, for IDE integration) and HTTP (for remote deployment with optional OIDC/OAuth2 authentication).

It implements the current MCP specification revision (2025-11-25) via the rmcp SDK. On the HTTP transport it negotiates the protocol version with the client: it echoes the client's requested version when supported and otherwise advertises the latest version it implements.

Tools

Tool Description
analyze_certificate Decode and analyze TLS certificates. Returns subject, issuer, SANs, validity, fingerprints, extensions, TLS connection info, and OSI-layer diagnostics. Supports mTLS.
check_expiry Check if certificates expire within N days. Returns ALL_VALID, EXPIRING_SOON, or ALREADY_EXPIRED. Supports mTLS.
check_revocation Check OCSP revocation status via the certificate's OCSP responder. Supports mTLS.
compare_certificates Compare certificates between two targets side-by-side.
tls_connection_info Get TLS connection details: protocol, cipher, ALPN, latency, verification, diagnostics. Supports mTLS.
export_pem Export TLS certificate chain from an HTTPS endpoint as PEM. Optionally saves to file and can exclude expired certs. Supports mTLS.
create_csr Create a PKCS#10 CSR and private key. Supports RSA/ECDSA, OU metadata, and encrypted keys. Compliant with CA/B Forum, DigiCert, and X9 standards.
validate_csr Validate a CSR for compliance with CA/B Forum Baseline Requirements, DigiCert, and X9 standards. Returns findings with severity levels.
validate_certificate Run compliance checks on a certificate (PEM file or HTTPS endpoint). Checks key size, signature algorithm, validity period, SANs, CT, EKU, and Basic Constraints against CA/B Forum standards.
verify_key_match Verify that a private key matches a certificate (PEM file or HTTPS endpoint).
verify_key_auto_discover Auto-discover and verify all matching cert/key pairs in a directory.
convert_pfx_to_pem Convert PKCS12/PFX to separate PEM files (cert, key, CA chain).
convert_pem_to_pfx Convert PEM certificate + key to PKCS12/PFX file.
create_keystore Create a PKCS12 keystore from PEM cert + key (Java-compatible).
create_truststore Create a PKCS12 truststore from CA certificate PEM