Skip to content

Smallstep Step-CA

Integrate Smallstep Step-CA with SSL-CLM to:

  • Issue certificates
  • Renew certificates
  • Revoke certificates
  • Sync certificate inventory
  • Use secure JWK-based authentication (One-Time Tokens)

Step-CA integrates directly via its REST API. No agent is required — the platform communicates with the CA from the backend.


SSL-CLM Platform (Backend)
│
│ (HTTPS + JWK-signed One-Time Tokens)
▼
Smallstep Step-CA (REST API)
│
▼
Internal Certificate Authority

  • Smallstep Step-CA installed and running
  • A JWK provisioner configured for SSL-CLM
  • Network access from the SSL-CLM platform to the Step-CA API
  • The provisioner private key (JWK format)

Install the Smallstep CLI on your CA server:

https://smallstep.com/docs/step-cli/installation

Verify:

Terminal window
step version

If you don’t already have a running Step-CA:

Terminal window
step ca init \
--name "Internal CA" \
--dns step-ca.internal.corp \
--address :9000 \
--provisioner admin@company.com \
--password-file step-ca-password.txt

Start the CA:

Terminal window
step-ca $(step path)/config/ca.json

The API will be available at:

https://step-ca.internal.corp:9000

Step 3 — Create a JWK Provisioner for SSL-CLM

Section titled “Step 3 — Create a JWK Provisioner for SSL-CLM”

Create a dedicated provisioner for the SSL-CLM platform (separate from any admin provisioner):

Terminal window
# Generate EC P-256 key pair
step crypto jwk create clm-pub.json clm-priv.json \
--kty EC \
--crv P-256 \
--no-password \
--insecure
# Add provisioner to Step-CA
step ca provisioner add clm@company.com \
--type JWK \
--public-key clm-pub.json

Verify it’s registered:

Terminal window
step ca provisioner list

Step 4 — Get the Private Key for SSL-CLM

Section titled “Step 4 — Get the Private Key for SSL-CLM”

View the provisioner private key:

Terminal window
cat clm-priv.json

Output (example):

{
"kty": "EC",
"crv": "P-256",
"kid": "pA46iGmXmpipV4HmqlvozxPde7VNavSdLZmiaEa5iyA",
"x": "...",
"y": "...",
"d": "..."
}

You will paste this into the SSL-CLM CA configuration. The platform stores it encrypted in the vault.


Step 5 — Add the Certificate Authority in SSL-CLM

Section titled “Step 5 — Add the Certificate Authority in SSL-CLM”
  1. Navigate to Infrastructure → Certificate Authorities
  2. Click + Add CA
  3. Select Smallstep CA from the type cards
  4. Fill in the configuration:

Connection:

FieldDescriptionExample
NameFriendly display nameSmallstep Internal CA
CA Base URLStep-CA API base URLhttps://step-ca.internal.corp:9000
API PathAPI version path (usually /1.0)/1.0

Authentication:

FieldDescriptionExample
Provisioner NameJWK provisioner name (iss claim)clm@company.com
Provisioner Key IDJWK key ID (kid header) — optional, auto-extracted from JWKpA46iGmX...
Provisioner Private Key (JWK)Full JWK private key JSON (stored encrypted in vault){"kty":"EC","crv":"P-256",...}

Advanced:

FieldDescriptionExample
OTT TTL (seconds)One-Time Token time-to-live300 (default)
Discovery IntervalHours between inventory syncs24
  1. Click Save

The platform stores the JWK private key securely in the vault. It generates short-lived One-Time Tokens (OTTs) at runtime for each operation — the key itself is never exposed.


  1. Navigate to Certificates → + New Certificate
  2. Select Issue from CA
  3. Choose the Smallstep CA
  4. Enter Common Name and SANs
  5. Click Submit

Flow:

  1. Platform generates a CSR
  2. Platform signs an OTT using the provisioner JWK (valid for 5 minutes)
  3. Platform calls Step-CA’s /sign endpoint with the CSR + OTT
  4. Step-CA validates the OTT and issues the certificate
  5. Certificate is stored in inventory

When revocation is requested:

  1. Platform signs an OTT for the revocation operation
  2. Platform calls Step-CA’s revoke endpoint
  3. Certificate status updated to REVOKED

SSL-CLM uses One-Time Tokens (OTTs) for every operation with Step-CA:

1. Platform loads the provisioner JWK private key from vault
2. Platform creates a JWT with:
- iss: provisioner name (e.g., "clm@company.com")
- sub: certificate CN being requested
- aud: Step-CA API URL
- exp: current time + TTL (300s)
- jti: unique token ID
3. JWT is signed with the provisioner's private key
4. JWT is sent to Step-CA as the authorization token
5. Step-CA validates the JWT against the provisioner's public key
6. Operation is executed
7. JWT cannot be reused (one-time)

This means no long-lived credentials are transmitted — each request gets a fresh, short-lived token.


PrincipleImplementation
No stored passwordsAuthentication via cryptographic key signing (JWK)
Short-lived tokensOTTs expire in 5 minutes and are single-use
Key in vaultProvisioner private key stored encrypted, never in config files
Separate provisionersUse a dedicated provisioner for SSL-CLM, separate from admin CLI
EC P-256Recommended key type for provisioners

IssuePossible CauseResolution
”Unauthorized” errorWrong provisioner name or kid mismatchVerify provisioner name matches exactly; check kid in the JWK
”Connection refused”Step-CA not running or wrong portConfirm Step-CA is running; verify base URL and port
”Provisioner not found”Provisioner not registered in Step-CARun step ca provisioner list to verify
Certificate not issuedOTT expired (clock skew)Ensure platform server clock is synced (NTP)
TLS handshake failurePlatform doesn’t trust Step-CA’s certificateAdd Step-CA’s root cert as trusted, or disable strict verification

  • Use a dedicated provisioner (clm@company.com) — don’t share with the admin CLI
  • Use EC P-256 keys (fast, secure, small tokens)
  • Set OTT TTL to 300 seconds (5 min) — long enough for network latency, short enough for security
  • Enable scheduled inventory refresh (24h) to keep the platform in sync with Step-CA
  • Rotate provisioner keys periodically — generate a new key pair, update in SSL-CLM, remove the old one from Step-CA
  • Back up the Step-CA PKI directory ($(step path))