22
33
Test that nothing is done if no ca-certs configuration is provided.
24
35
config = util.get_builtin_cfg()
25
self.mocker.replace(util.write_file, passthrough=False)
26
self.mocker.replace(cc_ca_certs.update_ca_certs, passthrough=False)
29
cc_ca_certs.handle(self.name, config, self.cloud_init, self.log,
33
class TestConfig(MockerTestCase):
36
with ExitStack() as mocks:
37
util_mock = mocks.enter_context(
38
mock.patch.object(util, 'write_file'))
39
certs_mock = mocks.enter_context(
40
mock.patch.object(cc_ca_certs, 'update_ca_certs'))
42
cc_ca_certs.handle(self.name, config, self.cloud_init, self.log,
45
self.assertEqual(util_mock.call_count, 0)
46
self.assertEqual(certs_mock.call_count, 0)
49
class TestConfig(TestCase):
35
51
super(TestConfig, self).setUp()
36
52
self.name = "ca-certs"
58
74
config = {"ca-certs": {}}
60
# No functions should be called
64
76
cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
78
self.assertEqual(self.mock_add.call_count, 0)
79
self.assertEqual(self.mock_update.call_count, 1)
80
self.assertEqual(self.mock_remove.call_count, 0)
66
82
def test_empty_trusted_list(self):
67
83
"""Test that no certificate are written if 'trusted' list is empty."""
68
84
config = {"ca-certs": {"trusted": []}}
70
# No functions should be called
74
86
cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
88
self.assertEqual(self.mock_add.call_count, 0)
89
self.assertEqual(self.mock_update.call_count, 1)
90
self.assertEqual(self.mock_remove.call_count, 0)
76
92
def test_single_trusted(self):
77
93
"""Test that a single cert gets passed to add_ca_certs."""
78
94
config = {"ca-certs": {"trusted": ["CERT1"]}}
80
self.mock_add(["CERT1"])
84
96
cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
98
self.mock_add.assert_called_once_with(['CERT1'])
99
self.assertEqual(self.mock_update.call_count, 1)
100
self.assertEqual(self.mock_remove.call_count, 0)
86
102
def test_multiple_trusted(self):
87
103
"""Test that multiple certs get passed to add_ca_certs."""
88
104
config = {"ca-certs": {"trusted": ["CERT1", "CERT2"]}}
90
self.mock_add(["CERT1", "CERT2"])
94
106
cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
108
self.mock_add.assert_called_once_with(['CERT1', 'CERT2'])
109
self.assertEqual(self.mock_update.call_count, 1)
110
self.assertEqual(self.mock_remove.call_count, 0)
96
112
def test_remove_default_ca_certs(self):
97
113
"""Test remove_defaults works as expected."""
98
114
config = {"ca-certs": {"remove-defaults": True}}
104
116
cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
118
self.assertEqual(self.mock_add.call_count, 0)
119
self.assertEqual(self.mock_update.call_count, 1)
120
self.assertEqual(self.mock_remove.call_count, 1)
106
122
def test_no_remove_defaults_if_false(self):
107
123
"""Test remove_defaults is not called when config value is False."""
108
124
config = {"ca-certs": {"remove-defaults": False}}
113
126
cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
128
self.assertEqual(self.mock_add.call_count, 0)
129
self.assertEqual(self.mock_update.call_count, 1)
130
self.assertEqual(self.mock_remove.call_count, 0)
115
132
def test_correct_order_for_remove_then_add(self):
116
133
"""Test remove_defaults is not called when config value is False."""
117
134
config = {"ca-certs": {"remove-defaults": True, "trusted": ["CERT1"]}}
120
self.mock_add(["CERT1"])
124
136
cc_ca_certs.handle(self.name, config, self.cloud, self.log, self.args)
127
class TestAddCaCerts(MockerTestCase):
138
self.mock_add.assert_called_once_with(['CERT1'])
139
self.assertEqual(self.mock_update.call_count, 1)
140
self.assertEqual(self.mock_remove.call_count, 1)
143
class TestAddCaCerts(TestCase):
130
146
super(TestAddCaCerts, self).setUp()
147
tmpdir = tempfile.mkdtemp()
148
self.addCleanup(shutil.rmtree, tmpdir)
131
149
self.paths = helpers.Paths({
132
'cloud_dir': self.makeDir()
135
153
def test_no_certs_in_list(self):
136
154
"""Test that no certificate are written if not provided."""
137
self.mocker.replace(util.write_file, passthrough=False)
139
cc_ca_certs.add_ca_certs([])
155
with mock.patch.object(util, 'write_file') as mockobj:
156
cc_ca_certs.add_ca_certs([])
157
self.assertEqual(mockobj.call_count, 0)
141
159
def test_single_cert_trailing_cr(self):
142
160
"""Test adding a single certificate to the trusted CAs
146
164
ca_certs_content = "line1\nline2\ncloud-init-ca-certs.crt\nline3\n"
147
165
expected = "line1\nline2\nline3\ncloud-init-ca-certs.crt\n"
149
mock_write = self.mocker.replace(util.write_file, passthrough=False)
150
mock_load = self.mocker.replace(util.load_file, passthrough=False)
152
mock_write("/usr/share/ca-certificates/cloud-init-ca-certs.crt",
155
mock_load("/etc/ca-certificates.conf")
156
self.mocker.result(ca_certs_content)
158
mock_write("/etc/ca-certificates.conf", expected, omode="wb")
161
cc_ca_certs.add_ca_certs([cert])
167
with ExitStack() as mocks:
168
mock_write = mocks.enter_context(
169
mock.patch.object(util, 'write_file'))
170
mock_load = mocks.enter_context(
171
mock.patch.object(util, 'load_file',
172
return_value=ca_certs_content))
174
cc_ca_certs.add_ca_certs([cert])
176
mock_write.assert_has_calls([
177
mock.call("/usr/share/ca-certificates/cloud-init-ca-certs.crt",
179
mock.call("/etc/ca-certificates.conf", expected, omode="wb"),
181
mock_load.assert_called_once_with("/etc/ca-certificates.conf")
163
183
def test_single_cert_no_trailing_cr(self):
164
184
"""Test adding a single certificate to the trusted CAs
168
188
ca_certs_content = "line1\nline2\nline3"
170
mock_write = self.mocker.replace(util.write_file, passthrough=False)
171
mock_load = self.mocker.replace(util.load_file, passthrough=False)
173
mock_write("/usr/share/ca-certificates/cloud-init-ca-certs.crt",
176
mock_load("/etc/ca-certificates.conf")
177
self.mocker.result(ca_certs_content)
179
mock_write("/etc/ca-certificates.conf",
180
"%s\n%s\n" % (ca_certs_content, "cloud-init-ca-certs.crt"),
184
cc_ca_certs.add_ca_certs([cert])
190
with ExitStack() as mocks:
191
mock_write = mocks.enter_context(
192
mock.patch.object(util, 'write_file'))
193
mock_load = mocks.enter_context(
194
mock.patch.object(util, 'load_file',
195
return_value=ca_certs_content))
197
cc_ca_certs.add_ca_certs([cert])
199
mock_write.assert_has_calls([
200
mock.call("/usr/share/ca-certificates/cloud-init-ca-certs.crt",
202
mock.call("/etc/ca-certificates.conf",
203
"%s\n%s\n" % (ca_certs_content,
204
"cloud-init-ca-certs.crt"),
208
mock_load.assert_called_once_with("/etc/ca-certificates.conf")
186
210
def test_multiple_certs(self):
187
211
"""Test adding multiple certificates to the trusted CAs."""
188
212
certs = ["CERT1\nLINE2\nLINE3", "CERT2\nLINE2\nLINE3"]
189
213
expected_cert_file = "\n".join(certs)
191
mock_write = self.mocker.replace(util.write_file, passthrough=False)
192
mock_load = self.mocker.replace(util.load_file, passthrough=False)
194
mock_write("/usr/share/ca-certificates/cloud-init-ca-certs.crt",
195
expected_cert_file, mode=0644)
197
214
ca_certs_content = "line1\nline2\nline3"
198
mock_load("/etc/ca-certificates.conf")
199
self.mocker.result(ca_certs_content)
201
out = "%s\n%s\n" % (ca_certs_content, "cloud-init-ca-certs.crt")
202
mock_write("/etc/ca-certificates.conf", out, omode="wb")
206
cc_ca_certs.add_ca_certs(certs)
209
class TestUpdateCaCerts(MockerTestCase):
216
with ExitStack() as mocks:
217
mock_write = mocks.enter_context(
218
mock.patch.object(util, 'write_file'))
219
mock_load = mocks.enter_context(
220
mock.patch.object(util, 'load_file',
221
return_value=ca_certs_content))
223
cc_ca_certs.add_ca_certs(certs)
225
mock_write.assert_has_calls([
226
mock.call("/usr/share/ca-certificates/cloud-init-ca-certs.crt",
227
expected_cert_file, mode=0o644),
228
mock.call("/etc/ca-certificates.conf",
229
"%s\n%s\n" % (ca_certs_content,
230
"cloud-init-ca-certs.crt"),
234
mock_load.assert_called_once_with("/etc/ca-certificates.conf")
237
class TestUpdateCaCerts(unittest.TestCase):
210
238
def test_commands(self):
211
mock_check_call = self.mocker.replace(util.subp,
213
mock_check_call(["update-ca-certificates"], capture=False)
216
cc_ca_certs.update_ca_certs()
219
class TestRemoveDefaultCaCerts(MockerTestCase):
239
with mock.patch.object(util, 'subp') as mockobj:
240
cc_ca_certs.update_ca_certs()
241
mockobj.assert_called_once_with(
242
["update-ca-certificates"], capture=False)
245
class TestRemoveDefaultCaCerts(TestCase):
222
248
super(TestRemoveDefaultCaCerts, self).setUp()
249
tmpdir = tempfile.mkdtemp()
250
self.addCleanup(shutil.rmtree, tmpdir)
223
251
self.paths = helpers.Paths({
224
'cloud_dir': self.makeDir()
227
255
def test_commands(self):
228
mock_delete_dir_contents = self.mocker.replace(
229
util.delete_dir_contents, passthrough=False)
230
mock_write = self.mocker.replace(util.write_file, passthrough=False)
231
mock_subp = self.mocker.replace(util.subp,
234
mock_delete_dir_contents("/usr/share/ca-certificates/")
235
mock_delete_dir_contents("/etc/ssl/certs/")
236
mock_write("/etc/ca-certificates.conf", "", mode=0644)
237
mock_subp(('debconf-set-selections', '-'),
238
"ca-certificates ca-certificates/trust_new_crts select no")
241
cc_ca_certs.remove_default_ca_certs()
256
with ExitStack() as mocks:
257
mock_delete = mocks.enter_context(
258
mock.patch.object(util, 'delete_dir_contents'))
259
mock_write = mocks.enter_context(
260
mock.patch.object(util, 'write_file'))
261
mock_subp = mocks.enter_context(mock.patch.object(util, 'subp'))
263
cc_ca_certs.remove_default_ca_certs()
265
mock_delete.assert_has_calls([
266
mock.call("/usr/share/ca-certificates/"),
267
mock.call("/etc/ssl/certs/"),
270
mock_write.assert_called_once_with(
271
"/etc/ca-certificates.conf", "", mode=0o644)
273
mock_subp.assert_called_once_with(
274
('debconf-set-selections', '-'),
275
"ca-certificates ca-certificates/trust_new_crts select no")