Merge ~powersj/cloud-init:test-set-password-list into cloud-init:master

Proposed by Joshua Powers on 2017-03-14
Status: Merged
Merged at revision: 41950e902f5dd6cb3118280d3d27409812702e41
Proposed branch: ~powersj/cloud-init:test-set-password-list
Merge into: cloud-init:master
Diff against target: 224 lines (+115/-27)
6 files modified
cloudinit/config/cc_set_passwords.py (+2/-2)
tests/cloud_tests/configs/modules/set_password_list.yaml (+12/-8)
tests/cloud_tests/configs/modules/set_password_list_string.yaml (+37/-0)
tests/cloud_tests/testcases/base.py (+52/-0)
tests/cloud_tests/testcases/modules/set_password_list.py (+2/-17)
tests/cloud_tests/testcases/modules/set_password_list_string.py (+10/-0)
Reviewer Review Type Date Requested Status
Scott Moser 2017-03-14 Approve on 2017-03-17
Server Team CI bot continuous-integration Approve on 2017-03-17
Review via email: mp+319878@code.launchpad.net

This proposal supersedes a proposal from 2017-03-14.

Commit Message

test: Add test for setting password as list

This adds an integration test for setting passwords when given
as a list, rather than a string. This also updates the docs and
tests so that Random is now RANDOM as is correct.

To post a comment you must log in.
5be8342... by Joshua Powers on 2017-03-16

Adding in smoser's commits to both files

a881acb... by Joshua Powers on 2017-03-16

Adding in smoser's commits to both files

9cd40a2... by Joshua Powers on 2017-03-16

Revrting expire on accident

41bf34e... by Joshua Powers on 2017-03-16

Revrting expire on accident

Joshua Powers (powersj) wrote :

Pulled in smoser's changes from https://paste.ubuntu.com/24191229/ and applied them to both set_password_list and set_password_list_string

d3c2e6c... by Joshua Powers on 2017-03-17

Fix flake8 errors

cc3aaf5... by Joshua Powers on 2017-03-17

Fix flake8 errors

Scott Moser (smoser) wrote :

Josh, this looks great. Thank you.

The only thing I don't like now is the duplication.

There are 2 ways i can think of to reduce it:
a.) both tests extend a base class that has the test_* functions.
   this is just less flexible than 'b', but because these things are identical now, its the easiest thing.

I started to write in text how you could do this, but found that it was just as easy to do it myself and describe it that way. I think acceptable: http://paste.ubuntu.com/24195190/

The thing i'm not sure of is if we need to somehow make sure that the 'PasswordListTest' base class somehow doesnt run. In curtin vmtest we always did this with __test__ = False. I'm happy that it doesnt appear we need this, but I didn't yet run a full simple 'run' without specific -t

b.) some helper functions for testing this, and then the test_* functions will have call helper functions and have less in them.

aba194b... by Joshua Powers on 2017-03-17

Using class + subclass for password list

This reduces the duplication of test cases since we are doing the
exact same thing for each.

c95f455... by Joshua Powers on 2017-03-17

Using class + subclass for password list

This reduces the duplication of test cases since we are doing the
exact same thing for each.

8451d0e... by Joshua Powers on 2017-03-17

Adding testcase as a parameter and enabling tests

c194276... by Joshua Powers on 2017-03-17

Adding testcase as a parameter and enabling tests

Joshua Powers (powersj) wrote :

I added class/subclass method you proposed, which I like a lot. There is no reason for duplicate code. My only concern is base.py filling up with a bunch of code, but I think that is ok.

However, I had to modify the parameters slightly so nose actually realizes there are tests to run and added the __test__ = True variable. Both were required for tests to be discovered and ran; I did try without each. I also added the description change that we recently added to curtin since we are now doing this.

Here is output of a run with those two tests:
https://paste.ubuntu.com/24196020/

d707e81... by Joshua Powers on 2017-03-17

Removing uncessary test case parameters

68b67d1... by Joshua Powers on 2017-03-17

Merge branch 'test-set-password-list' of git+ssh://git.launchpad.net/~powersj/cloud-init into test-set-password-list

Scott Moser (smoser) wrote :

