trust: add Repository client interface

Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
This commit is contained in:
Riyaz Faizullabhoy 2017-09-11 14:07:00 -07:00
parent 45c102a03d
commit 7c5b836ca5
36 changed files with 221 additions and 174 deletions

View File

@ -109,18 +109,19 @@ func PushTrustedReference(streams command.Streams, repoInfo *registry.Repository
} }
// get the latest repository metadata so we can figure out which roles to sign // get the latest repository metadata so we can figure out which roles to sign
err = repo.Update(false) // TODO(riyazdf): interface change to get back Update
_, err = repo.ListTargets()
switch err.(type) { switch err.(type) {
case client.ErrRepoNotInitialized, client.ErrRepositoryNotExist: case client.ErrRepoNotInitialized, client.ErrRepositoryNotExist:
keys := repo.CryptoService.ListKeys(data.CanonicalRootRole) keys := repo.GetCryptoService().ListKeys(data.CanonicalRootRole)
var rootKeyID string var rootKeyID string
// always select the first root key // always select the first root key
if len(keys) > 0 { if len(keys) > 0 {
sort.Strings(keys) sort.Strings(keys)
rootKeyID = keys[0] rootKeyID = keys[0]
} else { } else {
rootPublicKey, err := repo.CryptoService.Create(data.CanonicalRootRole, "", data.ECDSAKey) rootPublicKey, err := repo.GetCryptoService().Create(data.CanonicalRootRole, "", data.ECDSAKey)
if err != nil { if err != nil {
return err return err
} }
@ -157,7 +158,7 @@ func PushTrustedReference(streams command.Streams, repoInfo *registry.Repository
// (based on whether we have the signing key and whether the role's path allows // (based on whether we have the signing key and whether the role's path allows
// us to). // us to).
// If there are no delegation roles, we add to the targets role. // If there are no delegation roles, we add to the targets role.
func AddTargetToAllSignableRoles(repo *client.NotaryRepository, target *client.Target) error { func AddTargetToAllSignableRoles(repo client.Repository, target *client.Target) error {
signableRoles, err := trust.GetSignableRoles(repo, target) signableRoles, err := trust.GetSignableRoles(repo, target)
if err != nil { if err != nil {
return err return err

View File

@ -66,7 +66,7 @@ func TestAddTargetToAllSignableRolesError(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
notaryRepo, err := client.NewFileCachedNotaryRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever("password"), trustpinning.TrustPinConfig{}) notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever("password"), trustpinning.TrustPinConfig{})
target := client.Target{} target := client.Target{}
err = AddTargetToAllSignableRoles(notaryRepo, &target) err = AddTargetToAllSignableRoles(notaryRepo, &target)
assert.EqualError(t, err, "client is offline") assert.EqualError(t, err, "client is offline")
@ -77,7 +77,7 @@ func TestGetSignableRolesError(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
notaryRepo, err := client.NewFileCachedNotaryRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever("password"), trustpinning.TrustPinConfig{}) notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever("password"), trustpinning.TrustPinConfig{})
target := client.Target{} target := client.Target{}
_, err = trust.GetSignableRoles(notaryRepo, &target) _, err = trust.GetSignableRoles(notaryRepo, &target)
assert.EqualError(t, err, "client is offline") assert.EqualError(t, err, "client is offline")

View File

@ -92,7 +92,7 @@ func notaryRoleToSigner(tufRole data.RoleName) string {
return strings.TrimPrefix(tufRole.String(), "targets/") return strings.TrimPrefix(tufRole.String(), "targets/")
} }
func clearChangeList(notaryRepo *client.NotaryRepository) error { func clearChangeList(notaryRepo client.Repository) error {
cl, err := notaryRepo.GetChangelist() cl, err := notaryRepo.GetChangelist()
if err != nil { if err != nil {
return err return err

View File

@ -8,7 +8,6 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/Sirupsen/logrus"
"github.com/docker/cli/cli" "github.com/docker/cli/cli"
"github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/formatter" "github.com/docker/cli/cli/command/formatter"
@ -16,6 +15,7 @@ import (
"github.com/docker/notary" "github.com/docker/notary"
"github.com/docker/notary/client" "github.com/docker/notary/client"
"github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/data"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )

View File

@ -65,7 +65,7 @@ func revokeTrust(cli command.Cli, remote string, options revokeOptions) error {
return nil return nil
} }
func revokeSignature(notaryRepo *client.NotaryRepository, tag string) error { func revokeSignature(notaryRepo client.Repository, tag string) error {
if tag != "" { if tag != "" {
// Revoke signature for the specified tag // Revoke signature for the specified tag
if err := revokeSingleSig(notaryRepo, tag); err != nil { if err := revokeSingleSig(notaryRepo, tag); err != nil {
@ -82,7 +82,7 @@ func revokeSignature(notaryRepo *client.NotaryRepository, tag string) error {
return notaryRepo.Publish() return notaryRepo.Publish()
} }
func revokeSingleSig(notaryRepo *client.NotaryRepository, tag string) error { func revokeSingleSig(notaryRepo client.Repository, tag string) error {
releasedTargetWithRole, err := notaryRepo.GetTargetByName(tag, trust.ReleasesRole, data.CanonicalTargetsRole) releasedTargetWithRole, err := notaryRepo.GetTargetByName(tag, trust.ReleasesRole, data.CanonicalTargetsRole)
if err != nil { if err != nil {
return err return err
@ -91,7 +91,7 @@ func revokeSingleSig(notaryRepo *client.NotaryRepository, tag string) error {
return getSignableRolesForTargetAndRemove(releasedTarget, notaryRepo) return getSignableRolesForTargetAndRemove(releasedTarget, notaryRepo)
} }
func revokeAllSigs(notaryRepo *client.NotaryRepository) error { func revokeAllSigs(notaryRepo client.Repository) error {
releasedTargetWithRoleList, err := notaryRepo.ListTargets(trust.ReleasesRole, data.CanonicalTargetsRole) releasedTargetWithRoleList, err := notaryRepo.ListTargets(trust.ReleasesRole, data.CanonicalTargetsRole)
if err != nil { if err != nil {
return err return err
@ -108,7 +108,7 @@ func revokeAllSigs(notaryRepo *client.NotaryRepository) error {
} }
// get all the roles that signed the target and removes it from all roles. // get all the roles that signed the target and removes it from all roles.
func getSignableRolesForTargetAndRemove(releasedTarget client.Target, notaryRepo *client.NotaryRepository) error { func getSignableRolesForTargetAndRemove(releasedTarget client.Target, notaryRepo client.Repository) error {
signableRoles, err := trust.GetSignableRoles(notaryRepo, &releasedTarget) signableRoles, err := trust.GetSignableRoles(notaryRepo, &releasedTarget)
if err != nil { if err != nil {
return err return err

View File

@ -86,7 +86,7 @@ func TestGetSignableRolesForTargetAndRemoveError(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
notaryRepo, err := client.NewFileCachedNotaryRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever("password"), trustpinning.TrustPinConfig{}) notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever("password"), trustpinning.TrustPinConfig{})
target := client.Target{} target := client.Target{}
err = getSignableRolesForTargetAndRemove(target, notaryRepo) err = getSignableRolesForTargetAndRemove(target, notaryRepo)
assert.EqualError(t, err, "client is offline") assert.EqualError(t, err, "client is offline")

View File

@ -50,7 +50,8 @@ func signImage(cli command.Cli, imageName string) error {
defer clearChangeList(notaryRepo) defer clearChangeList(notaryRepo)
// get the latest repository metadata so we can figure out which roles to sign // get the latest repository metadata so we can figure out which roles to sign
if err = notaryRepo.Update(false); err != nil { // TODO(riyazdf): interface change to get back Update
if _, err = notaryRepo.ListTargets(); err != nil {
switch err.(type) { switch err.(type) {
case client.ErrRepoNotInitialized, client.ErrRepositoryNotExist: case client.ErrRepoNotInitialized, client.ErrRepositoryNotExist:
// before initializing a new repo, check that the image exists locally: // before initializing a new repo, check that the image exists locally:
@ -106,7 +107,7 @@ func checkLocalImageExistence(ctx context.Context, cli command.Cli, imageName st
return err return err
} }
func createTarget(notaryRepo *client.NotaryRepository, tag string) (client.Target, error) { func createTarget(notaryRepo client.Repository, tag string) (client.Target, error) {
target := &client.Target{} target := &client.Target{}
var err error var err error
if tag == "" { if tag == "" {
@ -117,7 +118,7 @@ func createTarget(notaryRepo *client.NotaryRepository, tag string) (client.Targe
return *target, err return *target, err
} }
func getSignedManifestHashAndSize(notaryRepo *client.NotaryRepository, tag string) (data.Hashes, int64, error) { func getSignedManifestHashAndSize(notaryRepo client.Repository, tag string) (data.Hashes, int64, error) {
targets, err := notaryRepo.GetAllTargetMetadataByName(tag) targets, err := notaryRepo.GetAllTargetMetadataByName(tag)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
@ -134,7 +135,7 @@ func getReleasedTargetHashAndSize(targets []client.TargetSignedStruct, tag strin
return nil, 0, client.ErrNoSuchTarget(tag) return nil, 0, client.ErrNoSuchTarget(tag)
} }
func getExistingSignatureInfoForReleasedTag(notaryRepo *client.NotaryRepository, tag string) (trustTagRow, error) { func getExistingSignatureInfoForReleasedTag(notaryRepo client.Repository, tag string) (trustTagRow, error) {
targets, err := notaryRepo.GetAllTargetMetadataByName(tag) targets, err := notaryRepo.GetAllTargetMetadataByName(tag)
if err != nil { if err != nil {
return trustTagRow{}, err return trustTagRow{}, err
@ -152,7 +153,7 @@ func prettyPrintExistingSignatureInfo(cli command.Cli, existingSigInfo trustTagR
fmt.Fprintf(cli.Out(), "Existing signatures for tag %s digest %s from:\n%s\n", existingSigInfo.TagName, existingSigInfo.HashHex, joinedSigners) fmt.Fprintf(cli.Out(), "Existing signatures for tag %s digest %s from:\n%s\n", existingSigInfo.TagName, existingSigInfo.HashHex, joinedSigners)
} }
func initNotaryRepoWithSigners(notaryRepo *client.NotaryRepository, newSigner data.RoleName) error { func initNotaryRepoWithSigners(notaryRepo client.Repository, newSigner data.RoleName) error {
rootKey, err := getOrGenerateNotaryKey(notaryRepo, data.CanonicalRootRole) rootKey, err := getOrGenerateNotaryKey(notaryRepo, data.CanonicalRootRole)
if err != nil { if err != nil {
return err return err
@ -174,25 +175,25 @@ func initNotaryRepoWithSigners(notaryRepo *client.NotaryRepository, newSigner da
} }
// generates an ECDSA key without a GUN for the specified role // generates an ECDSA key without a GUN for the specified role
func getOrGenerateNotaryKey(notaryRepo *client.NotaryRepository, role data.RoleName) (data.PublicKey, error) { func getOrGenerateNotaryKey(notaryRepo client.Repository, role data.RoleName) (data.PublicKey, error) {
// use the signer name in the PEM headers if this is a delegation key // use the signer name in the PEM headers if this is a delegation key
if data.IsDelegation(role) { if data.IsDelegation(role) {
role = data.RoleName(notaryRoleToSigner(role)) role = data.RoleName(notaryRoleToSigner(role))
} }
keys := notaryRepo.CryptoService.ListKeys(role) keys := notaryRepo.GetCryptoService().ListKeys(role)
var err error var err error
var key data.PublicKey var key data.PublicKey
// always select the first key by ID // always select the first key by ID
if len(keys) > 0 { if len(keys) > 0 {
sort.Strings(keys) sort.Strings(keys)
keyID := keys[0] keyID := keys[0]
privKey, _, err := notaryRepo.CryptoService.GetPrivateKey(keyID) privKey, _, err := notaryRepo.GetCryptoService().GetPrivateKey(keyID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
key = data.PublicKeyFromPrivate(privKey) key = data.PublicKeyFromPrivate(privKey)
} else { } else {
key, err = notaryRepo.CryptoService.Create(role, "", data.ECDSAKey) key, err = notaryRepo.GetCryptoService().Create(role, "", data.ECDSAKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -201,7 +202,7 @@ func getOrGenerateNotaryKey(notaryRepo *client.NotaryRepository, role data.RoleN
} }
// stages changes to add a signer with the specified name and key(s). Adds to targets/<name> and targets/releases // stages changes to add a signer with the specified name and key(s). Adds to targets/<name> and targets/releases
func addStagedSigner(notaryRepo *client.NotaryRepository, newSigner data.RoleName, signerKeys []data.PublicKey) { func addStagedSigner(notaryRepo client.Repository, newSigner data.RoleName, signerKeys []data.PublicKey) {
// create targets/<username> // create targets/<username>
notaryRepo.AddDelegationRoleAndKeys(newSigner, signerKeys) notaryRepo.AddDelegationRoleAndKeys(newSigner, signerKeys)
notaryRepo.AddDelegationPaths(newSigner, []string{""}) notaryRepo.AddDelegationPaths(newSigner, []string{""})

View File

@ -91,7 +91,7 @@ func TestGetOrGenerateNotaryKey(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
notaryRepo, err := client.NewFileCachedNotaryRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{}) notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{})
assert.NoError(t, err) assert.NoError(t, err)
// repo is empty, try making a root key // repo is empty, try making a root key
@ -100,9 +100,9 @@ func TestGetOrGenerateNotaryKey(t *testing.T) {
assert.NotNil(t, rootKeyA) assert.NotNil(t, rootKeyA)
// we should only have one newly generated key // we should only have one newly generated key
allKeys := notaryRepo.CryptoService.ListAllKeys() allKeys := notaryRepo.GetCryptoService().ListAllKeys()
assert.Len(t, allKeys, 1) assert.Len(t, allKeys, 1)
assert.NotNil(t, notaryRepo.CryptoService.GetKey(rootKeyA.ID())) assert.NotNil(t, notaryRepo.GetCryptoService().GetKey(rootKeyA.ID()))
// this time we should get back the same key if we ask for another root key // this time we should get back the same key if we ask for another root key
rootKeyB, err := getOrGenerateNotaryKey(notaryRepo, data.CanonicalRootRole) rootKeyB, err := getOrGenerateNotaryKey(notaryRepo, data.CanonicalRootRole)
@ -110,9 +110,9 @@ func TestGetOrGenerateNotaryKey(t *testing.T) {
assert.NotNil(t, rootKeyB) assert.NotNil(t, rootKeyB)
// we should only have one newly generated key // we should only have one newly generated key
allKeys = notaryRepo.CryptoService.ListAllKeys() allKeys = notaryRepo.GetCryptoService().ListAllKeys()
assert.Len(t, allKeys, 1) assert.Len(t, allKeys, 1)
assert.NotNil(t, notaryRepo.CryptoService.GetKey(rootKeyB.ID())) assert.NotNil(t, notaryRepo.GetCryptoService().GetKey(rootKeyB.ID()))
// The key we retrieved should be identical to the one we generated // The key we retrieved should be identical to the one we generated
assert.Equal(t, rootKeyA, rootKeyB) assert.Equal(t, rootKeyA, rootKeyB)
@ -123,9 +123,9 @@ func TestGetOrGenerateNotaryKey(t *testing.T) {
assert.NotNil(t, releasesKey) assert.NotNil(t, releasesKey)
// we should now have two keys // we should now have two keys
allKeys = notaryRepo.CryptoService.ListAllKeys() allKeys = notaryRepo.GetCryptoService().ListAllKeys()
assert.Len(t, allKeys, 2) assert.Len(t, allKeys, 2)
assert.NotNil(t, notaryRepo.CryptoService.GetKey(releasesKey.ID())) assert.NotNil(t, notaryRepo.GetCryptoService().GetKey(releasesKey.ID()))
// The key we retrieved should be identical to the one we generated // The key we retrieved should be identical to the one we generated
assert.NotEqual(t, releasesKey, rootKeyA) assert.NotEqual(t, releasesKey, rootKeyA)
assert.NotEqual(t, releasesKey, rootKeyB) assert.NotEqual(t, releasesKey, rootKeyB)
@ -136,7 +136,7 @@ func TestAddStageSigners(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
notaryRepo, err := client.NewFileCachedNotaryRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{}) notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{})
assert.NoError(t, err) assert.NoError(t, err)
// stage targets/user // stage targets/user
@ -216,7 +216,7 @@ func TestGetSignedManifestHashAndSize(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
notaryRepo, err := client.NewFileCachedNotaryRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{}) notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{})
assert.NoError(t, err) assert.NoError(t, err)
target := &client.Target{} target := &client.Target{}
target.Hashes, target.Length, err = getSignedManifestHashAndSize(notaryRepo, "test") target.Hashes, target.Length, err = getSignedManifestHashAndSize(notaryRepo, "test")
@ -244,7 +244,7 @@ func TestCreateTarget(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
notaryRepo, err := client.NewFileCachedNotaryRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{}) notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{})
assert.NoError(t, err) assert.NoError(t, err)
_, err = createTarget(notaryRepo, "") _, err = createTarget(notaryRepo, "")
assert.EqualError(t, err, "No tag specified") assert.EqualError(t, err, "No tag specified")
@ -257,7 +257,7 @@ func TestGetExistingSignatureInfoForReleasedTag(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
notaryRepo, err := client.NewFileCachedNotaryRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{}) notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{})
assert.NoError(t, err) assert.NoError(t, err)
_, err = getExistingSignatureInfoForReleasedTag(notaryRepo, "test") _, err = getExistingSignatureInfoForReleasedTag(notaryRepo, "test")
assert.EqualError(t, err, "client is offline") assert.EqualError(t, err, "client is offline")
@ -284,7 +284,7 @@ func TestChangeList(t *testing.T) {
cmd.SetArgs([]string{"ubuntu:latest"}) cmd.SetArgs([]string{"ubuntu:latest"})
cmd.SetOutput(ioutil.Discard) cmd.SetOutput(ioutil.Discard)
err = cmd.Execute() err = cmd.Execute()
notaryRepo, err := client.NewFileCachedNotaryRepository(tmpDir, "docker.io/library/ubuntu", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{}) notaryRepo, err := client.NewFileCachedRepository(tmpDir, "docker.io/library/ubuntu", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{})
assert.NoError(t, err) assert.NoError(t, err)
cl, err := notaryRepo.GetChangelist() cl, err := notaryRepo.GetChangelist()
assert.Equal(t, len(cl.List()), 0) assert.Equal(t, len(cl.List()), 0)

View File

@ -86,7 +86,7 @@ func (scs simpleCredentialStore) SetRefreshToken(*url.URL, string, string) {
// GetNotaryRepository returns a NotaryRepository which stores all the // GetNotaryRepository returns a NotaryRepository which stores all the
// information needed to operate on a notary repository. // information needed to operate on a notary repository.
// It creates an HTTP transport providing authentication support. // It creates an HTTP transport providing authentication support.
func GetNotaryRepository(streams command.Streams, repoInfo *registry.RepositoryInfo, authConfig types.AuthConfig, actions ...string) (*client.NotaryRepository, error) { func GetNotaryRepository(streams command.Streams, repoInfo *registry.RepositoryInfo, authConfig types.AuthConfig, actions ...string) (client.Repository, error) {
server, err := Server(repoInfo.Index) server, err := Server(repoInfo.Index)
if err != nil { if err != nil {
return nil, err return nil, err
@ -164,7 +164,7 @@ func GetNotaryRepository(streams command.Streams, repoInfo *registry.RepositoryI
modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, tokenHandler, basicHandler)) modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, tokenHandler, basicHandler))
tr := transport.NewTransport(base, modifiers...) tr := transport.NewTransport(base, modifiers...)
return client.NewFileCachedNotaryRepository( return client.NewFileCachedRepository(
trustDirectory(), trustDirectory(),
data.GUN(repoInfo.Name.Name()), data.GUN(repoInfo.Name.Name()),
server, server,
@ -233,12 +233,12 @@ func NotaryError(repoName string, err error) error {
// GetSignableRoles returns a list of roles for which we have valid signing // GetSignableRoles returns a list of roles for which we have valid signing
// keys, given a notary repository and a target // keys, given a notary repository and a target
func GetSignableRoles(repo *client.NotaryRepository, target *client.Target) ([]data.RoleName, error) { func GetSignableRoles(repo client.Repository, target *client.Target) ([]data.RoleName, error) {
var signableRoles []data.RoleName var signableRoles []data.RoleName
// translate the full key names, which includes the GUN, into just the key IDs // translate the full key names, which includes the GUN, into just the key IDs
allCanonicalKeyIDs := make(map[string]struct{}) allCanonicalKeyIDs := make(map[string]struct{})
for fullKeyID := range repo.CryptoService.ListAllKeys() { for fullKeyID := range repo.GetCryptoService().ListAllKeys() {
allCanonicalKeyIDs[path.Base(fullKeyID)] = struct{}{} allCanonicalKeyIDs[path.Base(fullKeyID)] = struct{}{}
} }

View File

@ -13,7 +13,7 @@ github.com/docker/go d30aec9fd63c35133f8f79c3412ad91a3b08be06
github.com/docker/go-connections 3ede32e2033de7505e6500d6c868c2b9ed9f169d github.com/docker/go-connections 3ede32e2033de7505e6500d6c868c2b9ed9f169d
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
github.com/docker/go-units 9e638d38cf6977a37a8ea0078f3ee75a7cdb2dd1 github.com/docker/go-units 9e638d38cf6977a37a8ea0078f3ee75a7cdb2dd1
github.com/docker/notary e8ee47e98edf5bb12c29735c5941fa6e482dcd9f github.com/docker/notary 8a1de3cfc3f1408e54d6364fc949214a4883a9f3
github.com/docker/swarmkit 79381d0840be27f8b3f5c667b348a4467d866eeb github.com/docker/swarmkit 79381d0840be27f8b3f5c667b348a4467d866eeb
github.com/flynn-archive/go-shlex 3f9db97f856818214da2e1057f8ad84803971cff github.com/flynn-archive/go-shlex 3f9db97f856818214da2e1057f8ad84803971cff
github.com/gogo/protobuf v0.4 github.com/gogo/protobuf v0.4

View File

@ -5,12 +5,12 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath"
"sort" "sort"
"time" "time"
"github.com/Sirupsen/logrus"
"github.com/docker/distribution/uuid" "github.com/docker/distribution/uuid"
"path/filepath" "github.com/sirupsen/logrus"
) )
// FileChangelist stores all the changes as files // FileChangelist stores all the changes as files

View File

@ -12,7 +12,6 @@ import (
"regexp" "regexp"
"time" "time"
"github.com/Sirupsen/logrus"
canonicaljson "github.com/docker/go/canonical/json" canonicaljson "github.com/docker/go/canonical/json"
"github.com/docker/notary" "github.com/docker/notary"
"github.com/docker/notary/client/changelist" "github.com/docker/notary/client/changelist"
@ -23,6 +22,7 @@ import (
"github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/signed" "github.com/docker/notary/tuf/signed"
"github.com/docker/notary/tuf/utils" "github.com/docker/notary/tuf/utils"
"github.com/sirupsen/logrus"
) )
const ( const (
@ -36,16 +36,15 @@ func init() {
data.SetDefaultExpiryTimes(data.NotaryDefaultExpiries) data.SetDefaultExpiryTimes(data.NotaryDefaultExpiries)
} }
// NotaryRepository stores all the information needed to operate on a notary // repository stores all the information needed to operate on a notary repository.
// repository. type repository struct {
type NotaryRepository struct {
baseDir string baseDir string
gun data.GUN gun data.GUN
baseURL string baseURL string
changelist changelist.Changelist changelist changelist.Changelist
cache store.MetadataStore cache store.MetadataStore
remoteStore store.RemoteStore remoteStore store.RemoteStore
CryptoService signed.CryptoService cryptoService signed.CryptoService
tufRepo *tuf.Repo tufRepo *tuf.Repo
invalid *tuf.Repo // known data that was parsable but deemed invalid invalid *tuf.Repo // known data that was parsable but deemed invalid
roundTrip http.RoundTripper roundTrip http.RoundTripper
@ -53,15 +52,14 @@ type NotaryRepository struct {
LegacyVersions int // number of versions back to fetch roots to sign with LegacyVersions int // number of versions back to fetch roots to sign with
} }
// NewFileCachedNotaryRepository is a wrapper for NewNotaryRepository that initializes // NewFileCachedRepository is a wrapper for NewRepository that initializes
// a file cache from the provided repository, local config information and a crypto service. // a file cache from the provided repository, local config information and a crypto service.
// It also retrieves the remote store associated to the base directory under where all the // It also retrieves the remote store associated to the base directory under where all the
// trust files will be stored and the specified GUN. // trust files will be stored and the specified GUN.
// //
// In case of a nil RoundTripper, a default offline store is used instead. // In case of a nil RoundTripper, a default offline store is used instead.
func NewFileCachedNotaryRepository(baseDir string, gun data.GUN, baseURL string, rt http.RoundTripper, func NewFileCachedRepository(baseDir string, gun data.GUN, baseURL string, rt http.RoundTripper,
retriever notary.PassRetriever, trustPinning trustpinning.TrustPinConfig) ( retriever notary.PassRetriever, trustPinning trustpinning.TrustPinConfig) (Repository, error) {
*NotaryRepository, error) {
cache, err := store.NewFileStore( cache, err := store.NewFileStore(
filepath.Join(baseDir, tufDir, filepath.FromSlash(gun.String()), "metadata"), filepath.Join(baseDir, tufDir, filepath.FromSlash(gun.String()), "metadata"),
@ -91,18 +89,17 @@ func NewFileCachedNotaryRepository(baseDir string, gun data.GUN, baseURL string,
return nil, err return nil, err
} }
return NewNotaryRepository(baseDir, gun, baseURL, remoteStore, cache, trustPinning, cryptoService, cl) return NewRepository(baseDir, gun, baseURL, remoteStore, cache, trustPinning, cryptoService, cl)
} }
// NewNotaryRepository is the base method that returns a new notary repository. // NewRepository is the base method that returns a new notary repository.
// It takes the base directory under where all the trust files will be stored // It takes the base directory under where all the trust files will be stored
// (This is normally defaults to "~/.notary" or "~/.docker/trust" when enabling // (This is normally defaults to "~/.notary" or "~/.docker/trust" when enabling
// docker content trust). // docker content trust).
// It expects an initialized cache. In case of a nil remote store, a default // It expects an initialized cache. In case of a nil remote store, a default
// offline store is used. // offline store is used.
func NewNotaryRepository(baseDir string, gun data.GUN, baseURL string, remoteStore store.RemoteStore, cache store.MetadataStore, func NewRepository(baseDir string, gun data.GUN, baseURL string, remoteStore store.RemoteStore, cache store.MetadataStore,
trustPinning trustpinning.TrustPinConfig, cryptoService signed.CryptoService, cl changelist.Changelist) ( trustPinning trustpinning.TrustPinConfig, cryptoService signed.CryptoService, cl changelist.Changelist) (Repository, error) {
*NotaryRepository, error) {
// Repo's remote store is either a valid remote store or an OfflineStore // Repo's remote store is either a valid remote store or an OfflineStore
if remoteStore == nil { if remoteStore == nil {
@ -113,14 +110,14 @@ func NewNotaryRepository(baseDir string, gun data.GUN, baseURL string, remoteSto
return nil, fmt.Errorf("got an invalid cache (nil metadata store)") return nil, fmt.Errorf("got an invalid cache (nil metadata store)")
} }
nRepo := &NotaryRepository{ nRepo := &repository{
gun: gun, gun: gun,
baseURL: baseURL, baseURL: baseURL,
baseDir: baseDir, baseDir: baseDir,
changelist: cl, changelist: cl,
cache: cache, cache: cache,
remoteStore: remoteStore, remoteStore: remoteStore,
CryptoService: cryptoService, cryptoService: cryptoService,
trustPinning: trustPinning, trustPinning: trustPinning,
LegacyVersions: 0, // By default, don't sign with legacy roles LegacyVersions: 0, // By default, don't sign with legacy roles
} }
@ -128,8 +125,8 @@ func NewNotaryRepository(baseDir string, gun data.GUN, baseURL string, remoteSto
return nRepo, nil return nRepo, nil
} }
// GetGUN is a getter for the GUN object from a NotaryRepository // GetGUN is a getter for the GUN object from a Repository
func (r *NotaryRepository) GetGUN() data.GUN { func (r *repository) GetGUN() data.GUN {
return r.gun return r.gun
} }
@ -182,8 +179,13 @@ func rootCertKey(gun data.GUN, privKey data.PrivateKey) (data.PublicKey, error)
return x509PublicKey, nil return x509PublicKey, nil
} }
// GetCryptoService is the getter for the repository's CryptoService
func (r *repository) GetCryptoService() signed.CryptoService {
return r.cryptoService
}
// initialize initializes the notary repository with a set of rootkeys, root certificates and roles. // initialize initializes the notary repository with a set of rootkeys, root certificates and roles.
func (r *NotaryRepository) initialize(rootKeyIDs []string, rootCerts []data.PublicKey, serverManagedRoles ...data.RoleName) error { func (r *repository) initialize(rootKeyIDs []string, rootCerts []data.PublicKey, serverManagedRoles ...data.RoleName) error {
// currently we only support server managing timestamps and snapshots, and // currently we only support server managing timestamps and snapshots, and
// nothing else - timestamps are always managed by the server, and implicit // nothing else - timestamps are always managed by the server, and implicit
@ -234,7 +236,7 @@ func (r *NotaryRepository) initialize(rootKeyIDs []string, rootCerts []data.Publ
return err return err
} }
r.tufRepo = tuf.NewRepo(r.CryptoService) r.tufRepo = tuf.NewRepo(r.GetCryptoService())
if err := r.tufRepo.InitRoot( if err := r.tufRepo.InitRoot(
rootRole, rootRole,
@ -261,10 +263,10 @@ func (r *NotaryRepository) initialize(rootKeyIDs []string, rootCerts []data.Publ
// createNewPublicKeyFromKeyIDs generates a set of public keys corresponding to the given list of // createNewPublicKeyFromKeyIDs generates a set of public keys corresponding to the given list of
// key IDs existing in the repository's CryptoService. // key IDs existing in the repository's CryptoService.
// the public keys returned are ordered to correspond to the keyIDs // the public keys returned are ordered to correspond to the keyIDs
func (r *NotaryRepository) createNewPublicKeyFromKeyIDs(keyIDs []string) ([]data.PublicKey, error) { func (r *repository) createNewPublicKeyFromKeyIDs(keyIDs []string) ([]data.PublicKey, error) {
publicKeys := []data.PublicKey{} publicKeys := []data.PublicKey{}
privKeys, err := getAllPrivKeys(keyIDs, r.CryptoService) privKeys, err := getAllPrivKeys(keyIDs, r.GetCryptoService())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -282,7 +284,7 @@ func (r *NotaryRepository) createNewPublicKeyFromKeyIDs(keyIDs []string) ([]data
// publicKeysOfKeyIDs confirms that the public key and private keys (by Key IDs) forms valid, strictly ordered key pairs // publicKeysOfKeyIDs confirms that the public key and private keys (by Key IDs) forms valid, strictly ordered key pairs
// (eg. keyIDs[0] must match pubKeys[0] and keyIDs[1] must match certs[1] and so on). // (eg. keyIDs[0] must match pubKeys[0] and keyIDs[1] must match certs[1] and so on).
// Or throw error when they mismatch. // Or throw error when they mismatch.
func (r *NotaryRepository) publicKeysOfKeyIDs(keyIDs []string, pubKeys []data.PublicKey) ([]data.PublicKey, error) { func (r *repository) publicKeysOfKeyIDs(keyIDs []string, pubKeys []data.PublicKey) ([]data.PublicKey, error) {
if len(keyIDs) != len(pubKeys) { if len(keyIDs) != len(pubKeys) {
err := fmt.Errorf("require matching number of keyIDs and public keys but got %d IDs and %d public keys", len(keyIDs), len(pubKeys)) err := fmt.Errorf("require matching number of keyIDs and public keys but got %d IDs and %d public keys", len(keyIDs), len(pubKeys))
return nil, err return nil, err
@ -296,9 +298,9 @@ func (r *NotaryRepository) publicKeysOfKeyIDs(keyIDs []string, pubKeys []data.Pu
// matchKeyIdsWithPubKeys validates that the private keys (represented by their IDs) and the public keys // matchKeyIdsWithPubKeys validates that the private keys (represented by their IDs) and the public keys
// forms matching key pairs // forms matching key pairs
func matchKeyIdsWithPubKeys(r *NotaryRepository, ids []string, pubKeys []data.PublicKey) error { func matchKeyIdsWithPubKeys(r *repository, ids []string, pubKeys []data.PublicKey) error {
for i := 0; i < len(ids); i++ { for i := 0; i < len(ids); i++ {
privKey, _, err := r.CryptoService.GetPrivateKey(ids[i]) privKey, _, err := r.GetCryptoService().GetPrivateKey(ids[i])
if err != nil { if err != nil {
return fmt.Errorf("could not get the private key matching id %v: %v", ids[i], err) return fmt.Errorf("could not get the private key matching id %v: %v", ids[i], err)
} }
@ -317,7 +319,7 @@ func matchKeyIdsWithPubKeys(r *NotaryRepository, ids []string, pubKeys []data.Pu
// timestamp key and possibly other serverManagedRoles), but the created repository // timestamp key and possibly other serverManagedRoles), but the created repository
// result is only stored on local disk, not published to the server. To do that, // result is only stored on local disk, not published to the server. To do that,
// use r.Publish() eventually. // use r.Publish() eventually.
func (r *NotaryRepository) Initialize(rootKeyIDs []string, serverManagedRoles ...data.RoleName) error { func (r *repository) Initialize(rootKeyIDs []string, serverManagedRoles ...data.RoleName) error {
return r.initialize(rootKeyIDs, nil, serverManagedRoles...) return r.initialize(rootKeyIDs, nil, serverManagedRoles...)
} }
@ -341,14 +343,14 @@ func keyExistsInList(cert data.PublicKey, ids map[string]bool) error {
} }
// InitializeWithCertificate initializes the repository with root keys and their corresponding certificates // InitializeWithCertificate initializes the repository with root keys and their corresponding certificates
func (r *NotaryRepository) InitializeWithCertificate(rootKeyIDs []string, rootCerts []data.PublicKey, func (r *repository) InitializeWithCertificate(rootKeyIDs []string, rootCerts []data.PublicKey,
nRepo *NotaryRepository, serverManagedRoles ...data.RoleName) error { serverManagedRoles ...data.RoleName) error {
// If we explicitly pass in certificate(s) but not key, then look keys up using certificate // If we explicitly pass in certificate(s) but not key, then look keys up using certificate
if len(rootKeyIDs) == 0 && len(rootCerts) != 0 { if len(rootKeyIDs) == 0 && len(rootCerts) != 0 {
rootKeyIDs = []string{} rootKeyIDs = []string{}
availableRootKeyIDs := make(map[string]bool) availableRootKeyIDs := make(map[string]bool)
for _, k := range nRepo.CryptoService.ListKeys(data.CanonicalRootRole) { for _, k := range r.GetCryptoService().ListKeys(data.CanonicalRootRole) {
availableRootKeyIDs[k] = true availableRootKeyIDs[k] = true
} }
@ -363,7 +365,7 @@ func (r *NotaryRepository) InitializeWithCertificate(rootKeyIDs []string, rootCe
return r.initialize(rootKeyIDs, rootCerts, serverManagedRoles...) return r.initialize(rootKeyIDs, rootCerts, serverManagedRoles...)
} }
func (r *NotaryRepository) initializeRoles(rootKeys []data.PublicKey, localRoles, remoteRoles []data.RoleName) ( func (r *repository) initializeRoles(rootKeys []data.PublicKey, localRoles, remoteRoles []data.RoleName) (
root, targets, snapshot, timestamp data.BaseRole, err error) { root, targets, snapshot, timestamp data.BaseRole, err error) {
root = data.NewBaseRole( root = data.NewBaseRole(
data.CanonicalRootRole, data.CanonicalRootRole,
@ -376,7 +378,7 @@ func (r *NotaryRepository) initializeRoles(rootKeys []data.PublicKey, localRoles
for _, role := range localRoles { for _, role := range localRoles {
// This is currently hardcoding the keys to ECDSA. // This is currently hardcoding the keys to ECDSA.
var key data.PublicKey var key data.PublicKey
key, err = r.CryptoService.Create(role, r.gun, data.ECDSAKey) key, err = r.GetCryptoService().Create(role, r.gun, data.ECDSAKey)
if err != nil { if err != nil {
return return
} }
@ -462,7 +464,7 @@ func addChange(cl changelist.Changelist, c changelist.Change, roles ...data.Role
// 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 applied at publish time. // in the repository when the changelist gets applied at publish time.
// If roles are unspecified, the default role is "targets" // If roles are unspecified, the default role is "targets"
func (r *NotaryRepository) AddTarget(target *Target, roles ...data.RoleName) error { func (r *repository) AddTarget(target *Target, roles ...data.RoleName) error {
if len(target.Hashes) == 0 { if len(target.Hashes) == 0 {
return fmt.Errorf("no hashes specified for target \"%s\"", target.Name) return fmt.Errorf("no hashes specified for target \"%s\"", target.Name)
} }
@ -483,7 +485,7 @@ func (r *NotaryRepository) AddTarget(target *Target, roles ...data.RoleName) err
// RemoveTarget creates new changelist entries to remove a target from the given // RemoveTarget creates new changelist entries to remove a target from the given
// roles in the repository when the changelist gets applied at publish time. // roles in the repository when the changelist gets applied at publish time.
// If roles are unspecified, the default role is "target". // If roles are unspecified, the default role is "target".
func (r *NotaryRepository) RemoveTarget(targetName string, roles ...data.RoleName) error { func (r *repository) RemoveTarget(targetName string, roles ...data.RoleName) error {
logrus.Debugf("Removing target \"%s\"", targetName) logrus.Debugf("Removing target \"%s\"", targetName)
template := changelist.NewTUFChange(changelist.ActionDelete, "", template := changelist.NewTUFChange(changelist.ActionDelete, "",
changelist.TypeTargetsTarget, targetName, nil) changelist.TypeTargetsTarget, targetName, nil)
@ -498,7 +500,7 @@ func (r *NotaryRepository) RemoveTarget(targetName string, roles ...data.RoleNam
// its entries will be strictly shadowed by those in other parts of the "targets/a" // its entries will be strictly shadowed by those in other parts of the "targets/a"
// subtree and also the "targets/x" subtree, as we will defer parsing it until // subtree and also the "targets/x" subtree, as we will defer parsing it until
// we explicitly reach it in our iteration of the provided list of roles. // we explicitly reach it in our iteration of the provided list of roles.
func (r *NotaryRepository) ListTargets(roles ...data.RoleName) ([]*TargetWithRole, error) { func (r *repository) ListTargets(roles ...data.RoleName) ([]*TargetWithRole, error) {
if err := r.Update(false); err != nil { if err := r.Update(false); err != nil {
return nil, err return nil, err
} }
@ -551,7 +553,7 @@ func (r *NotaryRepository) ListTargets(roles ...data.RoleName) ([]*TargetWithRol
// the target entry found in the subtree of the highest priority role // the target entry found in the subtree of the highest priority role
// will be returned. // will be returned.
// See the IMPORTANT section on ListTargets above. Those roles also apply here. // See the IMPORTANT section on ListTargets above. Those roles also apply here.
func (r *NotaryRepository) GetTargetByName(name string, roles ...data.RoleName) (*TargetWithRole, error) { func (r *repository) GetTargetByName(name string, roles ...data.RoleName) (*TargetWithRole, error) {
if err := r.Update(false); err != nil { if err := r.Update(false); err != nil {
return nil, err return nil, err
} }
@ -605,7 +607,7 @@ func (f ErrNoSuchTarget) Error() string {
// GetAllTargetMetadataByName searches the entire delegation role tree to find the specified target by name for all // GetAllTargetMetadataByName searches the entire delegation role tree to find the specified target by name for all
// roles, and returns a list of TargetSignedStructs for each time it finds the specified target. // roles, and returns a list of TargetSignedStructs for each time it finds the specified target.
// If given an empty string for a target name, it will return back all targets signed into the repository in every role // If given an empty string for a target name, it will return back all targets signed into the repository in every role
func (r *NotaryRepository) GetAllTargetMetadataByName(name string) ([]TargetSignedStruct, error) { func (r *repository) GetAllTargetMetadataByName(name string) ([]TargetSignedStruct, error) {
if err := r.Update(false); err != nil { if err := r.Update(false); err != nil {
return nil, err return nil, err
} }
@ -652,13 +654,13 @@ func (r *NotaryRepository) GetAllTargetMetadataByName(name string) ([]TargetSign
} }
// GetChangelist returns the list of the repository's unpublished changes // GetChangelist returns the list of the repository's unpublished changes
func (r *NotaryRepository) GetChangelist() (changelist.Changelist, error) { func (r *repository) GetChangelist() (changelist.Changelist, error) {
return r.changelist, nil return r.changelist, nil
} }
// getRemoteStore returns the remoteStore of a repository if valid or // getRemoteStore returns the remoteStore of a repository if valid or
// or an OfflineStore otherwise // or an OfflineStore otherwise
func (r *NotaryRepository) getRemoteStore() store.RemoteStore { func (r *repository) getRemoteStore() store.RemoteStore {
if r.remoteStore != nil { if r.remoteStore != nil {
return r.remoteStore return r.remoteStore
} }
@ -676,7 +678,7 @@ type RoleWithSignatures struct {
// ListRoles returns a list of RoleWithSignatures objects for this repo // ListRoles returns a list of RoleWithSignatures objects for this repo
// This represents the latest metadata for each role in this repo // This represents the latest metadata for each role in this repo
func (r *NotaryRepository) ListRoles() ([]RoleWithSignatures, error) { func (r *repository) ListRoles() ([]RoleWithSignatures, error) {
// Update to latest repo state // Update to latest repo state
if err := r.Update(false); err != nil { if err := r.Update(false); err != nil {
return nil, err return nil, err
@ -715,7 +717,7 @@ func (r *NotaryRepository) ListRoles() ([]RoleWithSignatures, error) {
// Publish pushes the local changes in signed material to the remote notary-server // Publish pushes the local changes in signed material to the remote notary-server
// Conceptually it performs an operation similar to a `git rebase` // Conceptually it performs an operation similar to a `git rebase`
func (r *NotaryRepository) Publish() error { func (r *repository) Publish() error {
if err := r.publish(r.changelist); err != nil { if err := r.publish(r.changelist); err != nil {
return err return err
} }
@ -730,7 +732,7 @@ func (r *NotaryRepository) Publish() error {
// publish pushes the changes in the given changelist to the remote notary-server // publish pushes the changes in the given changelist to the remote notary-server
// Conceptually it performs an operation similar to a `git rebase` // Conceptually it performs an operation similar to a `git rebase`
func (r *NotaryRepository) publish(cl changelist.Changelist) error { func (r *repository) publish(cl changelist.Changelist) error {
var initialPublish bool var initialPublish bool
// update first before publishing // update first before publishing
if err := r.Update(true); err != nil { if err := r.Update(true); err != nil {
@ -837,7 +839,7 @@ func signRootIfNecessary(updates map[data.RoleName][]byte, repo *tuf.Repo, extra
// Fetch back a `legacyVersions` number of roots files, collect the root public keys // Fetch back a `legacyVersions` number of roots files, collect the root public keys
// This includes old `root` roles as well as legacy versioned root roles, e.g. `1.root` // This includes old `root` roles as well as legacy versioned root roles, e.g. `1.root`
func (r *NotaryRepository) oldKeysForLegacyClientSupport(legacyVersions int, initialPublish bool) (data.KeyList, error) { func (r *repository) oldKeysForLegacyClientSupport(legacyVersions int, initialPublish bool) (data.KeyList, error) {
if initialPublish { if initialPublish {
return nil, nil return nil, nil
} }
@ -927,8 +929,8 @@ func signTargets(updates map[data.RoleName][]byte, repo *tuf.Repo, initialPublis
// r.tufRepo. This attempts to load metadata for all roles. Since server // r.tufRepo. This attempts to load metadata for all roles. Since server
// snapshots are supported, if the snapshot metadata fails to load, that's ok. // snapshots are supported, if the snapshot metadata fails to load, that's ok.
// This assumes that bootstrapRepo is only used by Publish() or RotateKey() // This assumes that bootstrapRepo is only used by Publish() or RotateKey()
func (r *NotaryRepository) bootstrapRepo() error { func (r *repository) bootstrapRepo() error {
b := tuf.NewRepoBuilder(r.gun, r.CryptoService, r.trustPinning) b := tuf.NewRepoBuilder(r.gun, r.GetCryptoService(), r.trustPinning)
logrus.Debugf("Loading trusted collection.") logrus.Debugf("Loading trusted collection.")
@ -958,7 +960,7 @@ func (r *NotaryRepository) bootstrapRepo() error {
// saveMetadata saves contents of r.tufRepo onto the local disk, creating // saveMetadata saves contents of r.tufRepo onto the local disk, creating
// signatures as necessary, possibly prompting for passphrases. // signatures as necessary, possibly prompting for passphrases.
func (r *NotaryRepository) saveMetadata(ignoreSnapshot bool) error { func (r *repository) saveMetadata(ignoreSnapshot bool) error {
logrus.Debugf("Saving changes to Trusted Collection.") logrus.Debugf("Saving changes to Trusted Collection.")
rootJSON, err := serializeCanonicalRole(r.tufRepo, data.CanonicalRootRole, nil) rootJSON, err := serializeCanonicalRole(r.tufRepo, data.CanonicalRootRole, nil)
@ -1002,7 +1004,7 @@ func (r *NotaryRepository) saveMetadata(ignoreSnapshot bool) error {
// returns a properly constructed ErrRepositoryNotExist error based on this // returns a properly constructed ErrRepositoryNotExist error based on this
// repo's information // repo's information
func (r *NotaryRepository) errRepositoryNotExist() error { func (r *repository) errRepositoryNotExist() error {
host := r.baseURL host := r.baseURL
parsed, err := url.Parse(r.baseURL) parsed, err := url.Parse(r.baseURL)
if err == nil { if err == nil {
@ -1013,7 +1015,7 @@ func (r *NotaryRepository) errRepositoryNotExist() error {
// Update bootstraps a trust anchor (root.json) before updating all the // Update bootstraps a trust anchor (root.json) before updating all the
// metadata from the repo. // metadata from the repo.
func (r *NotaryRepository) Update(forWrite bool) error { func (r *repository) Update(forWrite bool) error {
c, err := r.bootstrapClient(forWrite) c, err := r.bootstrapClient(forWrite)
if err != nil { if err != nil {
if _, ok := err.(store.ErrMetaNotFound); ok { if _, ok := err.(store.ErrMetaNotFound); ok {
@ -1059,14 +1061,14 @@ func (r *NotaryRepository) Update(forWrite bool) error {
// //
// Returns a TUFClient for the remote server, which may not be actually // Returns a TUFClient for the remote server, which may not be actually
// operational (if the URL is invalid but a root.json is cached). // operational (if the URL is invalid but a root.json is cached).
func (r *NotaryRepository) bootstrapClient(checkInitialized bool) (*TUFClient, error) { func (r *repository) bootstrapClient(checkInitialized bool) (*tufClient, error) {
minVersion := 1 minVersion := 1
// the old root on disk should not be validated against any trust pinning configuration // the old root on disk should not be validated against any trust pinning configuration
// because if we have an old root, it itself is the thing that pins trust // because if we have an old root, it itself is the thing that pins trust
oldBuilder := tuf.NewRepoBuilder(r.gun, r.CryptoService, trustpinning.TrustPinConfig{}) oldBuilder := tuf.NewRepoBuilder(r.gun, r.GetCryptoService(), trustpinning.TrustPinConfig{})
// by default, we want to use the trust pinning configuration on any new root that we download // by default, we want to use the trust pinning configuration on any new root that we download
newBuilder := tuf.NewRepoBuilder(r.gun, r.CryptoService, r.trustPinning) newBuilder := tuf.NewRepoBuilder(r.gun, r.GetCryptoService(), r.trustPinning)
// Try to read root from cache first. We will trust this root until we detect a problem // Try to read root from cache first. We will trust this root until we detect a problem
// during update which will cause us to download a new root and perform a rotation. // during update which will cause us to download a new root and perform a rotation.
@ -1080,7 +1082,7 @@ func (r *NotaryRepository) bootstrapClient(checkInitialized bool) (*TUFClient, e
// again, the root on disk is the source of trust pinning, so use an empty trust // again, the root on disk is the source of trust pinning, so use an empty trust
// pinning configuration // pinning configuration
newBuilder = tuf.NewRepoBuilder(r.gun, r.CryptoService, trustpinning.TrustPinConfig{}) newBuilder = tuf.NewRepoBuilder(r.gun, r.GetCryptoService(), trustpinning.TrustPinConfig{})
if err := newBuilder.Load(data.CanonicalRootRole, rootJSON, minVersion, false); err != nil { if err := newBuilder.Load(data.CanonicalRootRole, rootJSON, minVersion, false); err != nil {
// Ok, the old root is expired - we want to download a new one. But we want to use the // Ok, the old root is expired - we want to download a new one. But we want to use the
@ -1126,7 +1128,7 @@ func (r *NotaryRepository) bootstrapClient(checkInitialized bool) (*TUFClient, e
return nil, ErrRepoNotInitialized{} return nil, ErrRepoNotInitialized{}
} }
return NewTUFClient(oldBuilder, newBuilder, remote, r.cache), nil return newTufClient(oldBuilder, newBuilder, remote, r.cache), nil
} }
// RotateKey removes all existing keys associated with the role. If no keys are // RotateKey removes all existing keys associated with the role. If no keys are
@ -1134,7 +1136,7 @@ func (r *NotaryRepository) bootstrapClient(checkInitialized bool) (*TUFClient, e
// managing the key to the server. If key(s) are specified by keyList, then they are // managing the key to the server. If key(s) are specified by keyList, then they are
// used for signing the role. // used for signing the role.
// These changes are staged in a changelist until publish is called. // These changes are staged in a changelist until publish is called.
func (r *NotaryRepository) RotateKey(role data.RoleName, serverManagesKey bool, keyList []string) error { func (r *repository) RotateKey(role data.RoleName, serverManagesKey bool, keyList []string) error {
if err := checkRotationInput(role, serverManagesKey); err != nil { if err := checkRotationInput(role, serverManagesKey); err != nil {
return err return err
} }
@ -1152,7 +1154,7 @@ func (r *NotaryRepository) RotateKey(role data.RoleName, serverManagesKey bool,
} }
// Given a set of new keys to rotate to and a set of keys to drop, returns the list of current keys to use // Given a set of new keys to rotate to and a set of keys to drop, returns the list of current keys to use
func (r *NotaryRepository) pubKeyListForRotation(role data.RoleName, serverManaged bool, newKeys []string) (pubKeyList data.KeyList, err error) { func (r *repository) pubKeyListForRotation(role data.RoleName, serverManaged bool, newKeys []string) (pubKeyList data.KeyList, err error) {
var pubKey data.PublicKey var pubKey data.PublicKey
// If server manages the key being rotated, request a rotation and return the new key // If server manages the key being rotated, request a rotation and return the new key
@ -1170,7 +1172,7 @@ func (r *NotaryRepository) pubKeyListForRotation(role data.RoleName, serverManag
// If no new keys are passed in, we generate one // If no new keys are passed in, we generate one
if len(newKeys) == 0 { if len(newKeys) == 0 {
pubKeyList = make(data.KeyList, 0, 1) pubKeyList = make(data.KeyList, 0, 1)
pubKey, err = r.CryptoService.Create(role, r.gun, data.ECDSAKey) pubKey, err = r.GetCryptoService().Create(role, r.gun, data.ECDSAKey)
pubKeyList = append(pubKeyList, pubKey) pubKeyList = append(pubKeyList, pubKey)
} }
if err != nil { if err != nil {
@ -1181,7 +1183,7 @@ func (r *NotaryRepository) pubKeyListForRotation(role data.RoleName, serverManag
if len(newKeys) > 0 { if len(newKeys) > 0 {
pubKeyList = make(data.KeyList, 0, len(newKeys)) pubKeyList = make(data.KeyList, 0, len(newKeys))
for _, keyID := range newKeys { for _, keyID := range newKeys {
pubKey = r.CryptoService.GetKey(keyID) pubKey = r.GetCryptoService().GetKey(keyID)
if pubKey == nil { if pubKey == nil {
return nil, fmt.Errorf("unable to find key: %s", keyID) return nil, fmt.Errorf("unable to find key: %s", keyID)
} }
@ -1197,14 +1199,14 @@ func (r *NotaryRepository) pubKeyListForRotation(role data.RoleName, serverManag
return pubKeyList, nil return pubKeyList, nil
} }
func (r *NotaryRepository) pubKeysToCerts(role data.RoleName, pubKeyList data.KeyList) (data.KeyList, error) { func (r *repository) pubKeysToCerts(role data.RoleName, pubKeyList data.KeyList) (data.KeyList, error) {
// only generate certs for root keys // only generate certs for root keys
if role != data.CanonicalRootRole { if role != data.CanonicalRootRole {
return pubKeyList, nil return pubKeyList, nil
} }
for i, pubKey := range pubKeyList { for i, pubKey := range pubKeyList {
privKey, loadedRole, err := r.CryptoService.GetPrivateKey(pubKey.ID()) privKey, loadedRole, err := r.GetCryptoService().GetPrivateKey(pubKey.ID())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1238,7 +1240,7 @@ func checkRotationInput(role data.RoleName, serverManaged bool) error {
return nil return nil
} }
func (r *NotaryRepository) rootFileKeyChange(cl changelist.Changelist, role data.RoleName, action string, keyList []data.PublicKey) error { func (r *repository) rootFileKeyChange(cl changelist.Changelist, role data.RoleName, action string, keyList []data.PublicKey) error {
meta := changelist.TUFRootData{ meta := changelist.TUFRootData{
RoleName: role, RoleName: role,
Keys: keyList, Keys: keyList,
@ -1266,7 +1268,7 @@ func DeleteTrustData(baseDir string, gun data.GUN, URL string, rt http.RoundTrip
if err := os.RemoveAll(localRepo); err != nil { if err := os.RemoveAll(localRepo); err != nil {
return fmt.Errorf("error clearing TUF repo data: %v", err) return fmt.Errorf("error clearing TUF repo data: %v", err)
} }
// Note that this will require admin permission in this NotaryRepository's roundtripper // Note that this will require admin permission for the gun in the roundtripper
if deleteRemote { if deleteRemote {
remote, err := getRemoteStore(URL, gun, rt) remote, err := getRemoteStore(URL, gun, rt)
if err != nil { if err != nil {
@ -1279,3 +1281,9 @@ func DeleteTrustData(baseDir string, gun data.GUN, URL string, rt http.RoundTrip
} }
return nil return nil
} }
// SetLegacyVersions allows the number of legacy versions of the root
// to be inspected for old signing keys to be configured.
func (r *repository) SetLegacyVersions(n int) {
r.LegacyVersions = n
}

View File

@ -4,17 +4,17 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/Sirupsen/logrus"
"github.com/docker/notary" "github.com/docker/notary"
"github.com/docker/notary/client/changelist" "github.com/docker/notary/client/changelist"
store "github.com/docker/notary/storage" store "github.com/docker/notary/storage"
"github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/utils" "github.com/docker/notary/tuf/utils"
"github.com/sirupsen/logrus"
) )
// AddDelegation creates changelist entries to add provided delegation public keys and paths. // AddDelegation creates changelist entries to add provided delegation public keys and paths.
// This method composes AddDelegationRoleAndKeys and AddDelegationPaths (each creates one changelist if called). // This method composes AddDelegationRoleAndKeys and AddDelegationPaths (each creates one changelist if called).
func (r *NotaryRepository) AddDelegation(name data.RoleName, delegationKeys []data.PublicKey, paths []string) error { func (r *repository) AddDelegation(name data.RoleName, delegationKeys []data.PublicKey, paths []string) error {
if len(delegationKeys) > 0 { if len(delegationKeys) > 0 {
err := r.AddDelegationRoleAndKeys(name, delegationKeys) err := r.AddDelegationRoleAndKeys(name, delegationKeys)
if err != nil { if err != nil {
@ -33,7 +33,7 @@ func (r *NotaryRepository) AddDelegation(name data.RoleName, delegationKeys []da
// AddDelegationRoleAndKeys creates a changelist entry to add provided delegation public keys. // AddDelegationRoleAndKeys creates a changelist entry to add provided delegation public keys.
// This method is the simplest way to create a new delegation, because the delegation must have at least // This method is the simplest way to create a new delegation, because the delegation must have at least
// one key upon creation to be valid since we will reject the changelist while validating the threshold. // one key upon creation to be valid since we will reject the changelist while validating the threshold.
func (r *NotaryRepository) AddDelegationRoleAndKeys(name data.RoleName, delegationKeys []data.PublicKey) error { func (r *repository) AddDelegationRoleAndKeys(name data.RoleName, delegationKeys []data.PublicKey) error {
if !data.IsDelegation(name) { if !data.IsDelegation(name) {
return data.ErrInvalidRole{Role: name, Reason: "invalid delegation role name"} return data.ErrInvalidRole{Role: name, Reason: "invalid delegation role name"}
@ -57,7 +57,7 @@ func (r *NotaryRepository) AddDelegationRoleAndKeys(name data.RoleName, delegati
// AddDelegationPaths creates a changelist entry to add provided paths to an existing delegation. // AddDelegationPaths creates a changelist entry to add provided paths to an existing delegation.
// This method cannot create a new delegation itself because the role must meet the key threshold upon creation. // This method cannot create a new delegation itself because the role must meet the key threshold upon creation.
func (r *NotaryRepository) AddDelegationPaths(name data.RoleName, paths []string) error { func (r *repository) AddDelegationPaths(name data.RoleName, paths []string) error {
if !data.IsDelegation(name) { if !data.IsDelegation(name) {
return data.ErrInvalidRole{Role: name, Reason: "invalid delegation role name"} return data.ErrInvalidRole{Role: name, Reason: "invalid delegation role name"}
@ -78,7 +78,7 @@ func (r *NotaryRepository) AddDelegationPaths(name data.RoleName, paths []string
// RemoveDelegationKeysAndPaths creates changelist entries to remove provided delegation key IDs and paths. // RemoveDelegationKeysAndPaths creates changelist entries to remove provided delegation key IDs and paths.
// This method composes RemoveDelegationPaths and RemoveDelegationKeys (each creates one changelist if called). // This method composes RemoveDelegationPaths and RemoveDelegationKeys (each creates one changelist if called).
func (r *NotaryRepository) RemoveDelegationKeysAndPaths(name data.RoleName, keyIDs, paths []string) error { func (r *repository) RemoveDelegationKeysAndPaths(name data.RoleName, keyIDs, paths []string) error {
if len(paths) > 0 { if len(paths) > 0 {
err := r.RemoveDelegationPaths(name, paths) err := r.RemoveDelegationPaths(name, paths)
if err != nil { if err != nil {
@ -95,7 +95,7 @@ func (r *NotaryRepository) RemoveDelegationKeysAndPaths(name data.RoleName, keyI
} }
// RemoveDelegationRole creates a changelist to remove all paths and keys from a role, and delete the role in its entirety. // RemoveDelegationRole creates a changelist to remove all paths and keys from a role, and delete the role in its entirety.
func (r *NotaryRepository) RemoveDelegationRole(name data.RoleName) error { func (r *repository) RemoveDelegationRole(name data.RoleName) error {
if !data.IsDelegation(name) { if !data.IsDelegation(name) {
return data.ErrInvalidRole{Role: name, Reason: "invalid delegation role name"} return data.ErrInvalidRole{Role: name, Reason: "invalid delegation role name"}
@ -108,7 +108,7 @@ func (r *NotaryRepository) RemoveDelegationRole(name data.RoleName) error {
} }
// RemoveDelegationPaths creates a changelist entry to remove provided paths from an existing delegation. // RemoveDelegationPaths creates a changelist entry to remove provided paths from an existing delegation.
func (r *NotaryRepository) RemoveDelegationPaths(name data.RoleName, paths []string) error { func (r *repository) RemoveDelegationPaths(name data.RoleName, paths []string) error {
if !data.IsDelegation(name) { if !data.IsDelegation(name) {
return data.ErrInvalidRole{Role: name, Reason: "invalid delegation role name"} return data.ErrInvalidRole{Role: name, Reason: "invalid delegation role name"}
@ -132,7 +132,7 @@ func (r *NotaryRepository) RemoveDelegationPaths(name data.RoleName, paths []str
// the role itself will be deleted in its entirety. // the role itself will be deleted in its entirety.
// It can also delete a key from all delegations under a parent using a name // It can also delete a key from all delegations under a parent using a name
// with a wildcard at the end. // with a wildcard at the end.
func (r *NotaryRepository) RemoveDelegationKeys(name data.RoleName, keyIDs []string) error { func (r *repository) RemoveDelegationKeys(name data.RoleName, keyIDs []string) error {
if !data.IsDelegation(name) && !data.IsWildDelegation(name) { if !data.IsDelegation(name) && !data.IsWildDelegation(name) {
return data.ErrInvalidRole{Role: name, Reason: "invalid delegation role name"} return data.ErrInvalidRole{Role: name, Reason: "invalid delegation role name"}
@ -152,7 +152,7 @@ func (r *NotaryRepository) RemoveDelegationKeys(name data.RoleName, keyIDs []str
} }
// ClearDelegationPaths creates a changelist entry to remove all paths from an existing delegation. // ClearDelegationPaths creates a changelist entry to remove all paths from an existing delegation.
func (r *NotaryRepository) ClearDelegationPaths(name data.RoleName) error { func (r *repository) ClearDelegationPaths(name data.RoleName) error {
if !data.IsDelegation(name) { if !data.IsDelegation(name) {
return data.ErrInvalidRole{Role: name, Reason: "invalid delegation role name"} return data.ErrInvalidRole{Role: name, Reason: "invalid delegation role name"}
@ -203,7 +203,7 @@ func newDeleteDelegationChange(name data.RoleName, content []byte) *changelist.T
// GetDelegationRoles returns the keys and roles of the repository's delegations // GetDelegationRoles returns the keys and roles of the repository's delegations
// Also converts key IDs to canonical key IDs to keep consistent with signing prompts // Also converts key IDs to canonical key IDs to keep consistent with signing prompts
func (r *NotaryRepository) GetDelegationRoles() ([]data.Role, error) { func (r *repository) GetDelegationRoles() ([]data.Role, error) {
// Update state of the repo to latest // Update state of the repo to latest
if err := r.Update(false); err != nil { if err := r.Update(false); err != nil {
return nil, err return nil, err

View File

@ -2,6 +2,7 @@ package client
import ( import (
"fmt" "fmt"
"github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/data"
) )

View File

@ -6,13 +6,13 @@ import (
"net/http" "net/http"
"time" "time"
"github.com/Sirupsen/logrus"
"github.com/docker/notary/client/changelist" "github.com/docker/notary/client/changelist"
store "github.com/docker/notary/storage" store "github.com/docker/notary/storage"
"github.com/docker/notary/tuf" "github.com/docker/notary/tuf"
"github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/signed" "github.com/docker/notary/tuf/signed"
"github.com/docker/notary/tuf/utils" "github.com/docker/notary/tuf/utils"
"github.com/sirupsen/logrus"
) )
// Use this to initialize remote HTTPStores from the config settings // Use this to initialize remote HTTPStores from the config settings

47
vendor/github.com/docker/notary/client/interface.go generated vendored Normal file
View File

@ -0,0 +1,47 @@
package client
import (
"github.com/docker/notary/client/changelist"
"github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/signed"
)
// Repository represents the set of options that must be supported over a TUF repo.
type Repository interface {
// General management operations
Initialize(rootKeyIDs []string, serverManagedRoles ...data.RoleName) error
InitializeWithCertificate(rootKeyIDs []string, rootCerts []data.PublicKey, serverManagedRoles ...data.RoleName) error
Publish() error
// Target Operations
AddTarget(target *Target, roles ...data.RoleName) error
RemoveTarget(targetName string, roles ...data.RoleName) error
ListTargets(roles ...data.RoleName) ([]*TargetWithRole, error)
GetTargetByName(name string, roles ...data.RoleName) (*TargetWithRole, error)
GetAllTargetMetadataByName(name string) ([]TargetSignedStruct, error)
// Changelist operations
GetChangelist() (changelist.Changelist, error)
// Role operations
ListRoles() ([]RoleWithSignatures, error)
GetDelegationRoles() ([]data.Role, error)
AddDelegation(name data.RoleName, delegationKeys []data.PublicKey, paths []string) error
AddDelegationRoleAndKeys(name data.RoleName, delegationKeys []data.PublicKey) error
AddDelegationPaths(name data.RoleName, paths []string) error
RemoveDelegationKeysAndPaths(name data.RoleName, keyIDs, paths []string) error
RemoveDelegationRole(name data.RoleName) error
RemoveDelegationPaths(name data.RoleName, paths []string) error
RemoveDelegationKeys(name data.RoleName, keyIDs []string) error
ClearDelegationPaths(name data.RoleName) error
// Witness and other re-signing operations
Witness(roles ...data.RoleName) ([]data.RoleName, error)
// Key Operations
RotateKey(role data.RoleName, serverManagesKey bool, keyList []string) error
GetCryptoService() signed.CryptoService
SetLegacyVersions(int)
GetGUN() data.GUN
}

View File

@ -4,26 +4,26 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/Sirupsen/logrus"
"github.com/docker/notary" "github.com/docker/notary"
store "github.com/docker/notary/storage" store "github.com/docker/notary/storage"
"github.com/docker/notary/trustpinning" "github.com/docker/notary/trustpinning"
"github.com/docker/notary/tuf" "github.com/docker/notary/tuf"
"github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/signed" "github.com/docker/notary/tuf/signed"
"github.com/sirupsen/logrus"
) )
// TUFClient is a usability wrapper around a raw TUF repo // tufClient is a usability wrapper around a raw TUF repo
type TUFClient struct { type tufClient struct {
remote store.RemoteStore remote store.RemoteStore
cache store.MetadataStore cache store.MetadataStore
oldBuilder tuf.RepoBuilder oldBuilder tuf.RepoBuilder
newBuilder tuf.RepoBuilder newBuilder tuf.RepoBuilder
} }
// NewTUFClient initialized a TUFClient with the given repo, remote source of content, and cache // newTufClient initialized a tufClient with the given repo, remote source of content, and cache
func NewTUFClient(oldBuilder, newBuilder tuf.RepoBuilder, remote store.RemoteStore, cache store.MetadataStore) *TUFClient { func newTufClient(oldBuilder, newBuilder tuf.RepoBuilder, remote store.RemoteStore, cache store.MetadataStore) *tufClient {
return &TUFClient{ return &tufClient{
oldBuilder: oldBuilder, oldBuilder: oldBuilder,
newBuilder: newBuilder, newBuilder: newBuilder,
remote: remote, remote: remote,
@ -32,7 +32,7 @@ func NewTUFClient(oldBuilder, newBuilder tuf.RepoBuilder, remote store.RemoteSto
} }
// Update performs an update to the TUF repo as defined by the TUF spec // Update performs an update to the TUF repo as defined by the TUF spec
func (c *TUFClient) Update() (*tuf.Repo, *tuf.Repo, error) { func (c *tufClient) Update() (*tuf.Repo, *tuf.Repo, error) {
// 1. Get timestamp // 1. Get timestamp
// a. If timestamp error (verification, expired, etc...) download new root and return to 1. // a. If timestamp error (verification, expired, etc...) download new root and return to 1.
// 2. Check if local snapshot is up to date // 2. Check if local snapshot is up to date
@ -63,7 +63,7 @@ func (c *TUFClient) Update() (*tuf.Repo, *tuf.Repo, error) {
return c.newBuilder.Finish() return c.newBuilder.Finish()
} }
func (c *TUFClient) update() error { func (c *tufClient) update() error {
if err := c.downloadTimestamp(); err != nil { if err := c.downloadTimestamp(); err != nil {
logrus.Debugf("Client Update (Timestamp): %s", err.Error()) logrus.Debugf("Client Update (Timestamp): %s", err.Error())
return err return err
@ -82,7 +82,7 @@ func (c *TUFClient) update() error {
// updateRoot checks if there is a newer version of the root available, and if so // updateRoot checks if there is a newer version of the root available, and if so
// downloads all intermediate root files to allow proper key rotation. // downloads all intermediate root files to allow proper key rotation.
func (c *TUFClient) updateRoot() error { func (c *tufClient) updateRoot() error {
// Get current root version // Get current root version
currentRootConsistentInfo := c.oldBuilder.GetConsistentInfo(data.CanonicalRootRole) currentRootConsistentInfo := c.oldBuilder.GetConsistentInfo(data.CanonicalRootRole)
currentVersion := c.oldBuilder.GetLoadedVersion(currentRootConsistentInfo.RoleName) currentVersion := c.oldBuilder.GetLoadedVersion(currentRootConsistentInfo.RoleName)
@ -147,7 +147,7 @@ func (c *TUFClient) updateRoot() error {
// updateRootVersions updates the root from it's current version to a target, rotating keys // updateRootVersions updates the root from it's current version to a target, rotating keys
// as they are found // as they are found
func (c *TUFClient) updateRootVersions(fromVersion, toVersion int) error { func (c *tufClient) updateRootVersions(fromVersion, toVersion int) error {
for v := fromVersion; v <= toVersion; v++ { for v := fromVersion; v <= toVersion; v++ {
logrus.Debugf("updating root from version %d to version %d, currently fetching %d", fromVersion, toVersion, v) logrus.Debugf("updating root from version %d to version %d, currently fetching %d", fromVersion, toVersion, v)
@ -170,7 +170,7 @@ func (c *TUFClient) updateRootVersions(fromVersion, toVersion int) error {
// downloadTimestamp is responsible for downloading the timestamp.json // downloadTimestamp is responsible for downloading the timestamp.json
// Timestamps are special in that we ALWAYS attempt to download and only // Timestamps are special in that we ALWAYS attempt to download and only
// use cache if the download fails (and the cache is still valid). // use cache if the download fails (and the cache is still valid).
func (c *TUFClient) downloadTimestamp() error { func (c *tufClient) downloadTimestamp() error {
logrus.Debug("Loading timestamp...") logrus.Debug("Loading timestamp...")
role := data.CanonicalTimestampRole role := data.CanonicalTimestampRole
consistentInfo := c.newBuilder.GetConsistentInfo(role) consistentInfo := c.newBuilder.GetConsistentInfo(role)
@ -206,7 +206,7 @@ func (c *TUFClient) downloadTimestamp() error {
} }
// downloadSnapshot is responsible for downloading the snapshot.json // downloadSnapshot is responsible for downloading the snapshot.json
func (c *TUFClient) downloadSnapshot() error { func (c *tufClient) downloadSnapshot() error {
logrus.Debug("Loading snapshot...") logrus.Debug("Loading snapshot...")
role := data.CanonicalSnapshotRole role := data.CanonicalSnapshotRole
consistentInfo := c.newBuilder.GetConsistentInfo(role) consistentInfo := c.newBuilder.GetConsistentInfo(role)
@ -218,7 +218,7 @@ func (c *TUFClient) downloadSnapshot() error {
// downloadTargets downloads all targets and delegated targets for the repository. // downloadTargets downloads all targets and delegated targets for the repository.
// It uses a pre-order tree traversal as it's necessary to download parents first // It uses a pre-order tree traversal as it's necessary to download parents first
// to obtain the keys to validate children. // to obtain the keys to validate children.
func (c *TUFClient) downloadTargets() error { func (c *tufClient) downloadTargets() error {
toDownload := []data.DelegationRole{{ toDownload := []data.DelegationRole{{
BaseRole: data.BaseRole{Name: data.CanonicalTargetsRole}, BaseRole: data.BaseRole{Name: data.CanonicalTargetsRole},
Paths: []string{""}, Paths: []string{""},
@ -251,7 +251,7 @@ func (c *TUFClient) downloadTargets() error {
return nil return nil
} }
func (c TUFClient) getTargetsFile(role data.DelegationRole, ci tuf.ConsistentInfo) ([]data.DelegationRole, error) { func (c tufClient) getTargetsFile(role data.DelegationRole, ci tuf.ConsistentInfo) ([]data.DelegationRole, error) {
logrus.Debugf("Loading %s...", role.Name) logrus.Debugf("Loading %s...", role.Name)
tgs := &data.SignedTargets{} tgs := &data.SignedTargets{}
@ -267,7 +267,7 @@ func (c TUFClient) getTargetsFile(role data.DelegationRole, ci tuf.ConsistentInf
} }
// downloadRoot is responsible for downloading the root.json // downloadRoot is responsible for downloading the root.json
func (c *TUFClient) downloadRoot() ([]byte, error) { func (c *tufClient) downloadRoot() ([]byte, error) {
role := data.CanonicalRootRole role := data.CanonicalRootRole
consistentInfo := c.newBuilder.GetConsistentInfo(role) consistentInfo := c.newBuilder.GetConsistentInfo(role)
@ -284,7 +284,7 @@ func (c *TUFClient) downloadRoot() ([]byte, error) {
return c.tryLoadCacheThenRemote(consistentInfo) return c.tryLoadCacheThenRemote(consistentInfo)
} }
func (c *TUFClient) tryLoadCacheThenRemote(consistentInfo tuf.ConsistentInfo) ([]byte, error) { func (c *tufClient) tryLoadCacheThenRemote(consistentInfo tuf.ConsistentInfo) ([]byte, error) {
cachedTS, err := c.cache.GetSized(consistentInfo.RoleName.String(), consistentInfo.Length()) cachedTS, err := c.cache.GetSized(consistentInfo.RoleName.String(), consistentInfo.Length())
if err != nil { if err != nil {
logrus.Debugf("no %s in cache, must download", consistentInfo.RoleName) logrus.Debugf("no %s in cache, must download", consistentInfo.RoleName)
@ -300,7 +300,7 @@ func (c *TUFClient) tryLoadCacheThenRemote(consistentInfo tuf.ConsistentInfo) ([
return c.tryLoadRemote(consistentInfo, cachedTS) return c.tryLoadRemote(consistentInfo, cachedTS)
} }
func (c *TUFClient) tryLoadRemote(consistentInfo tuf.ConsistentInfo, old []byte) ([]byte, error) { func (c *tufClient) tryLoadRemote(consistentInfo tuf.ConsistentInfo, old []byte) ([]byte, error) {
consistentName := consistentInfo.ConsistentName() consistentName := consistentInfo.ConsistentName()
raw, err := c.remote.GetSized(consistentName, consistentInfo.Length()) raw, err := c.remote.GetSized(consistentName, consistentInfo.Length())
if err != nil { if err != nil {

View File

@ -8,7 +8,7 @@ import (
// Witness creates change objects to witness (i.e. re-sign) the given // Witness creates change objects to witness (i.e. re-sign) the given
// roles on the next publish. One change is created per role // roles on the next publish. One change is created per role
func (r *NotaryRepository) Witness(roles ...data.RoleName) ([]data.RoleName, error) { func (r *repository) Witness(roles ...data.RoleName) ([]data.RoleName, error) {
var err error var err error
successful := make([]data.RoleName, 0, len(roles)) successful := make([]data.RoleName, 0, len(roles))
for _, role := range roles { for _, role := range roles {

View File

@ -6,11 +6,11 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/Sirupsen/logrus"
"github.com/docker/notary" "github.com/docker/notary"
"github.com/docker/notary/trustmanager" "github.com/docker/notary/trustmanager"
"github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/utils" "github.com/docker/notary/tuf/utils"
"github.com/sirupsen/logrus"
) )
var ( var (
@ -36,6 +36,10 @@ func NewCryptoService(keyStores ...trustmanager.KeyStore) *CryptoService {
// Create is used to generate keys for targets, snapshots and timestamps // Create is used to generate keys for targets, snapshots and timestamps
func (cs *CryptoService) Create(role data.RoleName, gun data.GUN, algorithm string) (data.PublicKey, error) { func (cs *CryptoService) Create(role data.RoleName, gun data.GUN, algorithm string) (data.PublicKey, error) {
if algorithm == data.RSAKey {
return nil, fmt.Errorf("%s keys can only be imported", data.RSAKey)
}
privKey, err := utils.GenerateKey(algorithm) privKey, err := utils.GenerateKey(algorithm)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to generate %s key: %v", algorithm, err) return nil, fmt.Errorf("failed to generate %s key: %v", algorithm, err)

View File

@ -10,8 +10,8 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/Sirupsen/logrus"
"github.com/docker/notary" "github.com/docker/notary"
"github.com/sirupsen/logrus"
) )
// NewFileStore creates a fully configurable file store // NewFileStore creates a fully configurable file store
@ -63,7 +63,7 @@ func (f *FilesystemStore) moveKeyTo0Dot4Location(file string) {
fileDir = strings.TrimPrefix(fileDir, notary.RootKeysSubdir) fileDir = strings.TrimPrefix(fileDir, notary.RootKeysSubdir)
fileDir = strings.TrimPrefix(fileDir, notary.NonRootKeysSubdir) fileDir = strings.TrimPrefix(fileDir, notary.NonRootKeysSubdir)
if fileDir != "" { if fileDir != "" {
block.Headers["gun"] = fileDir[1:] block.Headers["gun"] = filepath.ToSlash(fileDir[1:])
} }
if strings.Contains(keyID, "_") { if strings.Contains(keyID, "_") {
role := strings.Split(keyID, "_")[1] role := strings.Split(keyID, "_")[1]

View File

@ -22,10 +22,10 @@ import (
"net/url" "net/url"
"path" "path"
"github.com/Sirupsen/logrus"
"github.com/docker/notary" "github.com/docker/notary"
"github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/validation" "github.com/docker/notary/tuf/validation"
"github.com/sirupsen/logrus"
) )
const ( const (

View File

@ -6,11 +6,11 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/Sirupsen/logrus"
"github.com/docker/notary" "github.com/docker/notary"
store "github.com/docker/notary/storage" store "github.com/docker/notary/storage"
"github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/utils" "github.com/docker/notary/tuf/utils"
"github.com/sirupsen/logrus"
) )
type keyInfoMap map[string]KeyInfo type keyInfoMap map[string]KeyInfo

View File

@ -5,6 +5,7 @@ package yubikey
import ( import (
"encoding/pem" "encoding/pem"
"errors" "errors"
"github.com/docker/notary" "github.com/docker/notary"
"github.com/docker/notary/trustmanager" "github.com/docker/notary/trustmanager"
"github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/data"

View File

@ -16,13 +16,13 @@ import (
"os" "os"
"time" "time"
"github.com/Sirupsen/logrus"
"github.com/docker/notary" "github.com/docker/notary"
"github.com/docker/notary/trustmanager" "github.com/docker/notary/trustmanager"
"github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/signed" "github.com/docker/notary/tuf/signed"
"github.com/docker/notary/tuf/utils" "github.com/docker/notary/tuf/utils"
"github.com/miekg/pkcs11" "github.com/miekg/pkcs11"
"github.com/sirupsen/logrus"
) )
const ( const (

View File

@ -6,10 +6,10 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/Sirupsen/logrus"
"github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/signed" "github.com/docker/notary/tuf/signed"
"github.com/docker/notary/tuf/utils" "github.com/docker/notary/tuf/utils"
"github.com/sirupsen/logrus"
) )
const wildcard = "*" const wildcard = "*"

View File

@ -5,9 +5,9 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/Sirupsen/logrus"
"github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/utils" "github.com/docker/notary/tuf/utils"
"github.com/sirupsen/logrus"
) )
// TrustPinConfig represents the configuration under the trust_pinning section of the config file // TrustPinConfig represents the configuration under the trust_pinning section of the config file

View File

@ -12,9 +12,9 @@ import (
"io" "io"
"math/big" "math/big"
"github.com/Sirupsen/logrus"
"github.com/agl/ed25519" "github.com/agl/ed25519"
"github.com/docker/go/canonical/json" "github.com/docker/go/canonical/json"
"github.com/sirupsen/logrus"
) )
// PublicKey is the necessary interface for public keys // PublicKey is the necessary interface for public keys

View File

@ -6,7 +6,7 @@ import (
"regexp" "regexp"
"strings" "strings"
"github.com/Sirupsen/logrus" "github.com/sirupsen/logrus"
) )
// Canonical base role names // Canonical base role names

View File

@ -4,9 +4,9 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/Sirupsen/logrus"
"github.com/docker/go/canonical/json" "github.com/docker/go/canonical/json"
"github.com/docker/notary" "github.com/docker/notary"
"github.com/sirupsen/logrus"
) )
// SignedSnapshot is a fully unpacked snapshot.json // SignedSnapshot is a fully unpacked snapshot.json

View File

@ -14,9 +14,9 @@ import (
"strings" "strings"
"time" "time"
"github.com/Sirupsen/logrus"
"github.com/docker/go/canonical/json" "github.com/docker/go/canonical/json"
"github.com/docker/notary" "github.com/docker/notary"
"github.com/sirupsen/logrus"
) )
// GUN type for specifying gun // GUN type for specifying gun

View File

@ -14,10 +14,10 @@ package signed
import ( import (
"crypto/rand" "crypto/rand"
"github.com/Sirupsen/logrus"
"github.com/docker/notary/trustmanager" "github.com/docker/notary/trustmanager"
"github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/utils" "github.com/docker/notary/tuf/utils"
"github.com/sirupsen/logrus"
) )
// Sign takes a data.Signed and a cryptoservice containing private keys, // Sign takes a data.Signed and a cryptoservice containing private keys,

View File

@ -10,9 +10,9 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"github.com/Sirupsen/logrus"
"github.com/agl/ed25519" "github.com/agl/ed25519"
"github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/data"
"github.com/sirupsen/logrus"
) )
const ( const (

View File

@ -6,10 +6,10 @@ import (
"strings" "strings"
"time" "time"
"github.com/Sirupsen/logrus"
"github.com/docker/go/canonical/json" "github.com/docker/go/canonical/json"
"github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/utils" "github.com/docker/notary/tuf/utils"
"github.com/sirupsen/logrus"
) )
// Various basic signing errors // Various basic signing errors

View File

@ -8,11 +8,11 @@ import (
"strings" "strings"
"time" "time"
"github.com/Sirupsen/logrus"
"github.com/docker/notary" "github.com/docker/notary"
"github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/signed" "github.com/docker/notary/tuf/signed"
"github.com/docker/notary/tuf/utils" "github.com/docker/notary/tuf/utils"
"github.com/sirupsen/logrus"
) )
// ErrSigVerifyFail - signature verification failed // ErrSigVerifyFail - signature verification failed

View File

@ -16,10 +16,10 @@ import (
"math/big" "math/big"
"time" "time"
"github.com/Sirupsen/logrus"
"github.com/agl/ed25519" "github.com/agl/ed25519"
"github.com/docker/notary" "github.com/docker/notary"
"github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/data"
"github.com/sirupsen/logrus"
) )
// CanonicalKeyID returns the ID of the public bytes version of a TUF key. // CanonicalKeyID returns the ID of the public bytes version of a TUF key.
@ -339,8 +339,6 @@ func ValidateCertificate(c *x509.Certificate, checkExpiry bool) error {
// error detailing why the key could not be generated // error detailing why the key could not be generated
func GenerateKey(algorithm string) (data.PrivateKey, error) { func GenerateKey(algorithm string) (data.PrivateKey, error) {
switch algorithm { switch algorithm {
case data.RSAKey:
return GenerateRSAKey(rand.Reader, notary.MinRSABitSize)
case data.ECDSAKey: case data.ECDSAKey:
return GenerateECDSAKey(rand.Reader) return GenerateECDSAKey(rand.Reader)
case data.ED25519Key: case data.ED25519Key:
@ -349,23 +347,6 @@ func GenerateKey(algorithm string) (data.PrivateKey, error) {
return nil, fmt.Errorf("private key type not supported for key generation: %s", algorithm) return nil, fmt.Errorf("private key type not supported for key generation: %s", algorithm)
} }
// GenerateRSAKey generates an RSA private key and returns a TUF PrivateKey
func GenerateRSAKey(random io.Reader, bits int) (data.PrivateKey, error) {
rsaPrivKey, err := rsa.GenerateKey(random, bits)
if err != nil {
return nil, fmt.Errorf("could not generate private key: %v", err)
}
tufPrivKey, err := RSAToPrivateKey(rsaPrivKey)
if err != nil {
return nil, err
}
logrus.Debugf("generated RSA key with keyID: %s", tufPrivKey.ID())
return tufPrivKey, nil
}
// RSAToPrivateKey converts an rsa.Private key to a TUF data.PrivateKey type // RSAToPrivateKey converts an rsa.Private key to a TUF data.PrivateKey type
func RSAToPrivateKey(rsaPrivKey *rsa.PrivateKey) (data.PrivateKey, error) { func RSAToPrivateKey(rsaPrivKey *rsa.PrivateKey) (data.PrivateKey, error) {
// Get a DER-encoded representation of the PublicKey // Get a DER-encoded representation of the PublicKey

View File

@ -1,11 +1,12 @@
github.com/Shopify/logrus-bugsnag 5a46080c635f13e8b60c24765c19d62e1ca8d0fb github.com/Shopify/logrus-bugsnag 6dbc35f2c30d1e37549f9673dd07912452ab28a5
github.com/Sirupsen/logrus 6d9ae300aaf85d6acd2e5424081c7fcddb21dab8 github.com/sirupsen/logrus f006c2ac4710855cf0f916dd6b77acf6b048dc6e # v1.0.3
github.com/agl/ed25519 278e1ec8e8a6e017cd07577924d6766039146ced github.com/agl/ed25519 278e1ec8e8a6e017cd07577924d6766039146ced
github.com/bugsnag/bugsnag-go 13fd6b8acda029830ef9904df6b63be0a83369d0 github.com/bugsnag/bugsnag-go 13fd6b8acda029830ef9904df6b63be0a83369d0
github.com/bugsnag/panicwrap e2c28503fcd0675329da73bf48b33404db873782 github.com/bugsnag/panicwrap e2c28503fcd0675329da73bf48b33404db873782
github.com/bugsnag/osext 0dd3f918b21bec95ace9dc86c7e70266cfc5c702 github.com/bugsnag/osext 0dd3f918b21bec95ace9dc86c7e70266cfc5c702
github.com/docker/distribution 325b0804fef3a66309d962357aac3c2ce3f4d329 # v2.6.0 github.com/docker/distribution edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c
github.com/docker/go-connections f549a9393d05688dff0992ef3efd8bbe6c628aeb github.com/opencontainers/go-digest a6d0ee40d4207ea02364bd3b9e8e77b9159ba1eb
github.com/docker/go-connections 3ede32e2033de7505e6500d6c868c2b9ed9f169d
github.com/docker/go d30aec9fd63c35133f8f79c3412ad91a3b08be06 github.com/docker/go d30aec9fd63c35133f8f79c3412ad91a3b08be06
github.com/dvsekhvalnov/jose2go 6387d3c1f5abd8443b223577d5a7e0f4e0e5731f # v1.2 github.com/dvsekhvalnov/jose2go 6387d3c1f5abd8443b223577d5a7e0f4e0e5731f # v1.2
github.com/go-sql-driver/mysql a0583e0143b1624142adab07e0e97fe106d99561 # v1.3 github.com/go-sql-driver/mysql a0583e0143b1624142adab07e0e97fe106d99561 # v1.3
@ -25,7 +26,9 @@ github.com/spf13/cobra f368244301305f414206f889b1735a54cfc8bde8
github.com/spf13/viper be5ff3e4840cf692388bde7a057595a474ef379e github.com/spf13/viper be5ff3e4840cf692388bde7a057595a474ef379e
golang.org/x/crypto 5bcd134fee4dd1475da17714aac19c0aa0142e2f golang.org/x/crypto 5bcd134fee4dd1475da17714aac19c0aa0142e2f
golang.org/x/net 6a513affb38dc9788b449d59ffed099b8de18fa0 golang.org/x/net 6a513affb38dc9788b449d59ffed099b8de18fa0
golang.org/x/sys 739734461d1c916b6c72a63d7efda2b27edb369f
google.golang.org/grpc 708a7f9f3283aa2d4f6132d287d78683babe55c8 # v1.0.5 google.golang.org/grpc 708a7f9f3283aa2d4f6132d287d78683babe55c8 # v1.0.5
github.com/pkg/errors 839d9e913e063e28dfd0e6c7b7512793e0a48be9
github.com/spf13/pflag cb88ea77998c3f024757528e3305022ab50b43be github.com/spf13/pflag cb88ea77998c3f024757528e3305022ab50b43be
github.com/spf13/cast 4d07383ffe94b5e5a6fa3af9211374a4507a0184 github.com/spf13/cast 4d07383ffe94b5e5a6fa3af9211374a4507a0184
@ -40,14 +43,14 @@ github.com/kr/pretty bc9499caa0f45ee5edb2f0209fbd61fbf3d9018f # go.weekly.
github.com/hailocab/go-hostpool e80d13ce29ede4452c43dea11e79b9bc8a15b478 github.com/hailocab/go-hostpool e80d13ce29ede4452c43dea11e79b9bc8a15b478
github.com/docker/libtrust aabc10ec26b754e797f9028f4589c5b7bd90dc20 github.com/docker/libtrust aabc10ec26b754e797f9028f4589c5b7bd90dc20
github.com/beorn7/perks b965b613227fddccbfffe13eae360ed3fa822f8d github.com/beorn7/perks b965b613227fddccbfffe13eae360ed3fa822f8d
github.com/BurntSushi/toml bd2bdf7f18f849530ef7a1c29a4290217cab32a1 github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
github.com/matttproud/golang_protobuf_extensions d0c3fe89de86839aecf2e0579c40ba3bb336a453 github.com/matttproud/golang_protobuf_extensions d0c3fe89de86839aecf2e0579c40ba3bb336a453
github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
gopkg.in/dancannon/gorethink.v3 417badecf1ab14d0d6e38ad82397da2a59e2f6ca # v3.0.0 gopkg.in/dancannon/gorethink.v3 e324d6ad938205da6c1e8a0179dc97a5b1a92185 https://github.com/docker/gorethink # v3.0.0-logrus
# dependencies of gorethink.v3 # dependencies of gorethink.v3
gopkg.in/gorethink/gorethink.v2 016a1d3b4d15951ab2e39bd3596718ba94d298ba # v2.2.2 gopkg.in/gorethink/gorethink.v2 ac5be4ae8538d44ae8843b97fc9f90860cb48a85 https://github.com/docker/gorethink # v2.2.2-logrus
github.com/cenk/backoff 32cd0c5b3aef12c76ed64aaf678f6c79736be7dc # v1.0.0 github.com/cenk/backoff 32cd0c5b3aef12c76ed64aaf678f6c79736be7dc # v1.0.0
# Testing requirements # Testing requirements