Skip to content

Commit

Permalink
feat(authsign): store additional metadata/fields in certdb
Browse files Browse the repository at this point in the history
This is a major change in that the included DB migrations *must* be run before the new version of `cfssl` is deployed.
This allows for clients (i.e. https://github.com/cloudflare/certmgr) to send some additional optional fields to `/api/v1/cfssl/authsign` to be stored in `certdb`. It also starts saving SANs, common name, and NotBefore from the issued certificates so that they can be queried without having to parse the PEM.
  • Loading branch information
nickysemenza committed Sep 15, 2020
1 parent 2916a1f commit 35f9d5c
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 20 deletions.
9 changes: 9 additions & 0 deletions certdb/certdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ type CertificateRecord struct {
Expiry time.Time `db:"expiry"`
RevokedAt time.Time `db:"revoked_at"`
PEM string `db:"pem"`
//new
IssuedAt time.Time `db:"issued_at"`
NotBefore time.Time `db:"not_before"`
OriginatingHost string `db:"originating_host"`
SANs string `db:"sans"`
CommonName string `db:"common_name"`
Tags string `db:"tags"`
Filename string `db:"filename"`
ApplicationName string `db:"application_name"`
}

// OCSPRecord encodes a OCSP response body and its metadata
Expand Down
21 changes: 21 additions & 0 deletions certdb/mysql/migrations/002_AddMetadataToCertificates.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-- +goose Up
-- SQL in section 'Up' is executed when this migration is applied
ALTER TABLE certificates
ADD COLUMN issued_at timestamp DEFAULT '0000-00-00 00:00:00',
ADD COLUMN not_before timestamp DEFAULT '0000-00-00 00:00:00',
ADD COLUMN originating_host TEXT,
ADD COLUMN sans TEXT,
ADD COLUMN tags TEXT,
ADD COLUMN common_name TEXT,
ADD COLUMN filename TEXT,
ADD COLUMN application_name TEXT;
-- +goose Down
-- SQL section 'Down' is executed when this migration is rolled back
ALTER TABLE certificates DROP COLUMN issued_at,
DROP COLUMN not_before,
DROP COLUMN originating_host,
DROP COLUMN sans,
DROP COLUMN tags,
DROP COLUMN common_name,
DROP COLUMN filename,
DROP COLUMN application_name;
21 changes: 21 additions & 0 deletions certdb/pg/migrations/002_AddMetadataToCertificates.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-- +goose Up
-- SQL in section 'Up' is executed when this migration is applied
ALTER TABLE certificates
ADD COLUMN issued_at timestamptz,
ADD COLUMN not_before timestamptz,
ADD COLUMN originating_host TEXT,
ADD COLUMN sans TEXT,
ADD COLUMN tags TEXT,
ADD COLUMN common_name TEXT,
ADD COLUMN filename TEXT,
ADD COLUMN application_name TEXT;
-- +goose Down
-- SQL section 'Down' is executed when this migration is rolled back
ALTER TABLE certificates DROP COLUMN issued_at,
DROP COLUMN not_before,
DROP COLUMN originating_host,
DROP COLUMN sans,
DROP COLUMN tags,
DROP COLUMN common_name,
DROP COLUMN filename,
DROP COLUMN application_name;
30 changes: 20 additions & 10 deletions certdb/sql/database_accessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ func init() {

const (
insertSQL = `
INSERT INTO certificates (serial_number, authority_key_identifier, ca_label, status, reason, expiry, revoked_at, pem)
VALUES (:serial_number, :authority_key_identifier, :ca_label, :status, :reason, :expiry, :revoked_at, :pem);`
INSERT INTO certificates (serial_number, authority_key_identifier, ca_label, status, reason, expiry, revoked_at, pem,
issued_at, not_before, originating_host, sans, common_name, tags, filename, application_name)
VALUES (:serial_number, :authority_key_identifier, :ca_label, :status, :reason, :expiry, :revoked_at, :pem,
:issued_at, :not_before, :originating_host, :sans, :common_name, :tags, :filename, :application_name);`

selectSQL = `
SELECT %s FROM certificates
Expand Down Expand Up @@ -100,14 +102,22 @@ func (d *Accessor) InsertCertificate(cr certdb.CertificateRecord) error {
}

res, err := d.db.NamedExec(insertSQL, &certdb.CertificateRecord{
Serial: cr.Serial,
AKI: cr.AKI,
CALabel: cr.CALabel,
Status: cr.Status,
Reason: cr.Reason,
Expiry: cr.Expiry.UTC(),
RevokedAt: cr.RevokedAt.UTC(),
PEM: cr.PEM,
Serial: cr.Serial,
AKI: cr.AKI,
CALabel: cr.CALabel,
Status: cr.Status,
Reason: cr.Reason,
Expiry: cr.Expiry.UTC(),
RevokedAt: cr.RevokedAt.UTC(),
PEM: cr.PEM,
IssuedAt: cr.IssuedAt.UTC(),
NotBefore: cr.NotBefore.UTC(),
OriginatingHost: cr.OriginatingHost,
SANs: cr.SANs,
CommonName: cr.CommonName,
Tags: cr.Tags,
Filename: cr.Filename,
ApplicationName: cr.ApplicationName,
})
if err != nil {
return wrapSQLError(err)
Expand Down
16 changes: 16 additions & 0 deletions certdb/sqlite/migrations/002_AddMetadataToCertificates.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-- +goose Up
-- SQL in section 'Up' is executed when this migration is applied

ALTER TABLE certificates ADD COLUMN "issued_at" timestamp;
ALTER TABLE certificates ADD COLUMN "not_before" timestamp;
ALTER TABLE certificates ADD COLUMN "originating_host" text;
ALTER TABLE certificates ADD COLUMN "sans" text;
ALTER TABLE certificates ADD COLUMN "tags" text;
ALTER TABLE certificates ADD COLUMN "common_name" text;
ALTER TABLE certificates ADD COLUMN "filename" text;
ALTER TABLE certificates ADD COLUMN "application_name" text;

-- +goose Down
-- SQL section 'Down' is executed when this migration is rolled back

-- can't drop columns in sqlite
Binary file modified certdb/testdb/certstore_development.db
Binary file not shown.
23 changes: 16 additions & 7 deletions signer/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"net/mail"
"net/url"
"os"
"strings"
"time"

"github.com/cloudflare/cfssl/certdb"
"github.com/cloudflare/cfssl/config"
Expand All @@ -29,7 +31,7 @@ import (
"github.com/cloudflare/cfssl/info"
"github.com/cloudflare/cfssl/log"
"github.com/cloudflare/cfssl/signer"
"github.com/google/certificate-transparency-go"
ct "github.com/google/certificate-transparency-go"
"github.com/google/certificate-transparency-go/client"
"github.com/google/certificate-transparency-go/jsonclient"

Expand Down Expand Up @@ -509,13 +511,20 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
Serial: certTBS.SerialNumber.String(),
// this relies on the specific behavior of x509.CreateCertificate
// which sets the AuthorityKeyId from the signer's SubjectKeyId
AKI: hex.EncodeToString(parsedCert.AuthorityKeyId),
CALabel: req.Label,
Status: "good",
Expiry: certTBS.NotAfter,
PEM: string(signedCert),
AKI: hex.EncodeToString(parsedCert.AuthorityKeyId),
CALabel: req.Label,
Status: "good",
Expiry: certTBS.NotAfter,
PEM: string(signedCert),
IssuedAt: time.Now(),
NotBefore: certTBS.NotBefore,
OriginatingHost: req.OriginatingHost,
SANs: strings.Join(certTBS.DNSNames, ","),
CommonName: certTBS.Subject.CommonName,
Tags: strings.Join(req.Tags, ","),
Filename: req.Filename,
ApplicationName: req.ApplicationName,
}

err = s.dbAccessor.InsertCertificate(certRecord)
if err != nil {
return nil, err
Expand Down
15 changes: 12 additions & 3 deletions signer/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ type SignRequest struct {
// be passed to SignFromPrecert with the SCTs in order to create a
// valid certificate.
ReturnPrecert bool

// Arbitrary tags describing the sign request / cert.
Tags []string `json:"tags"`
// Host which is initiating the sign request.
OriginatingHost string `json:"originating_host"`
// Filename that the resulting cert will be stored in/
Filename string `json:"filename"`
// Application that the resulting cert will be used for.
ApplicationName string `json:"application_name"`
}

// appendIf appends to a if s is not an empty string.
Expand Down Expand Up @@ -193,8 +202,8 @@ func ParseCertificateRequest(s Signer, p *config.SigningProfile, csrBytes []byte
IPAddresses: csrv.IPAddresses,
EmailAddresses: csrv.EmailAddresses,
URIs: csrv.URIs,
Extensions: csrv.Extensions,
ExtraExtensions: []pkix.Extension{},
Extensions: csrv.Extensions,
ExtraExtensions: []pkix.Extension{},
}

for _, val := range csrv.Extensions {
Expand All @@ -216,7 +225,7 @@ func ParseCertificateRequest(s Signer, p *config.SigningProfile, csrBytes []byte
template.MaxPathLenZero = template.MaxPathLen == 0
} else {
// If the profile has 'copy_extensions' to true then lets add it
if (p.CopyExtensions) {
if p.CopyExtensions {
template.ExtraExtensions = append(template.ExtraExtensions, val)
}
}
Expand Down

0 comments on commit 35f9d5c

Please sign in to comment.