mirror of https://github.com/docker/docs.git
validate root file against cert store
This commit is contained in:
parent
908378c5ca
commit
cf2a819b21
|
@ -3,7 +3,9 @@ package main
|
|||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
@ -207,7 +209,7 @@ func tufList(cmd *cobra.Command, args []string) {
|
|||
"json",
|
||||
"",
|
||||
)
|
||||
c, err := bootstrapClient(remote, repo, kdb)
|
||||
c, err := bootstrapClient(gun, remote, repo, kdb)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -244,7 +246,7 @@ func tufLookup(cmd *cobra.Command, args []string) {
|
|||
"json",
|
||||
"",
|
||||
)
|
||||
c, err := bootstrapClient(remote, repo, kdb)
|
||||
c, err := bootstrapClient(gun, remote, repo, kdb)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -439,7 +441,7 @@ func saveRepo(repo *tuf.TufRepo, filestore store.MetadataStore) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func bootstrapClient(remote store.RemoteStore, repo *tuf.TufRepo, kdb *keys.KeyDB) (*client.Client, error) {
|
||||
func bootstrapClient(gun string, remote store.RemoteStore, repo *tuf.TufRepo, kdb *keys.KeyDB) (*client.Client, error) {
|
||||
rootJSON, err := remote.GetMeta("root", 5<<20)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -449,7 +451,10 @@ func bootstrapClient(remote store.RemoteStore, repo *tuf.TufRepo, kdb *keys.KeyD
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO: Validate the root file against the key store
|
||||
err = validateRoot(gun, root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = repo.SetRoot(root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -461,6 +466,35 @@ func bootstrapClient(remote store.RemoteStore, repo *tuf.TufRepo, kdb *keys.KeyD
|
|||
), nil
|
||||
}
|
||||
|
||||
func validateRoot(gun string, root *data.Signed) error {
|
||||
rootSigned := &data.Root{}
|
||||
err := json.Unmarshal(root.Signed, rootSigned)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
certs := make(map[string]*data.PublicKey)
|
||||
for _, kID := range rootSigned.Roles["root"].KeyIDs {
|
||||
// TODO: currently assuming only one cert contained in
|
||||
// public key entry
|
||||
k, _ := pem.Decode([]byte(rootSigned.Keys["kid"].Public()))
|
||||
rootCert, err := x509.ParseCertificates(k.Bytes)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
err = caStore.Verify(gun, rootCert[0])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
certs[kID] = rootSigned.Keys[kID]
|
||||
}
|
||||
_, err = signed.VerifyRoot(root, 0, certs, 1)
|
||||
if err != nil {
|
||||
// failed to validate the signatures against the certificates
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func bootstrapRepo(gun string, repo *tuf.TufRepo) store.MetadataStore {
|
||||
filestore, err := store.NewFilesystemStore(
|
||||
path.Join(viper.GetString("tufDir"), gun),
|
||||
|
|
|
@ -203,6 +203,28 @@ func (s X509FileStore) GetVerifyOptions(dnsName string) (x509.VerifyOptions, err
|
|||
return opts, nil
|
||||
}
|
||||
|
||||
func (s X509FileStore) Verify(dnsName string, certs ...*x509.Certificate) error {
|
||||
// If we have no Certificates loaded return error (we don't want to rever to using
|
||||
// system CAs).
|
||||
if len(s.fingerprintMap) == 0 {
|
||||
return errors.New("no root CAs available")
|
||||
}
|
||||
|
||||
// TODO: determine which cert in rootCerts is the leaf and add
|
||||
// the intermediates to verifyOpts.Intermediates
|
||||
opts := x509.VerifyOptions{
|
||||
DNSName: dnsName,
|
||||
Roots: s.GetCertificatePool(),
|
||||
}
|
||||
|
||||
// TODO: assuming only one cert ever passed and that it's the leaf
|
||||
chains, err := certs[0].Verify(opts)
|
||||
if len(chains) == 0 || err != nil {
|
||||
return errors.New("Certificate did not verify")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fileName(cert *x509.Certificate) string {
|
||||
return path.Join(cert.Subject.CommonName, string(FingerprintCert(cert)))
|
||||
}
|
||||
|
|
|
@ -171,3 +171,27 @@ func (s X509MemStore) GetVerifyOptions(dnsName string) (x509.VerifyOptions, erro
|
|||
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
// TODO: Create a parent Store object that implements the shared methods
|
||||
// and gets embedded into this and the X509MemoryStore
|
||||
func (s X509MemStore) Verify(dnsName string, certs ...*x509.Certificate) error {
|
||||
// If we have no Certificates loaded return error (we don't want to rever to using
|
||||
// system CAs).
|
||||
if len(s.fingerprintMap) == 0 {
|
||||
return errors.New("no root CAs available")
|
||||
}
|
||||
|
||||
// TODO: determine which cert in rootCerts is the leaf and add
|
||||
// the intermediates to verifyOpts.Intermediates
|
||||
opts := x509.VerifyOptions{
|
||||
DNSName: dnsName,
|
||||
Roots: s.GetCertificatePool(),
|
||||
}
|
||||
|
||||
// TODO: assuming only one cert ever passed and that it's the leaf
|
||||
chains, err := certs[0].Verify(opts)
|
||||
if len(chains) == 0 || err != nil {
|
||||
return errors.New("Certificate did not verify")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ type X509Store interface {
|
|||
GetCertificates() []*x509.Certificate
|
||||
GetCertificatePool() *x509.CertPool
|
||||
GetVerifyOptions(dnsName string) (x509.VerifyOptions, error)
|
||||
Verify(dnsName string, certs ...*x509.Certificate) error
|
||||
}
|
||||
|
||||
type CertID string
|
||||
|
|
Loading…
Reference in New Issue