thanks josh

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/cloudinit/config/cc_set_passwords.py b/cloudinit/config/cc_set_passwords.py
2index 1611704..8440e59 100755
3--- a/cloudinit/config/cc_set_passwords.py
4+++ b/cloudinit/config/cc_set_passwords.py
5@@ -47,7 +47,7 @@ enabled, disabled, or left to system defaults using ``ssh_pwauth``.
6 chpasswd:
7 list: |
8 user1:password1
9- user2:Random
10+ user2:RANDOM
11 user3:password3
12 user4:R
13
14@@ -57,7 +57,7 @@ enabled, disabled, or left to system defaults using ``ssh_pwauth``.
15 chpasswd:
16 list:
17 - user1:password1
18- - user2:Random
19+ - user2:RANDOM
20 - user3:password3
21 - user4:R
22 """
23diff --git a/tests/cloud_tests/configs/modules/set_password_list.yaml b/tests/cloud_tests/configs/modules/set_password_list.yaml
24index 3612904..a1eadd7 100644
25--- a/tests/cloud_tests/configs/modules/set_password_list.yaml
26+++ b/tests/cloud_tests/configs/modules/set_password_list.yaml
27@@ -6,22 +6,26 @@ cloud_config: |
28 ssh_pwauth: yes
29 users:
30 - name: tom
31- password: $1$xyz$sPMsLNmf66Ohl.ol6JvzE.
32+ # md5 gotomgo
33+ passwd: "$1$S7$tT1BEDIYrczeryDQJfdPe0"
34 lock_passwd: false
35 - name: dick
36- password: $1$xyz$sPMsLNmf66Ohl.ol6JvzE.
37+ # md5 gocubsgo
38+ passwd: "$1$ssisyfpf$YqvuJLfrrW6Cg/l53Pi1n1"
39 lock_passwd: false
40 - name: harry
41- password: $1$xyz$sPMsLNmf66Ohl.ol6JvzE.
42+ # sha512 goharrygo
43+ passwd: "$6$LF$9Z2p6rWK6TNC1DC6393ec0As.18KRAvKDbfsGJEdWN3sRQRwpdfoh37EQ3yUh69tP4GSrGW5XKHxMLiKowJgm/"
44 lock_passwd: false
45 - name: jane
46- password: $1$xyz$sPMsLNmf66Ohl.ol6JvzE.
47+ # sha256 gojanego
48+ passwd: "$5$iW$XsxmWCdpwIW8Yhv.Jn/R3uk6A4UaicfW5Xp7C9p9pg."
49 lock_passwd: false
50 chpasswd:
51- list: |
52- tom:mypassword123!
53- dick:R
54- harry:Random
55+ list:
56+ - tom:mypassword123!
57+ - dick:RANDOM
58+ - harry:RANDOM
59 collect_scripts:
60 shadow: |
61 #!/bin/bash
62diff --git a/tests/cloud_tests/configs/modules/set_password_list_string.yaml b/tests/cloud_tests/configs/modules/set_password_list_string.yaml
63new file mode 100644
64index 0000000..cbb71be
65--- /dev/null
66+++ b/tests/cloud_tests/configs/modules/set_password_list_string.yaml
67@@ -0,0 +1,37 @@
68+#
69+# Set password of list of users as a string
70+#
71+cloud_config: |
72+ #cloud-config
73+ ssh_pwauth: yes
74+ users:
75+ - name: tom
76+ # md5 gotomgo
77+ passwd: "$1$S7$tT1BEDIYrczeryDQJfdPe0"
78+ lock_passwd: false
79+ - name: dick
80+ # md5 gocubsgo
81+ passwd: "$1$ssisyfpf$YqvuJLfrrW6Cg/l53Pi1n1"
82+ lock_passwd: false
83+ - name: harry
84+ # sha512 goharrygo
85+ passwd: "$6$LF$9Z2p6rWK6TNC1DC6393ec0As.18KRAvKDbfsGJEdWN3sRQRwpdfoh37EQ3yUh69tP4GSrGW5XKHxMLiKowJgm/"
86+ lock_passwd: false
87+ - name: jane
88+ # sha256 gojanego
89+ passwd: "$5$iW$XsxmWCdpwIW8Yhv.Jn/R3uk6A4UaicfW5Xp7C9p9pg."
90+ lock_passwd: false
91+ chpasswd:
92+ list: |
93+ tom:mypassword123!
94+ dick:RANDOM
95+ harry:RANDOM
96+collect_scripts:
97+ shadow: |
98+ #!/bin/bash
99+ cat /etc/shadow
100+ sshd_config: |
101+ #!/bin/bash
102+ grep '^PasswordAuth' /etc/ssh/sshd_config
103+
104+# vi: ts=4 expandtab
105diff --git a/tests/cloud_tests/testcases/base.py b/tests/cloud_tests/testcases/base.py
106index 5395b9a..51ce2b4 100644
107--- a/tests/cloud_tests/testcases/base.py
108+++ b/tests/cloud_tests/testcases/base.py
109@@ -2,6 +2,7 @@
110
111 from cloudinit import util as c_util
112
113+import crypt
114 import json
115 import unittest
116
117@@ -14,6 +15,9 @@ class CloudTestCase(unittest.TestCase):
118 conf = None
119 _cloud_config = None
120
121+ def shortDescription(self):
122+ return None
123+
124 @property
125 def cloud_config(self):
126 """
127@@ -78,4 +82,52 @@ class CloudTestCase(unittest.TestCase):
128 result = self.get_status_data(self.get_data_file('result.json'))
129 self.assertEqual(len(result['errors']), 0)
130
131+
132+class PasswordListTest(CloudTestCase):
133+ def test_shadow_passwords(self):
134+ shadow = self.get_data_file('shadow')
135+ users = {}
136+ dupes = []
137+ for line in shadow.splitlines():
138+ user, encpw = line.split(":")[0:2]
139+ if user in users:
140+ dupes.append(user)
141+ users[user] = encpw
142+
143+ jane_enc = "$5$iW$XsxmWCdpwIW8Yhv.Jn/R3uk6A4UaicfW5Xp7C9p9pg."
144+ self.assertEqual([], dupes)
145+ self.assertEqual(jane_enc, users['jane'])
146+
147+ # shadow entry is $N$salt$, so we encrypt with the same format
148+ # and salt and expect the result.
149+ tom = "mypassword123!"
150+ fmtsalt = users['tom'][0:users['tom'].rfind("$") + 1]
151+ tom_enc = crypt.crypt(tom, fmtsalt)
152+ self.assertEqual(tom_enc, users['tom'])
153+
154+ harry_enc = ("$6$LF$9Z2p6rWK6TNC1DC6393ec0As.18KRAvKDbfsG"
155+ "JEdWN3sRQRwpdfoh37EQ3yUh69tP4GSrGW5XKHxMLiKowJgm/")
156+ dick_enc = "$1$ssisyfpf$YqvuJLfrrW6Cg/l53Pi1n1"
157+
158+ # these should have been changed to random values.
159+ self.assertNotEqual(harry_enc, users['harry'])
160+ self.assertTrue(users['harry'].startswith("$"))
161+ self.assertNotEqual(dick_enc, users['dick'])
162+ self.assertTrue(users['dick'].startswith("$"))
163+
164+ self.assertNotEqual(users['harry'], users['dick'])
165+
166+ def test_shadow_expected_users(self):
167+ """Test every tom, dick, and harry user in shadow"""
168+ out = self.get_data_file('shadow')
169+ self.assertIn('tom:', out)
170+ self.assertIn('dick:', out)
171+ self.assertIn('harry:', out)
172+ self.assertIn('jane:', out)
173+
174+ def test_sshd_config(self):
175+ """Test sshd config allows passwords"""
176+ out = self.get_data_file('sshd_config')
177+ self.assertIn('PasswordAuthentication yes', out)
178+
179 # vi: ts=4 expandtab
180diff --git a/tests/cloud_tests/testcases/modules/set_password_list.py b/tests/cloud_tests/testcases/modules/set_password_list.py
181index b764362..5671de1 100644
182--- a/tests/cloud_tests/testcases/modules/set_password_list.py
183+++ b/tests/cloud_tests/testcases/modules/set_password_list.py
184@@ -4,22 +4,7 @@
185 from tests.cloud_tests.testcases import base
186
187
188-class TestPasswordList(base.CloudTestCase):
189- """Test password module"""
190-
191- # TODO: Verify dick and harry passwords are random
192- # TODO: Verify tom's password was changed
193-
194- def test_shadow(self):
195- """Test every tom, dick, and harry user in shadow"""
196- out = self.get_data_file('shadow')
197- self.assertIn('tom:', out)
198- self.assertIn('dick:', out)
199- self.assertIn('harry:', out)
200-
201- def test_sshd_config(self):
202- """Test sshd config allows passwords"""
203- out = self.get_data_file('sshd_config')
204- self.assertIn('PasswordAuthentication yes', out)
205+class TestPasswordList(base.PasswordListTest):
206+ """Test password setting via list in chpasswd/list"""
207
208 # vi: ts=4 expandtab
209diff --git a/tests/cloud_tests/testcases/modules/set_password_list_string.py b/tests/cloud_tests/testcases/modules/set_password_list_string.py
210new file mode 100644
211index 0000000..9e77c87
212--- /dev/null
213+++ b/tests/cloud_tests/testcases/modules/set_password_list_string.py
214@@ -0,0 +1,10 @@
215+# This file is part of cloud-init. See LICENSE file for license information.
216+
217+"""cloud-init Integration Test Verify Script"""
218+from tests.cloud_tests.testcases import base
219+
220+
221+class TestPasswordListString(base.PasswordListTest):
222+ """Test password setting via string in chpasswd/list"""
223+
224+# vi: ts=4 expandtab

Subscribers

People subscribed via source and target branches