← Week 3: TLS Integration and CLI

Day 19: CLI — pki issue, pki revoke, pki inspect

Phase 2 · July 5, 2026

← Week 3: TLS Integration and CLI

Agenda (2–3 hours)

  • Read (20 min): clap derive API docs — subcommands, required args
  • Build (130 min): Wire all modules into a usable CLI in main.rs
  • Verify (30 min): Full CLI walkthrough from init to inspect
← Week 3: TLS Integration and CLI

CLI Design

pki init [--dir ./pki]
    Create root CA + intermediate CA, save to --dir

pki issue server <hostname> [--alt <name>...] [--dir ./pki]
    Issue a TLS server cert; print cert path and serial

pki issue client <identity> [--dir ./pki]
    Issue a client auth cert

pki revoke <serial> [--reason keyCompromise|superseded|...] [--dir ./pki]
    Revoke a cert, regenerate CRL

pki inspect <path-to-cert.pem>
    Print human-readable cert fields

pki list [--dir ./pki]
    List all issued certs with status (valid/revoked/expired)

pki serve-ocsp [--port 8080] [--dir ./pki]
    Start the OCSP responder
← Week 3: TLS Integration and CLI

clap Derive API

use clap::{Parser, Subcommand};

#[derive(Parser)]
#[command(name = "pki", about = "Toy PKI for learning")]
struct Cli {
    #[arg(long, default_value = "./pki")]
    dir: PathBuf,
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand)]
enum Commands {
    Init,
    Issue {
        #[command(subcommand)]
        cert_type: IssueType,
    },
    Revoke {
        serial: String,
        #[arg(long, default_value = "unspecified")]
        reason: String,
    },
    Inspect { path: PathBuf },
    List,
    ServeOcsp {
        #[arg(long, default_value_t = 8080)]
        port: u16,
    },
}
← Week 3: TLS Integration and CLI

pki inspect Output

$ pki inspect pki/certs/abc123.crt

Subject:     CN=localhost
Issuer:      CN=Toy Intermediate CA
Serial:      abc123...
Type:        TLS Server
Valid:        2026-06-20 → 2026-09-18 (75 days remaining)
SANs:        localhost, 127.0.0.1
KeyUsage:    digitalSignature
EKU:         serverAuth
AKI:         linked ✓
Status:      VALID

Reuse your x509-parser code from Phase 1's tls-inspect tool.

← Week 3: TLS Integration and CLI

pki list Output

$ pki list

SERIAL    SUBJECT                  TYPE    EXPIRY              STATUS
abc123    CN=localhost              server  2026-09-18          VALID
def456    CN=device-001            client  2027-06-20          VALID
789abc    CN=device-002            client  2027-06-20          REVOKED (2026-06-30)
← Week 3: TLS Integration and CLI

Challenge Assignment

Implement all 7 subcommands in main.rs.

Then run the complete workflow manually:

cargo build
./target/debug/pki init
./target/debug/pki issue server localhost
./target/debug/pki issue client device-001
./target/debug/pki list
./target/debug/pki inspect pki/certs/<serial>.crt
./target/debug/pki revoke <serial> --reason keyCompromise
./target/debug/pki list   # verify revoked status
./target/debug/pki serve-ocsp &
openssl ocsp -issuer pki/ca/intermediate.crt -cert pki/certs/<serial>.crt \
  -url http://localhost:8080/ocsp -text

Document any rough edges — they're what to polish tomorrow.

← Week 3: TLS Integration and CLI

Resources

  • clap derive API: docs.rs/clap — #[derive(Parser)], #[derive(Subcommand)]
  • clap examples: github.com/clap-rs/clap/tree/master/examples