kubernetes/vendor/github.com/cloudflare/cfssl/cli/ocsprefresh/ocsprefresh.go
2018-08-08 21:01:29 -07:00

113 lines
3.1 KiB
Go

// Package ocsprefresh implements the ocsprefresh command.
package ocsprefresh
import (
"encoding/hex"
"errors"
"time"
"github.com/cloudflare/cfssl/certdb/dbconf"
"github.com/cloudflare/cfssl/certdb/sql"
"github.com/cloudflare/cfssl/cli"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/log"
"github.com/cloudflare/cfssl/ocsp"
)
// Usage text of 'cfssl ocsprefresh'
var ocsprefreshUsageText = `cfssl ocsprefresh -- refreshes the ocsp_responses table
with new OCSP responses for all known unexpired certificates
Usage of ocsprefresh:
cfssl ocsprefresh -db-config db-config -ca cert -responder cert -responder-key key [-interval 96h]
Flags:
`
// Flags of 'cfssl ocsprefresh'
var ocsprefreshFlags = []string{"ca", "responder", "responder-key", "db-config", "interval"}
// ocsprefreshMain is the main CLI of OCSP refresh functionality.
func ocsprefreshMain(args []string, c cli.Config) error {
if c.DBConfigFile == "" {
return errors.New("need DB config file (provide with -db-config)")
}
if c.ResponderFile == "" {
return errors.New("need responder certificate (provide with -responder)")
}
if c.ResponderKeyFile == "" {
return errors.New("need responder key (provide with -responder-key)")
}
if c.CAFile == "" {
return errors.New("need CA certificate (provide with -ca)")
}
s, err := SignerFromConfig(c)
if err != nil {
log.Critical("Unable to create OCSP signer: ", err)
return err
}
db, err := dbconf.DBFromConfig(c.DBConfigFile)
if err != nil {
return err
}
dbAccessor := sql.NewAccessor(db)
certs, err := dbAccessor.GetUnexpiredCertificates()
if err != nil {
return err
}
// Set an expiry timestamp for all certificates refreshed in this batch
ocspExpiry := time.Now().Add(c.Interval)
for _, certRecord := range certs {
cert, err := helpers.ParseCertificatePEM([]byte(certRecord.PEM))
if err != nil {
log.Critical("Unable to parse certificate: ", err)
return err
}
req := ocsp.SignRequest{
Certificate: cert,
Status: certRecord.Status,
}
if certRecord.Status == "revoked" {
req.Reason = int(certRecord.Reason)
req.RevokedAt = certRecord.RevokedAt
}
resp, err := s.Sign(req)
if err != nil {
log.Critical("Unable to sign OCSP response: ", err)
return err
}
err = dbAccessor.UpsertOCSP(cert.SerialNumber.String(), hex.EncodeToString(cert.AuthorityKeyId), string(resp), ocspExpiry)
if err != nil {
log.Critical("Unable to save OCSP response: ", err)
return err
}
}
return nil
}
// SignerFromConfig creates a signer from a cli.Config as a helper for cli and serve
func SignerFromConfig(c cli.Config) (ocsp.Signer, error) {
//if this is called from serve then we need to use the specific responder key file
//fallback to key for backwards-compatibility
k := c.ResponderKeyFile
if k == "" {
k = c.KeyFile
}
return ocsp.NewSignerFromFile(c.CAFile, c.ResponderFile, k, time.Duration(c.Interval))
}
// Command assembles the definition of Command 'ocsprefresh'
var Command = &cli.Command{UsageText: ocsprefreshUsageText, Flags: ocsprefreshFlags, Main: ocsprefreshMain}