|
|
|
@ -16,6 +16,7 @@ import (
|
|
|
|
|
var (
|
|
|
|
|
certsTable = []byte("x509_certs")
|
|
|
|
|
revokedCertsTable = []byte("revoked_x509_certs")
|
|
|
|
|
crlTable = []byte("x509_crl")
|
|
|
|
|
revokedSSHCertsTable = []byte("revoked_ssh_certs")
|
|
|
|
|
usedOTTTable = []byte("used_ott")
|
|
|
|
|
sshCertsTable = []byte("ssh_certs")
|
|
|
|
@ -24,6 +25,9 @@ var (
|
|
|
|
|
sshHostPrincipalsTable = []byte("ssh_host_principals")
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var crlKey = []byte("crl") //TODO: at the moment we store a single CRL in the database, in a dedicated table.
|
|
|
|
|
// is this acceptable? probably not....
|
|
|
|
|
|
|
|
|
|
// ErrAlreadyExists can be returned if the DB attempts to set a key that has
|
|
|
|
|
// been previously set.
|
|
|
|
|
var ErrAlreadyExists = errors.New("already exists")
|
|
|
|
@ -47,6 +51,9 @@ type AuthDB interface {
|
|
|
|
|
IsSSHRevoked(sn string) (bool, error)
|
|
|
|
|
Revoke(rci *RevokedCertificateInfo) error
|
|
|
|
|
RevokeSSH(rci *RevokedCertificateInfo) error
|
|
|
|
|
GetRevokedCertificates() (*[]RevokedCertificateInfo, error)
|
|
|
|
|
GetCRL() (*CertificateRevocationListInfo, error)
|
|
|
|
|
StoreCRL(*CertificateRevocationListInfo) error
|
|
|
|
|
GetCertificate(serialNumber string) (*x509.Certificate, error)
|
|
|
|
|
StoreCertificate(crt *x509.Certificate) error
|
|
|
|
|
UseToken(id, tok string) (bool, error)
|
|
|
|
@ -82,7 +89,7 @@ func New(c *Config) (AuthDB, error) {
|
|
|
|
|
tables := [][]byte{
|
|
|
|
|
revokedCertsTable, certsTable, usedOTTTable,
|
|
|
|
|
sshCertsTable, sshHostsTable, sshHostPrincipalsTable, sshUsersTable,
|
|
|
|
|
revokedSSHCertsTable,
|
|
|
|
|
revokedSSHCertsTable, crlTable,
|
|
|
|
|
}
|
|
|
|
|
for _, b := range tables {
|
|
|
|
|
if err := db.CreateTable(b); err != nil {
|
|
|
|
@ -106,6 +113,14 @@ type RevokedCertificateInfo struct {
|
|
|
|
|
MTLS bool
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CertificateRevocationListInfo contains a CRL in PEM and associated metadata to allow a decision on whether
|
|
|
|
|
// to regenerate the CRL or not easier
|
|
|
|
|
type CertificateRevocationListInfo struct {
|
|
|
|
|
Number int64
|
|
|
|
|
ExpiresAt time.Time
|
|
|
|
|
PEM string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IsRevoked returns whether or not a certificate with the given identifier
|
|
|
|
|
// has been revoked.
|
|
|
|
|
// In the case of an X509 Certificate the `id` should be the Serial Number of
|
|
|
|
@ -188,6 +203,58 @@ func (db *DB) RevokeSSH(rci *RevokedCertificateInfo) error {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetRevokedCertificates gets a list of all revoked certificates.
|
|
|
|
|
func (db *DB) GetRevokedCertificates() (*[]RevokedCertificateInfo, error) {
|
|
|
|
|
entries, err := db.List(revokedCertsTable)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
var revokedCerts []RevokedCertificateInfo
|
|
|
|
|
for _, e := range entries {
|
|
|
|
|
var data RevokedCertificateInfo
|
|
|
|
|
if err := json.Unmarshal(e.Value, &data); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
revokedCerts = append(revokedCerts, data)
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return &revokedCerts, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// StoreCRL stores a CRL in the DB
|
|
|
|
|
func (db *DB) StoreCRL(crlInfo *CertificateRevocationListInfo) error {
|
|
|
|
|
|
|
|
|
|
crlInfoBytes, err := json.Marshal(crlInfo)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return errors.Wrap(err, "json Marshal error")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := db.Set(crlTable, crlKey, crlInfoBytes); err != nil {
|
|
|
|
|
return errors.Wrap(err, "database Set error")
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetCRL gets the existing CRL from the database
|
|
|
|
|
func (db *DB) GetCRL() (*CertificateRevocationListInfo, error) {
|
|
|
|
|
crlInfoBytes, err := db.Get(crlTable, crlKey)
|
|
|
|
|
|
|
|
|
|
if database.IsErrNotFound(err) {
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, errors.Wrap(err, "database Get error")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var crlInfo CertificateRevocationListInfo
|
|
|
|
|
err = json.Unmarshal(crlInfoBytes, &crlInfo)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, errors.Wrap(err, "json Unmarshal error")
|
|
|
|
|
}
|
|
|
|
|
return &crlInfo, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetCertificate retrieves a certificate by the serial number.
|
|
|
|
|
func (db *DB) GetCertificate(serialNumber string) (*x509.Certificate, error) {
|
|
|
|
|
asn1Data, err := db.Get(certsTable, []byte(serialNumber))
|
|
|
|
|