Browse code

Lock/unlock integration tests

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>

Aaron Lehmann authored on 2016/11/01 07:02:34
Showing 2 changed files
... ...
@@ -584,15 +584,15 @@ func (c *Cluster) UnlockSwarm(req types.UnlockRequest) error {
584 584
 	n, err := c.startNewNode(config)
585 585
 	if err != nil {
586 586
 		c.Unlock()
587
-		if errors.Cause(err) == ErrSwarmLocked {
588
-			return errors.New("swarm could not be unlocked: invalid key provided")
589
-		}
590 587
 		return err
591 588
 	}
592 589
 	c.Unlock()
593 590
 	select {
594 591
 	case <-n.Ready():
595 592
 	case <-n.done:
593
+		if errors.Cause(c.err) == ErrSwarmLocked {
594
+			return errors.New("swarm could not be unlocked: invalid key provided")
595
+		}
596 596
 		return fmt.Errorf("swarm component could not be started: %v", c.err)
597 597
 	}
598 598
 	go c.reconnectOnFailure(n)
... ...
@@ -881,6 +881,8 @@ func (c *Cluster) Info() types.Info {
881 881
 		info.LocalNodeState = types.LocalNodeStatePending
882 882
 		if c.ready == true {
883 883
 			info.LocalNodeState = types.LocalNodeStateActive
884
+		} else if c.locked {
885
+			info.LocalNodeState = types.LocalNodeStateLocked
884 886
 		}
885 887
 	}
886 888
 	if c.err != nil {
... ...
@@ -855,56 +855,86 @@ func (s *DockerSwarmSuite) TestDNSConfigUpdate(c *check.C) {
855 855
 func (s *DockerSwarmSuite) TestSwarmInitLocked(c *check.C) {
856 856
 	d := s.AddDaemon(c, false, false)
857 857
 
858
-	cmd := d.command("swarm", "init", "--lock-key")
859
-	cmd.Stdin = bytes.NewBufferString("my-secret-key")
860
-	out, err := cmd.CombinedOutput()
861
-	c.Assert(err, checker.IsNil, check.Commentf("out: %v", string(out)))
858
+	outs, err := d.Cmd("swarm", "init", "--autolock")
859
+	c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
860
+
861
+	c.Assert(outs, checker.Contains, "docker swarm unlock")
862
+
863
+	var unlockKey string
864
+	for _, line := range strings.Split(outs, "\n") {
865
+		if strings.Contains(line, "SWMKEY") {
866
+			unlockKey = strings.TrimSpace(line)
867
+			break
868
+		}
869
+	}
870
+
871
+	c.Assert(unlockKey, checker.Not(checker.Equals), "")
862 872
 
863
-	c.Assert(string(out), checker.Contains, "docker swarm unlock")
873
+	outs, err = d.Cmd("swarm", "unlock-key", "-q")
874
+	c.Assert(outs, checker.Equals, unlockKey+"\n")
864 875
 
865 876
 	info, err := d.info()
866 877
 	c.Assert(err, checker.IsNil)
867 878
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
868 879
 
869
-	c.Assert(d.Stop(), checker.IsNil)
870
-	c.Assert(d.Start(), checker.IsNil)
880
+	c.Assert(d.Restart(), checker.IsNil)
871 881
 
872 882
 	info, err = d.info()
873 883
 	c.Assert(err, checker.IsNil)
874 884
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateLocked)
875 885
 
876
-	cmd = d.command("swarm", "unlock")
886
+	cmd := d.command("swarm", "unlock")
877 887
 	cmd.Stdin = bytes.NewBufferString("wrong-secret-key")
878
-	out, err = cmd.CombinedOutput()
888
+	out, err := cmd.CombinedOutput()
879 889
 	c.Assert(err, checker.NotNil, check.Commentf("out: %v", string(out)))
880 890
 	c.Assert(string(out), checker.Contains, "invalid key")
881 891
 
882 892
 	cmd = d.command("swarm", "unlock")
883
-	cmd.Stdin = bytes.NewBufferString("my-secret-key")
893
+	cmd.Stdin = bytes.NewBufferString(unlockKey)
884 894
 	out, err = cmd.CombinedOutput()
885 895
 	c.Assert(err, checker.IsNil, check.Commentf("out: %v", string(out)))
886 896
 
887 897
 	info, err = d.info()
888 898
 	c.Assert(err, checker.IsNil)
889 899
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
900
+
901
+	outs, err = d.Cmd("node", "ls")
902
+	c.Assert(err, checker.IsNil)
903
+	c.Assert(outs, checker.Not(checker.Contains), "Swarm is encrypted and needs to be unlocked")
904
+
905
+	outs, err = d.Cmd("swarm", "update", "--autolock=false")
906
+	c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
907
+
908
+	// Wait for autolock to be turned off
909
+	time.Sleep(time.Second)
910
+
911
+	c.Assert(d.Restart(), checker.IsNil)
912
+
913
+	info, err = d.info()
914
+	c.Assert(err, checker.IsNil)
915
+	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
916
+
917
+	outs, err = d.Cmd("node", "ls")
918
+	c.Assert(err, checker.IsNil)
919
+	c.Assert(outs, checker.Not(checker.Contains), "Swarm is encrypted and needs to be unlocked")
890 920
 }
891 921
 
892 922
 func (s *DockerSwarmSuite) TestSwarmLeaveLocked(c *check.C) {
893 923
 	d := s.AddDaemon(c, false, false)
894 924
 
895
-	cmd := d.command("swarm", "init", "--lock-key")
896
-	cmd.Stdin = bytes.NewBufferString("foobar")
897
-	out, err := cmd.CombinedOutput()
898
-	c.Assert(err, checker.IsNil, check.Commentf("out: %v", string(out)))
925
+	outs, err := d.Cmd("swarm", "init", "--autolock")
926
+	c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
899 927
 
900
-	c.Assert(d.Stop(), checker.IsNil)
901
-	c.Assert(d.Start(), checker.IsNil)
928
+	c.Assert(d.Restart("--swarm-default-advertise-addr=lo"), checker.IsNil)
902 929
 
903 930
 	info, err := d.info()
904 931
 	c.Assert(err, checker.IsNil)
905 932
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateLocked)
906 933
 
907
-	outs, err := d.Cmd("swarm", "leave", "--force")
934
+	outs, _ = d.Cmd("node", "ls")
935
+	c.Assert(outs, checker.Contains, "Swarm is encrypted and needs to be unlocked")
936
+
937
+	outs, err = d.Cmd("swarm", "leave", "--force")
908 938
 	c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
909 939
 
910 940
 	info, err = d.info()
... ...
@@ -918,3 +948,83 @@ func (s *DockerSwarmSuite) TestSwarmLeaveLocked(c *check.C) {
918 918
 	c.Assert(err, checker.IsNil)
919 919
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
920 920
 }
921
+
922
+func (s *DockerSwarmSuite) TestSwarmRotateUnlockKey(c *check.C) {
923
+	d := s.AddDaemon(c, true, true)
924
+
925
+	outs, err := d.Cmd("swarm", "update", "--autolock")
926
+	c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
927
+
928
+	c.Assert(outs, checker.Contains, "docker swarm unlock")
929
+
930
+	var unlockKey string
931
+	for _, line := range strings.Split(outs, "\n") {
932
+		if strings.Contains(line, "SWMKEY") {
933
+			unlockKey = strings.TrimSpace(line)
934
+			break
935
+		}
936
+	}
937
+
938
+	c.Assert(unlockKey, checker.Not(checker.Equals), "")
939
+
940
+	outs, err = d.Cmd("swarm", "unlock-key", "-q")
941
+	c.Assert(outs, checker.Equals, unlockKey+"\n")
942
+
943
+	// Rotate multiple times
944
+	for i := 0; i != 3; i++ {
945
+		outs, err = d.Cmd("swarm", "unlock-key", "-q", "--rotate")
946
+		c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
947
+		// Strip \n
948
+		newUnlockKey := outs[:len(outs)-1]
949
+		c.Assert(newUnlockKey, checker.Not(checker.Equals), "")
950
+
951
+		c.Assert(d.Restart(), checker.IsNil)
952
+
953
+		info, err := d.info()
954
+		c.Assert(err, checker.IsNil)
955
+		c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateLocked)
956
+
957
+		outs, _ = d.Cmd("node", "ls")
958
+		c.Assert(outs, checker.Contains, "Swarm is encrypted and needs to be unlocked")
959
+
960
+		cmd := d.command("swarm", "unlock")
961
+		cmd.Stdin = bytes.NewBufferString(unlockKey)
962
+		out, err := cmd.CombinedOutput()
963
+
964
+		if err == nil {
965
+			// On occasion, the daemon may not have finished
966
+			// rotating the KEK before restarting. The test is
967
+			// intentionally written to explore this behavior.
968
+			// When this happens, unlocking with the old key will
969
+			// succeed. If we wait for the rotation to happen and
970
+			// restart again, the new key should be required this
971
+			// time.
972
+
973
+			time.Sleep(3 * time.Second)
974
+
975
+			c.Assert(d.Restart(), checker.IsNil)
976
+
977
+			cmd = d.command("swarm", "unlock")
978
+			cmd.Stdin = bytes.NewBufferString(unlockKey)
979
+			out, err = cmd.CombinedOutput()
980
+		}
981
+		c.Assert(err, checker.NotNil, check.Commentf("out: %v", string(out)))
982
+		c.Assert(string(out), checker.Contains, "invalid key")
983
+
984
+		outs, _ = d.Cmd("node", "ls")
985
+		c.Assert(outs, checker.Contains, "Swarm is encrypted and needs to be unlocked")
986
+
987
+		cmd = d.command("swarm", "unlock")
988
+		cmd.Stdin = bytes.NewBufferString(newUnlockKey)
989
+		out, err = cmd.CombinedOutput()
990
+		c.Assert(err, checker.IsNil, check.Commentf("out: %v", string(out)))
991
+
992
+		info, err = d.info()
993
+		c.Assert(err, checker.IsNil)
994
+		c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
995
+
996
+		outs, err = d.Cmd("node", "ls")
997
+		c.Assert(err, checker.IsNil)
998
+		c.Assert(outs, checker.Not(checker.Contains), "Swarm is encrypted and needs to be unlocked")
999
+	}
1000
+}