Browse code

update tests and error messages, revendor notary with tag

Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>

Riyaz Faizullabhoy authored on 2016/01/08 11:43:01
Showing 20 changed files
... ...
@@ -153,11 +153,11 @@ RUN set -x \
153 153
 	&& rm -rf "$GOPATH"
154 154
 
155 155
 # Install notary server
156
-ENV NOTARY_COMMIT 30c488b3b4c62fdbc2c1eae7cf3b62ca73f95fad
156
+ENV NOTARY_VERSION docker-v1.10-1
157 157
 RUN set -x \
158 158
 	&& export GOPATH="$(mktemp -d)" \
159 159
 	&& git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
160
-	&& (cd "$GOPATH/src/github.com/docker/notary" && git checkout -q "$NOTARY_COMMIT") \
160
+	&& (cd "$GOPATH/src/github.com/docker/notary" && git checkout -q "$NOTARY_VERSION") \
161 161
 	&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
162 162
 		go build -o /usr/local/bin/notary-server github.com/docker/notary/cmd/notary-server \
163 163
 	&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
... ...
@@ -278,22 +278,24 @@ func notaryError(repoName string, err error) error {
278 278
 	case *json.SyntaxError:
279 279
 		logrus.Debugf("Notary syntax error: %s", err)
280 280
 		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)
281
-	case client.ErrExpired:
281
+	case signed.ErrExpired:
282 282
 		return fmt.Errorf("Error: remote repository %s out-of-date: %v", repoName, err)
283 283
 	case trustmanager.ErrKeyNotFound:
284 284
 		return fmt.Errorf("Error: signing keys for remote repository %s not found: %v", repoName, err)
285 285
 	case *net.OpError:
286 286
 		return fmt.Errorf("Error: error contacting notary server: %v", err)
287 287
 	case store.ErrMetaNotFound:
288
-		return fmt.Errorf("Error: trust data missing for remote repository %s: %v", repoName, err)
288
+		return fmt.Errorf("Error: trust data missing for remote repository %s or remote repository not found: %v", repoName, err)
289 289
 	case signed.ErrInvalidKeyType:
290
-		return fmt.Errorf("Error: trust data mismatch for remote repository %s, could be malicious behavior: %v", repoName, err)
290
+		return fmt.Errorf("Warning: potential malicious behavior - trust data mismatch for remote repository %s: %v", repoName, err)
291 291
 	case signed.ErrNoKeys:
292 292
 		return fmt.Errorf("Error: could not find signing keys for remote repository %s: %v", repoName, err)
293 293
 	case signed.ErrLowVersion:
294
-		return fmt.Errorf("Error: trust data version is lower than expected for remote repository %s, could be malicious behavior: %v", repoName, err)
294
+		return fmt.Errorf("Warning: potential malicious behavior - trust data version is lower than expected for remote repository %s: %v", repoName, err)
295 295
 	case signed.ErrInsufficientSignatures:
296
-		return fmt.Errorf("Error: trust data has insufficient signatures for remote repository %s, could be malicious behavior: %v", repoName, err)
296
+		return fmt.Errorf("Warning: potential malicious behavior - trust data has insufficient signatures for remote repository %s: %v", repoName, err)
297
+	case client.ErrRepositoryNotExist:
298
+		return fmt.Errorf("Error: remote trust data repository not initialized for %s: %v", repoName, err)
297 299
 	}
298 300
 
299 301
 	return err
... ...
@@ -432,7 +434,7 @@ func (cli *DockerCli) trustedPush(repoInfo *registry.RepositoryInfo, tag string,
432 432
 
433 433
 	repo, err := cli.getNotaryRepository(repoInfo, authConfig)
434 434
 	if err != nil {
435
-		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)
435
+		fmt.Fprintf(cli.out, "Error establishing connection to notary repository: %s\n", err)
436 436
 		return err
437 437
 	}
438 438
 
... ...
@@ -454,7 +456,7 @@ func (cli *DockerCli) trustedPush(repoInfo *registry.RepositoryInfo, tag string,
454 454
 	}
455 455
 
456 456
 	err = repo.Publish()
