Browse code

Add tests simulating an evil server

Signed-off-by: Nathan McCauley <nathan.mccauley@docker.com>

Nathan McCauley authored on 2015/07/23 08:10:25
Showing 5 changed files
... ...
@@ -12,6 +12,7 @@ import (
12 12
 
13 13
 	"github.com/docker/docker/pkg/nat"
14 14
 	"github.com/go-check/check"
15
+	"io/ioutil"
15 16
 )
16 17
 
17 18
 // Make sure we can create a simple container with some args
... ...
@@ -376,3 +377,74 @@ func (s *DockerTrustSuite) TestCreateWhenCertExpired(c *check.C) {
376 376
 		}
377 377
 	})
378 378
 }
379
+
380
+func (s *DockerTrustSuite) TestTrustedCreateFromBadTrustServer(c *check.C) {
381
+	repoName := fmt.Sprintf("%v/dockerclievilcreate/trusted:latest", privateRegistryURL)
382
+	evilLocalConfigDir, err := ioutil.TempDir("", "evil-local-config-dir")
383
+	if err != nil {
384
+		c.Fatalf("Failed to create local temp dir")
385
+	}
386
+
387
+	// tag the image and upload it to the private registry
388
+	dockerCmd(c, "tag", "busybox", repoName)
389
+
390
+	pushCmd := exec.Command(dockerBinary, "push", repoName)
391
+	s.trustedCmd(pushCmd)
392
+	out, _, err := runCommandWithOutput(pushCmd)
393
+	if err != nil {
394
+		c.Fatalf("Error creating trusted push: %s\n%s", err, out)
395
+	}
396
+	if !strings.Contains(string(out), "Signing and pushing trust metadata") {
397
+		c.Fatalf("Missing expected output on trusted push:\n%s", out)
398
+	}
399
+
400
+	dockerCmd(c, "rmi", repoName)
401
+
402
+	// Try create
403
+	createCmd := exec.Command(dockerBinary, "create", repoName)
404
+	s.trustedCmd(createCmd)
405
+	out, _, err = runCommandWithOutput(createCmd)
406
+	if err != nil {
407
+		c.Fatalf("Error creating trusted create: %s\n%s", err, out)
408
+	}
409
+
410
+	if !strings.Contains(string(out), "Tagging") {
411
+		c.Fatalf("Missing expected output on trusted push:\n%s", out)
412
+	}
413
+
414
+	dockerCmd(c, "rmi", repoName)
415
+
416
+	// Kill the notary server, start a new "evil" one.
417
+	s.not.Close()
418
+	s.not, err = newTestNotary(c)
419
+	if err != nil {
420
+		c.Fatalf("Restarting notary server failed.")
421
+	}
422
+
423
+	// In order to make an evil server, lets re-init a client (with a different trust dir) and push new data.
424
+	// tag an image and upload it to the private registry
425
+	dockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName)
426
+
427
+	// Push up to the new server
428
+	pushCmd = exec.Command(dockerBinary, "--config", evilLocalConfigDir, "push", repoName)
429
+	s.trustedCmd(pushCmd)
430
+	out, _, err = runCommandWithOutput(pushCmd)
431
+	if err != nil {
432
+		c.Fatalf("Error creating trusted push: %s\n%s", err, out)
433
+	}
434
+	if !strings.Contains(string(out), "Signing and pushing trust metadata") {
435
+		c.Fatalf("Missing expected output on trusted push:\n%s", out)
436
+	}
437
+
438
+	// Now, try creating with the original client from this new trust server. This should fail.
439
+	createCmd = exec.Command(dockerBinary, "create", repoName)
440
+	s.trustedCmd(createCmd)
441
+	out, _, err = runCommandWithOutput(createCmd)
442
+	if err == nil {
443
+		c.Fatalf("Expected to fail on this create due to different remote data: %s\n%s", err, out)
444
+	}
445
+
446
+	if !strings.Contains(string(out), "failed to validate integrity of roots") {
447
+		c.Fatalf("Missing expected output on trusted push:\n%s", out)
448
+	}
449
+}
... ...
@@ -7,6 +7,7 @@ import (
7 7
 	"time"
8 8
 
9 9
 	"github.com/go-check/check"
10
+	"io/ioutil"
10 11
 )
11 12
 
12 13
 // See issue docker/docker#8141
... ...
@@ -256,3 +257,74 @@ func (s *DockerTrustSuite) TestPullWhenCertExpired(c *check.C) {
256 256
 		}
