mirror of https://github.com/docker/cli.git
trust: add Repository client interface
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
This commit is contained in:
parent
45c102a03d
commit
7c5b836ca5
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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{""})
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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{}{}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -2,6 +2,7 @@ package client
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/notary/tuf/data"
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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 = "*"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Canonical base role names
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue