mirror of https://github.com/docker/docs.git
Adding Cert retrieval by common name, and renaming KeyID to CertID
Signed-off-by: Diogo Monica <diogo@docker.com>
This commit is contained in:
parent
0313aa5958
commit
58e6544d0a
|
@ -64,7 +64,7 @@ func keysRemove(cmd *cobra.Command, args []string) {
|
||||||
gunOrID := args[0]
|
gunOrID := args[0]
|
||||||
|
|
||||||
// Try to retrieve the ID from the CA store.
|
// Try to retrieve the ID from the CA store.
|
||||||
cert, err := caStore.GetCertificateByKeyID(gunOrID)
|
cert, err := caStore.GetCertificateByCertID(gunOrID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
fmt.Printf("Removing: ")
|
fmt.Printf("Removing: ")
|
||||||
printCert(cert)
|
printCert(cert)
|
||||||
|
@ -78,7 +78,7 @@ func keysRemove(cmd *cobra.Command, args []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to retrieve the ID from the Certificate store.
|
// Try to retrieve the ID from the Certificate store.
|
||||||
cert, err = certificateStore.GetCertificateByKeyID(gunOrID)
|
cert, err = certificateStore.GetCertificateByCertID(gunOrID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
fmt.Printf("Removing: ")
|
fmt.Printf("Removing: ")
|
||||||
printCert(cert)
|
printCert(cert)
|
||||||
|
@ -216,12 +216,12 @@ func keysGenerate(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
func printCert(cert *x509.Certificate) {
|
func printCert(cert *x509.Certificate) {
|
||||||
timeDifference := cert.NotAfter.Sub(time.Now())
|
timeDifference := cert.NotAfter.Sub(time.Now())
|
||||||
keyID, err := trustmanager.FingerprintCert(cert)
|
certID, err := trustmanager.FingerprintCert(cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("could not fingerprint certificate: %v", err)
|
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) {
|
func printKey(keyPath string) {
|
||||||
|
|
|
@ -70,14 +70,14 @@ func (s X509FileStore) AddCert(cert *x509.Certificate) error {
|
||||||
// addNamedCert allows adding a certificate while controling the filename it gets
|
// addNamedCert allows adding a certificate while controling the filename it gets
|
||||||
// stored under. If the file does not exist on disk, saves it.
|
// stored under. If the file does not exist on disk, saves it.
|
||||||
func (s X509FileStore) addNamedCert(cert *x509.Certificate) error {
|
func (s X509FileStore) addNamedCert(cert *x509.Certificate) error {
|
||||||
fileName, keyID, err := fileName(cert)
|
fileName, certID, err := fileName(cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Debug("Adding cert with keyID: ", keyID)
|
logrus.Debug("Adding cert with certID: ", certID)
|
||||||
// Validate if we already loaded this certificate before
|
// 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")
|
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
|
// We wrote the certificate succcessfully, add it to our in-memory storage
|
||||||
s.fingerprintMap[keyID] = cert
|
s.fingerprintMap[certID] = cert
|
||||||
s.fileMap[keyID] = fileName
|
s.fileMap[certID] = fileName
|
||||||
|
|
||||||
name := string(cert.RawSubject)
|
name := string(cert.Subject.CommonName)
|
||||||
s.nameMap[name] = append(s.nameMap[name], keyID)
|
s.nameMap[name] = append(s.nameMap[name], certID)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -113,13 +113,13 @@ func (s X509FileStore) RemoveCert(cert *x509.Certificate) error {
|
||||||
return errors.New("removing nil Certificate from X509Store")
|
return errors.New("removing nil Certificate from X509Store")
|
||||||
}
|
}
|
||||||
|
|
||||||
keyID, err := fingerprintCert(cert)
|
certID, err := fingerprintCert(cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
delete(s.fingerprintMap, keyID)
|
delete(s.fingerprintMap, certID)
|
||||||
filename := s.fileMap[keyID]
|
filename := s.fileMap[certID]
|
||||||
delete(s.fileMap, keyID)
|
delete(s.fileMap, certID)
|
||||||
|
|
||||||
name := string(cert.RawSubject)
|
name := string(cert.RawSubject)
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ func (s X509FileStore) RemoveCert(cert *x509.Certificate) error {
|
||||||
fpList := s.nameMap[name]
|
fpList := s.nameMap[name]
|
||||||
newfpList := fpList[:0]
|
newfpList := fpList[:0]
|
||||||
for _, x := range fpList {
|
for _, x := range fpList {
|
||||||
if x != keyID {
|
if x != certID {
|
||||||
newfpList = append(newfpList, x)
|
newfpList = append(newfpList, x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,21 +183,48 @@ func (s X509FileStore) GetCertificatePool() *x509.CertPool {
|
||||||
return pool
|
return pool
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCertificateByKeyID returns the certificate that matches a certain keyID or error
|
// GetCertificateByCertID returns the certificate that matches a certain certID
|
||||||
func (s X509FileStore) GetCertificateByKeyID(keyID string) (*x509.Certificate, error) {
|
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 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")
|
return nil, errors.New("invalid Subject Key Identifier")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if this subject key identifier exists
|
// 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 cert, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
return nil, errors.New("certificate not found in Key Store")
|
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
|
// GetVerifyOptions returns VerifyOptions with the certificates within the KeyStore
|
||||||
// as part of the roots list. This never allows the use of system roots, returning
|
// as part of the roots list. This never allows the use of system roots, returning
|
||||||
// an error if there are no root CAs.
|
// 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) {
|
func fileName(cert *x509.Certificate) (string, CertID, error) {
|
||||||
keyID, err := fingerprintCert(cert)
|
certID, err := fingerprintCert(cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return path.Join(cert.Subject.CommonName, string(keyID)), keyID, nil
|
return path.Join(cert.Subject.CommonName, string(certID)), certID, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
// that are added.
|
||||||
func NewX509FilteredMemStore(validate func(*x509.Certificate) bool) *X509MemStore {
|
func NewX509FilteredMemStore(validate func(*x509.Certificate) bool) *X509MemStore {
|
||||||
s := &X509MemStore{
|
s := &X509MemStore{
|
||||||
|
@ -46,14 +46,14 @@ func (s X509MemStore) AddCert(cert *x509.Certificate) error {
|
||||||
return errors.New("certificate failed validation")
|
return errors.New("certificate failed validation")
|
||||||
}
|
}
|
||||||
|
|
||||||
keyID, err := fingerprintCert(cert)
|
certID, err := fingerprintCert(cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.fingerprintMap[keyID] = cert
|
s.fingerprintMap[certID] = cert
|
||||||
name := string(cert.RawSubject)
|
name := string(cert.RawSubject)
|
||||||
s.nameMap[name] = append(s.nameMap[name], keyID)
|
s.nameMap[name] = append(s.nameMap[name], certID)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -64,18 +64,18 @@ func (s X509MemStore) RemoveCert(cert *x509.Certificate) error {
|
||||||
return errors.New("removing nil Certificate to X509Store")
|
return errors.New("removing nil Certificate to X509Store")
|
||||||
}
|
}
|
||||||
|
|
||||||
keyID, err := fingerprintCert(cert)
|
certID, err := fingerprintCert(cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
delete(s.fingerprintMap, keyID)
|
delete(s.fingerprintMap, certID)
|
||||||
name := string(cert.RawSubject)
|
name := string(cert.RawSubject)
|
||||||
|
|
||||||
// Filter the fingerprint out of this name entry
|
// Filter the fingerprint out of this name entry
|
||||||
fpList := s.nameMap[name]
|
fpList := s.nameMap[name]
|
||||||
newfpList := fpList[:0]
|
newfpList := fpList[:0]
|
||||||
for _, x := range fpList {
|
for _, x := range fpList {
|
||||||
if x != keyID {
|
if x != certID {
|
||||||
newfpList = append(newfpList, x)
|
newfpList = append(newfpList, x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,21 +125,48 @@ func (s X509MemStore) GetCertificatePool() *x509.CertPool {
|
||||||
return pool
|
return pool
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCertificateByKeyID returns the certificate that matches a certain keyID or error
|
// GetCertificateByCertID returns the certificate that matches a certain certID
|
||||||
func (s X509MemStore) GetCertificateByKeyID(keyID string) (*x509.Certificate, error) {
|
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 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")
|
return nil, errors.New("invalid Subject Key Identifier")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if this subject key identifier exists
|
// 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 cert, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
return nil, errors.New("certificate not found in Key Store")
|
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
|
// GetVerifyOptions returns VerifyOptions with the certificates within the KeyStore
|
||||||
// as part of the roots list. This never allows the use of system roots, returning
|
// as part of the roots list. This never allows the use of system roots, returning
|
||||||
// an error if there are no root CAs.
|
// an error if there are no root CAs.
|
||||||
|
|
|
@ -106,14 +106,14 @@ func TestRemoveCert(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInexistentGetCertificateByKeyID(t *testing.T) {
|
func TestInexistentGetCertificateByCertID(t *testing.T) {
|
||||||
store := NewX509MemStore()
|
store := NewX509MemStore()
|
||||||
err := store.AddCertFromFile("../fixtures/root-ca.crt")
|
err := store.AddCertFromFile("../fixtures/root-ca.crt")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to load certificate from file: %v", err)
|
t.Fatalf("failed to load certificate from file: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = store.GetCertificateByKeyID("4d06afd30b8bed131d2a84c97d00b37f422021598bfae34285ce98e77b708b5a")
|
_, err = store.GetCertificateByCertID("4d06afd30b8bed131d2a84c97d00b37f422021598bfae34285ce98e77b708b5a")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("no error returned for inexistent certificate")
|
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)
|
t.Fatalf("failed to load certificate from PEM: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
keyID, err := FingerprintCert(cert)
|
certID, err := FingerprintCert(cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to fingerprint the certificate: %v", err)
|
t.Fatalf("failed to fingerprint the certificate: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tries to retrieve cert by Subject Key IDs
|
// Tries to retrieve cert by Subject Key IDs
|
||||||
_, err = store.GetCertificateByKeyID(keyID)
|
_, err = store.GetCertificateByCertID(certID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("expected certificate in store: %s", keyID)
|
t.Fatalf("expected certificate in store: %s", certID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,8 @@ type X509Store interface {
|
||||||
AddCertFromPEM(pemCerts []byte) error
|
AddCertFromPEM(pemCerts []byte) error
|
||||||
AddCertFromFile(filename string) error
|
AddCertFromFile(filename string) error
|
||||||
RemoveCert(cert *x509.Certificate) 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
|
GetCertificates() []*x509.Certificate
|
||||||
GetCertificatePool() *x509.CertPool
|
GetCertificatePool() *x509.CertPool
|
||||||
GetVerifyOptions(dnsName string) (x509.VerifyOptions, error)
|
GetVerifyOptions(dnsName string) (x509.VerifyOptions, error)
|
||||||
|
|
Loading…
Reference in New Issue