257 257
 	})
258 258
 }
259
+
260
+func (s *DockerTrustSuite) TestTrustedPullFromBadTrustServer(c *check.C) {
261
+	repoName := fmt.Sprintf("%v/dockerclievilpull/trusted:latest", privateRegistryURL)
262
+	evilLocalConfigDir, err := ioutil.TempDir("", "evil-local-config-dir")
263
+	if err != nil {
264
+		c.Fatalf("Failed to create local temp dir")
265
+	}
266
+
267
+	// tag the image and upload it to the private registry
268
+	dockerCmd(c, "tag", "busybox", repoName)
269
+
270
+	pushCmd := exec.Command(dockerBinary, "push", repoName)
271
+	s.trustedCmd(pushCmd)
272
+	out, _, err := runCommandWithOutput(pushCmd)
273
+	if err != nil {
274
+		c.Fatalf("Error running trusted push: %s\n%s", err, out)
275
+	}
276
+	if !strings.Contains(string(out), "Signing and pushing trust metadata") {
277
+		c.Fatalf("Missing expected output on trusted push:\n%s", out)
278
+	}
279
+
280
+	dockerCmd(c, "rmi", repoName)
281
+
282
+	// Try pull
283
+	pullCmd := exec.Command(dockerBinary, "pull", repoName)
284
+	s.trustedCmd(pullCmd)
285
+	out, _, err = runCommandWithOutput(pullCmd)
286
+	if err != nil {
287
+		c.Fatalf("Error running trusted pull: %s\n%s", err, out)
288
+	}
289
+
290
+	if !strings.Contains(string(out), "Tagging") {
291
+		c.Fatalf("Missing expected output on trusted push:\n%s", out)
292
+	}
293
+
294
+	dockerCmd(c, "rmi", repoName)
295
+
296
+	// Kill the notary server, start a new "evil" one.
297
+	s.not.Close()
298
+	s.not, err = newTestNotary(c)
299
+	if err != nil {
300
+		c.Fatalf("Restarting notary server failed.")
301
+	}
302
+
303
+	// In order to make an evil server, lets re-init a client (with a different trust dir) and push new data.
304
+	// tag an image and upload it to the private registry
305
+	dockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName)
306
+
307
+	// Push up to the new server
308
+	pushCmd = exec.Command(dockerBinary, "--config", evilLocalConfigDir, "push", repoName)
309
+	s.trustedCmd(pushCmd)
310
+	out, _, err = runCommandWithOutput(pushCmd)
311
+	if err != nil {
312
+		c.Fatalf("Error running trusted push: %s\n%s", err, out)
313
+	}
314
+	if !strings.Contains(string(out), "Signing and pushing trust metadata") {
315
+		c.Fatalf("Missing expected output on trusted push:\n%s", out)
316
+	}
317
+
318
+	// Now, try pulling with the original client from this new trust server. This should fail.
319
+	pullCmd = exec.Command(dockerBinary, "pull", repoName)
320
+	s.trustedCmd(pullCmd)
321
+	out, _, err = runCommandWithOutput(pullCmd)
322
+	if err == nil {
323
+		c.Fatalf("Expected to fail on this pull due to different remote data: %s\n%s", err, out)
324
+	}
325
+
326
+	if !strings.Contains(string(out), "failed to validate integrity of roots") {
327
+		c.Fatalf("Missing expected output on trusted push:\n%s", out)
328
+	}
329
+}
... ...
@@ -2632,3 +2632,74 @@ func (s *DockerTrustSuite) TestRunWhenCertExpired(c *check.C) {
2632 2632
 		}
2633 2633
 	})
2634 2634
 }
