mirror of https://github.com/docker/docs.git
make x509 certs viable as delegated public key object
Signed-off-by: David Lawrence <david.lawrence@docker.com> (github: endophage)
This commit is contained in:
parent
2bf5d4b09a
commit
fa788cb2a9
|
@ -367,7 +367,7 @@ func (r *NotaryRepository) RemoveDelegation(name string) error {
|
||||||
|
|
||||||
// AddTarget creates new changelist entries to add a target to the given roles
|
// AddTarget creates new changelist entries to add a target to the given roles
|
||||||
// in the repository when the changelist gets appied at publish time.
|
// in the repository when the changelist gets appied at publish time.
|
||||||
// If roles are unspecified, the default role is "target".
|
// If roles are unspecified, the default role is "targets".
|
||||||
func (r *NotaryRepository) AddTarget(target *Target, roles ...string) error {
|
func (r *NotaryRepository) AddTarget(target *Target, roles ...string) error {
|
||||||
|
|
||||||
cl, err := changelist.NewFileChangelist(filepath.Join(r.tufRepoPath, "changelist"))
|
cl, err := changelist.NewFileChangelist(filepath.Join(r.tufRepoPath, "changelist"))
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
ctxu "github.com/docker/distribution/context"
|
ctxu "github.com/docker/distribution/context"
|
||||||
|
@ -1581,6 +1582,93 @@ func TestPublishDelegations(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Publishing delegations works so long as the delegation parent exists by the
|
||||||
|
// time that delegation addition change is applied. Most of the tests for
|
||||||
|
// applying delegation changes in in helpers_test.go (applyTargets tests), so
|
||||||
|
// this is just a sanity test to make sure Publish calls it correctly and
|
||||||
|
// no fallback happens.
|
||||||
|
func TestPublishDelegationsX509(t *testing.T) {
|
||||||
|
var tempDirs [2]string
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
|
||||||
|
assert.NoError(t, err, "failed to create a temporary directory: %s", err)
|
||||||
|
defer os.RemoveAll(tempBaseDir)
|
||||||
|
tempDirs[i] = tempBaseDir
|
||||||
|
}
|
||||||
|
|
||||||
|
gun := "docker.com/notary"
|
||||||
|
ts := fullTestServer(t)
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
repo1, _ := initializeRepo(t, data.ECDSAKey, tempDirs[0], gun, ts.URL, false)
|
||||||
|
delgKey, err := repo1.CryptoService.Create("targets/a", data.ECDSAKey)
|
||||||
|
assert.NoError(t, err, "error creating delegation key")
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
privKey, _, err := repo1.CryptoService.GetPrivateKey(delgKey.ID())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
cert, err := cryptoservice.GenerateCertificate(
|
||||||
|
privKey, "targets/a", start, start.AddDate(1, 0, 0),
|
||||||
|
)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
delgCert := data.NewECDSAx509PublicKey(trustmanager.CertToPEM(cert))
|
||||||
|
|
||||||
|
// This should publish fine, even though targets/a/b is dependent upon
|
||||||
|
// targets/a, because these should execute in order
|
||||||
|
for _, delgName := range []string{"targets/a", "targets/a/b", "targets/c"} {
|
||||||
|
assert.NoError(t,
|
||||||
|
repo1.AddDelegation(delgName, 1, []data.PublicKey{delgCert}, []string{""}),
|
||||||
|
"error creating delegation")
|
||||||
|
}
|
||||||
|
assert.Len(t, getChanges(t, repo1), 3, "wrong number of changelist files found")
|
||||||
|
assert.NoError(t, repo1.Publish())
|
||||||
|
assert.Len(t, getChanges(t, repo1), 0, "wrong number of changelist files found")
|
||||||
|
|
||||||
|
// this should not publish, because targets/z doesn't exist
|
||||||
|
assert.NoError(t,
|
||||||
|
repo1.AddDelegation("targets/z/y", 1, []data.PublicKey{delgCert}, []string{""}),
|
||||||
|
"error creating delegation")
|
||||||
|
assert.Len(t, getChanges(t, repo1), 1, "wrong number of changelist files found")
|
||||||
|
assert.Error(t, repo1.Publish())
|
||||||
|
assert.Len(t, getChanges(t, repo1), 1, "wrong number of changelist files found")
|
||||||
|
|
||||||
|
// Create a new repo and pull from the server
|
||||||
|
repo2, err := NewNotaryRepository(tempDirs[1], gun, ts.URL,
|
||||||
|
http.DefaultTransport, passphraseRetriever)
|
||||||
|
assert.NoError(t, err, "error creating repository: %s", err)
|
||||||
|
|
||||||
|
// pull
|
||||||
|
_, err = repo2.ListTargets()
|
||||||
|
assert.NoError(t, err, "unable to pull repo")
|
||||||
|
|
||||||
|
for _, repo := range []*NotaryRepository{repo1, repo2} {
|
||||||
|
// targets should have delegations targets/a and targets/c
|
||||||
|
targets := repo.tufRepo.Targets[data.CanonicalTargetsRole]
|
||||||
|
assert.Len(t, targets.Signed.Delegations.Roles, 2)
|
||||||
|
assert.Len(t, targets.Signed.Delegations.Keys, 1)
|
||||||
|
|
||||||
|
_, ok := targets.Signed.Delegations.Keys[delgCert.ID()]
|
||||||
|
assert.True(t, ok)
|
||||||
|
|
||||||
|
foundRoleNames := make(map[string]bool)
|
||||||
|
for _, r := range targets.Signed.Delegations.Roles {
|
||||||
|
foundRoleNames[r.Name] = true
|
||||||
|
}
|
||||||
|
assert.True(t, foundRoleNames["targets/a"])
|
||||||
|
assert.True(t, foundRoleNames["targets/c"])
|
||||||
|
|
||||||
|
// targets/a should have delegation targets/a/b only
|
||||||
|
a := repo.tufRepo.Targets["targets/a"]
|
||||||
|
assert.Len(t, a.Signed.Delegations.Roles, 1)
|
||||||
|
assert.Len(t, a.Signed.Delegations.Keys, 1)
|
||||||
|
|
||||||
|
_, ok = a.Signed.Delegations.Keys[delgCert.ID()]
|
||||||
|
assert.True(t, ok)
|
||||||
|
|
||||||
|
assert.Equal(t, "targets/a/b", a.Signed.Delegations.Roles[0].Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If a changelist specifies a particular role to push targets to, and there
|
// If a changelist specifies a particular role to push targets to, and there
|
||||||
// is no such role, publish will try to publish to its parent. If the parent
|
// is no such role, publish will try to publish to its parent. If the parent
|
||||||
// doesn't work, it falls back on its parent, and so forth, and eventually
|
// doesn't work, it falls back on its parent, and so forth, and eventually
|
||||||
|
|
14
tuf/tuf.go
14
tuf/tuf.go
|
@ -530,9 +530,17 @@ func (tr *Repo) VerifyCanSign(roleName string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, keyID := range role.KeyIDs {
|
for _, keyID := range role.KeyIDs {
|
||||||
p, _, err := tr.cryptoService.GetPrivateKey(keyID)
|
k := tr.keysDB.GetKey(keyID)
|
||||||
if err == nil && p != nil {
|
canonicalID, err := utils.CanonicalKeyID(k)
|
||||||
return nil
|
check := []string{keyID}
|
||||||
|
if err == nil {
|
||||||
|
check = append(check, canonicalID)
|
||||||
|
}
|
||||||
|
for _, id := range check {
|
||||||
|
p, _, err := tr.cryptoService.GetPrivateKey(id)
|
||||||
|
if err == nil && p != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return signed.ErrNoKeys{KeyIDs: role.KeyIDs}
|
return signed.ErrNoKeys{KeyIDs: role.KeyIDs}
|
||||||
|
|
Loading…
Reference in New Issue