mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
update tests and error messages, revendor notary with tag
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
This commit is contained in:
parent
1db0c7bb01
commit
1c32a66877
20 changed files with 117 additions and 168 deletions
|
|
@ -153,11 +153,11 @@ RUN set -x \
|
|||
&& rm -rf "$GOPATH"
|
||||
|
||||
# Install notary server
|
||||
ENV NOTARY_COMMIT 30c488b3b4c62fdbc2c1eae7cf3b62ca73f95fad
|
||||
ENV NOTARY_VERSION docker-v1.10-1
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
|
||||
&& (cd "$GOPATH/src/github.com/docker/notary" && git checkout -q "$NOTARY_COMMIT") \
|
||||
&& (cd "$GOPATH/src/github.com/docker/notary" && git checkout -q "$NOTARY_VERSION") \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
|
||||
go build -o /usr/local/bin/notary-server github.com/docker/notary/cmd/notary-server \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
|
||||
|
|
|
|||
|
|
@ -278,22 +278,24 @@ func notaryError(repoName string, err error) error {
|
|||
case *json.SyntaxError:
|
||||
logrus.Debugf("Notary syntax error: %s", err)
|
||||
return fmt.Errorf("Error: no trust data available for remote repository %s. Try running notary server and setting DOCKER_CONTENT_TRUST_SERVER to its HTTPS address?", repoName)
|
||||
case client.ErrExpired:
|
||||
case signed.ErrExpired:
|
||||
return fmt.Errorf("Error: remote repository %s out-of-date: %v", repoName, err)
|
||||
case trustmanager.ErrKeyNotFound:
|
||||
return fmt.Errorf("Error: signing keys for remote repository %s not found: %v", repoName, err)
|
||||
case *net.OpError:
|
||||
return fmt.Errorf("Error: error contacting notary server: %v", err)
|
||||
case store.ErrMetaNotFound:
|
||||
return fmt.Errorf("Error: trust data missing for remote repository %s: %v", repoName, err)
|
||||
return fmt.Errorf("Error: trust data missing for remote repository %s or remote repository not found: %v", repoName, err)
|
||||
case signed.ErrInvalidKeyType:
|
||||
return fmt.Errorf("Error: trust data mismatch for remote repository %s, could be malicious behavior: %v", repoName, err)
|
||||
return fmt.Errorf("Warning: potential malicious behavior - trust data mismatch for remote repository %s: %v", repoName, err)
|
||||
case signed.ErrNoKeys:
|
||||
return fmt.Errorf("Error: could not find signing keys for remote repository %s: %v", repoName, err)
|
||||
case signed.ErrLowVersion:
|
||||
return fmt.Errorf("Error: trust data version is lower than expected for remote repository %s, could be malicious behavior: %v", repoName, err)
|
||||
return fmt.Errorf("Warning: potential malicious behavior - trust data version is lower than expected for remote repository %s: %v", repoName, err)
|
||||
case signed.ErrInsufficientSignatures:
|
||||
return fmt.Errorf("Error: trust data has insufficient signatures for remote repository %s, could be malicious behavior: %v", repoName, err)
|
||||
return fmt.Errorf("Warning: potential malicious behavior - trust data has insufficient signatures for remote repository %s: %v", repoName, err)
|
||||
case client.ErrRepositoryNotExist:
|
||||
return fmt.Errorf("Error: remote trust data repository not initialized for %s: %v", repoName, err)
|
||||
}
|
||||
|
||||
return err
|
||||
|
|
@ -432,7 +434,7 @@ func (cli *DockerCli) trustedPush(repoInfo *registry.RepositoryInfo, tag string,
|
|||
|
||||
repo, err := cli.getNotaryRepository(repoInfo, authConfig)
|
||||
if err != nil {
|
||||
fmt.Fprintf(cli.out, "Error establishing connection to notary repository, has a notary server been setup and pointed to by the DOCKER_CONTENT_TRUST_SERVER environment variable?: %s\n", err)
|
||||
fmt.Fprintf(cli.out, "Error establishing connection to notary repository: %s\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -454,7 +456,7 @@ func (cli *DockerCli) trustedPush(repoInfo *registry.RepositoryInfo, tag string,
|
|||
}
|
||||
|
||||
err = repo.Publish()
|
||||
if _, ok := err.(*client.ErrRepoNotInitialized); !ok {
|
||||
if _, ok := err.(client.ErrRepoNotInitialized); !ok {
|
||||
return notaryError(repoInfo.FullName(), err)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ clone git github.com/docker/distribution 568bf038af6d65b376165d02886b1c7fcaef1f6
|
|||
clone git github.com/vbatts/tar-split v0.9.11
|
||||
|
||||
# get desired notary commit, might also need to be updated in Dockerfile
|
||||
clone git github.com/docker/notary 30c488b3b4c62fdbc2c1eae7cf3b62ca73f95fad
|
||||
clone git github.com/docker/notary docker-v1.10-1
|
||||
|
||||
clone git google.golang.org/grpc 174192fc93efcb188fc8f46ca447f0da606b6885 https://github.com/grpc/grpc-go.git
|
||||
clone git github.com/miekg/pkcs11 80f102b5cac759de406949c47f0928b99bd64cdf
|
||||
|
|
|
|||
|
|
@ -5805,7 +5805,7 @@ func (s *DockerTrustSuite) TestTrustedBuildUntrustedTag(c *check.C) {
|
|||
c.Fatalf("Expected error on trusted build with untrusted tag: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(out, fmt.Sprintf("trust data unavailable")) {
|
||||
if !strings.Contains(out, "does not have trust data for") {
|
||||
c.Fatalf("Unexpected output on trusted build with untrusted tag:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -312,7 +312,7 @@ func (s *DockerTrustSuite) TestUntrustedCreate(c *check.C) {
|
|||
s.trustedCmd(createCmd)
|
||||
out, _, err := runCommandWithOutput(createCmd)
|
||||
c.Assert(err, check.Not(check.IsNil))
|
||||
c.Assert(string(out), checker.Contains, "trust data unavailable", check.Commentf("Missing expected output on trusted create:\n%s", out))
|
||||
c.Assert(string(out), checker.Contains, "does not have trust data for", check.Commentf("Missing expected output on trusted create:\n%s", out))
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ func (s *DockerTrustSuite) TestUntrustedPull(c *check.C) {
|
|||
out, _, err := runCommandWithOutput(pullCmd)
|
||||
|
||||
c.Assert(err, check.NotNil, check.Commentf(out))
|
||||
c.Assert(string(out), checker.Contains, "trust data unavailable", check.Commentf(out))
|
||||
c.Assert(string(out), checker.Contains, "Error: remote trust data repository not initialized", check.Commentf(out))
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestPullWhenCertExpired(c *check.C) {
|
||||
|
|
|
|||
|
|
@ -3087,7 +3087,7 @@ func (s *DockerTrustSuite) TestUntrustedRun(c *check.C) {
|
|||
c.Fatalf("Error expected when running trusted run with:\n%s", out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "trust data unavailable") {
|
||||
if !strings.Contains(string(out), "does not have trust data for") {
|
||||
c.Fatalf("Missing expected output on trusted run:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ RUN softhsm2-util --init-token --slot 0 --label "test_token" --pin $NOTARY_SIGNE
|
|||
ENV NOTARYPKG github.com/docker/notary
|
||||
ENV GOPATH /go/src/${NOTARYPKG}/Godeps/_workspace:$GOPATH
|
||||
|
||||
EXPOSE 4443
|
||||
EXPOSE 4444
|
||||
|
||||
# Copy the local repo to the expected go path
|
||||
COPY . /go/src/github.com/docker/notary
|
||||
|
|
|
|||
115
vendor/src/github.com/docker/notary/client/client.go
vendored
115
vendor/src/github.com/docker/notary/client/client.go
vendored
|
|
@ -2,17 +2,18 @@ package client
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/jfrazelle/go/canonical/json"
|
||||
|
||||
"github.com/docker/notary/certs"
|
||||
"github.com/docker/notary/client/changelist"
|
||||
"github.com/docker/notary/cryptoservice"
|
||||
|
|
@ -39,19 +40,12 @@ func init() {
|
|||
)
|
||||
}
|
||||
|
||||
// ErrRepoNotInitialized is returned when trying to can publish on an uninitialized
|
||||
// ErrRepoNotInitialized is returned when trying to publish an uninitialized
|
||||
// notary repository
|
||||
type ErrRepoNotInitialized struct{}
|
||||
|
||||
// ErrRepoNotInitialized is returned when trying to can publish on an uninitialized
|
||||
// notary repository
|
||||
func (err *ErrRepoNotInitialized) Error() string {
|
||||
return "Repository has not been initialized"
|
||||
}
|
||||
|
||||
// ErrExpired is returned when the metadata for a role has expired
|
||||
type ErrExpired struct {
|
||||
signed.ErrExpired
|
||||
func (err ErrRepoNotInitialized) Error() string {
|
||||
return "repository has not been initialized"
|
||||
}
|
||||
|
||||
// ErrInvalidRemoteRole is returned when the server is requested to manage
|
||||
|
|
@ -65,14 +59,21 @@ func (e ErrInvalidRemoteRole) Error() string {
|
|||
"notary does not support the server managing the %s key", e.Role)
|
||||
}
|
||||
|
||||
// ErrRepositoryNotExist is returned when an action is taken on a remote
|
||||
// repository that doesn't exist
|
||||
type ErrRepositoryNotExist struct {
|
||||
remote string
|
||||
gun string
|
||||
}
|
||||
|
||||
func (err ErrRepositoryNotExist) Error() string {
|
||||
return fmt.Sprintf("%s does not have trust data for %s", err.remote, err.gun)
|
||||
}
|
||||
|
||||
const (
|
||||
tufDir = "tuf"
|
||||
)
|
||||
|
||||
// ErrRepositoryNotExist gets returned when trying to make an action over a repository
|
||||
/// that doesn't exist.
|
||||
var ErrRepositoryNotExist = errors.New("repository does not exist")
|
||||
|
||||
// NotaryRepository stores all the information needed to operate on a notary
|
||||
// repository.
|
||||
type NotaryRepository struct {
|
||||
|
|
@ -323,7 +324,7 @@ func (r *NotaryRepository) AddDelegation(name string, threshold int,
|
|||
logrus.Debugf(`Adding delegation "%s" with threshold %d, and %d keys\n`,
|
||||
name, threshold, len(delegationKeys))
|
||||
|
||||
tdJSON, err := json.Marshal(&changelist.TufDelegation{
|
||||
tdJSON, err := json.MarshalCanonical(&changelist.TufDelegation{
|
||||
NewThreshold: threshold,
|
||||
AddKeys: data.KeyList(delegationKeys),
|
||||
AddPaths: paths,
|
||||
|
|
@ -385,7 +386,7 @@ func (r *NotaryRepository) AddTarget(target *Target, roles ...string) error {
|
|||
logrus.Debugf("Adding target \"%s\" with sha256 \"%x\" and size %d bytes.\n", target.Name, target.Hashes["sha256"], target.Length)
|
||||
|
||||
meta := data.FileMeta{Length: target.Length, Hashes: target.Hashes}
|
||||
metaJSON, err := json.Marshal(meta)
|
||||
metaJSON, err := json.MarshalCanonical(meta)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -419,19 +420,11 @@ func (r *NotaryRepository) RemoveTarget(targetName string, roles ...string) erro
|
|||
// 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 ...string) ([]*TargetWithRole, error) {
|
||||
c, err := r.bootstrapClient()
|
||||
_, err := r.Update()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = c.Update()
|
||||
if err != nil {
|
||||
if err, ok := err.(signed.ErrExpired); ok {
|
||||
return nil, ErrExpired{err}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(roles) == 0 {
|
||||
roles = []string{data.CanonicalTargetsRole}
|
||||
}
|
||||
|
|
@ -487,19 +480,11 @@ func (r *NotaryRepository) listSubtree(targets map[string]*TargetWithRole, role
|
|||
// will be returned
|
||||
// See the IMPORTANT section on ListTargets above. Those roles also apply here.
|
||||
func (r *NotaryRepository) GetTargetByName(name string, roles ...string) (*TargetWithRole, error) {
|
||||
c, err := r.bootstrapClient()
|
||||
c, err := r.Update()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = c.Update()
|
||||
if err != nil {
|
||||
if err, ok := err.(signed.ErrExpired); ok {
|
||||
return nil, ErrExpired{err}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(roles) == 0 {
|
||||
roles = append(roles, data.CanonicalTargetsRole)
|
||||
}
|
||||
|
|
@ -529,47 +514,33 @@ func (r *NotaryRepository) GetChangelist() (changelist.Changelist, error) {
|
|||
// Conceptually it performs an operation similar to a `git rebase`
|
||||
func (r *NotaryRepository) Publish() error {
|
||||
var initialPublish bool
|
||||
// attempt to initialize the repo from the remote store
|
||||
c, err := r.bootstrapClient()
|
||||
// update first before publishing
|
||||
_, err := r.Update()
|
||||
if err != nil {
|
||||
if _, ok := err.(store.ErrMetaNotFound); ok {
|
||||
// if the remote store return a 404 (translated into ErrMetaNotFound),
|
||||
// there is no trust data for yet. Attempt to load it from disk.
|
||||
// If the remote is not aware of the repo, then this is being published
|
||||
// for the first time. Try to load from disk instead for publishing.
|
||||
if _, ok := err.(ErrRepositoryNotExist); ok {
|
||||
err := r.bootstrapRepo()
|
||||
if err != nil {
|
||||
// There are lots of reasons there might be an error, such as
|
||||
// corrupt metadata. We need better errors from bootstrapRepo.
|
||||
logrus.Debugf("Unable to load repository from local files: %s",
|
||||
err.Error())
|
||||
if _, ok := err.(store.ErrMetaNotFound); ok {
|
||||
return &ErrRepoNotInitialized{}
|
||||
return ErrRepoNotInitialized{}
|
||||
}
|
||||
return err
|
||||
}
|
||||
// We had local data but the server doesn't know about the repo yet,
|
||||
// ensure we will push the initial root and targets file. Either or
|
||||
// Ensure we will push the initial root and targets file. Either or
|
||||
// both of the root and targets may not be marked as Dirty, since
|
||||
// there may not be any changes that update them, so use a
|
||||
// different boolean.
|
||||
initialPublish = true
|
||||
} else {
|
||||
// The remote store returned an error other than 404. We're
|
||||
// unable to determine if the repo has been initialized or not.
|
||||
// We could not update, so we cannot publish.
|
||||
logrus.Error("Could not publish Repository: ", err.Error())
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// If we were successfully able to bootstrap the client (which only pulls
|
||||
// root.json), update it with the rest of the tuf metadata in
|
||||
// preparation for applying the changelist.
|
||||
err = c.Update()
|
||||
if err != nil {
|
||||
if err, ok := err.(signed.ErrExpired); ok {
|
||||
return ErrExpired{err}
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
cl, err := r.GetChangelist()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -719,7 +690,7 @@ func (r *NotaryRepository) saveMetadata(ignoreSnapshot bool) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
targetsJSON, err := json.Marshal(signedTargets)
|
||||
targetsJSON, err := json.MarshalCanonical(signedTargets)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -744,6 +715,28 @@ func (r *NotaryRepository) saveMetadata(ignoreSnapshot bool) error {
|
|||
return r.fileStore.SetMeta(data.CanonicalSnapshotRole, snapshotJSON)
|
||||
}
|
||||
|
||||
// Update bootstraps a trust anchor (root.json) before updating all the
|
||||
// metadata from the repo.
|
||||
func (r *NotaryRepository) Update() (*tufclient.Client, error) {
|
||||
c, err := r.bootstrapClient()
|
||||
if err != nil {
|
||||
if _, ok := err.(store.ErrMetaNotFound); ok {
|
||||
host := r.baseURL
|
||||
parsed, err := url.Parse(r.baseURL)
|
||||
if err == nil {
|
||||
host = parsed.Host // try to exclude the scheme and any paths
|
||||
}
|
||||
return nil, ErrRepositoryNotExist{remote: host, gun: r.gun}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
err = c.Update()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (r *NotaryRepository) bootstrapClient() (*tufclient.Client, error) {
|
||||
var rootJSON []byte
|
||||
remote, err := getRemoteStore(r.baseURL, r.gun, r.roundTrip)
|
||||
|
|
@ -845,7 +838,7 @@ func (r *NotaryRepository) rootFileKeyChange(role, action string, key data.Publi
|
|||
RoleName: role,
|
||||
Keys: kl,
|
||||
}
|
||||
metaJSON, err := json.Marshal(meta)
|
||||
metaJSON, err := json.MarshalCanonical(meta)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/jfrazelle/go/canonical/json"
|
||||
|
||||
"github.com/docker/notary/client/changelist"
|
||||
tuf "github.com/docker/notary/tuf"
|
||||
"github.com/docker/notary/tuf/data"
|
||||
|
|
@ -261,5 +262,5 @@ func serializeCanonicalRole(tufRepo *tuf.Repo, role string) (out []byte, err err
|
|||
return
|
||||
}
|
||||
|
||||
return json.Marshal(s)
|
||||
return json.MarshalCanonical(s)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ package yubikey
|
|||
|
||||
var possiblePkcs11Libs = []string{
|
||||
"/usr/lib/libykcs11.so",
|
||||
"/usr/lib64/libykcs11.so",
|
||||
"/usr/lib/x86_64-linux-gnu/libykcs11.so",
|
||||
"/usr/local/lib/libykcs11.so",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ func (c *Client) update() error {
|
|||
// hash and size in snapshot are unchanged but the root file has expired,
|
||||
// there is little expectation that the situation can be remedied.
|
||||
func (c Client) checkRoot() error {
|
||||
role := data.RoleName("root")
|
||||
role := data.CanonicalRootRole
|
||||
size := c.local.Snapshot.Signed.Meta[role].Length
|
||||
hashSha256 := c.local.Snapshot.Signed.Meta[role].Hashes["sha256"]
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ func (c Client) checkRoot() error {
|
|||
|
||||
// downloadRoot is responsible for downloading the root.json
|
||||
func (c *Client) downloadRoot() error {
|
||||
role := data.RoleName("root")
|
||||
role := data.CanonicalRootRole
|
||||
size := maxSize
|
||||
var expectedSha256 []byte
|
||||
if c.local.Snapshot != nil {
|
||||
|
|
@ -241,7 +241,7 @@ func (c Client) verifyRoot(role string, s *data.Signed, minVersion int) error {
|
|||
// use cache if the download fails (and the cache is still valid).
|
||||
func (c *Client) downloadTimestamp() error {
|
||||
logrus.Debug("downloadTimestamp")
|
||||
role := data.RoleName("timestamp")
|
||||
role := data.CanonicalTimestampRole
|
||||
|
||||
// We may not have a cached timestamp if this is the first time
|
||||
// we're interacting with the repo. This will result in the
|
||||
|
|
@ -272,7 +272,7 @@ func (c *Client) downloadTimestamp() error {
|
|||
if err == nil {
|
||||
// couldn't retrieve data from server and don't have valid
|
||||
// data in cache.
|
||||
return store.ErrMetaNotFound{}
|
||||
return store.ErrMetaNotFound{Resource: data.CanonicalTimestampRole}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
@ -300,7 +300,7 @@ func (c *Client) downloadTimestamp() error {
|
|||
// downloadSnapshot is responsible for downloading the snapshot.json
|
||||
func (c *Client) downloadSnapshot() error {
|
||||
logrus.Debug("downloadSnapshot")
|
||||
role := data.RoleName("snapshot")
|
||||
role := data.CanonicalSnapshotRole
|
||||
if c.local.Timestamp == nil {
|
||||
return ErrMissingMeta{role: "snapshot"}
|
||||
}
|
||||
|
|
@ -379,7 +379,6 @@ func (c *Client) downloadTargets(role string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
role = data.RoleName(role) // this will really only do something for base targets role
|
||||
if c.local.Snapshot == nil {
|
||||
return ErrMissingMeta{role: role}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,17 +15,18 @@ const (
|
|||
CanonicalTimestampRole = "timestamp"
|
||||
)
|
||||
|
||||
// ValidRoles holds an overrideable mapping of canonical role names
|
||||
// to any custom roles names a user wants to make use of. This allows
|
||||
// us to be internally consistent while using different roles in the
|
||||
// public TUF files.
|
||||
var ValidRoles = map[string]string{
|
||||
CanonicalRootRole: CanonicalRootRole,
|
||||
CanonicalTargetsRole: CanonicalTargetsRole,
|
||||
CanonicalSnapshotRole: CanonicalSnapshotRole,
|
||||
CanonicalTimestampRole: CanonicalTimestampRole,
|
||||
// BaseRoles is an easy to iterate list of the top level
|
||||
// roles.
|
||||
var BaseRoles = []string{
|
||||
CanonicalRootRole,
|
||||
CanonicalTargetsRole,
|
||||
CanonicalSnapshotRole,
|
||||
CanonicalTimestampRole,
|
||||
}
|
||||
|
||||
// Regex for validating delegation names
|
||||
var delegationRegexp = regexp.MustCompile("^[-a-z0-9_/]+$")
|
||||
|
||||
// ErrNoSuchRole indicates the roles doesn't exist
|
||||
type ErrNoSuchRole struct {
|
||||
Role string
|
||||
|
|
@ -50,62 +51,15 @@ func (e ErrInvalidRole) Error() string {
|
|||
return fmt.Sprintf("tuf: invalid role %s.", e.Role)
|
||||
}
|
||||
|
||||
// SetValidRoles is a utility function to override some or all of the roles
|
||||
func SetValidRoles(rs map[string]string) {
|
||||
// iterate ValidRoles
|
||||
for k := range ValidRoles {
|
||||
if v, ok := rs[k]; ok {
|
||||
ValidRoles[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RoleName returns the (possibly overridden) role name for the provided
|
||||
// canonical role name
|
||||
func RoleName(canonicalRole string) string {
|
||||
if r, ok := ValidRoles[canonicalRole]; ok {
|
||||
return r
|
||||
}
|
||||
return canonicalRole
|
||||
}
|
||||
|
||||
// CanonicalRole does a reverse lookup to get the canonical role name
|
||||
// from the (possibly overridden) role name
|
||||
func CanonicalRole(role string) string {
|
||||
name := strings.ToLower(role)
|
||||
if _, ok := ValidRoles[name]; ok {
|
||||
// The canonical version is always lower case
|
||||
// se ensure we return name, not role
|
||||
return name
|
||||
}
|
||||
targetsBase := fmt.Sprintf("%s/", ValidRoles[CanonicalTargetsRole])
|
||||
if strings.HasPrefix(name, targetsBase) {
|
||||
role = strings.TrimPrefix(role, targetsBase)
|
||||
role = fmt.Sprintf("%s/%s", CanonicalTargetsRole, role)
|
||||
return role
|
||||
}
|
||||
for r, v := range ValidRoles {
|
||||
if role == v {
|
||||
return r
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// ValidRole only determines the name is semantically
|
||||
// correct. For target delegated roles, it does NOT check
|
||||
// the the appropriate parent roles exist.
|
||||
func ValidRole(name string) bool {
|
||||
name = strings.ToLower(name)
|
||||
if v, ok := ValidRoles[name]; ok {
|
||||
return name == v
|
||||
}
|
||||
|
||||
if IsDelegation(name) {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, v := range ValidRoles {
|
||||
for _, v := range BaseRoles {
|
||||
if name == v {
|
||||
return true
|
||||
}
|
||||
|
|
@ -115,9 +69,8 @@ func ValidRole(name string) bool {
|
|||
|
||||
// IsDelegation checks if the role is a delegation or a root role
|
||||
func IsDelegation(role string) bool {
|
||||
targetsBase := ValidRoles[CanonicalTargetsRole] + "/"
|
||||
targetsBase := CanonicalTargetsRole + "/"
|
||||
|
||||
delegationRegexp := regexp.MustCompile("^[-a-z0-9_/]+$")
|
||||
whitelistedChars := delegationRegexp.MatchString(role)
|
||||
|
||||
// Limit size of full role string to 255 chars for db column size limit
|
||||
|
|
|
|||
|
|
@ -27,12 +27,12 @@ type Snapshot struct {
|
|||
// and targets objects
|
||||
func NewSnapshot(root *Signed, targets *Signed) (*SignedSnapshot, error) {
|
||||
logrus.Debug("generating new snapshot...")
|
||||
targetsJSON, err := json.Marshal(targets)
|
||||
targetsJSON, err := json.MarshalCanonical(targets)
|
||||
if err != nil {
|
||||
logrus.Debug("Error Marshalling Targets")
|
||||
return nil, err
|
||||
}
|
||||
rootJSON, err := json.Marshal(root)
|
||||
rootJSON, err := json.MarshalCanonical(root)
|
||||
if err != nil {
|
||||
logrus.Debug("Error Marshalling Root")
|
||||
return nil, err
|
||||
|
|
@ -52,8 +52,8 @@ func NewSnapshot(root *Signed, targets *Signed) (*SignedSnapshot, error) {
|
|||
Version: 0,
|
||||
Expires: DefaultExpires("snapshot"),
|
||||
Meta: Files{
|
||||
ValidRoles["root"]: rootMeta,
|
||||
ValidRoles["targets"]: targetsMeta,
|
||||
CanonicalRootRole: rootMeta,
|
||||
CanonicalTargetsRole: targetsMeta,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ type Timestamp struct {
|
|||
|
||||
// NewTimestamp initializes a timestamp with an existing snapshot
|
||||
func NewTimestamp(snapshot *Signed) (*SignedTimestamp, error) {
|
||||
snapshotJSON, err := json.Marshal(snapshot)
|
||||
snapshotJSON, err := json.MarshalCanonical(snapshot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -39,7 +39,7 @@ func NewTimestamp(snapshot *Signed) (*SignedTimestamp, error) {
|
|||
Version: 0,
|
||||
Expires: DefaultExpires("timestamp"),
|
||||
Meta: Files{
|
||||
ValidRoles["snapshot"]: snapshotMeta,
|
||||
CanonicalSnapshotRole: snapshotMeta,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ func ValidTUFType(typ, role string) bool {
|
|||
if ValidRole(role) {
|
||||
// All targets delegation roles must have
|
||||
// the valid type is for targets.
|
||||
role = CanonicalRole(role)
|
||||
if role == "" {
|
||||
// role is unknown and does not map to
|
||||
// a type
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ import "fmt"
|
|||
// ErrMetaNotFound indicates we did not find a particular piece
|
||||
// of metadata in the store
|
||||
type ErrMetaNotFound struct {
|
||||
Role string
|
||||
Resource string
|
||||
}
|
||||
|
||||
func (err ErrMetaNotFound) Error() string {
|
||||
return fmt.Sprintf("%s trust data unavailable", err.Role)
|
||||
return fmt.Sprintf("%s trust data unavailable. Has a notary repository been initialized?", err.Resource)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ func (f *FilesystemStore) GetMeta(name string, size int64) ([]byte, error) {
|
|||
meta, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
err = ErrMetaNotFound{Role: name}
|
||||
err = ErrMetaNotFound{Resource: name}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ func (m *memoryStore) GetMeta(name string, size int64) ([]byte, error) {
|
|||
}
|
||||
return d[:size], nil
|
||||
}
|
||||
return nil, ErrMetaNotFound{}
|
||||
return nil, ErrMetaNotFound{Resource: name}
|
||||
}
|
||||
|
||||
func (m *memoryStore) SetMeta(name string, meta []byte) error {
|
||||
|
|
@ -75,7 +75,7 @@ func (m *memoryStore) WalkStagedTargets(paths []string, targetsFn targetsWalkFun
|
|||
for _, path := range paths {
|
||||
dat, ok := m.files[path]
|
||||
if !ok {
|
||||
return ErrMetaNotFound{}
|
||||
return ErrMetaNotFound{Resource: path}
|
||||
}
|
||||
meta, err := data.NewFileMeta(bytes.NewReader(dat), "sha256")
|
||||
if err != nil {
|
||||
|
|
|
|||
27
vendor/src/github.com/docker/notary/tuf/tuf.go
vendored
27
vendor/src/github.com/docker/notary/tuf/tuf.go
vendored
|
|
@ -5,13 +5,14 @@ import (
|
|||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/jfrazelle/go/canonical/json"
|
||||
|
||||
"github.com/docker/notary/tuf/data"
|
||||
"github.com/docker/notary/tuf/keys"
|
||||
"github.com/docker/notary/tuf/signed"
|
||||
|
|
@ -306,7 +307,7 @@ func (tr *Repo) DeleteDelegation(role data.Role) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// InitRepo creates the base files for a repo. It inspects data.ValidRoles and
|
||||
// InitRepo creates the base files for a repo. It inspects data.BaseRoles and
|
||||
// data.ValidTypes to determine what the role names and filename should be. It
|
||||
// also relies on the keysDB having already been populated with the keys and
|
||||
// roles.
|
||||
|
|
@ -328,7 +329,7 @@ func (tr *Repo) InitRepo(consistent bool) error {
|
|||
func (tr *Repo) InitRoot(consistent bool) error {
|
||||
rootRoles := make(map[string]*data.RootRole)
|
||||
rootKeys := make(map[string]data.PublicKey)
|
||||
for _, r := range data.ValidRoles {
|
||||
for _, r := range data.BaseRoles {
|
||||
role := tr.keysDB.GetRole(r)
|
||||
if role == nil {
|
||||
return data.ErrInvalidRole{Role: data.CanonicalRootRole, Reason: "root role not initialized in key database"}
|
||||
|
|
@ -352,14 +353,14 @@ func (tr *Repo) InitRoot(consistent bool) error {
|
|||
// InitTargets initializes an empty targets, and returns the new empty target
|
||||
func (tr *Repo) InitTargets(role string) (*data.SignedTargets, error) {
|
||||
r := data.Role{Name: role}
|
||||
if !r.IsDelegation() && data.CanonicalRole(role) != data.CanonicalTargetsRole {
|
||||
if !r.IsDelegation() && role != data.CanonicalTargetsRole {
|
||||
return nil, data.ErrInvalidRole{
|
||||
Role: role,
|
||||
Reason: fmt.Sprintf("role is not a valid targets role name: %s", role),
|
||||
}
|
||||
}
|
||||
targets := data.NewTargets()
|
||||
tr.Targets[data.RoleName(role)] = targets
|
||||
tr.Targets[role] = targets
|
||||
return targets, nil
|
||||
}
|
||||
|
||||
|
|
@ -373,10 +374,10 @@ func (tr *Repo) InitSnapshot() error {
|
|||
return err
|
||||
}
|
||||
|
||||
if _, ok := tr.Targets[data.RoleName(data.CanonicalTargetsRole)]; !ok {
|
||||
if _, ok := tr.Targets[data.CanonicalTargetsRole]; !ok {
|
||||
return ErrNotLoaded{role: "targets"}
|
||||
}
|
||||
targets, err := tr.Targets[data.RoleName(data.CanonicalTargetsRole)].ToSigned()
|
||||
targets, err := tr.Targets[data.CanonicalTargetsRole].ToSigned()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -573,7 +574,7 @@ func (tr *Repo) AddTargets(role string, targets data.Files) (data.Files, error)
|
|||
for path, target := range targets {
|
||||
pathDigest := sha256.Sum256([]byte(path))
|
||||
pathHex := hex.EncodeToString(pathDigest[:])
|
||||
if role == data.ValidRoles["targets"] || (r.CheckPaths(path) || r.CheckPrefixes(pathHex)) {
|
||||
if role == data.CanonicalTargetsRole || (r.CheckPaths(path) || r.CheckPrefixes(pathHex)) {
|
||||
t.Signed.Targets[path] = target
|
||||
} else {
|
||||
invalid[path] = target
|
||||
|
|
@ -606,7 +607,7 @@ func (tr *Repo) RemoveTargets(role string, targets ...string) error {
|
|||
|
||||
// UpdateSnapshot updates the FileMeta for the given role based on the Signed object
|
||||
func (tr *Repo) UpdateSnapshot(role string, s *data.Signed) error {
|
||||
jsonData, err := json.Marshal(s)
|
||||
jsonData, err := json.MarshalCanonical(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -621,7 +622,7 @@ func (tr *Repo) UpdateSnapshot(role string, s *data.Signed) error {
|
|||
|
||||
// UpdateTimestamp updates the snapshot meta in the timestamp based on the Signed object
|
||||
func (tr *Repo) UpdateTimestamp(s *data.Signed) error {
|
||||
jsonData, err := json.Marshal(s)
|
||||
jsonData, err := json.MarshalCanonical(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -639,7 +640,7 @@ func (tr *Repo) SignRoot(expires time.Time) (*data.Signed, error) {
|
|||
logrus.Debug("signing root...")
|
||||
tr.Root.Signed.Expires = expires
|
||||
tr.Root.Signed.Version++
|
||||
root := tr.keysDB.GetRole(data.ValidRoles["root"])
|
||||
root := tr.keysDB.GetRole(data.CanonicalRootRole)
|
||||
signed, err := tr.Root.ToSigned()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -707,7 +708,7 @@ func (tr *Repo) SignSnapshot(expires time.Time) (*data.Signed, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
snapshot := tr.keysDB.GetRole(data.ValidRoles["snapshot"])
|
||||
snapshot := tr.keysDB.GetRole(data.CanonicalSnapshotRole)
|
||||
signed, err = tr.sign(signed, *snapshot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -733,7 +734,7 @@ func (tr *Repo) SignTimestamp(expires time.Time) (*data.Signed, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
timestamp := tr.keysDB.GetRole(data.ValidRoles["timestamp"])
|
||||
timestamp := tr.keysDB.GetRole(data.CanonicalTimestampRole)
|
||||
signed, err = tr.sign(signed, *timestamp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue