forked from keylime/keylime
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_config.py
More file actions
243 lines (198 loc) · 10.6 KB
/
Copy pathtest_config.py
File metadata and controls
243 lines (198 loc) · 10.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
import importlib
import logging
import os
import shutil
import tempfile
import unittest
from configparser import NoOptionError
from keylime import config
DATA_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "data"))
CONFIG_DIR = os.path.abspath(os.path.join(DATA_DIR, "config"))
class TestConfig(unittest.TestCase):
def setUp(self):
"""Dummy setup so that the tearDown() is executed"""
# See the following documentation:
# https://docs.python.org/3/library/unittest.html#unittest.TestCase.tearDown
return
def tearDown(self):
"""The config module should be reloaded."""
# Because we can alter global state, we should reload the
# config module after every test
importlib.reload(config)
def test_default_config_files(self):
"""Test default config file list."""
self.assertEqual(
config.CONFIG_FILES,
{
"verifier": ["/etc/keylime/verifier.conf", "/usr/etc/keylime/verifier.conf"],
"tenant": ["/etc/keylime/tenant.conf", "/usr/etc/keylime/tenant.conf"],
"registrar": ["/etc/keylime/registrar.conf", "/usr/etc/keylime/registrar.conf"],
"ca": ["/etc/keylime/ca.conf", "/usr/etc/keylime/ca.conf"],
"logging": ["/etc/keylime/logging.conf", "/usr/etc/keylime/logging.conf"],
},
)
def test_no_component(self):
"""Test that no component causes exception"""
self.assertRaises(Exception, config.get, "")
def test_invalid_env(self):
"""Test that invalid CONFIG_ENV causes exception"""
config.CONFIG_ENV = []
self.assertRaises(Exception, config.get_config, "test")
def test_invalid_files(self):
"""Test that invalid CONFIG_FILES causes exception"""
config.CONFIG_FILES = []
self.assertRaises(Exception, config.get_config, "test")
def test_invalid_component(self):
"""Test that invalid component causes exception"""
self.assertRaises(Exception, config.get_config, "test")
def test_single_config(self):
"""Test reading a single config file."""
config.CONFIG_FILES = {"test": [os.path.join(CONFIG_DIR, "keylime-1.conf")]}
config.CONFIG_ENV = {"test": ""}
config.CONFIG_SNIPPETS_DIRS = {"test": ""}
c = config.get_config("test")
self.assertEqual(c.get("default", "attribute_1"), "value_1")
def test_first_base_file_used(self):
"""Test giving multiple possibilities for base file."""
config.CONFIG_FILES = {
"test": [
os.path.join(CONFIG_DIR, "keylime-1.conf"),
os.path.join(CONFIG_DIR, "keylime-2.conf"),
]
}
config.CONFIG_ENV = {"test": ""}
config.CONFIG_SNIPPETS_DIRS = {"test": ""}
c = config.get_config("test")
self.assertEqual(c.get("default", "attribute_1"), "value_1")
# Assert that if the first file is found, the second is ignored
self.assertRaises(NoOptionError, c.get, "default", "attribute_2")
def test_missing_base_file_ignored(self):
"""Test that if a file is missing, it tries the next."""
# Now use a non-existent first file to test if the second file is used
# instead
config.CONFIG_FILES = {
"test": [
os.path.join(CONFIG_DIR, "non-existent.conf"),
os.path.join(CONFIG_DIR, "keylime-2.conf"),
]
}
config.CONFIG_ENV = {"test": ""}
config.CONFIG_SNIPPETS_DIRS = {"test": ""}
c = config.get_config("test")
self.assertRaises(NoOptionError, c.get, "default", "attribute_1")
self.assertEqual(c.get("default", "attribute_2"), "value_2")
def test_merge_config(self):
"""Test reading multiple config files and merging them."""
config.CONFIG_FILES = {"verifier": [os.path.join(CONFIG_DIR, "verifier.conf")]}
config.CONFIG_ENV = {"verifier": ""}
config.CONFIG_SNIPPETS_DIRS = {"verifier": [os.path.join(CONFIG_DIR, "verifier.conf.d")]}
c = config.get_config("verifier")
self.assertEqual(c.get("verifier", "attribute_1"), "value_1_3")
self.assertEqual(c.get("verifier", "attribute_2"), "value_2")
self.assertEqual(c.get("verifier", "attribute_3"), "value_3")
def test_cache_config(self):
"""Test the config is properly cached between calls."""
config.CONFIG_FILES = {"verifier": [os.path.join(CONFIG_DIR, "verifier.conf")]}
config.CONFIG_ENV = {"verifier": ""}
config.CONFIG_SNIPPETS_DIRS = {"verifier": ""}
c = config.get_config("verifier")
self.assertEqual(c.get("verifier", "attribute", fallback=None), None)
c.set("verifier", "attribute", "value")
self.assertEqual(c.get("verifier", "attribute"), "value")
c_copy = config.get_config("verifier")
self.assertEqual(c_copy.get("verifier", "attribute"), "value")
def test_reexport_function(self):
"""Test re-exported functions to access data."""
config.CONFIG_FILES = {"test": [os.path.join(CONFIG_DIR, "keylime-1.conf")]}
config.CONFIG_ENV = {"test": ""}
config.CONFIG_SNIPPETS_DIRS = {"test": ""}
self.assertEqual(config.get("test", "attribute", section="default", fallback=""), "")
def test_env_overrides_all(self):
"""Test that using an env var to set config ignore other files"""
if "KEYLIME_VERIFIER_CONFIG" in os.environ:
env_bkp = os.environ["KEYLIME_VERIFIER_CONFIG"]
else:
env_bkp = ""
os.environ["KEYLIME_VERIFIER_CONFIG"] = os.path.join(CONFIG_DIR, "verifier.conf")
# Reload the configuration to use the set environment variable on setup
importlib.reload(config)
config.CONFIG_SNIPPETS_DIRS = {"verifier": [os.path.join(CONFIG_DIR, "verifier.conf.d")]}
c = config.get_config("verifier")
self.assertEqual(c.get("verifier", "attribute_1"), "value_1")
self.assertRaises(Exception, c.get, "verifier", "attribute_2")
self.assertRaises(Exception, c.get, "verifier", "attribute_3")
# Unset the variable to not affect other tests
os.environ["KEYLIME_VERIFIER_CONFIG"] = env_bkp
def test_get(self) -> None:
"""Sanity test for config.get()"""
config.CONFIG_FILES = {"verifier": [os.path.join(CONFIG_DIR, "verifier.conf")]}
config.CONFIG_ENV = {"verifier": ""}
config.CONFIG_SNIPPETS_DIRS = {"verifier": ""}
# Check that non-existing option will fallback
self.assertEqual(config.get("verifier", "attribute", fallback="fallback"), "fallback")
# Check that existing option is properly obtained
self.assertEqual(config.get("verifier", "attribute_1", fallback="fallback"), "value_1")
# Check that quoted option is unquoted
self.assertEqual(config.get("verifier", "quoted"), "unquoted")
# Check that quotes and trailing spaces are properly removed
self.assertEqual(config.get("verifier", "quotes_spaces"), "unquoted")
def test_check_version(self) -> None:
"""Sanity check for check_version"""
config.CONFIG_FILES = {"comp1": [os.path.join(CONFIG_DIR, "comp1_old.conf")]}
config.CONFIG_ENV = {"comp1": ""}
config.CONFIG_SNIPPETS_DIRS = {"comp1": ""}
config.TEMPLATES_DIR = os.path.join(DATA_DIR, "templates")
self.assertTrue(os.path.exists(config.TEMPLATES_DIR))
self.assertTrue(config.check_version("comp1"))
with self.assertLogs("test_config", level="DEBUG") as cm:
logger = logging.getLogger("test_config")
# Check with non-existing directory
config.TEMPLATES_DIR = "non-existing"
self.assertFalse(config.check_version("comp1", logger=logger))
self.assertTrue(
f"WARNING:test_config:The configuration upgrade templates path {config.TEMPLATES_DIR} does not exist"
in cm.output
)
# Check with existing file that is not a directory
config.TEMPLATES_DIR = os.path.join(CONFIG_DIR, "comp1.conf")
self.assertTrue(os.path.exists(config.TEMPLATES_DIR))
self.assertFalse(config.check_version("comp1", logger=logger))
self.assertTrue(f"WARNING:test_config:The path {config.TEMPLATES_DIR} is not a directory" in cm.output)
with tempfile.TemporaryDirectory() as tempdir:
config.TEMPLATES_DIR = tempdir
logger = logging.getLogger("test_config")
# Check with empty directory
self.assertFalse(config.check_version("comp1", logger=logger))
self.assertTrue(
f"WARNING:test_config:The path {tempdir} does not contain version directories for config upgrade templates"
in cm.output
)
# Check with up-to-date version
shutil.copytree(os.path.join(DATA_DIR, "templates/1.0"), os.path.join(tempdir, "1.0"))
self.assertFalse(config.check_version("comp1"))
# Check with minor update available
shutil.copytree(os.path.join(DATA_DIR, "templates/1.0"), os.path.join(tempdir, "1.2"))
self.assertTrue(config.check_version("comp1", logger=logger))
self.assertTrue(
"INFO:test_config:A minor configuration upgrade is available (from 1.0 to 1.2). Run 'keylime_upgrade_config' to upgrade the configuration"
in cm.output
)
# Check with major update available
shutil.copytree(os.path.join(DATA_DIR, "templates/2.0"), os.path.join(tempdir, "2.0"))
self.assertTrue(config.check_version("comp1", logger=logger))
print(cm.output)
self.assertTrue(
"WARNING:test_config:A major configuration upgrade is available (from 1.0 to 2.0). Run 'keylime_upgrade_config' to upgrade the configuration"
in cm.output
)
with tempfile.TemporaryDirectory() as tempdir:
config.TEMPLATES_DIR = tempdir
# Check with invalid directory naming (should be version number)
shutil.copytree(os.path.join(DATA_DIR, "templates/2.0"), os.path.join(tempdir, "not_version"))
self.assertFalse(config.check_version("comp1", logger=logger))
self.assertTrue(
f"WARNING:test_config:The path {tempdir} does not contain valid config version upgrade directories"
in cm.output
)
if __name__ == "__main__":
unittest.main()