Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Smallstep

DSecurity

Expert agent for smallstep step-ca and step CLI. Covers lightweight internal PKI, OIDC-based certificate issuance, short-lived certificates, SSH certificates (user and host), Kubernetes integration, ACME support, and zero-trust patterns. WHEN: \"smallstep\", \"step-ca\", \"step CLI\", \"step certificate\", \"SSH certificate authority\", \"OIDC certificate\", \"short-lived cert\", \"step-ca ACME\", \"step-ca Kubernetes\".

4 stars
0 votes
0 copies
0 views
Added 9/24/2026
devopsrustgobashkubernetesawsgcpazuretestinggitapi

Works with

cliapi

Security Analysis

D46/100
mediumUses curl or wget to download content
criticalAccesses sensitive system or user directories
criticalReads or references SSH private keys
criticalExfiltrates credentials via HTTP — exact pattern from Snyk ToxicSkills study
criticalSends environment variables or credentials to an external URL

Pro shows the line behind each finding and how to fix it

Scanned 9/24/2026

$npx -y skills add chrishuffman5/domain-expert --skill smallstep --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Smallstep?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Smallstep
[![Security: D — Skills Directory](https://www.skillsdirectory.com/api/skills/chrishuffman5-smallstep/badge)](https://www.skillsdirectory.com/skills/chrishuffman5-smallstep)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: smallstep
description: "Expert agent for smallstep step-ca and step CLI. Covers lightweight internal PKI, OIDC-based certificate issuance, short-lived certificates, SSH certificates (user and host), Kubernetes integration, ACME support, and zero-trust patterns. WHEN: \"smallstep\", \"step-ca\", \"step CLI\", \"step certificate\", \"SSH certificate authority\", \"OIDC certificate\", \"short-lived cert\", \"step-ca ACME\", \"step-ca Kubernetes\"."
license: MIT
---

# smallstep step-ca

This skill covers smallstep's step-ca (open-source CA) and step CLI. It has deep knowledge of internal PKI, OIDC-based issuance, short-lived certificates, SSH certificate authority patterns, and Kubernetes integration.

## How to Approach Tasks

1. **Classify the request**:
   - **Setup** — step-ca initialization, first-time configuration
   - **X.509 certificates** — TLS server, client (mTLS), leaf cert patterns
   - **SSH certificates** — User certificates, host certificates, certificate authority setup
   - **OIDC integration** — OIDC provisioner, identity-based issuance
   - **Kubernetes** — Helm deployment, cert-manager integration
   - **ACME** — step-ca as ACME server for internal services
   - **Provisioner configuration** — JWK, OIDC, ACME, K8sSA, AWS, GCP, Azure

2. **Identify use case**: Internal TLS/mTLS, SSH certificate authority, workload identity, or developer certificate automation.

## Why smallstep?

smallstep excels at:
- **Zero-trust internal PKI**: Short-lived certificates (1h-24h) for services
- **SSH certificate authority**: Replace static SSH keys with short-lived certificates
- **OIDC-based issuance**: Use your existing SSO (Okta, Google, Azure AD) to issue certificates
- **Developer experience**: Simple CLI (`step ca certificate`) vs. complex openssl commands
- **Lightweight**: Single binary, runs anywhere, minimal dependencies

---

## Installation

```bash
# Install step CLI
# macOS
brew install step

# Linux
curl -L https://dl.smallstep.com/install/linux/amd64/step/latest/step.tar.gz | tar xz
sudo install step /usr/local/bin/

# Windows (scoop)
scoop bucket add smallstep https://github.com/smallstep/scoop-bucket.git
scoop install step

# Install step-ca
# macOS
brew install step-ca

# Linux
curl -L https://dl.smallstep.com/install/linux/amd64/step-ca/latest/step-ca.tar.gz | tar xz
sudo install step-ca /usr/local/bin/
```

---

## Initializing a CA

```bash
# Initialize a new CA (interactive)
step ca init

# Initialize non-interactively
step ca init \
    --name "Example Internal CA" \
    --dns ca.internal.example.com \
    --address :8443 \
    --provisioner admin@example.com \
    --password-file /path/to/password.txt

# This creates ~/.step/config/ca.json and generates:
#   Root CA: ~/.step/certs/root_ca.crt
#   Intermediate CA: ~/.step/certs/intermediate_ca.crt
#   Root CA key: ~/.step/secrets/root_ca_key (encrypted)
#   Intermediate CA key: ~/.step/secrets/intermediate_ca_key (encrypted)
```

### Start the CA

```bash
# Start step-ca (uses ~/.step/config/ca.json)
step-ca ~/.step/config/ca.json

# Or with password file
step-ca --password-file password.txt ~/.step/config/ca.json

# As a systemd service
cat > /etc/systemd/system/step-ca.service << 'EOF'
[Unit]
Description=step-ca service
After=network.target

[Service]
User=step
ExecStart=/usr/local/bin/step-ca /etc/step-ca/config/ca.json \
    --password-file /etc/step-ca/password.txt
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF
```

---

## Provisioners

Provisioners define how clients authenticate to get certificates.

### JWK Provisioner (Default)

Simple key-based provisioner using JOSE/JWK. Good for testing and service-to-service.

```bash
# Issue a certificate using JWK provisioner
step ca certificate myservice.internal.example.com myservice.crt myservice.key \
    --ca-url https://ca.internal.example.com:8443 \
    --root ~/.step/certs/root_ca.crt \
    --provisioner admin@example.com
# Prompts for provisioner password

# Short-lived certificate (1 hour)
step ca certificate myservice.internal.example.com myservice.crt myservice.key \
    --not-after 1h \
    --provisioner admin@example.com
```

### ACME Provisioner

Enables ACME clients (certbot, cert-manager, acme.sh) to use step-ca:

```bash
# Add ACME provisioner
step ca provisioner add acme --type ACME

# ACME directory URL
# https://ca.internal.example.com:8443/acme/acme/directory

# certbot with step-ca
step ca root root.crt  # Download root certificate
certbot certonly \
    --server https://ca.internal.example.com:8443/acme/acme/directory \
    --standalone \
    -d myservice.internal.example.com \
    --email admin@example.com \
    --agree-tos \
    --no-verify-ssl  # Only if TLS uses private root (configure properly in production)

# Better: Install step root CA in system trust store
sudo step certificate install root.crt
```

### OIDC Provisioner

Use your OIDC provider (Okta, Google, Azure AD) to issue certificates:

```bash
# Add OIDC provisioner (Google example)
step ca provisioner add google-workspace \
    --type OIDC \
    --client-id <google-oauth-client-id> \
    --client-secret <client-secret> \
    --configuration-endpoint https://accounts.google.com/.well-known/openid-configuration \
    --domain example.com  # Restrict to your Google Workspace domain

# Issue certificate via OIDC (user opens browser for Google login)
step ca certificate user@example.com user.crt user.key \
    --provisioner google-workspace \
    --san user@example.com
```

**How it works**: User authenticates with Google, gets an OIDC token, step CLI exchanges token for a certificate. Certificate subject and SANs derived from OIDC claims.

### Kubernetes Service Account Provisioner

For pods to get certificates without static credentials:

```bash
# Add K8sSA provisioner
step ca provisioner add k8s-sa \
    --type K8sSA \
    --pem-keys k8s-ca.crt  # K8s API server CA cert

# Pod authentication: uses projected service account token
step ca certificate myapp myapp.crt myapp.key \
    --provisioner k8s-sa \
    --token $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
```

### Cloud Instance Provisioners

For cloud VM instances using platform identity:

```bash
# AWS EC2 instance identity document
step ca provisioner add aws-dev \
    --type AWS \
    --aws-account 123456789

# GCP instance
step ca provisioner add gcp-prod \
    --type GCP \
    --gcp-project my-project

# Azure VM
step ca provisioner add azure-prod \
    --type Azure \
    --azure-tenant <tenant-id> \
    --azure-resource-group my-rg
```

---

## SSH Certificate Authority

step-ca can act as an SSH CA, issuing SSH certificates for users and hosts.

### SSH User Certificates

SSH user certificates authenticate users to hosts without distributing public keys:

```bash
# Initialize SSH CA (add to existing step-ca config)
step ca provisioner add ssh-users \
    --type OIDC \
    --ssh \
    --client-id <okta-client-id> \
    --configuration-endpoint https://dev-xxx.okta.com/.well-known/openid-configuration

# User requests SSH certificate (after Okta login)
step ssh certificate user@example.com \
    --provisioner ssh-users
# Creates: ~/.step/ssh/id_ecdsa-cert.pub

# Certificate is valid for default duration (8-12 hours)
# Extensions in certificate define principals, force-command, etc.
```

**Host trust**: Users' SSH config or authorized_keys replacement:
```bash
# Add step-ca as SSH CA to known_hosts (for host cert verification)
step ssh config --host --roots >> /etc/ssh/ssh_known_hosts
```

### SSH Host Certificates

Hosts present certificates signed by step-ca instead of generating self-signed host keys:

```bash
# On the server: get a host certificate (via systemd or init)
step ssh certificate $(hostname) /etc/ssh/ssh_host_ecdsa_key-cert.pub \
    --host \
    --provisioner aws-prod \  # Uses EC2 instance identity for auth
    --san $(hostname) \
    --san $(hostname).internal.example.com

# sshd_config: point to host certificate
HostCertificate /etc/ssh/ssh_host_ecdsa_key-cert.pub
```

**User trust**: Clients trust the step-ca SSH CA instead of individual host keys:
```bash
# In ~/.ssh/known_hosts
@cert-authority *.internal.example.com <step-ca-ssh-host-public-key>
```

### SSH Certificate Rotation

Automate host certificate renewal with a systemd timer:

```bash
# /usr/local/bin/renew-ssh-cert.sh
#!/bin/bash
step ssh certificate $(hostname) /etc/ssh/ssh_host_ecdsa_key-cert.pub \
    --host \
    --provisioner aws-prod \
    --san $(hostname) \
    --force
systemctl reload sshd
```

```ini
# /etc/systemd/system/renew-ssh-cert.timer
[Timer]
OnActiveSec=8h
OnUnitActiveSec=8h

[Install]
WantedBy=timers.target
```

---

## Kubernetes Deployment

```bash
# Install step-ca via Helm
helm repo add smallstep https://smallstep.github.io/helm-charts
helm install step-certificates smallstep/step-certificates \
    --namespace step-ca \
    --create-namespace

# Or cert-manager integration:
# step-ca as ClusterIssuer backend via step-issuer
helm install step-issuer smallstep/step-issuer \
    --namespace step-ca
```

```yaml
# StepClusterIssuer (cert-manager integration)
apiVersion: certmanager.step.sm/v1beta1
kind: StepClusterIssuer
metadata:
  name: step-cluster-issuer
spec:
  url: https://step-ca.step-ca.svc.cluster.local
  caBundle: <base64-root-ca-cert>
  provisioner:
    name: k8s-sa
    kid: <provisioner-key-id>
    passwordRef:
      name: step-ca-provisioner-password
      key: password

---
# Certificate using step-ca
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: myservice-tls
spec:
  secretName: myservice-tls
  issuerRef:
    group: certmanager.step.sm
    kind: StepClusterIssuer
    name: step-cluster-issuer
  dnsNames:
    - myservice.production.svc.cluster.local
  duration: 24h
  renewBefore: 4h
```

---

## Configuration — ca.json

```json
{
  "root": "/etc/step-ca/certs/root_ca.crt",
  "federatedRoots": [],
  "crt": "/etc/step-ca/certs/intermediate_ca.crt",
  "key": "/etc/step-ca/secrets/intermediate_ca_key",
  "address": ":8443",
  "dnsNames": ["ca.internal.example.com"],
  "logger": {"format": "json"},
  "db": {
    "type": "badger",
    "dataSource": "/etc/step-ca/db"
  },
  "tls": {
    "minVersion": 1.2,
    "maxVersion": 1.3
  },
  "authority": {
    "claims": {
      "minTLSCertDuration": "5m",
      "maxTLSCertDuration": "24h",
      "defaultTLSCertDuration": "24h",
      "disableRenewalUntilPercentage": 66,
      "minHostSSHCertDuration": "5m",
      "maxHostSSHCertDuration": "1680h",
      "defaultHostSSHCertDuration": "720h",
      "minUserSSHCertDuration": "5m",
      "maxUserSSHCertDuration": "24h",
      "defaultUserSSHCertDuration": "16h"
    },
    "provisioners": [...],
    "template": {
      "subject": {
        "country": "US",
        "organization": "Example Corp",
        "commonName": "{{ .Subject.CommonName }}"
      },
      "sans": {{ toJson .SANs }},
      "keyUsage": ["digitalSignature"],
      "extKeyUsage": ["serverAuth", "clientAuth"]
    }
  }
}
```

---

## Certificate Renewal

```bash
# Renew certificate (must be within renewal window — last 1/3 of lifetime)
step ca renew myservice.crt myservice.key \
    --ca-url https://ca.internal.example.com:8443 \
    --root root.crt

# Force renewal (before window)
step ca renew --force myservice.crt myservice.key

# Daemon mode: auto-renew continuously
step ca renew --daemon myservice.crt myservice.key \
    --exec "systemctl reload myservice"
# Renews at 66% of lifetime, executes --exec command after successful renewal
```

The `--daemon` mode is ideal for long-running services that need certificate rotation without restarts.

---

## Practical Patterns

### Short-Lived mTLS for Services

```bash
# Service A requests cert on startup
step ca certificate service-a service-a.crt service-a.key \
    --not-after 1h \
    --san service-a.internal.example.com \
    --provisioner k8s-sa \
    --token $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)

# Service B trusts service-a's certificate because it's signed by the same CA
# Both services' TLS library verifies the cert chain to the internal root CA

# Renewal daemon keeps cert fresh
step ca renew --daemon service-a.crt service-a.key \
    --not-after 1h
```

### Replace SSH Keys with Certificates Org-Wide

1. Initialize step-ca with OIDC + SSH provisioner
2. Add step-ca SSH host public key to all hosts' `ssh_known_hosts`
3. Add step-ca SSH user CA public key to all hosts' `TrustedUserCAKeys`
4. Provision host certificates on all servers
5. Users authenticate with `step ssh login` (browser-based OIDC)
6. Step CLI places signed certificate in SSH agent
7. Access works — no static keys distributed

Attribution

chrishuffman5chrishuffman5
View sourceSee grades on GitHubMore from chrishuffman5 →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Terraform Module Library

Build reusable Terraform modules for AWS, Azure, and GCP infrastructure following infrastructure-as-code best practices. Use when creating infrastructure modules, standardizing cloud provisioning, or implementing reusable IaC components.

401991 votes

sematext-otel

Wire a service's OpenTelemetry output to Sematext Cloud. Walks through region, App-type, instrumentation flow (managed OTLP endpoint vs Sematext Agent), and signal selection (traces/metrics/logs), then produces the exact env-var block and points at a runnable reference example in this repo. Invoke when instrumenting a new app for Sematext.

01 votes

Deployment Patterns

Deployment workflows, CI/CD pipeline patterns, Docker containerization, health checks, rollback strategies, and production readiness checklists for web applications. Use when setting up deployment infrastructure or planning releases.

2699140 votes

Babysit

Watch a pull request or review cycle until it is ready to merge. Use when asked to babysit, monitor, or keep checking PR comments, reviews, and CI until all actionable issues are resolved.

971540 votes

V7 Roster

Interact with the Paperclip control plane API for task coordination and governance. Use when checking assignments, updating issue status, posting comments, delegating work, managing routines, or calling Paperclip API endpoints.

953190 votes
View all in devops →