2635
+
2636
+func (s *DockerTrustSuite) TestTrustedRunFromBadTrustServer(c *check.C) {
2637
+	repoName := fmt.Sprintf("%v/dockerclievilrun/trusted:latest", privateRegistryURL)
2638
+	evilLocalConfigDir, err := ioutil.TempDir("", "evil-local-config-dir")
2639
+	if err != nil {
2640
+		c.Fatalf("Failed to create local temp dir")
2641
+	}
2642
+
2643
+	// tag the image and upload it to the private registry
2644
+	dockerCmd(c, "tag", "busybox", repoName)
2645
+
2646
+	pushCmd := exec.Command(dockerBinary, "push", repoName)
2647
+	s.trustedCmd(pushCmd)
2648
+	out, _, err := runCommandWithOutput(pushCmd)
2649
+	if err != nil {
2650
+		c.Fatalf("Error running trusted push: %s\n%s", err, out)
2651
+	}
2652
+	if !strings.Contains(string(out), "Signing and pushing trust metadata") {
2653
+		c.Fatalf("Missing expected output on trusted push:\n%s", out)
2654
+	}
2655
+
2656
+	dockerCmd(c, "rmi", repoName)
2657
+
2658
+	// Try run
2659
+	runCmd := exec.Command(dockerBinary, "run", repoName)
2660
+	s.trustedCmd(runCmd)
2661
+	out, _, err = runCommandWithOutput(runCmd)
2662
+	if err != nil {
2663
+		c.Fatalf("Error running trusted run: %s\n%s", err, out)
2664
+	}
2665
+
2666
+	if !strings.Contains(string(out), "Tagging") {
2667
+		c.Fatalf("Missing expected output on trusted push:\n%s", out)
2668
+	}
2669
+
2670
+	dockerCmd(c, "rmi", repoName)
2671
+
2672
+	// Kill the notary server, start a new "evil" one.
2673
+	s.not.Close()
2674
+	s.not, err = newTestNotary(c)
2675
+	if err != nil {
2676
+		c.Fatalf("Restarting notary server failed.")
2677
+	}
2678
+
2679
+	// In order to make an evil server, lets re-init a client (with a different trust dir) and push new data.
2680
+	// tag an image and upload it to the private registry
2681
+	dockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName)
2682
+
2683
+	// Push up to the new server
2684
+	pushCmd = exec.Command(dockerBinary, "--config", evilLocalConfigDir, "push", repoName)
2685
+	s.trustedCmd(pushCmd)
2686
+	out, _, err = runCommandWithOutput(pushCmd)
2687
+	if err != nil {
2688
+		c.Fatalf("Error running trusted push: %s\n%s", err, out)
2689
+	}
2690
+	if !strings.Contains(string(out), "Signing and pushing trust metadata") {
2691
+		c.Fatalf("Missing expected output on trusted push:\n%s", out)
2692
+	}
2693
+
2694
+	// Now, try running with the original client from this new trust server. This should fail.
2695
+	runCmd = exec.Command(dockerBinary, "run", repoName)
2696
+	s.trustedCmd(runCmd)
2697
+	out, _, err = runCommandWithOutput(runCmd)
2698
+	if err == nil {
2699
+		c.Fatalf("Expected to fail on this run due to different remote data: %s\n%s", err, out)
2700
+	}
2701
+
2702
+	if !strings.Contains(string(out), "failed to validate integrity of roots") {
2703
+		c.Fatalf("Missing expected output on trusted push:\n%s", out)
2704
+	}
2705
+}
... ...
@@ -1267,17 +1267,6 @@ func setupNotary(c *check.C) *testNotary {
1267 1267
 		c.Fatal(err)
1268 1268
 	}
1269 1269
 
1270
-	// Wait for notary to be ready to serve requests.
1271
-	for i := 1; i <= 5; i++ {
1272
-		if err = ts.Ping(); err == nil {
1273
-			break
1274
-		}
1275
-		time.Sleep(10 * time.Millisecond * time.Duration(i*i))
1276
-	}
1277
-
1278
-	if err != nil {
1279
-		c.Fatalf("Timeout waiting for test notary to become available: %s", err)
1280
-	}
1281 1270
 	return ts
1282 1271
 }
1283 1272
 
... ...
@@ -60,10 +60,25 @@ func newTestNotary(c *check.C) (*testNotary, error) {
60 60
 		}
61 61
 		return nil, err
62 62
 	}
63
-	return &testNotary{
63
+
64
+	testNotary := &testNotary{
64 65
 		cmd: cmd,
65 66
 		dir: tmp,
66
-	}, nil
67
+	}
68
+
69
+	// Wait for notary to be ready to serve requests.
70
+	for i := 1; i <= 5; i++ {
71
+		if err = testNotary.Ping(); err == nil {
72
+			break
73
+		}
74
+		time.Sleep(10 * time.Millisecond * time.Duration(i*i))
75
+	}
76
+
77
+	if err != nil {
78
+		c.Fatalf("Timeout waiting for test notary to become available: %s", err)
79
+	}
80
+
81
+	return testNotary, nil
67 82
 }
68 83
 
69 84
 func (t *testNotary) address() string {