457
-	if _, ok := err.(*client.ErrRepoNotInitialized); !ok {
457
+	if _, ok := err.(client.ErrRepoNotInitialized); !ok {
458 458
 		return notaryError(repoInfo.FullName(), err)
459 459
 	}
460 460
 
... ...
@@ -47,7 +47,7 @@ clone git github.com/docker/distribution 568bf038af6d65b376165d02886b1c7fcaef1f6
47 47
 clone git github.com/vbatts/tar-split v0.9.11
48 48
 
49 49
 # get desired notary commit, might also need to be updated in Dockerfile
50
-clone git github.com/docker/notary 30c488b3b4c62fdbc2c1eae7cf3b62ca73f95fad
50
+clone git github.com/docker/notary docker-v1.10-1
51 51
 
52 52
 clone git google.golang.org/grpc 174192fc93efcb188fc8f46ca447f0da606b6885 https://github.com/grpc/grpc-go.git
53 53
 clone git github.com/miekg/pkcs11 80f102b5cac759de406949c47f0928b99bd64cdf
... ...
@@ -5805,7 +5805,7 @@ func (s *DockerTrustSuite) TestTrustedBuildUntrustedTag(c *check.C) {
5805 5805
 		c.Fatalf("Expected error on trusted build with untrusted tag: %s\n%s", err, out)
5806 5806
 	}
5807 5807
 
5808
-	if !strings.Contains(out, fmt.Sprintf("trust data unavailable")) {
5808
+	if !strings.Contains(out, "does not have trust data for") {
5809 5809
 		c.Fatalf("Unexpected output on trusted build with untrusted tag:\n%s", out)
5810 5810
 	}
5811 5811
 }
... ...
@@ -312,7 +312,7 @@ func (s *DockerTrustSuite) TestUntrustedCreate(c *check.C) {
312 312
 	s.trustedCmd(createCmd)
313 313
 	out, _, err := runCommandWithOutput(createCmd)
314 314
 	c.Assert(err, check.Not(check.IsNil))
315
-	c.Assert(string(out), checker.Contains, "trust data unavailable", check.Commentf("Missing expected output on trusted create:\n%s", out))
315
+	c.Assert(string(out), checker.Contains, "does not have trust data for", check.Commentf("Missing expected output on trusted create:\n%s", out))
316 316
 
317 317
 }
318 318
 
... ...
@@ -58,7 +58,7 @@ func (s *DockerTrustSuite) TestUntrustedPull(c *check.C) {
58 58
 	out, _, err := runCommandWithOutput(pullCmd)
59 59
 
60 60
 	c.Assert(err, check.NotNil, check.Commentf(out))
61
-	c.Assert(string(out), checker.Contains, "trust data unavailable", check.Commentf(out))
61
+	c.Assert(string(out), checker.Contains, "Error: remote trust data repository not initialized", check.Commentf(out))
62 62
 }
63 63
 
64 64
 func (s *DockerTrustSuite) TestPullWhenCertExpired(c *check.C) {
... ...
@@ -3087,7 +3087,7 @@ func (s *DockerTrustSuite) TestUntrustedRun(c *check.C) {
3087 3087
 		c.Fatalf("Error expected when running trusted run with:\n%s", out)
3088 3088
 	}
3089 3089
 
3090
-	if !strings.Contains(string(out), "trust data unavailable") {
3090
+	if !strings.Contains(string(out), "does not have trust data for") {
3091 3091
 		c.Fatalf("Missing expected output on trusted run:\n%s", out)
3092 3092
 	}
3093 3093
 }
... ...
@@ -23,7 +23,7 @@ RUN softhsm2-util --init-token --slot 0 --label "test_token" --pin $NOTARY_SIGNE
23 23
 ENV NOTARYPKG github.com/docker/notary
24 24
 ENV GOPATH /go/src/${NOTARYPKG}/Godeps/_workspace:$GOPATH
25 25
 
26
-EXPOSE 4443
26
+EXPOSE 4444
27 27
 
28 28
 # Copy the local repo to the expected go path
29 29
 COPY . /go/src/github.com/docker/notary
... ...
@@ -2,17 +2,18 @@ package client
2 2
 
3 3
 import (
4 4
 	"bytes"
5
-	"encoding/json"
6
-	"errors"
7 5
 	"fmt"
8 6
 	"io/ioutil"
9 7
 	"net/http"
8
+	"net/url"
10 9
 	"os"
11 10
 	"path/filepath"
12 11
 	"strings"
13 12
 	"time"
14 13
 
15 14
 	"github.com/Sirupsen/logrus"
15
+	"github.com/jfrazelle/go/canonical/json"
16
+
16 17
 	"github.com/docker/notary/certs"
17 18
 	"github.com/docker/notary/client/changelist"
18 19
 	"github.com/docker/notary/cryptoservice"
... ...
@@ -39,19 +40,12 @@ func init() {
39 39
 	)
40 40
 }
41 41
 
42
-// ErrRepoNotInitialized is returned when trying to can publish on an uninitialized
42
+// ErrRepoNotInitialized is returned when trying to publish an uninitialized
43 43
 // notary repository
44 44
 type ErrRepoNotInitialized struct{}
45 45
 
46
-// ErrRepoNotInitialized is returned when trying to can publish on an uninitialized
47
-// notary repository
48
-func (err *ErrRepoNotInitialized) Error() string {
49
-	return "Repository has not been initialized"
50
-}
51
-
52
-// ErrExpired is returned when the metadata for a role has expired
53
-type ErrExpired struct {
54
-	signed.ErrExpired
46
+func (err ErrRepoNotInitialized) Error() string {
47
+	return "repository has not been initialized"
55 48
 }
56 49
 
57 50
 // ErrInvalidRemoteRole is returned when the server is requested to manage
... ...
@@ -65,14 +59,21 @@ func (e ErrInvalidRemoteRole) Error() string {
65 65
 		"notary does not support the server managing the %s key", e.Role)
66 66
 }
67 67
 
68
+// ErrRepositoryNotExist is returned when an action is taken on a remote
69
+// repository that doesn't exist
70
+type ErrRepositoryNotExist struct {
71
+	remote string
72
+	gun    string
73
+}
74
+
75
+func (err ErrRepositoryNotExist) Error() string {
76
+	return fmt.Sprintf("%s does not have trust data for %s", err.remote, err.gun)
77
+}
78
+
68 79
 const (
69 80
 	tufDir = "tuf"
70 81
 )
71 82
 
72
-// ErrRepositoryNotExist gets returned when trying to make an action over a repository
73
-/// that doesn't exist.
74
-var ErrRepositoryNotExist = errors.New("repository does not exist")
75
-
76 83
 // NotaryRepository stores all the information needed to operate on a notary
77 84
 // repository.
78 85
 type NotaryRepository struct {
... ...
@@ -323,7 +324,7 @@ func (r *NotaryRepository) AddDelegation(name string, threshold int,
323 323
 	logrus.Debugf(`Adding delegation "%s" with threshold %d, and %d keys\n`,
324 324
 		name, threshold, len(delegationKeys))
325 325
 
326
-	tdJSON, err := json.Marshal(&changelist.TufDelegation{
326
+	tdJSON, err := json.MarshalCanonical(&changelist.TufDelegation{
327 327
 		NewThreshold: threshold,
328 328
 		AddKeys:      data.KeyList(delegationKeys),
329 329
 		AddPaths:     paths,
... ...
@@ -385,7 +386,7 @@ func (r *NotaryRepository) AddTarget(target *Target, roles ...string) error {
385 385
 	logrus.Debugf("Adding target \"%s\" with sha256 \"%x\" and size %d bytes.\n", target.Name, target.Hashes["sha256"], target.Length)
386 386
 
387 387
 	meta := data.FileMeta{Length: target.Length, Hashes: target.Hashes}
388
-	metaJSON, err := json.Marshal(meta)
388
+	metaJSON, err := json.MarshalCanonical(meta)
389 389
 	if err != nil {
390 390
 		return err
391 391
 	}
... ...
@@ -419,16 +420,8 @@ func (r *NotaryRepository) RemoveTarget(targetName string, roles ...string) erro
419 419
 // subtree and also the "targets/x" subtree, as we will defer parsing it until
420 420
 // we explicitly reach it in our iteration of the provided list of roles.
421 421
 func (r *NotaryRepository) ListTargets(roles ...string) ([]*TargetWithRole, error) {
422
-	c, err := r.bootstrapClient()
423
-	if err != nil {
424
-		return nil, err
425
-	}
426
-
427
-	err = c.Update()
422
+	_, err := r.Update()
428 423
 	if err != nil {
429
-		if err, ok := err.(signed.ErrExpired); ok {
430
-			return nil, ErrExpired{err}
431
-		}
432 424
 		return nil, err
433 425
 	}
434 426
 
... ...
@@ -487,16 +480,8 @@ func (r *NotaryRepository) listSubtree(targets map[string]*TargetWithRole, role
487 487
 // will be returned
488 488
 // See the IMPORTANT section on ListTargets above. Those roles also apply here.
489 489
 func (r *NotaryRepository) GetTargetByName(name string, roles ...string) (*TargetWithRole, error) {
490
-	c, err := r.bootstrapClient()
491
-	if err != nil {
492
-		return nil, err
493
-	}
494
-
495
-	err = c.Update()
490
+	c, err := r.Update()
496 491
 	if err != nil {
497
-		if err, ok := err.(signed.ErrExpired); ok {
498
-			return nil, ErrExpired{err}
499
-		}
500 492
 		return nil, err
501 493
 	}
502 494
 
... ...
@@ -529,47 +514,33 @@ func (r *NotaryRepository) GetChangelist() (changelist.Changelist, error) {
529 529
 // Conceptually it performs an operation similar to a `git rebase`
530 530
 func (r *NotaryRepository) Publish() error {
531 531
 	var initialPublish bool
532
-	// attempt to initialize the repo from the remote store
533
-	c, err := r.bootstrapClient()
532
+	// update first before publishing
533
+	_, err := r.Update()
534 534
 	if err != nil {
535
-		if _, ok := err.(store.ErrMetaNotFound); ok {
536
-			// if the remote store return a 404 (translated into ErrMetaNotFound),
537
-			// there is no trust data for yet. Attempt to load it from disk.
535
+		// If the remote is not aware of the repo, then this is being published
536
+		// for the first time.  Try to load from disk instead for publishing.
537
+		if _, ok := err.(ErrRepositoryNotExist); ok {
538 538
 			err := r.bootstrapRepo()
539 539
 			if err != nil {
540
-				// There are lots of reasons there might be an error, such as
541
-				// corrupt metadata.  We need better errors from bootstrapRepo.
542 540
 				logrus.Debugf("Unable to load repository from local files: %s",
543 541
 					err.Error())
544 542
 				if _, ok := err.(store.ErrMetaNotFound); ok {
545
-					return &ErrRepoNotInitialized{}
543
+					return ErrRepoNotInitialized{}
546 544
 				}
547 545
 				return err
548 546
 			}
549
-			// We had local data but the server doesn't know about the repo yet,
550
-			// ensure we will push the initial root and targets file.  Either or
547
+			// Ensure we will push the initial root and targets file.  Either or
551 548
 			// both of the root and targets may not be marked as Dirty, since
552 549
 			// there may not be any changes that update them, so use a
553 550
 			// different boolean.
554 551
 			initialPublish = true
555 552
 		} else {
556
-			// The remote store returned an error other than 404. We're
557
-			// unable to determine if the repo has been initialized or not.
553
+			// We could not update, so we cannot publish.
558 554
 			logrus.Error("Could not publish Repository: ", err.Error())
559 555
 			return err
560 556
 		}
561
-	} else {
562
-		// If we were successfully able to bootstrap the client (which only pulls
563
-		// root.json), update it with the rest of the tuf metadata in
564
-		// preparation for applying the changelist.
565
-		err = c.Update()
566
-		if err != nil {
567
-			if err, ok := err.(signed.ErrExpired); ok {
568
-				return ErrExpired{err}
569
-			}
570
-			return err
571
-		}
572 557
 	}
558
+
573 559
 	cl, err := r.GetChangelist()
574 560
 	if err != nil {
575 561
 		return err
... ...
@@ -719,7 +690,7 @@ func (r *NotaryRepository) saveMetadata(ignoreSnapshot bool) error {
719 719
 		if err != nil {
720 720
 			return err
721 721
 		}
722
-		targetsJSON, err := json.Marshal(signedTargets)
722
+		targetsJSON, err := json.MarshalCanonical(signedTargets)
723 723
 		if err != nil {
724 724
 			return err
725 725
 		}
... ...
@@ -744,6 +715,28 @@ func (r *NotaryRepository) saveMetadata(ignoreSnapshot bool) error {
744 744
 	return r.fileStore.SetMeta(data.CanonicalSnapshotRole, snapshotJSON)
745 745
 }
746 746
 
747
+// Update bootstraps a trust anchor (root.json) before updating all the
748
+// metadata from the repo.
749
+func (r *NotaryRepository) Update() (*tufclient.Client, error) {
750
+	c, err := r.bootstrapClient()
751
+	if err != nil {
752
+		if _, ok := err.(store.ErrMetaNotFound); ok {
753
+			host := r.baseURL
754
+			parsed, err := url.Parse(r.baseURL)
755
+			if err == nil {
756
+				host = parsed.Host // try to exclude the scheme and any paths
757
+			}
758
+			return nil, ErrRepositoryNotExist{remote: host, gun: r.gun}
759
+		}
760
+		return nil, err
761
+	}
762
+	err = c.Update()
763
+	if err != nil {
764
+		return nil, err
765
+	}
766
+	return c, nil
767
+}
768
+
747 769
 func (r *NotaryRepository) bootstrapClient() (*tufclient.Client, error) {
748 770
 	var rootJSON []byte
749 771
 	remote, err := getRemoteStore(r.baseURL, r.gun, r.roundTrip)
... ...
@@ -845,7 +838,7 @@ func (r *NotaryRepository) rootFileKeyChange(role, action string, key data.Publi
845 845
 		RoleName: role,
846 846
 		Keys:     kl,
847 847
 	}
848
-	metaJSON, err := json.Marshal(meta)
848
+	metaJSON, err := json.MarshalCanonical(meta)
849 849
 	if err != nil {
850 850
 		return err
851 851
 	}
... ...
@@ -1,13 +1,14 @@
1 1
 package client
2 2
 
3 3
 import (
4
-	"encoding/json"
5 4
 	"fmt"
6 5
 	"net/http"
7 6
 	"path"
8 7
 	"time"
9 8
 
10 9
 	"github.com/Sirupsen/logrus"
10
+	"github.com/jfrazelle/go/canonical/json"
11
+
11 12
 	"github.com/docker/notary/client/changelist"
12 13
 	tuf "github.com/docker/notary/tuf"
13 14
 	"github.com/docker/notary/tuf/data"
... ...
@@ -261,5 +262,5 @@ func serializeCanonicalRole(tufRepo *tuf.Repo, role string) (out []byte, err err
261 261
 		return
262 262
 	}
263 263
 
264
-	return json.Marshal(s)
264
+	return json.MarshalCanonical(s)
265 265
 }
... ...
@@ -4,6 +4,7 @@ package yubikey
4 4
 
5 5
 var possiblePkcs11Libs = []string{
6 6
 	"/usr/lib/libykcs11.so",
7
+	"/usr/lib64/libykcs11.so",
7 8
 	"/usr/lib/x86_64-linux-gnu/libykcs11.so",
8 9
 	"/usr/local/lib/libykcs11.so",
9 10
 }
... ...
@@ -97,7 +97,7 @@ func (c *Client) update() error {
97 97
 // hash and size in snapshot are unchanged but the root file has expired,
98 98
 // there is little expectation that the situation can be remedied.
99 99
 func (c Client) checkRoot() error {
100
-	role := data.RoleName("root")
100
+	role := data.CanonicalRootRole
101 101
 	size := c.local.Snapshot.Signed.Meta[role].Length
102 102
 	hashSha256 := c.local.Snapshot.Signed.Meta[role].Hashes["sha256"]
103 103
 
... ...
@@ -129,7 +129,7 @@ func (c Client) checkRoot() error {
129 129
 
130 130
 // downloadRoot is responsible for downloading the root.json
131 131
 func (c *Client) downloadRoot() error {
132
-	role := data.RoleName("root")
132
+	role := data.CanonicalRootRole
133 133
 	size := maxSize
134 134
 	var expectedSha256 []byte
135 135
 	if c.local.Snapshot != nil {
... ...
@@ -241,7 +241,7 @@ func (c Client) verifyRoot(role string, s *data.Signed, minVersion int) error {
241 241
 // use cache if the download fails (and the cache is still valid).
242 242
 func (c *Client) downloadTimestamp() error {
243 243
 	logrus.Debug("downloadTimestamp")
244
-	role := data.RoleName("timestamp")
244
+	role := data.CanonicalTimestampRole
245 245
 
246 246
 	// We may not have a cached timestamp if this is the first time
247 247
 	// we're interacting with the repo. This will result in the
... ...
@@ -272,7 +272,7 @@ func (c *Client) downloadTimestamp() error {
272 272
 			if err == nil {
273 273
 				// couldn't retrieve data from server and don't have valid
274 274
 				// data in cache.
275
-				return store.ErrMetaNotFound{}
275
+				return store.ErrMetaNotFound{Resource: data.CanonicalTimestampRole}
276 276
 			}
277 277
 			return err
278 278
 		}
... ...
@@ -300,7 +300,7 @@ func (c *Client) downloadTimestamp() error {
300 300
 // downloadSnapshot is responsible for downloading the snapshot.json
301 301
 func (c *Client) downloadSnapshot() error {
302 302
 	logrus.Debug("downloadSnapshot")
303
-	role := data.RoleName("snapshot")
303
+	role := data.CanonicalSnapshotRole
304 304
 	if c.local.Timestamp == nil {
305 305
 		return ErrMissingMeta{role: "snapshot"}
306 306
 	}
... ...
@@ -379,7 +379,6 @@ func (c *Client) downloadTargets(role string) error {
379 379
 		if err != nil {
380 380
 			return err
381 381
 		}
382
-		role = data.RoleName(role) // this will really only do something for base targets role
383 382
 		if c.local.Snapshot == nil {
384 383
 			return ErrMissingMeta{role: role}
385 384
 		}
... ...
@@ -15,17 +15,18 @@ const (
15 15
 	CanonicalTimestampRole = "timestamp"
16 16
 )
17 17
 
18
-// ValidRoles holds an overrideable mapping of canonical role names
19
-// to any custom roles names a user wants to make use of. This allows
20
-// us to be internally consistent while using different roles in the
21
-// public TUF files.
22
-var ValidRoles = map[string]string{
23
-	CanonicalRootRole:      CanonicalRootRole,
24
-	CanonicalTargetsRole:   CanonicalTargetsRole,
25
-	CanonicalSnapshotRole:  CanonicalSnapshotRole,
26
-	CanonicalTimestampRole: CanonicalTimestampRole,
18
+// BaseRoles is an easy to iterate list of the top level
19
+// roles.
20
+var BaseRoles = []string{
21
+	CanonicalRootRole,
22
+	CanonicalTargetsRole,
23
+	CanonicalSnapshotRole,
24
+	CanonicalTimestampRole,
27 25
 }
28 26
 
27
+// Regex for validating delegation names
28
+var delegationRegexp = regexp.MustCompile("^[-a-z0-9_/]+$")
29
+
29 30
 // ErrNoSuchRole indicates the roles doesn't exist
30 31
 type ErrNoSuchRole struct {
31 32
 	Role string
... ...
@@ -50,62 +51,15 @@ func (e ErrInvalidRole) Error() string {
50 50
 	return fmt.Sprintf("tuf: invalid role %s.", e.Role)
51 51
 }
52 52
 
53
-// SetValidRoles is a utility function to override some or all of the roles
54
-func SetValidRoles(rs map[string]string) {
55
-	// iterate ValidRoles
56
-	for k := range ValidRoles {
57
-		if v, ok := rs[k]; ok {
58
-			ValidRoles[k] = v
59
-		}
60
-	}
61
-}
62
-
63
-// RoleName returns the (possibly overridden) role name for the provided
64
-// canonical role name
65
-func RoleName(canonicalRole string) string {
66
-	if r, ok := ValidRoles[canonicalRole]; ok {
67
-		return r
68
-	}
69
-	return canonicalRole
70
-}
71
-
72
-// CanonicalRole does a reverse lookup to get the canonical role name
73
-// from the (possibly overridden) role name
74
-func CanonicalRole(role string) string {
75
-	name := strings.ToLower(role)
76
-	if _, ok := ValidRoles[name]; ok {
77
-		// The canonical version is always lower case
78
-		// se ensure we return name, not role
79
-		return name
80
-	}
81
-	targetsBase := fmt.Sprintf("%s/", ValidRoles[CanonicalTargetsRole])
82
-	if strings.HasPrefix(name, targetsBase) {
83
-		role = strings.TrimPrefix(role, targetsBase)
84
-		role = fmt.Sprintf("%s/%s", CanonicalTargetsRole, role)
85
-		return role
86
-	}
87
-	for r, v := range ValidRoles {
88
-		if role == v {
89
-			return r
90
-		}
91
-	}
92
-	return ""
93
-}
94
-
95 53
 // ValidRole only determines the name is semantically
96 54
 // correct. For target delegated roles, it does NOT check
97 55
 // the the appropriate parent roles exist.
98 56
 func ValidRole(name string) bool {
99
-	name = strings.ToLower(name)
100
-	if v, ok := ValidRoles[name]; ok {
101
-		return name == v
102
-	}
103
-
104 57
 	if IsDelegation(name) {
105 58
 		return true
106 59
 	}
107 60
 
108
-	for _, v := range ValidRoles {
61
+	for _, v := range BaseRoles {
109 62
 		if name == v {
110 63
 			return true
111 64
 		}
... ...
@@ -115,9 +69,8 @@ func ValidRole(name string) bool {
115 115
 
116 116
 // IsDelegation checks if the role is a delegation or a root role
117 117
 func IsDelegation(role string) bool {
118
-	targetsBase := ValidRoles[CanonicalTargetsRole] + "/"
118
+	targetsBase := CanonicalTargetsRole + "/"
119 119
 
120
-	delegationRegexp := regexp.MustCompile("^[-a-z0-9_/]+$")
121 120
 	whitelistedChars := delegationRegexp.MatchString(role)
122 121
 
123 122
 	// Limit size of full role string to 255 chars for db column size limit
... ...
@@ -27,12 +27,12 @@ type Snapshot struct {
27 27
 // and targets objects
28 28
 func NewSnapshot(root *Signed, targets *Signed) (*SignedSnapshot, error) {
29 29
 	logrus.Debug("generating new snapshot...")
30
-	targetsJSON, err := json.Marshal(targets)
30
+	targetsJSON, err := json.MarshalCanonical(targets)
31 31
 	if err != nil {
32 32
 		logrus.Debug("Error Marshalling Targets")
33 33
 		return nil, err
34 34
 	}
35
-	rootJSON, err := json.Marshal(root)
35
+	rootJSON, err := json.MarshalCanonical(root)
36 36
 	if err != nil {
37 37
 		logrus.Debug("Error Marshalling Root")
38 38
 		return nil, err
... ...
@@ -52,8 +52,8 @@ func NewSnapshot(root *Signed, targets *Signed) (*SignedSnapshot, error) {
52 52
 			Version: 0,
53 53
 			Expires: DefaultExpires("snapshot"),
54 54
 			Meta: Files{
55
-				ValidRoles["root"]:    rootMeta,
56
-				ValidRoles["targets"]: targetsMeta,
55
+				CanonicalRootRole:    rootMeta,
56
+				CanonicalTargetsRole: targetsMeta,
57 57
 			},
58 58
 		},
59 59
 	}, nil
... ...
@@ -24,7 +24,7 @@ type Timestamp struct {
24 24
 
25 25
 // NewTimestamp initializes a timestamp with an existing snapshot
26 26
 func NewTimestamp(snapshot *Signed) (*SignedTimestamp, error) {
27
-	snapshotJSON, err := json.Marshal(snapshot)
27
+	snapshotJSON, err := json.MarshalCanonical(snapshot)
28 28
 	if err != nil {
29 29
 		return nil, err
30 30
 	}
... ...
@@ -39,7 +39,7 @@ func NewTimestamp(snapshot *Signed) (*SignedTimestamp, error) {
39 39
 			Version: 0,
40 40
 			Expires: DefaultExpires("timestamp"),
41 41
 			Meta: Files{
42
-				ValidRoles["snapshot"]: snapshotMeta,
42
+				CanonicalSnapshotRole: snapshotMeta,
43 43
 			},
44 44
 		},
45 45
 	}, nil
... ...
@@ -62,7 +62,6 @@ func ValidTUFType(typ, role string) bool {
62 62
 	if ValidRole(role) {
63 63
 		// All targets delegation roles must have
64 64
 		// the valid type is for targets.
65
-		role = CanonicalRole(role)
66 65
 		if role == "" {
67 66
 			// role is unknown and does not map to
68 67
 			// a type
... ...
@@ -5,9 +5,9 @@ import "fmt"
5 5
 // ErrMetaNotFound indicates we did not find a particular piece
6 6
 // of metadata in the store
7 7
 type ErrMetaNotFound struct {
8
-	Role string
8
+	Resource string
9 9
 }
10 10
 
11 11
 func (err ErrMetaNotFound) Error() string {
12
-	return fmt.Sprintf("%s trust data unavailable", err.Role)
12
+	return fmt.Sprintf("%s trust data unavailable.  Has a notary repository been initialized?", err.Resource)
13 13
 }
... ...
@@ -46,7 +46,7 @@ func (f *FilesystemStore) GetMeta(name string, size int64) ([]byte, error) {
46 46
 	meta, err := ioutil.ReadFile(path)
47 47
 	if err != nil {
48 48
 		if os.IsNotExist(err) {
49
-			err = ErrMetaNotFound{Role: name}
49
+			err = ErrMetaNotFound{Resource: name}
50 50
 		}
51 51
 		return nil, err
52 52
 	}
... ...
@@ -39,7 +39,7 @@ func (m *memoryStore) GetMeta(name string, size int64) ([]byte, error) {
39 39
 		}
40 40
 		return d[:size], nil
41 41
 	}
42
-	return nil, ErrMetaNotFound{}
42
+	return nil, ErrMetaNotFound{Resource: name}
43 43
 }
44 44
 
45 45
 func (m *memoryStore) SetMeta(name string, meta []byte) error {
... ...
@@ -75,7 +75,7 @@ func (m *memoryStore) WalkStagedTargets(paths []string, targetsFn targetsWalkFun
75 75
 	for _, path := range paths {
76 76
 		dat, ok := m.files[path]
77 77
 		if !ok {
78
-			return ErrMetaNotFound{}
78
+			return ErrMetaNotFound{Resource: path}
79 79
 		}
80 80
 		meta, err := data.NewFileMeta(bytes.NewReader(dat), "sha256")
81 81
 		if err != nil {
... ...
@@ -5,13 +5,14 @@ import (
5 5
 	"bytes"
6 6
 	"crypto/sha256"
7 7
 	"encoding/hex"
8
-	"encoding/json"
9 8
 	"fmt"
10 9
 	"path"
11 10
 	"strings"
12 11
 	"time"
13 12
 
14 13
 	"github.com/Sirupsen/logrus"
14
+	"github.com/jfrazelle/go/canonical/json"
15
+
15 16
 	"github.com/docker/notary/tuf/data"
16 17
 	"github.com/docker/notary/tuf/keys"
17 18
 	"github.com/docker/notary/tuf/signed"
... ...
@@ -306,7 +307,7 @@ func (tr *Repo) DeleteDelegation(role data.Role) error {
306 306
 	return nil
307 307
 }
308 308
 
309
-// InitRepo creates the base files for a repo. It inspects data.ValidRoles and
309
+// InitRepo creates the base files for a repo. It inspects data.BaseRoles and
310 310
 // data.ValidTypes to determine what the role names and filename should be. It
311 311
 // also relies on the keysDB having already been populated with the keys and
312 312
 // roles.
... ...
@@ -328,7 +329,7 @@ func (tr *Repo) InitRepo(consistent bool) error {
328 328
 func (tr *Repo) InitRoot(consistent bool) error {
329 329
 	rootRoles := make(map[string]*data.RootRole)
330 330
 	rootKeys := make(map[string]data.PublicKey)
331
-	for _, r := range data.ValidRoles {
331
+	for _, r := range data.BaseRoles {
332 332
 		role := tr.keysDB.GetRole(r)
333 333
 		if role == nil {
334 334
 			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 {
352 352
 // InitTargets initializes an empty targets, and returns the new empty target
353 353
 func (tr *Repo) InitTargets(role string) (*data.SignedTargets, error) {
354 354
 	r := data.Role{Name: role}
355
-	if !r.IsDelegation() && data.CanonicalRole(role) != data.CanonicalTargetsRole {
355
+	if !r.IsDelegation() && role != data.CanonicalTargetsRole {
356 356
 		return nil, data.ErrInvalidRole{
357 357
 			Role:   role,
358 358
 			Reason: fmt.Sprintf("role is not a valid targets role name: %s", role),
359 359
 		}
360 360
 	}
361 361
 	targets := data.NewTargets()
362
-	tr.Targets[data.RoleName(role)] = targets
362
+	tr.Targets[role] = targets
363 363
 	return targets, nil
364 364
 }
365 365
 
... ...
@@ -373,10 +374,10 @@ func (tr *Repo) InitSnapshot() error {
373 373
 		return err
374 374
 	}
375 375
 
376
-	if _, ok := tr.Targets[data.RoleName(data.CanonicalTargetsRole)]; !ok {
376
+	if _, ok := tr.Targets[data.CanonicalTargetsRole]; !ok {
377 377
 		return ErrNotLoaded{role: "targets"}
378 378
 	}
379
-	targets, err := tr.Targets[data.RoleName(data.CanonicalTargetsRole)].ToSigned()
379
+	targets, err := tr.Targets[data.CanonicalTargetsRole].ToSigned()
380 380
 	if err != nil {
381 381
 		return err
382 382
 	}
... ...
@@ -573,7 +574,7 @@ func (tr *Repo) AddTargets(role string, targets data.Files) (data.Files, error)
573 573
 	for path, target := range targets {
574 574
 		pathDigest := sha256.Sum256([]byte(path))
575 575
 		pathHex := hex.EncodeToString(pathDigest[:])
576
-		if role == data.ValidRoles["targets"] || (r.CheckPaths(path) || r.CheckPrefixes(pathHex)) {
576
+		if role == data.CanonicalTargetsRole || (r.CheckPaths(path) || r.CheckPrefixes(pathHex)) {
577 577
 			t.Signed.Targets[path] = target
578 578
 		} else {
579 579
 			invalid[path] = target
... ...
@@ -606,7 +607,7 @@ func (tr *Repo) RemoveTargets(role string, targets ...string) error {
606 606
 
607 607
 // UpdateSnapshot updates the FileMeta for the given role based on the Signed object
608 608
 func (tr *Repo) UpdateSnapshot(role string, s *data.Signed) error {
609
-	jsonData, err := json.Marshal(s)
609
+	jsonData, err := json.MarshalCanonical(s)
610 610
 	if err != nil {
611 611
 		return err
612 612
 	}
... ...
@@ -621,7 +622,7 @@ func (tr *Repo) UpdateSnapshot(role string, s *data.Signed) error {
621 621
 
622 622
 // UpdateTimestamp updates the snapshot meta in the timestamp based on the Signed object
623 623
 func (tr *Repo) UpdateTimestamp(s *data.Signed) error {
624
-	jsonData, err := json.Marshal(s)
624
+	jsonData, err := json.MarshalCanonical(s)
625 625
 	if err != nil {
626 626
 		return err
627 627
 	}
... ...
@@ -639,7 +640,7 @@ func (tr *Repo) SignRoot(expires time.Time) (*data.Signed, error) {
639 639
 	logrus.Debug("signing root...")
640 640
 	tr.Root.Signed.Expires = expires
641 641
 	tr.Root.Signed.Version++
642
-	root := tr.keysDB.GetRole(data.ValidRoles["root"])
642
+	root := tr.keysDB.GetRole(data.CanonicalRootRole)
643 643
 	signed, err := tr.Root.ToSigned()
644 644
 	if err != nil {
645 645
 		return nil, err
... ...
@@ -707,7 +708,7 @@ func (tr *Repo) SignSnapshot(expires time.Time) (*data.Signed, error) {
707 707
 	if err != nil {
708 708
 		return nil, err
709 709
 	}
710
-	snapshot := tr.keysDB.GetRole(data.ValidRoles["snapshot"])
710
+	snapshot := tr.keysDB.GetRole(data.CanonicalSnapshotRole)
711 711
 	signed, err = tr.sign(signed, *snapshot)
712 712
 	if err != nil {
713 713
 		return nil, err
... ...
@@ -733,7 +734,7 @@ func (tr *Repo) SignTimestamp(expires time.Time) (*data.Signed, error) {
733 733
 	if err != nil {
734 734
 		return nil, err
735 735
 	}
736
-	timestamp := tr.keysDB.GetRole(data.ValidRoles["timestamp"])
736
+	timestamp := tr.keysDB.GetRole(data.CanonicalTimestampRole)
737 737
 	signed, err = tr.sign(signed, *timestamp)
738 738
 	if err != nil {
739 739
 		return nil, err