mirror of https://github.com/docker/docs.git
add test for using a pinned cert ID when the root Public field has a bundle with intermediates
Signed-off-by: David Lawrence <david.lawrence@docker.com> (github: endophage)
This commit is contained in:
parent
94a2e3a741
commit
4776700215
|
@ -2,21 +2,28 @@ package trustpinning
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"text/template"
|
||||
|
||||
"time"
|
||||
|
||||
"github.com/docker/notary"
|
||||
"github.com/docker/notary/cryptoservice"
|
||||
"github.com/docker/notary/trustmanager"
|
||||
"github.com/docker/notary/tuf/data"
|
||||
"github.com/docker/notary/tuf/signed"
|
||||
"github.com/stretchr/testify/require"
|
||||
"time"
|
||||
)
|
||||
|
||||
type SignedRSARootTemplate struct {
|
||||
|
@ -278,6 +285,181 @@ func TestValidateRootWithPinnedCert(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestValidateRootWithPinnerCertAndIntermediates(t *testing.T) {
|
||||
now := time.Now()
|
||||
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
||||
|
||||
pass := func(keyName, alias string, createNew bool, attempts int) (passphrase string, giveup bool, err error) {
|
||||
return "password", false, nil
|
||||
}
|
||||
memStore := trustmanager.NewKeyMemoryStore(pass)
|
||||
cs := cryptoservice.NewCryptoService(memStore)
|
||||
|
||||
// generate CA cert
|
||||
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
||||
require.NoError(t, err)
|
||||
caTmpl := x509.Certificate{
|
||||
SerialNumber: serialNumber,
|
||||
Subject: pkix.Name{
|
||||
CommonName: "notary testing CA",
|
||||
},
|
||||
NotBefore: now.Add(-time.Hour),
|
||||
NotAfter: now.Add(time.Hour),
|
||||
KeyUsage: x509.KeyUsageCertSign,
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
MaxPathLen: 3,
|
||||
}
|
||||
caPrivKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
require.NoError(t, err)
|
||||
_, err = x509.CreateCertificate(
|
||||
rand.Reader,
|
||||
&caTmpl,
|
||||
&caTmpl,
|
||||
caPrivKey.Public(),
|
||||
caPrivKey,
|
||||
)
|
||||
|
||||
// generate intermediate
|
||||
intTmpl := x509.Certificate{
|
||||
SerialNumber: serialNumber,
|
||||
Subject: pkix.Name{
|
||||
CommonName: "notary testing intermediate",
|
||||
},
|
||||
NotBefore: now.Add(-time.Hour),
|
||||
NotAfter: now.Add(time.Hour),
|
||||
KeyUsage: x509.KeyUsageCertSign,
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
MaxPathLen: 2,
|
||||
}
|
||||
intPrivKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
require.NoError(t, err)
|
||||
intCert, err := x509.CreateCertificate(
|
||||
rand.Reader,
|
||||
&intTmpl,
|
||||
&caTmpl,
|
||||
intPrivKey.Public(),
|
||||
caPrivKey,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// generate leaf
|
||||
serialNumber, err = rand.Int(rand.Reader, serialNumberLimit)
|
||||
require.NoError(t, err)
|
||||
leafTmpl := x509.Certificate{
|
||||
SerialNumber: serialNumber,
|
||||
Subject: pkix.Name{
|
||||
CommonName: "docker.io/notary/test",
|
||||
},
|
||||
NotBefore: now.Add(-time.Hour),
|
||||
NotAfter: now.Add(time.Hour),
|
||||
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageCodeSigning},
|
||||
BasicConstraintsValid: true,
|
||||
}
|
||||
|
||||
leafPubKey, err := cs.Create("root", "docker.io/notary/test", data.ECDSAKey)
|
||||
require.NoError(t, err)
|
||||
leafPrivKey, _, err := cs.GetPrivateKey(leafPubKey.ID())
|
||||
require.NoError(t, err)
|
||||
signer := leafPrivKey.CryptoSigner()
|
||||
leafCert, err := x509.CreateCertificate(
|
||||
rand.Reader,
|
||||
&leafTmpl,
|
||||
&intTmpl,
|
||||
signer.Public(),
|
||||
intPrivKey,
|
||||
)
|
||||
|
||||
rootBundleWriter := bytes.NewBuffer(nil)
|
||||
pem.Encode(
|
||||
rootBundleWriter,
|
||||
&pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: leafCert,
|
||||
},
|
||||
)
|
||||
pem.Encode(
|
||||
rootBundleWriter,
|
||||
&pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: intCert,
|
||||
},
|
||||
)
|
||||
|
||||
rootBundle := rootBundleWriter.Bytes()
|
||||
|
||||
ecdsax509Key := data.NewECDSAx509PublicKey(rootBundle)
|
||||
|
||||
otherKey, err := cs.Create("targets", "docker.io/notary/test", data.ED25519Key)
|
||||
require.NoError(t, err)
|
||||
|
||||
root := data.SignedRoot{
|
||||
Signatures: make([]data.Signature, 0),
|
||||
Signed: data.Root{
|
||||
SignedCommon: data.SignedCommon{
|
||||
Type: "Root",
|
||||
Expires: now.Add(time.Hour),
|
||||
Version: 1,
|
||||
},
|
||||
Keys: map[string]data.PublicKey{
|
||||
ecdsax509Key.ID(): ecdsax509Key,
|
||||
otherKey.ID(): otherKey,
|
||||
},
|
||||
Roles: map[string]*data.RootRole{
|
||||
"root": &data.RootRole{
|
||||
KeyIDs: []string{ecdsax509Key.ID()},
|
||||
Threshold: 1,
|
||||
},
|
||||
"targets": &data.RootRole{
|
||||
KeyIDs: []string{otherKey.ID()},
|
||||
Threshold: 1,
|
||||
},
|
||||
"snapshot": &data.RootRole{
|
||||
KeyIDs: []string{otherKey.ID()},
|
||||
Threshold: 1,
|
||||
},
|
||||
"timestamp": &data.RootRole{
|
||||
KeyIDs: []string{otherKey.ID()},
|
||||
Threshold: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
Dirty: true,
|
||||
}
|
||||
|
||||
signedRoot, err := root.ToSigned()
|
||||
require.NoError(t, err)
|
||||
err = signed.Sign(cs, signedRoot, []data.PublicKey{ecdsax509Key}, 1, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
|
||||
defer os.RemoveAll(tempBaseDir)
|
||||
require.NoError(t, err, "failed to create a temporary directory: %s", err)
|
||||
// Create a X509Store
|
||||
trustPath := filepath.Join(tempBaseDir, notary.TrustedCertsDir)
|
||||
certStore, err := trustmanager.NewX509FilteredFileStore(
|
||||
trustPath,
|
||||
trustmanager.FilterCertsExpiredSha1,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = ValidateRoot(
|
||||
certStore,
|
||||
signedRoot,
|
||||
"docker.io/notary/test",
|
||||
TrustPinConfig{
|
||||
Certs: map[string][]string{
|
||||
"docker.io/notary/test": {ecdsax509Key.ID()},
|
||||
},
|
||||
DisableTOFU: true,
|
||||
},
|
||||
)
|
||||
require.NoError(t, err, "failed to validate certID with intermediate")
|
||||
}
|
||||
|
||||
func TestValidateRootFailuresWithPinnedCert(t *testing.T) {
|
||||
var testSignedRoot data.Signed
|
||||
var signedRootBytes bytes.Buffer
|
||||
|
|
Loading…
Reference in New Issue