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
err = repo.Update(false)
// TODO(riyazdf): interface change to get back Update
_, err = repo.ListTargets()
switch err.(type) {
case client.ErrRepoNotInitialized, client.ErrRepositoryNotExist:
keys := repo.CryptoService.ListKeys(data.CanonicalRootRole)
keys := repo.GetCryptoService().ListKeys(data.CanonicalRootRole)
var rootKeyID string
// always select the first root key
if len(keys) > 0 {
sort.Strings(keys)
rootKeyID = keys[0]
} else {
rootPublicKey, err := repo.CryptoService.Create(data.CanonicalRootRole, "", data.ECDSAKey)
rootPublicKey, err := repo.GetCryptoService().Create(data.CanonicalRootRole, "", data.ECDSAKey)
if err != nil {
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
// us to).
// 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)
if err != nil {
return err

View File

@ -66,7 +66,7 @@ func TestAddTargetToAllSignableRolesError(t *testing.T) {
assert.NoError(t, err)
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{}
err = AddTargetToAllSignableRoles(notaryRepo, &target)
assert.EqualError(t, err, "client is offline")
@ -77,7 +77,7 @@ func TestGetSignableRolesError(t *testing.T) {
assert.NoError(t, err)
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{}
_, err = trust.GetSignableRoles(notaryRepo, &target)
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/")
}
func clearChangeList(notaryRepo *client.NotaryRepository) error {
func clearChangeList(notaryRepo client.Repository) error {
cl, err := notaryRepo.GetChangelist()
if err != nil {
return err

View File

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

View File

@ -65,7 +65,7 @@ func revokeTrust(cli command.Cli, remote string, options revokeOptions) error {
return nil
}
func revokeSignature(notaryRepo *client.NotaryRepository, tag string) error {
func revokeSignature(notaryRepo client.Repository, tag string) error {
if tag != "" {
// Revoke signature for the specified tag
if err := revokeSingleSig(notaryRepo, tag); err != nil {
@ -82,7 +82,7 @@ func revokeSignature(notaryRepo *client.NotaryRepository, tag string) error {
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)
if err != nil {
return err
@ -91,7 +91,7 @@ func revokeSingleSig(notaryRepo *client.NotaryRepository, tag string) error {
return getSignableRolesForTargetAndRemove(releasedTarget, notaryRepo)
}
func revokeAllSigs(notaryRepo *client.NotaryRepository) error {
func revokeAllSigs(notaryRepo client.Repository) error {
releasedTargetWithRoleList, err := notaryRepo.ListTargets(trust.ReleasesRole, data.CanonicalTargetsRole)
if err != nil {
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.
func getSignableRolesForTargetAndRemove(releasedTarget client.Target, notaryRepo *client.NotaryRepository) error {
func getSignableRolesForTargetAndRemove(releasedTarget client.Target, notaryRepo client.Repository) error {
signableRoles, err := trust.GetSignableRoles(notaryRepo, &releasedTarget)
if err != nil {
return err

View File

@ -86,7 +86,7 @@ func TestGetSignableRolesForTargetAndRemoveError(t *testing.T) {
assert.NoError(t, err)
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{}
err = getSignableRolesForTargetAndRemove(target, notaryRepo)
assert.EqualError(t, err, "client is offline")

View File

@ -50,7 +50,8 @@ func signImage(cli command.Cli, imageName string) error {
defer clearChangeList(notaryRepo)
// 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) {
case client.ErrRepoNotInitialized, client.ErrRepositoryNotExist:
// 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
}
func createTarget(notaryRepo *client.NotaryRepository, tag string) (client.Target, error) {
func createTarget(notaryRepo client.Repository, tag string) (client.Target, error) {
target := &client.Target{}
var err error
if tag == "" {
@ -117,7 +118,7 @@ func createTarget(notaryRepo *client.NotaryRepository, tag string) (client.Targe
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)
if err != nil {
return nil, 0, err
@ -134,7 +135,7 @@ func getReleasedTargetHashAndSize(targets []client.TargetSignedStruct, tag strin
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)
if err != nil {
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)
}
func initNotaryRepoWithSigners(notaryRepo *client.NotaryRepository, newSigner data.RoleName) error {
func initNotaryRepoWithSigners(notaryRepo client.Repository, newSigner data.RoleName) error {
rootKey, err := getOrGenerateNotaryKey(notaryRepo, data.CanonicalRootRole)
if err != nil {
return err
@ -174,25 +175,25 @@ func initNotaryRepoWithSigners(notaryRepo *client.NotaryRepository, newSigner da
}
// 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
if data.IsDelegation(role) {
role = data.RoleName(notaryRoleToSigner(role))
}
keys := notaryRepo.CryptoService.ListKeys(role)
keys := notaryRepo.GetCryptoService().ListKeys(role)
var err error
var key data.PublicKey
// always select the first key by ID
if len(keys) > 0 {
sort.Strings(keys)
keyID := keys[0]
privKey, _, err := notaryRepo.CryptoService.GetPrivateKey(keyID)
privKey, _, err := notaryRepo.GetCryptoService().GetPrivateKey(keyID)
if err != nil {
return nil, err
}
key = data.PublicKeyFromPrivate(privKey)
} else {
key, err = notaryRepo.CryptoService.Create(role, "", data.ECDSAKey)
key, err = notaryRepo.GetCryptoService().Create(role, "", data.ECDSAKey)
if err != nil {
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
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>
notaryRepo.AddDelegationRoleAndKeys(newSigner, signerKeys)
notaryRepo.AddDelegationPaths(newSigner, []string{""})

View File

@ -91,7 +91,7 @@ func TestGetOrGenerateNotaryKey(t *testing.T) {
assert.NoError(t, err)
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)
// repo is empty, try making a root key
@ -100,9 +100,9 @@ func TestGetOrGenerateNotaryKey(t *testing.T) {
assert.NotNil(t, rootKeyA)
// we should only have one newly generated key
allKeys := notaryRepo.CryptoService.ListAllKeys()
allKeys := notaryRepo.GetCryptoService().ListAllKeys()
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
rootKeyB, err := getOrGenerateNotaryKey(notaryRepo, data.CanonicalRootRole)
@ -110,9 +110,9 @@ func TestGetOrGenerateNotaryKey(t *testing.T) {
assert.NotNil(t, rootKeyB)
// we should only have one newly generated key
allKeys = notaryRepo.CryptoService.ListAllKeys()
allKeys = notaryRepo.GetCryptoService().ListAllKeys()
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
assert.Equal(t, rootKeyA, rootKeyB)
@ -123,9 +123,9 @@ func TestGetOrGenerateNotaryKey(t *testing.T) {
assert.NotNil(t, releasesKey)
// we should now have two keys
allKeys = notaryRepo.CryptoService.ListAllKeys()
allKeys = notaryRepo.GetCryptoService().ListAllKeys()
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
assert.NotEqual(t, releasesKey, rootKeyA)
assert.NotEqual(t, releasesKey, rootKeyB)
@ -136,7 +136,7 @@ func TestAddStageSigners(t *testing.T) {
assert.NoError(t, err)
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)
// stage targets/user
@ -216,7 +216,7 @@ func TestGetSignedManifestHashAndSize(t *testing.T) {
assert.NoError(t, err)
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)
target := &client.Target{}
target.Hashes, target.Length, err = getSignedManifestHashAndSize(notaryRepo, "test")
@ -244,7 +244,7 @@ func TestCreateTarget(t *testing.T) {
assert.NoError(t, err)
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)
_, err = createTarget(notaryRepo, "")
assert.EqualError(t, err, "No tag specified")
@ -257,7 +257,7 @@ func TestGetExistingSignatureInfoForReleasedTag(t *testing.T) {
assert.NoError(t, err)
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)
_, err = getExistingSignatureInfoForReleasedTag(notaryRepo, "test")
assert.EqualError(t, err, "client is offline")
@ -284,7 +284,7 @@ func TestChangeList(t *testing.T) {
cmd.SetArgs([]string{"ubuntu:latest"})
cmd.SetOutput(ioutil.Discard)
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)
cl, err := notaryRepo.GetChangelist()
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
// information needed to operate on a notary repository.
// 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)
if err != nil {
return nil, err
@ -164,7 +164,7 @@ func GetNotaryRepository(streams command.Streams, repoInfo *registry.RepositoryI
modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, tokenHandler, basicHandler))
tr := transport.NewTransport(base, modifiers...)
return client.NewFileCachedNotaryRepository(
return client.NewFileCachedRepository(
trustDirectory(),
data.GUN(repoInfo.Name.Name()),
server,
@ -233,12 +233,12 @@ func NotaryError(repoName string, err error) error {
// GetSignableRoles returns a list of roles for which we have valid signing
// 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
// translate the full key names, which includes the GUN, into just the key IDs
allCanonicalKeyIDs := make(map[string]struct{})
for fullKeyID := range repo.CryptoService.ListAllKeys() {
for fullKeyID := range repo.GetCryptoService().ListAllKeys() {
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-events 9461782956ad83b30282bf90e31fa6a70c255ba9
github.com/docker/go-units 9e638d38cf6977a37a8ea0078f3ee75a7cdb2dd1
github.com/docker/notary e8ee47e98edf5bb12c29735c5941fa6e482dcd9f
github.com/docker/notary 8a1de3cfc3f1408e54d6364fc949214a4883a9f3
github.com/docker/swarmkit 79381d0840be27f8b3f5c667b348a4467d866eeb
github.com/flynn-archive/go-shlex 3f9db97f856818214da2e1057f8ad84803971cff
github.com/gogo/protobuf v0.4

View File

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

View File

@ -12,7 +12,6 @@ import (
"regexp"
"time"
"github.com/Sirupsen/logrus"
canonicaljson "github.com/docker/go/canonical/json"
"github.com/docker/notary"
"github.com/docker/notary/client/changelist"
@ -23,6 +22,7 @@ import (
"github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/signed"
"github.com/docker/notary/tuf/utils"
"github.com/sirupsen/logrus"
)
const (
@ -36,16 +36,15 @@ func init() {
data.SetDefaultExpiryTimes(data.NotaryDefaultExpiries)
}
// NotaryRepository stores all the information needed to operate on a notary
// repository.
type NotaryRepository struct {
// repository stores all the information needed to operate on a notary repository.
type repository struct {
baseDir string
gun data.GUN
baseURL string
changelist changelist.Changelist
cache store.MetadataStore
remoteStore store.RemoteStore
CryptoService signed.CryptoService
cryptoService signed.CryptoService
tufRepo *tuf.Repo
invalid *tuf.Repo // known data that was parsable but deemed invalid
roundTrip http.RoundTripper
@ -53,15 +52,14 @@ type NotaryRepository struct {
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.
// It also retrieves the remote store associated to the base directory under where all the
// trust files will be stored and the specified GUN.
//
// 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,
retriever notary.PassRetriever, trustPinning trustpinning.TrustPinConfig) (
*NotaryRepository, error) {
func NewFileCachedRepository(baseDir string, gun data.GUN, baseURL string, rt http.RoundTripper,
retriever notary.PassRetriever, trustPinning trustpinning.TrustPinConfig) (Repository, error) {
cache, err := store.NewFileStore(
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 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
// (This is normally defaults to "~/.notary" or "~/.docker/trust" when enabling
// docker content trust).
// It expects an initialized cache. In case of a nil remote store, a default
// offline store is used.
func NewNotaryRepository(baseDir string, gun data.GUN, baseURL string, remoteStore store.RemoteStore, cache store.MetadataStore,
trustPinning trustpinning.TrustPinConfig, cryptoService signed.CryptoService, cl changelist.Changelist) (
*NotaryRepository, error) {
func NewRepository(baseDir string, gun data.GUN, baseURL string, remoteStore store.RemoteStore, cache store.MetadataStore,
trustPinning trustpinning.TrustPinConfig, cryptoService signed.CryptoService, cl changelist.Changelist) (Repository, error) {
// Repo's remote store is either a valid remote store or an OfflineStore
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)")
}
nRepo := &NotaryRepository{
nRepo := &repository{
gun: gun,
baseURL: baseURL,
baseDir: baseDir,
changelist: cl,
cache: cache,
remoteStore: remoteStore,
CryptoService: cryptoService,
cryptoService: cryptoService,
trustPinning: trustPinning,
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
}
// GetGUN is a getter for the GUN object from a NotaryRepository
func (r *NotaryRepository) GetGUN() data.GUN {
// GetGUN is a getter for the GUN object from a Repository
func (r *repository) GetGUN() data.GUN {
return r.gun
}
@ -182,8 +179,13 @@ func rootCertKey(gun data.GUN, privKey data.PrivateKey) (data.PublicKey, error)
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.
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
// 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
}
r.tufRepo = tuf.NewRepo(r.CryptoService)
r.tufRepo = tuf.NewRepo(r.GetCryptoService())
if err := r.tufRepo.InitRoot(
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
// key IDs existing in the repository's CryptoService.
// 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{}
privKeys, err := getAllPrivKeys(keyIDs, r.CryptoService)
privKeys, err := getAllPrivKeys(keyIDs, r.GetCryptoService())
if err != nil {
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
// (eg. keyIDs[0] must match pubKeys[0] and keyIDs[1] must match certs[1] and so on).
// 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) {
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
@ -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
// 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++ {
privKey, _, err := r.CryptoService.GetPrivateKey(ids[i])
privKey, _, err := r.GetCryptoService().GetPrivateKey(ids[i])
if err != nil {
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
// result is only stored on local disk, not published to the server. To do that,
// 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...)
}
@ -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
func (r *NotaryRepository) InitializeWithCertificate(rootKeyIDs []string, rootCerts []data.PublicKey,
nRepo *NotaryRepository, serverManagedRoles ...data.RoleName) error {
func (r *repository) InitializeWithCertificate(rootKeyIDs []string, rootCerts []data.PublicKey,
serverManagedRoles ...data.RoleName) error {
// If we explicitly pass in certificate(s) but not key, then look keys up using certificate
if len(rootKeyIDs) == 0 && len(rootCerts) != 0 {
rootKeyIDs = []string{}
availableRootKeyIDs := make(map[string]bool)
for _, k := range nRepo.CryptoService.ListKeys(data.CanonicalRootRole) {
for _, k := range r.GetCryptoService().ListKeys(data.CanonicalRootRole) {
availableRootKeyIDs[k] = true
}
@ -363,7 +365,7 @@ func (r *NotaryRepository) InitializeWithCertificate(rootKeyIDs []string, rootCe
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 = data.NewBaseRole(
data.CanonicalRootRole,
@ -376,7 +378,7 @@ func (r *NotaryRepository) initializeRoles(rootKeys []data.PublicKey, localRoles
for _, role := range localRoles {
// This is currently hardcoding the keys to ECDSA.
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 {
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
// in the repository when the changelist gets applied at publish time.
// 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 {
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
// roles in the repository when the changelist gets applied at publish time.
// 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)
template := changelist.NewTUFChange(changelist.ActionDelete, "",
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"
// 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.
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 {
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
// will be returned.
// 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 {
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
// 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
func (r *NotaryRepository) GetAllTargetMetadataByName(name string) ([]TargetSignedStruct, error) {
func (r *repository) GetAllTargetMetadataByName(name string) ([]TargetSignedStruct, error) {
if err := r.Update(false); err != nil {
return nil, err
}
@ -652,13 +654,13 @@ func (r *NotaryRepository) GetAllTargetMetadataByName(name string) ([]TargetSign
}
// 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
}
// getRemoteStore returns the remoteStore of a repository if valid or
// or an OfflineStore otherwise
func (r *NotaryRepository) getRemoteStore() store.RemoteStore {
func (r *repository) getRemoteStore() store.RemoteStore {
if r.remoteStore != nil {
return r.remoteStore
}
@ -676,7 +678,7 @@ type RoleWithSignatures struct {
// ListRoles returns a list of RoleWithSignatures objects for 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
if err := r.Update(false); err != nil {
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
// 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 {
return err
}
@ -730,7 +732,7 @@ func (r *NotaryRepository) Publish() error {
// publish pushes the changes in the given changelist to the remote notary-server
// 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
// update first before publishing
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
// 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 {
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
// snapshots are supported, if the snapshot metadata fails to load, that's ok.
// This assumes that bootstrapRepo is only used by Publish() or RotateKey()
func (r *NotaryRepository) bootstrapRepo() error {
b := tuf.NewRepoBuilder(r.gun, r.CryptoService, r.trustPinning)
func (r *repository) bootstrapRepo() error {
b := tuf.NewRepoBuilder(r.gun, r.GetCryptoService(), r.trustPinning)
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
// 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.")
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
// repo's information
func (r *NotaryRepository) errRepositoryNotExist() error {
func (r *repository) errRepositoryNotExist() error {
host := r.baseURL
parsed, err := url.Parse(r.baseURL)
if err == nil {
@ -1013,7 +1015,7 @@ func (r *NotaryRepository) errRepositoryNotExist() error {
// Update bootstraps a trust anchor (root.json) before updating all the
// metadata from the repo.
func (r *NotaryRepository) Update(forWrite bool) error {
func (r *repository) Update(forWrite bool) error {
c, err := r.bootstrapClient(forWrite)
if err != nil {
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
// 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
// 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
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
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
// 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
// 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 {
// 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 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
@ -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
// used for signing the role.
// 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 {
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
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
// 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 len(newKeys) == 0 {
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)
}
if err != nil {
@ -1181,7 +1183,7 @@ func (r *NotaryRepository) pubKeyListForRotation(role data.RoleName, serverManag
if len(newKeys) > 0 {
pubKeyList = make(data.KeyList, 0, len(newKeys))
for _, keyID := range newKeys {
pubKey = r.CryptoService.GetKey(keyID)
pubKey = r.GetCryptoService().GetKey(keyID)
if pubKey == nil {
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
}
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
if role != data.CanonicalRootRole {
return pubKeyList, nil
}
for i, pubKey := range pubKeyList {
privKey, loadedRole, err := r.CryptoService.GetPrivateKey(pubKey.ID())
privKey, loadedRole, err := r.GetCryptoService().GetPrivateKey(pubKey.ID())
if err != nil {
return nil, err
}
@ -1238,7 +1240,7 @@ func checkRotationInput(role data.RoleName, serverManaged bool) error {
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{
RoleName: role,
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 {
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 {
remote, err := getRemoteStore(URL, gun, rt)
if err != nil {
@ -1279,3 +1281,9 @@ func DeleteTrustData(baseDir string, gun data.GUN, URL string, rt http.RoundTrip
}
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"
"fmt"
"github.com/Sirupsen/logrus"
"github.com/docker/notary"
"github.com/docker/notary/client/changelist"
store "github.com/docker/notary/storage"
"github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/utils"
"github.com/sirupsen/logrus"
)
// AddDelegation creates changelist entries to add provided delegation public keys and paths.
// 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 {
err := r.AddDelegationRoleAndKeys(name, delegationKeys)
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.
// 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.
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) {
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.
// 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) {
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.
// 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 {
err := r.RemoveDelegationPaths(name, paths)
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.
func (r *NotaryRepository) RemoveDelegationRole(name data.RoleName) error {
func (r *repository) RemoveDelegationRole(name data.RoleName) error {
if !data.IsDelegation(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.
func (r *NotaryRepository) RemoveDelegationPaths(name data.RoleName, paths []string) error {
func (r *repository) RemoveDelegationPaths(name data.RoleName, paths []string) error {
if !data.IsDelegation(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.
// It can also delete a key from all delegations under a parent using a name
// 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) {
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.
func (r *NotaryRepository) ClearDelegationPaths(name data.RoleName) error {
func (r *repository) ClearDelegationPaths(name data.RoleName) error {
if !data.IsDelegation(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
// 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
if err := r.Update(false); err != nil {
return nil, err

View File

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

View File

@ -6,13 +6,13 @@ import (
"net/http"
"time"
"github.com/Sirupsen/logrus"
"github.com/docker/notary/client/changelist"
store "github.com/docker/notary/storage"
"github.com/docker/notary/tuf"
"github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/signed"
"github.com/docker/notary/tuf/utils"
"github.com/sirupsen/logrus"
)
// 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"
"fmt"
"github.com/Sirupsen/logrus"
"github.com/docker/notary"
store "github.com/docker/notary/storage"
"github.com/docker/notary/trustpinning"
"github.com/docker/notary/tuf"
"github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/signed"
"github.com/sirupsen/logrus"
)
// TUFClient is a usability wrapper around a raw TUF repo
type TUFClient struct {
// tufClient is a usability wrapper around a raw TUF repo
type tufClient struct {
remote store.RemoteStore
cache store.MetadataStore
oldBuilder tuf.RepoBuilder
newBuilder tuf.RepoBuilder
}
// 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 {
return &TUFClient{
// 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 {
return &tufClient{
oldBuilder: oldBuilder,
newBuilder: newBuilder,
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
func (c *TUFClient) Update() (*tuf.Repo, *tuf.Repo, error) {
func (c *tufClient) Update() (*tuf.Repo, *tuf.Repo, error) {
// 1. Get timestamp
// a. If timestamp error (verification, expired, etc...) download new root and return to 1.
// 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()
}
func (c *TUFClient) update() error {
func (c *tufClient) update() error {
if err := c.downloadTimestamp(); err != nil {
logrus.Debugf("Client Update (Timestamp): %s", err.Error())
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
// downloads all intermediate root files to allow proper key rotation.
func (c *TUFClient) updateRoot() error {
func (c *tufClient) updateRoot() error {
// Get current root version
currentRootConsistentInfo := c.oldBuilder.GetConsistentInfo(data.CanonicalRootRole)
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
// 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++ {
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
// Timestamps are special in that we ALWAYS attempt to download and only
// 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...")
role := data.CanonicalTimestampRole
consistentInfo := c.newBuilder.GetConsistentInfo(role)
@ -206,7 +206,7 @@ func (c *TUFClient) downloadTimestamp() error {
}
// downloadSnapshot is responsible for downloading the snapshot.json
func (c *TUFClient) downloadSnapshot() error {
func (c *tufClient) downloadSnapshot() error {
logrus.Debug("Loading snapshot...")
role := data.CanonicalSnapshotRole
consistentInfo := c.newBuilder.GetConsistentInfo(role)
@ -218,7 +218,7 @@ func (c *TUFClient) downloadSnapshot() error {
// 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
// to obtain the keys to validate children.
func (c *TUFClient) downloadTargets() error {
func (c *tufClient) downloadTargets() error {
toDownload := []data.DelegationRole{{
BaseRole: data.BaseRole{Name: data.CanonicalTargetsRole},
Paths: []string{""},
@ -251,7 +251,7 @@ func (c *TUFClient) downloadTargets() error {
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)
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
func (c *TUFClient) downloadRoot() ([]byte, error) {
func (c *tufClient) downloadRoot() ([]byte, error) {
role := data.CanonicalRootRole
consistentInfo := c.newBuilder.GetConsistentInfo(role)
@ -284,7 +284,7 @@ func (c *TUFClient) downloadRoot() ([]byte, error) {
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())
if err != nil {
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)
}
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()
raw, err := c.remote.GetSized(consistentName, consistentInfo.Length())
if err != nil {

View File

@ -8,7 +8,7 @@ import (
// Witness creates change objects to witness (i.e. re-sign) the given
// 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
successful := make([]data.RoleName, 0, len(roles))
for _, role := range roles {

View File

@ -6,11 +6,11 @@ import (
"errors"
"fmt"
"github.com/Sirupsen/logrus"
"github.com/docker/notary"
"github.com/docker/notary/trustmanager"
"github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/utils"
"github.com/sirupsen/logrus"
)
var (
@ -36,6 +36,10 @@ func NewCryptoService(keyStores ...trustmanager.KeyStore) *CryptoService {
// 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) {
if algorithm == data.RSAKey {
return nil, fmt.Errorf("%s keys can only be imported", data.RSAKey)
}
privKey, err := utils.GenerateKey(algorithm)
if err != nil {
return nil, fmt.Errorf("failed to generate %s key: %v", algorithm, err)

View File

@ -10,8 +10,8 @@ import (
"path/filepath"
"strings"
"github.com/Sirupsen/logrus"
"github.com/docker/notary"
"github.com/sirupsen/logrus"
)
// 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.NonRootKeysSubdir)
if fileDir != "" {
block.Headers["gun"] = fileDir[1:]
block.Headers["gun"] = filepath.ToSlash(fileDir[1:])
}
if strings.Contains(keyID, "_") {
role := strings.Split(keyID, "_")[1]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -16,10 +16,10 @@ import (
"math/big"
"time"
"github.com/Sirupsen/logrus"
"github.com/agl/ed25519"
"github.com/docker/notary"
"github.com/docker/notary/tuf/data"
"github.com/sirupsen/logrus"
)
// 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
func GenerateKey(algorithm string) (data.PrivateKey, error) {
switch algorithm {
case data.RSAKey:
return GenerateRSAKey(rand.Reader, notary.MinRSABitSize)
case data.ECDSAKey:
return GenerateECDSAKey(rand.Reader)
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)
}
// 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
func RSAToPrivateKey(rsaPrivKey *rsa.PrivateKey) (data.PrivateKey, error) {
// Get a DER-encoded representation of the PublicKey

View File

@ -1,11 +1,12 @@
github.com/Shopify/logrus-bugsnag 5a46080c635f13e8b60c24765c19d62e1ca8d0fb
github.com/Sirupsen/logrus 6d9ae300aaf85d6acd2e5424081c7fcddb21dab8
github.com/Shopify/logrus-bugsnag 6dbc35f2c30d1e37549f9673dd07912452ab28a5
github.com/sirupsen/logrus f006c2ac4710855cf0f916dd6b77acf6b048dc6e # v1.0.3
github.com/agl/ed25519 278e1ec8e8a6e017cd07577924d6766039146ced
github.com/bugsnag/bugsnag-go 13fd6b8acda029830ef9904df6b63be0a83369d0
github.com/bugsnag/panicwrap e2c28503fcd0675329da73bf48b33404db873782
github.com/bugsnag/osext 0dd3f918b21bec95ace9dc86c7e70266cfc5c702
github.com/docker/distribution 325b0804fef3a66309d962357aac3c2ce3f4d329 # v2.6.0
github.com/docker/go-connections f549a9393d05688dff0992ef3efd8bbe6c628aeb
github.com/docker/distribution edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c
github.com/opencontainers/go-digest a6d0ee40d4207ea02364bd3b9e8e77b9159ba1eb
github.com/docker/go-connections 3ede32e2033de7505e6500d6c868c2b9ed9f169d
github.com/docker/go d30aec9fd63c35133f8f79c3412ad91a3b08be06
github.com/dvsekhvalnov/jose2go 6387d3c1f5abd8443b223577d5a7e0f4e0e5731f # v1.2
github.com/go-sql-driver/mysql a0583e0143b1624142adab07e0e97fe106d99561 # v1.3
@ -25,7 +26,9 @@ github.com/spf13/cobra f368244301305f414206f889b1735a54cfc8bde8
github.com/spf13/viper be5ff3e4840cf692388bde7a057595a474ef379e
golang.org/x/crypto 5bcd134fee4dd1475da17714aac19c0aa0142e2f
golang.org/x/net 6a513affb38dc9788b449d59ffed099b8de18fa0
golang.org/x/sys 739734461d1c916b6c72a63d7efda2b27edb369f
google.golang.org/grpc 708a7f9f3283aa2d4f6132d287d78683babe55c8 # v1.0.5
github.com/pkg/errors 839d9e913e063e28dfd0e6c7b7512793e0a48be9
github.com/spf13/pflag cb88ea77998c3f024757528e3305022ab50b43be
github.com/spf13/cast 4d07383ffe94b5e5a6fa3af9211374a4507a0184
@ -40,14 +43,14 @@ github.com/kr/pretty bc9499caa0f45ee5edb2f0209fbd61fbf3d9018f # go.weekly.
github.com/hailocab/go-hostpool e80d13ce29ede4452c43dea11e79b9bc8a15b478
github.com/docker/libtrust aabc10ec26b754e797f9028f4589c5b7bd90dc20
github.com/beorn7/perks b965b613227fddccbfffe13eae360ed3fa822f8d
github.com/BurntSushi/toml bd2bdf7f18f849530ef7a1c29a4290217cab32a1
github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
github.com/matttproud/golang_protobuf_extensions d0c3fe89de86839aecf2e0579c40ba3bb336a453
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
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
# Testing requirements