Skip to content

Instantly share code, notes, and snippets.

@bombsimon
Created June 27, 2019 12:40
Show Gist options
  • Save bombsimon/f7c016c9c2a5920905125e9e78fa831a to your computer and use it in GitHub Desktop.
Save bombsimon/f7c016c9c2a5920905125e9e78fa831a to your computer and use it in GitHub Desktop.
Notes and information about CFSSL + OCSP

CFSSL Summary

Notes and useful commands and configuration for a minimal setup of CFSSL using root CA issued by mkcert.

Setup DB schema

Main article

To be able to store certificates their states we need to set up a database backend. CFSSL is shipped with goose migrations so we just install goose and migrate!

# Install goose
go get -u github.com/pressly/goose/cmd/goose

# Run migration
goose -dir certdb/sqlite/migrations sqlite3 cerstore.db up

Configuration

We must create a few configration files for CFSSL to use.

config.json

config.json holds configuration related to the signing of certificates.

{
  "signing": {
    "profiles": {
      "CA": {
        "usages": [
          "cert sign"
        ],
        "expiry": "720h",
        "auth_key": "ca-auth"
      },
      "email": {
        "usages": [
          "s/mime"
        ],
        "expiry": "720h"
      }
    },
    "default": {
      "usages": [
        "digital signature",
        "email protection"
      ],
      "expiry": "8000h"
    }
  },
  "auth_keys": {
    "ca-auth": {
      "type": "standard",
      "key": "0123456789ABCDEF0123456789ABCDEF"
    }
  }
}

db-config.json

Minimum configuration for database connections.

{
  "driver": "sqlite3",
  "data_source": "./certstore.db"
}

Certificates

Generate a root CA and root CA key with mkcert. Copy to your working directory.

mkcert -install
cp "$(mkcert -CAROOT)/rootCA*" .

Start server

go run cmd/cfssl/cfssl.go serve \
    --ca rootCA.pem \
    --ca-key rootCA-key.pem \
    --config config.json \
    --db-config db-config.json

Issue a certificate

Just create a certificate and save to file.

echo '{"request":{"CN":"Test"}}' | \
    http POST http://127.0.0.1:8888/api/v1/cfssl/newcert | \
    jq .result.certificate | \
    gsed 's,\\n,\n,g' | gsed 's,",,g' > my-cert.pem

Create a certificate and store both the certificate and the key file.

r=$( echo '{"request":{"CN":"Test"}}' | \
    http POST http://127.0.0.1:8888/api/v1/cfssl/newcert); \
    echo $r | jq .result.certificate | \
        gsed 's,\\n,\n,g' | gsed 's,",,g' > my-cert.pem; \
    echo $r | jq .result.private_key | \
        gsed 's,\\n,\n,g' | gsed 's,",,g' > my-key.pem

Revoke certificate

http POST http://127.0.0.1:8888/api/v1/cfssl/revoke \
    serial=74809552255845637962813547409096274906778910495 \
    authority_key_id=d9dda678a8b7292a7c16033195a350c8af6a8c95 \
    reason=keycompromise

HTTP/1.1 200 OK
Content-Length: 55
Content-Type: application/json
Date: Thu, 27 Jun 2019 11:57:21 GMT

{
    "errors": [],
    "messages": [],
    "result": {},
    "success": true
}

OCSP

Refresh OCSP database

cfssl ocsprefresh \
    -db-config my-config.json \
    -ca my-ca.pem \
    -responder my-ca.pem \
    -responder-key my-ca-key.pem

Dump OCSP database to file

cfssl ocspdump -db-config my-config.json > ocsp-responses

Serve OCSP

The OCSP server can serve information from file or from the database holding all the certificates issued.

ASN1. JavaScript decoder

Serve from file

cfssl ocspserve \
    -port=8889 \
    -loglevel=0 \
    -responses=ocsp-responses

Serve from DB

cfssl ocspserve \
    -port 8889 \
    -ca rootCA.pem \
    -ca-key rootCA_key.pem \
    -config config.json \
    -db-config db-config.json \
    -loglevel 0

Perform OCSP request with openssl

openssl ocsp \
    -no_nonce \
    -text \
    -issuer rootCA.pem \
    -cert my-cert.pem \
    -CAfile rootCA.pem \
    -respout response.out \
    -reqout request.out \
    -url http://127.0.0.1:8889

Perform OCSP request with HTTPie

http http://127.0.0.1:8889/"$(cat request.out | base64)"
HTTP/1.1 200 OK
Cache-Control: max-age=343501, public, no-transform, must-revalidate
Content-Length: 707
Content-Type: application/ocsp-response
Date: Sat, 06 Apr 2019 20:34:58 GMT
Etag: "2FB278A1D5CF3CD7E6F4BEF90BEF1307E1626F07F2BC4C7E52608679EA08C96D"
Expires: Wed, 10 Apr 2019 20:00:00 UTC
Last-Modified: Sat, 06 Apr 2019 20:00:00 UTC



+-----------------------------------------+
| NOTE: binary data not shown in terminal |
+-----------------------------------------+

Perform OCSP request with Go

// Construct an OCSP request from the *x509.Certificate
request, _ := ocsp.CreateRequest(cert, issuing, nil)

// Construct the URL with the base64 encoded request
httpResponse, _ := http.Get(
    fmt.Sprintf("http://127.0.0.1:8889/%s", base64.StdEncoding.EncodeToString(request)),
)

// Read response from body
responseBody, _ := ioutil.ReadAll(httpResponse.Body)

// Parse OCSP response
ocspResponse, _ := ocsp.ParseResponse(responseBody, issuing)

// ocspResponse.Status == ocsp.Good returns true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment