Adding Cert retrieval by common name, and renaming KeyID to CertID

Signed-off-by: Diogo Monica <diogo@docker.com>
This commit is contained in:
Diogo Monica 2015-07-15 17:30:21 -07:00
parent 0313aa5958
commit 58e6544d0a
5 changed files with 94 additions and 39 deletions

View File

@ -64,7 +64,7 @@ func keysRemove(cmd *cobra.Command, args []string) {
gunOrID := args[0]
// Try to retrieve the ID from the CA store.
cert, err := caStore.GetCertificateByKeyID(gunOrID)
cert, err := caStore.GetCertificateByCertID(gunOrID)
if err == nil {
fmt.Printf("Removing: ")
printCert(cert)
@ -78,7 +78,7 @@ func keysRemove(cmd *cobra.Command, args []string) {
}
// Try to retrieve the ID from the Certificate store.
cert, err = certificateStore.GetCertificateByKeyID(gunOrID)
cert, err = certificateStore.GetCertificateByCertID(gunOrID)
if err == nil {
fmt.Printf("Removing: ")
printCert(cert)
@ -216,12 +216,12 @@ func keysGenerate(cmd *cobra.Command, args []string) {
func printCert(cert *x509.Certificate) {
timeDifference := cert.NotAfter.Sub(time.Now())
keyID, err := trustmanager.FingerprintCert(cert)
certID, err := trustmanager.FingerprintCert(cert)
if err != nil {
fatalf("could not fingerprint certificate: %v", err)
}
fmt.Printf("%s %s (expires in: %v days)\n", cert.Subject.CommonName, keyID, math.Floor(timeDifference.Hours()/24))
fmt.Printf("%s %s (expires in: %v days)\n", cert.Subject.CommonName, certID, math.Floor(timeDifference.Hours()/24))
}
func printKey(keyPath string) {

View File

@ -70,14 +70,14 @@ func (s X509FileStore) AddCert(cert *x509.Certificate) error {
// addNamedCert allows adding a certificate while controling the filename it gets
// stored under. If the file does not exist on disk, saves it.
func (s X509FileStore) addNamedCert(cert *x509.Certificate) error {
fileName, keyID, err := fileName(cert)
fileName, certID, err := fileName(cert)
if err != nil {
return err
}
logrus.Debug("Adding cert with keyID: ", keyID)
logrus.Debug("Adding cert with certID: ", certID)
// Validate if we already loaded this certificate before
if _, ok := s.fingerprintMap[keyID]; ok {
if _, ok := s.fingerprintMap[certID]; ok {
return errors.New("certificate already in the store")
}
@ -98,11 +98,11 @@ func (s X509FileStore) addNamedCert(cert *x509.Certificate) error {
}
// We wrote the certificate succcessfully, add it to our in-memory storage
s.fingerprintMap[keyID] = cert
s.fileMap[keyID] = fileName
s.fingerprintMap[certID] = cert
s.fileMap[certID] = fileName
name := string(cert.RawSubject)
s.nameMap[name] = append(s.nameMap[name], keyID)
name := string(cert.Subject.CommonName)
s.nameMap[name] = append(s.nameMap[name], certID)
return nil
}
@ -113,13 +113,13 @@ func (s X509FileStore) RemoveCert(cert *x509.Certificate) error {
return errors.New("removing nil Certificate from X509Store")
}
keyID, err := fingerprintCert(cert)
certID, err := fingerprintCert(cert)
if err != nil {
return err
}
delete(s.fingerprintMap, keyID)
filename := s.fileMap[keyID]
delete(s.fileMap, keyID)
delete(s.fingerprintMap, certID)
filename := s.fileMap[certID]
delete(s.fileMap, certID)
name := string(cert.RawSubject)
@ -127,7 +127,7 @@ func (s X509FileStore) RemoveCert(cert *x509.Certificate) error {
fpList := s.nameMap[name]
newfpList := fpList[:0]
for _, x := range fpList {
if x != keyID {
if x != certID {
newfpList = append(newfpList, x)
}
}
@ -183,21 +183,48 @@ func (s X509FileStore) GetCertificatePool() *x509.CertPool {
return pool
}
// GetCertificateByKeyID returns the certificate that matches a certain keyID or error
func (s X509FileStore) GetCertificateByKeyID(keyID string) (*x509.Certificate, error) {
// GetCertificateByCertID returns the certificate that matches a certain certID
func (s X509FileStore) GetCertificateByCertID(certID string) (*x509.Certificate, error) {
return s.getCertificateByCertID(CertID(certID))
}
// getCertificateByCertID returns the certificate that matches a certain certID
func (s X509FileStore) getCertificateByCertID(certID CertID) (*x509.Certificate, error) {
// If it does not look like a hex encoded sha256 hash, error
if len(keyID) != 64 {
if len(certID) != 64 {
return nil, errors.New("invalid Subject Key Identifier")
}
// Check to see if this subject key identifier exists
if cert, ok := s.fingerprintMap[CertID(keyID)]; ok {
if cert, ok := s.fingerprintMap[CertID(certID)]; ok {
return cert, nil
}
return nil, errors.New("certificate not found in Key Store")
}
// GetCertificatesByCN returns all the certificates that match a specific
// CommonName
func (s X509FileStore) GetCertificatesByCN(cn string) ([]*x509.Certificate, error) {
var certs []*x509.Certificate
if ids, ok := s.nameMap[cn]; ok {
for _, v := range ids {
cert, err := s.getCertificateByCertID(v)
if err != nil {
// This error should never happen. This would mean that we have
// an inconsistent X509FileStore
return nil, err
}
certs = append(certs, cert)
}
}
if len(certs) == 0 {
return nil, errors.New("common name not found in Key Store")
}
return certs, nil
}
// GetVerifyOptions returns VerifyOptions with the certificates within the KeyStore
// as part of the roots list. This never allows the use of system roots, returning
// an error if there are no root CAs.
@ -217,10 +244,10 @@ func (s X509FileStore) GetVerifyOptions(dnsName string) (x509.VerifyOptions, err
}
func fileName(cert *x509.Certificate) (string, CertID, error) {
keyID, err := fingerprintCert(cert)
certID, err := fingerprintCert(cert)
if err != nil {
return "", "", err
}
return path.Join(cert.Subject.CommonName, string(keyID)), keyID, nil
return path.Join(cert.Subject.CommonName, string(certID)), certID, nil
}

View File

@ -23,7 +23,7 @@ func NewX509MemStore() *X509MemStore {
}
}
// NewX509FilteredMemStore returns a new X509FileStore that validates certificates
// NewX509FilteredMemStore returns a new X509Memstore that validates certificates
// that are added.
func NewX509FilteredMemStore(validate func(*x509.Certificate) bool) *X509MemStore {
s := &X509MemStore{
@ -46,14 +46,14 @@ func (s X509MemStore) AddCert(cert *x509.Certificate) error {
return errors.New("certificate failed validation")
}
keyID, err := fingerprintCert(cert)
certID, err := fingerprintCert(cert)
if err != nil {
return err
}
s.fingerprintMap[keyID] = cert
s.fingerprintMap[certID] = cert
name := string(cert.RawSubject)
s.nameMap[name] = append(s.nameMap[name], keyID)
s.nameMap[name] = append(s.nameMap[name], certID)
return nil
}
@ -64,18 +64,18 @@ func (s X509MemStore) RemoveCert(cert *x509.Certificate) error {
return errors.New("removing nil Certificate to X509Store")
}
keyID, err := fingerprintCert(cert)
certID, err := fingerprintCert(cert)
if err != nil {
return err
}
delete(s.fingerprintMap, keyID)
delete(s.fingerprintMap, certID)
name := string(cert.RawSubject)
// Filter the fingerprint out of this name entry
fpList := s.nameMap[name]
newfpList := fpList[:0]
for _, x := range fpList {
if x != keyID {
if x != certID {
newfpList = append(newfpList, x)
}
}
@ -125,21 +125,48 @@ func (s X509MemStore) GetCertificatePool() *x509.CertPool {
return pool
}
// GetCertificateByKeyID returns the certificate that matches a certain keyID or error
func (s X509MemStore) GetCertificateByKeyID(keyID string) (*x509.Certificate, error) {
// GetCertificateByCertID returns the certificate that matches a certain certID
func (s X509MemStore) GetCertificateByCertID(certID string) (*x509.Certificate, error) {
return s.getCertificateByCertID(CertID(certID))
}
// getCertificateByCertID returns the certificate that matches a certain certID or error
func (s X509MemStore) getCertificateByCertID(certID CertID) (*x509.Certificate, error) {
// If it does not look like a hex encoded sha256 hash, error
if len(keyID) != 64 {
if len(certID) != 64 {
return nil, errors.New("invalid Subject Key Identifier")
}
// Check to see if this subject key identifier exists
if cert, ok := s.fingerprintMap[CertID(keyID)]; ok {
if cert, ok := s.fingerprintMap[CertID(certID)]; ok {
return cert, nil
}
return nil, errors.New("certificate not found in Key Store")
}
// GetCertificatesByCN returns all the certificates that match a specific
// CommonName
func (s X509MemStore) GetCertificatesByCN(cn string) ([]*x509.Certificate, error) {
var certs []*x509.Certificate
if ids, ok := s.nameMap[cn]; ok {
for _, v := range ids {
cert, err := s.getCertificateByCertID(v)
if err != nil {
// This error should never happen. This would mean that we have
// an inconsistent X509MemStore
return nil, err
}
certs = append(certs, cert)
}
}
if len(certs) == 0 {
return nil, errors.New("common name not found in Key Store")
}
return certs, nil
}
// GetVerifyOptions returns VerifyOptions with the certificates within the KeyStore
// as part of the roots list. This never allows the use of system roots, returning
// an error if there are no root CAs.

View File

@ -106,14 +106,14 @@ func TestRemoveCert(t *testing.T) {
}
}
func TestInexistentGetCertificateByKeyID(t *testing.T) {
func TestInexistentGetCertificateByCertID(t *testing.T) {
store := NewX509MemStore()
err := store.AddCertFromFile("../fixtures/root-ca.crt")
if err != nil {
t.Fatalf("failed to load certificate from file: %v", err)
}
_, err = store.GetCertificateByKeyID("4d06afd30b8bed131d2a84c97d00b37f422021598bfae34285ce98e77b708b5a")
_, err = store.GetCertificateByCertID("4d06afd30b8bed131d2a84c97d00b37f422021598bfae34285ce98e77b708b5a")
if err == nil {
t.Fatalf("no error returned for inexistent certificate")
}
@ -138,15 +138,15 @@ func TestGetCertificateByKeyID(t *testing.T) {
t.Fatalf("failed to load certificate from PEM: %v", err)
}
keyID, err := FingerprintCert(cert)
certID, err := FingerprintCert(cert)
if err != nil {
t.Fatalf("failed to fingerprint the certificate: %v", err)
}
// Tries to retrieve cert by Subject Key IDs
_, err = store.GetCertificateByKeyID(keyID)
_, err = store.GetCertificateByCertID(certID)
if err != nil {
t.Fatalf("expected certificate in store: %s", keyID)
t.Fatalf("expected certificate in store: %s", certID)
}
}

View File

@ -14,7 +14,8 @@ type X509Store interface {
AddCertFromPEM(pemCerts []byte) error
AddCertFromFile(filename string) error
RemoveCert(cert *x509.Certificate) error
GetCertificateByKeyID(keyID string) (*x509.Certificate, error)
GetCertificateByCertID(certID string) (*x509.Certificate, error)
GetCertificatesByCN(cn string) ([]*x509.Certificate, error)
GetCertificates() []*x509.Certificate
GetCertificatePool() *x509.CertPool
GetVerifyOptions(dnsName string) (x509.VerifyOptions, error)