Skip to content

Commit

Permalink
Split up boulder-config.json (Single OCSP) + Cleanup (letsencrypt#2069)
Browse files Browse the repository at this point in the history
This PR removes the use of the global configuration variable BOULDER_CONFIG. It also removes the global configuration struct cmd.Config. Furthermore, it removes the dependency codegangsta/cli and the last bit of code that was using it cmd/single-ocsp/main.go.

This is the final (hopefully) pull request in the work to remove the reliance on a global configuration structure. Included below is a history of all other pull requests relevant in accomplishing this:

 WFE (letsencrypt#1973)
 RA (letsencrypt#1974)
 SA (letsencrypt#1975)
 CA (letsencrypt#1978)
 VA (letsencrypt#1979)
 Publisher (letsencrypt#2008)
 OCSP Updater (letsencrypt#2013)
 OCSP Responder (letsencrypt#2017)
 Admin Revoker (letsencrypt#2053)
 Expiration Mailer (letsencrypt#2036)
 Cert Checker (letsencrypt#2058)
 Orphan Finder (letsencrypt#2059)
 Single OCSP (this PR)

Closes letsencrypt#1962
  • Loading branch information
benileo authored and Roland Bracewell Shoemaker committed Jul 22, 2016
1 parent f5d0038 commit 159aeca
Show file tree
Hide file tree
Showing 16 changed files with 87 additions and 2,035 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ env:
- RUN="vet fmt migrations integration godep-restore errcheck generate"
# Config changes that have landed in master but not yet been applied to
# production can be made in boulder-config-next.json.
- RUN="integration" BOULDER_CONFIG="test/boulder-config-next.json" BOULDER_CONFIG_DIR="test/config-next"
- RUN="integration" BOULDER_CONFIG_DIR="test/config-next"
- RUN="unit"

install:
Expand All @@ -49,4 +49,4 @@ install:
- docker-compose build

script:
- docker-compose run -e BOULDER_CONFIG="${BOULDER_CONFIG}" -e BOULDER_CONFIG_DIR="${BOULDER_CONFIG_DIR}" -e RUN="${RUN}" -e TRAVIS="${TRAVIS}" -e TRAVIS_COMMIT="${TRAVIS_COMMIT}" -e TRAVIS_PULL_REQUEST="${TRAVIS_PULL_REQUEST}" -e TRAVIS_PULL_REQUEST="${TRAVIS_PULL_REQUEST}" -e TRAVIS_JOB_ID="${TRAVIS_JOB_ID}" -e COVERALLS_TOKEN="${COVERALLS_TOKEN}" boulder ./test.sh
- docker-compose run -e BOULDER_CONFIG_DIR="${BOULDER_CONFIG_DIR}" -e RUN="${RUN}" -e TRAVIS="${TRAVIS}" -e TRAVIS_COMMIT="${TRAVIS_COMMIT}" -e TRAVIS_PULL_REQUEST="${TRAVIS_PULL_REQUEST}" -e TRAVIS_PULL_REQUEST="${TRAVIS_PULL_REQUEST}" -e TRAVIS_JOB_ID="${TRAVIS_JOB_ID}" -e COVERALLS_TOKEN="${COVERALLS_TOKEN}" boulder ./test.sh
5 changes: 0 additions & 5 deletions Godeps/Godeps.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 0 additions & 37 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,43 +15,6 @@ import (
"github.com/letsencrypt/boulder/goodkey"
)

// Config stores configuration parameters that applications
// will need. For simplicity, we just lump them all into
// one struct, and use encoding/json to read it from a file.
//
// Note: NO DEFAULTS are provided.
type Config struct {
// Default AMQPConfig for services that don't specify one.
// TODO(jsha): Delete this after a deploy.
AMQP *AMQPConfig

Statsd StatsdConfig

Syslog SyslogConfig

PA PAConfig

Common struct {
BaseURL string
// Path to a PEM-encoded copy of the issuer certificate.
IssuerCert string

DNSResolver string
DNSTimeout string
DNSAllowLoopbackAddresses bool

CT struct {
Logs []LogDescription
IntermediateBundleFilename string
}
}

AllowedSigningAlgos *AllowedSigningAlgos

// TODO: remove after production configs use SubscriberAgreementURL in the wfe section
SubscriberAgreementURL string
}

// AllowedSigningAlgos defines which algorithms be used for keys that we will
// sign.
type AllowedSigningAlgos struct {
Expand Down
172 changes: 74 additions & 98 deletions cmd/single-ocsp/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ package main
import (
"crypto/x509"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"os"

"github.com/letsencrypt/boulder/cmd"

"github.com/codegangsta/cli"
"github.com/letsencrypt/pkcs11key"
"golang.org/x/crypto/ocsp"
)
Expand All @@ -23,9 +22,52 @@ type PKCS11Config struct {
PIN string
}

func readFiles(c *cli.Context) (issuer, responder, target *x509.Certificate, template ocsp.Response, pkcs11 PKCS11Config, err error) {
const usage = `
name:
single-ocsp - Creates a single OCSP response
usage:
single-ocsp [args]
description:
According to the BRs, the OCSP responses for intermediate certificate must
be issued once per year. So there's a need to issue OCSP responses for
these certificates, but it doesn't make sense to use all the infrastructure
that the "ocsp-updater" tool requires. This tool allows an administrator
to manually generate an OCSP response for an intermediate certificate.
`

const templateUsage = `
OCSP template file (JSON), e.g.:
{
"Status": 0, // Good
"ThisUpdate": "2015-08-26T00:00:00Z",
"NextUpdate": "2016-08-26T00:00:00Z"
}
{
"Status": 1, // Revoked
"ThisUpdate": "2015-08-26T00:00:00Z",
"NextUpdate": "2016-08-26T00:00:00Z",
"RevokedAt": "2015-08-20T00:00:00Z",
"RevocationReason": 1 // Key compromise
}
`

const pkcs11Usage = `
PKCS#11 configuration (JSON), e.g.:
{
"Module": "/Library/OpenSC/lib/opensc-pkcs11.so",
"Token": "Yubico Yubikey NEO CCID",
"Label": "PIV AUTH key",
"PIN": "123456"
}
`

func readFiles(issuerFileName, responderFileName, targetFileName, templateFileName, pkcs11FileName string) (issuer, responder, target *x509.Certificate, template ocsp.Response, pkcs11 PKCS11Config, err error) {
// Issuer certificate
issuerFileName := c.GlobalString("issuer")
issuerBytes, err := ioutil.ReadFile(issuerFileName)
if err != nil {
return
Expand All @@ -37,7 +79,6 @@ func readFiles(c *cli.Context) (issuer, responder, target *x509.Certificate, tem
}

// Responder certificate
responderFileName := c.GlobalString("responder")
responderBytes, err := ioutil.ReadFile(responderFileName)
if err != nil {
return
Expand All @@ -49,7 +90,6 @@ func readFiles(c *cli.Context) (issuer, responder, target *x509.Certificate, tem
}

// Target certificate
targetFileName := c.GlobalString("target")
targetBytes, err := ioutil.ReadFile(targetFileName)
if err != nil {
return
Expand All @@ -61,7 +101,6 @@ func readFiles(c *cli.Context) (issuer, responder, target *x509.Certificate, tem
}

// OCSP template
templateFileName := c.GlobalString("template")
templateBytes, err := ioutil.ReadFile(templateFileName)
if err != nil {
return
Expand All @@ -73,7 +112,6 @@ func readFiles(c *cli.Context) (issuer, responder, target *x509.Certificate, tem
}

// PKCS#11 config
pkcs11FileName := c.GlobalString("pkcs11")
pkcs11Bytes, err := ioutil.ReadFile(pkcs11FileName)
if err != nil {
return
Expand All @@ -84,95 +122,33 @@ func readFiles(c *cli.Context) (issuer, responder, target *x509.Certificate, tem
}

func main() {
app := cli.NewApp()
app.Name = "single-ocsp"
app.Usage = `Creates a single OCSP response.
According to the BRs, the OCSP responses for intermediate certificate must
be issued once per year. So there's a need to issue OCSP responses for
these certificates, but it doesn't make sense to use all the infrastructure
that the "ocsp-updater" tool requires. This tool allows an administrator
to manually generate an OCSP response for an intermediate certificate.
`
app.Version = cmd.Version()
app.Author = "Boulder contributors"
app.Email = "[email protected]"

app.Flags = []cli.Flag{
cli.StringFlag{
Name: "issuer",
Usage: "Issuer certificate (DER)",
},
cli.StringFlag{
Name: "responder",
Usage: "OCSP responder certificate (DER)",
},
cli.StringFlag{
Name: "target",
Usage: "Certificate whose status is being reported (DER)",
},
cli.StringFlag{
Name: "template",
Usage: `OCSP template file (JSON), e.g.:
{
"Status": 0, // Good
"ThisUpdate": "2015-08-26T00:00:00Z",
"NextUpdate": "2016-08-26T00:00:00Z"
}
{
"Status": 1, // Revoked
"ThisUpdate": "2015-08-26T00:00:00Z",
"NextUpdate": "2016-08-26T00:00:00Z",
"RevokedAt": "2015-08-20T00:00:00Z",
"RevocationReason": 1 // Key compromise
}
`,
},
cli.StringFlag{
Name: "pkcs11",
Usage: `PKCS#11 configuration (JSON), e.g.:
{
"Module": "/Library/OpenSC/lib/opensc-pkcs11.so",
"Token": "Yubico Yubikey NEO CCID",
"Label": "PIV AUTH key",
"PIN": "123456"
}
`,
},
cli.StringFlag{
Name: "out",
Usage: "File to which the OCSP response will be written",
},
}

app.Action = func(c *cli.Context) {
issuer, responder, target, template, pkcs11, err := readFiles(c)
cmd.FailOnError(err, "Failed to read files")

// Instantiate the private key from PKCS11
priv, err := pkcs11key.New(pkcs11.Module, pkcs11.TokenLabel, pkcs11.PIN, pkcs11.PrivateKeyLabel)
cmd.FailOnError(err, "Failed to load PKCS#11 key")

// Populate the remaining fields in the template
template.SerialNumber = target.SerialNumber
template.Certificate = responder

// Sign the OCSP response
responseBytes, err := ocsp.CreateResponse(issuer, responder, template, priv)
cmd.FailOnError(err, "Failed to sign OCSP response")

// Write the OCSP response to stdout
outFile := c.GlobalString("out")
if len(outFile) == 0 {
cmd.FailOnError(fmt.Errorf(""), "No output file provided")
}
err = ioutil.WriteFile(outFile, responseBytes, 0666)
cmd.FailOnError(err, "Failed to write output file")
issuerFile := flag.String("issuer", "", "Issuer certificate (DER)")
responderFile := flag.String("responder", "", "OCSP responder certificate (DER)")
targetFile := flag.String("target", "", "Certificate whose status is being reported (DER)")
templateFile := flag.String("template", "", templateUsage)
pkcs11File := flag.String("pkcs11", "", pkcs11Usage)
outFile := flag.String("out", "", "File to which the OCSP response will be written")
flag.Parse()

issuer, responder, target, template, pkcs11, err := readFiles(*issuerFile, *responderFile, *targetFile, *templateFile, *pkcs11File)
cmd.FailOnError(err, "Failed to read files")

// Instantiate the private key from PKCS11
priv, err := pkcs11key.New(pkcs11.Module, pkcs11.TokenLabel, pkcs11.PIN, pkcs11.PrivateKeyLabel)
cmd.FailOnError(err, "Failed to load PKCS#11 key")

// Populate the remaining fields in the template
template.SerialNumber = target.SerialNumber
template.Certificate = responder

// Sign the OCSP response
responseBytes, err := ocsp.CreateResponse(issuer, responder, template, priv)
cmd.FailOnError(err, "Failed to sign OCSP response")

// Write the OCSP response to stdout
if len(*outFile) == 0 {
cmd.FailOnError(fmt.Errorf(""), "No output file provided")
}

err := app.Run(os.Args)
cmd.FailOnError(err, "Failed to run application")
err = ioutil.WriteFile(*outFile, responseBytes, 0666)
cmd.FailOnError(err, "Failed to write output file")
}
42 changes: 0 additions & 42 deletions test/boulder-config-next.json

This file was deleted.

45 changes: 0 additions & 45 deletions test/boulder-config.json

This file was deleted.

Loading

0 comments on commit 159aeca

Please sign in to comment.