Skip to content

Instantly share code, notes, and snippets.

@mcarbonneaux
Last active May 29, 2025 13:42
Show Gist options
  • Save mcarbonneaux/2b92761b13e17e46c20e34e9de5771a9 to your computer and use it in GitHub Desktop.
Save mcarbonneaux/2b92761b13e17e46c20e34e9de5771a9 to your computer and use it in GitHub Desktop.
openapi: 3.0.3
info:
title: Smallstep Certificates API
description: |
A private certificate authority (X.509 & SSH) & ACME server for secure automated certificate management.
This API allows you to:
- Issue and manage X.509 TLS certificates
- Handle SSH certificates
- Manage certificate renewal and revocation
- Perform health checks and get CA information
## Authentication
Most endpoints require JWT token authentication or mTLS client certificates.
## Base URL Structure
The API is typically served on `https://your-ca-server:port/1.0/`
version: "1.0"
contact:
name: Smallstep Labs
url: https://smallstep.com
license:
name: Apache 2.0
url: https://github.com/smallstep/certificates/blob/master/LICENSE
servers:
- url: https://localhost:9000/1.0
description: Default local step-ca server
- url: https://ca.example.com/1.0
description: Production CA server
security:
- BearerAuth: []
- mTLS: []
paths:
/health:
get:
summary: Health Check
description: Check the health status of the CA server
operationId: getHealth
tags:
- Health
security: []
responses:
'200':
description: CA server is healthy
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: "ok"
time:
type: string
format: date-time
'500':
$ref: '#/components/responses/InternalServerError'
/root/{fingerprint}:
get:
summary: Get Root Certificate
description: Retrieve the root certificate by fingerprint
operationId: getRootCertificate
tags:
- Certificates
security: []
parameters:
- name: fingerprint
in: path
required: true
description: SHA256 fingerprint of the root certificate
schema:
type: string
example: "a1b2c3d4e5f6..."
responses:
'200':
description: Root certificate in PEM format
content:
application/pem-certificate-chain:
schema:
type: string
format: binary
example: |
-----BEGIN CERTIFICATE-----
MIIBkTCB+wIJAK...
-----END CERTIFICATE-----
'404':
$ref: '#/components/responses/NotFound'
/roots:
get:
summary: Get Root Certificates
description: Retrieve all root certificates
operationId: getRootCertificates
tags:
- Certificates
security: []
responses:
'200':
description: List of root certificates
content:
application/json:
schema:
type: object
properties:
crts:
type: array
items:
type: string
description: PEM-encoded certificate
example: |
-----BEGIN CERTIFICATE-----
MIIBkTCB+wIJAK...
-----END CERTIFICATE-----
/sign:
post:
summary: Sign Certificate Request
description: |
Sign a Certificate Signing Request (CSR) and return a signed certificate.
This is the primary endpoint for certificate issuance.
operationId: signCertificate
tags:
- Certificates
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SignRequest'
examples:
basic_tls:
summary: Basic TLS Certificate Request
value:
csr: "-----BEGIN CERTIFICATE REQUEST-----\nMIICWjCCAUICAQAwFTETMBEGA1UEAwwKZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3\n..."
ott: "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9..."
with_provisioner:
summary: Request with Specific Provisioner
value:
csr: "-----BEGIN CERTIFICATE REQUEST-----\nMIICWjCCAUICAQAwFTETMBEGA1UEAwwKZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3\n..."
ott: "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9..."
provisioner: "my-provisioner"
responses:
'201':
description: Certificate successfully signed
content:
application/json:
schema:
$ref: '#/components/schemas/SignResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
/renew:
post:
summary: Renew Certificate
description: |
Renew an existing certificate. The request must be authenticated with the
current certificate that needs to be renewed.
operationId: renewCertificate
tags:
- Certificates
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RenewRequest'
responses:
'201':
description: Certificate successfully renewed
content:
application/json:
schema:
$ref: '#/components/schemas/SignResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/revoke:
post:
summary: Revoke Certificate
description: Revoke a certificate using its serial number or certificate PEM
operationId: revokeCertificate
tags:
- Certificates
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RevokeRequest'
responses:
'200':
description: Certificate successfully revoked
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: "ok"
message:
type: string
example: "Certificate revoked"
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/provisioners:
get:
summary: List Provisioners
description: Get list of configured provisioners
operationId: getProvisioners
tags:
- Provisioners
parameters:
- name: cursor
in: query
description: Pagination cursor
schema:
type: string
- name: limit
in: query
description: Maximum number of items to return
schema:
type: integer
minimum: 1
maximum: 100
default: 20
responses:
'200':
description: List of provisioners
content:
application/json:
schema:
type: object
properties:
provisioners:
type: array
items:
$ref: '#/components/schemas/Provisioner'
nextCursor:
type: string
description: Cursor for next page
/ssh/sign:
post:
summary: Sign SSH Certificate
description: Sign an SSH public key and return an SSH certificate
operationId: signSSHCertificate
tags:
- SSH Certificates
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SSHSignRequest'
responses:
'201':
description: SSH certificate successfully signed
content:
application/json:
schema:
$ref: '#/components/schemas/SSHSignResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/ssh/renew:
post:
summary: Renew SSH Certificate
description: Renew an existing SSH certificate
operationId: renewSSHCertificate
tags:
- SSH Certificates
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SSHRenewRequest'
responses:
'201':
description: SSH certificate successfully renewed
content:
application/json:
schema:
$ref: '#/components/schemas/SSHSignResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/ssh/revoke:
post:
summary: Revoke SSH Certificate
description: Revoke an SSH certificate
operationId: revokeSSHCertificate
tags:
- SSH Certificates
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SSHRevokeRequest'
responses:
'200':
description: SSH certificate successfully revoked
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: "ok"
/ssh/config:
get:
summary: Get SSH Configuration
description: Get SSH configuration for clients
operationId: getSSHConfig
tags:
- SSH Certificates
parameters:
- name: type
in: query
description: Configuration type (user or host)
schema:
type: string
enum: [user, host]
default: user
- name: template
in: query
description: Template name for configuration
schema:
type: string
responses:
'200':
description: SSH configuration
content:
application/json:
schema:
$ref: '#/components/schemas/SSHConfigResponse'
/ssh/check-host:
post:
summary: Check SSH Host
description: Check if an SSH host is valid and get host certificate
operationId: checkSSHHost
tags:
- SSH Certificates
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
host:
type: string
description: Hostname to check
example: "example.com"
port:
type: string
description: Port number
default: "22"
responses:
'200':
description: Host check result
content:
application/json:
schema:
type: object
properties:
exists:
type: boolean
certificate:
type: string
description: SSH host certificate if available
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: JWT token for authentication
mTLS:
type: mutualTLS
description: Mutual TLS authentication using client certificates
schemas:
SignRequest:
type: object
required:
- csr
- ott
properties:
csr:
type: string
description: PEM-encoded Certificate Signing Request
example: |
-----BEGIN CERTIFICATE REQUEST-----
MIICWjCCAUICAQAwFTETMBEGA1UEAwwKZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3
...
-----END CERTIFICATE REQUEST-----
ott:
type: string
description: One-time token (JWT) for authentication
example: "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9..."
provisioner:
type: string
description: Name of the provisioner to use
example: "my-provisioner"
SignResponse:
type: object
properties:
crt:
type: string
description: PEM-encoded signed certificate
example: |
-----BEGIN CERTIFICATE-----
MIIBkTCB+wIJAK...
-----END CERTIFICATE-----
ca:
type: string
description: PEM-encoded CA certificate
example: |
-----BEGIN CERTIFICATE-----
MIIBkTCB+wIJAK...
-----END CERTIFICATE-----
certChain:
type: array
items:
type: string
description: Full certificate chain
RenewRequest:
type: object
properties:
crt:
type: string
description: PEM-encoded certificate to renew
example: |
-----BEGIN CERTIFICATE-----
MIIBkTCB+wIJAK...
-----END CERTIFICATE-----
RevokeRequest:
type: object
required:
- serial
properties:
serial:
type: string
description: Serial number of certificate to revoke
example: "123456789"
crt:
type: string
description: PEM-encoded certificate to revoke (alternative to serial)
reason:
type: string
description: Reason for revocation
enum:
- unspecified
- keyCompromise
- caCompromise
- affiliationChanged
- superseded
- cessationOfOperation
- certificateHold
- removeFromCRL
- privilegeWithdrawn
- aaCompromise
default: unspecified
reasonCode:
type: integer
description: Numeric reason code
minimum: 0
maximum: 10
passiveOnly:
type: boolean
description: Passive revocation only (don't add to CRL)
default: false
Provisioner:
type: object
properties:
name:
type: string
description: Provisioner name
example: "my-provisioner"
type:
type: string
description: Provisioner type
enum: [JWK, OIDC, X5C, K8sSA, SSHPOP, ACME, SCEP, Nebula, AWS, Azure, GCP]
example: "JWK"
key:
type: object
description: Provisioner key configuration
encryptedKey:
type: string
description: Encrypted provisioner key
claims:
type: object
description: Provisioner claims and constraints
properties:
minTLSCertDuration:
type: string
example: "1h"
maxTLSCertDuration:
type: string
example: "8760h"
defaultTLSCertDuration:
type: string
example: "24h"
SSHSignRequest:
type: object
required:
- publicKey
- ott
properties:
publicKey:
type: string
description: SSH public key to sign
example: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQ..."
ott:
type: string
description: One-time token for authentication
validAfter:
type: string
description: Certificate valid after (RFC3339 format)
validBefore:
type: string
description: Certificate valid before (RFC3339 format)
certType:
type: string
enum: [user, host]
default: user
keyID:
type: string
description: Key identifier for the certificate
principals:
type: array
items:
type: string
description: List of principals (usernames/hostnames)
SSHSignResponse:
type: object
properties:
certificate:
type: string
description: SSH certificate
example: "[email protected] AAAAB3NzaC1yc2..."
identities:
type: array
items:
$ref: '#/components/schemas/SSHIdentity'
SSHIdentity:
type: object
properties:
type:
type: string
enum: [user, host]
certificate:
type: string
description: SSH certificate
config:
type: string
description: SSH configuration snippet
SSHRenewRequest:
type: object
required:
- certificate
properties:
certificate:
type: string
description: SSH certificate to renew
SSHRevokeRequest:
type: object
required:
- serial
properties:
serial:
type: string
description: Serial number of SSH certificate to revoke
SSHConfigResponse:
type: object
properties:
config:
type: string
description: SSH configuration content
example: |
Host *
UserKnownHostsFile ~/.ssh/known_hosts ~/.ssh/known_hosts_ca
CertificateFile ~/.ssh/id_ecdsa-cert.pub
Error:
type: object
properties:
status:
type: integer
description: HTTP status code
message:
type: string
description: Error message
details:
type: string
description: Additional error details
responses:
BadRequest:
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
status: 400
message: "Invalid request format"
Unauthorized:
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
status: 401
message: "Authentication required"
Forbidden:
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
status: 403
message: "Access denied"
NotFound:
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
status: 404
message: "Resource not found"
InternalServerError:
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
status: 500
message: "Internal server error"
tags:
- name: Health
description: Health check operations
- name: Certificates
description: X.509 certificate operations
- name: SSH Certificates
description: SSH certificate operations
- name: Provisioners
description: Provisioner management operations
externalDocs:
description: Smallstep Certificates Documentation
url: https://smallstep.com/docs/step-ca/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment