Merge lp:~hopem/charms/trusty/keystone/fix-pki-token-support into lp:~openstack-charmers-archive/charms/trusty/keystone/next
- Trusty Tahr (14.04)
- fix-pki-token-support
- Merge into next
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 129 | ||||
Proposed branch: | lp:~hopem/charms/trusty/keystone/fix-pki-token-support | ||||
Merge into: | lp:~openstack-charmers-archive/charms/trusty/keystone/next | ||||
Diff against target: |
1010 lines (+382/-126) 8 files modified
hooks/keystone_context.py (+28/-3) hooks/keystone_hooks.py (+66/-21) hooks/keystone_ssl.py (+76/-43) hooks/keystone_utils.py (+98/-31) templates/icehouse/keystone.conf (+9/-3) templates/parts/section-signing (+13/-0) unit_tests/test_keystone_hooks.py (+77/-14) unit_tests/test_keystone_utils.py (+15/-11) |
||||
To merge this branch: | bzr merge lp:~hopem/charms/trusty/keystone/fix-pki-token-support | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Liam Young (community) | Approve | ||
Review via email: mp+249881@code.launchpad.net |
Commit message
Description of the change
uosci-testing-bot (uosci-testing-bot) wrote : | # |
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_unit_test #1922 keystone-next for hopem mp249881
UNIT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_amulet_test #2041 keystone-next for hopem mp249881
AMULET OK: passed
Build: http://
- 123. By Edward Hope-Morley
-
synced /next
- 124. By Edward Hope-Morley
-
synced charm-helpers;
- 125. By Edward Hope-Morley
-
don't push race-prone data on cluster relation to avoid spinning
- 126. By Edward Hope-Morley
-
remove pkiz
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_lint_check #2206 keystone-next for hopem mp249881
LINT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_unit_test #1995 keystone-next for hopem mp249881
UNIT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_amulet_test #2152 keystone-next for hopem mp249881
AMULET FAIL: amulet-test failed
AMULET Results (max last 2 lines):
ERROR subprocess encountered error code 1
make: *** [test] Error 1
Full amulet test output: http://
Build: http://
- 127. By Edward Hope-Morley
-
synced /next
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_lint_check #2560 keystone-next for hopem mp249881
LINT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_unit_test #2350 keystone-next for hopem mp249881
UNIT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_amulet_test #2429 keystone-next for hopem mp249881
AMULET FAIL: juju-pull-logs failed
AMULET Results (max last 2 lines):
WARNING cannot delete security group "juju-osci-sv07-0". Used by another environment?
juju-test INFO : Results: 3 passed, 0 failed, 0 errored
Full amulet test output: http://
Build: http://
- 128. By Edward Hope-Morley
-
cleanuo
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_lint_check #2604 keystone-next for hopem mp249881
LINT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_unit_test #2394 keystone-next for hopem mp249881
UNIT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_amulet_test #2432 keystone-next for hopem mp249881
AMULET OK: passed
Build: http://
Preview Diff
1 | === modified file 'hooks/keystone_context.py' |
2 | --- hooks/keystone_context.py 2015-02-16 11:38:34 +0000 |
3 | +++ hooks/keystone_context.py 2015-03-11 14:46:50 +0000 |
4 | @@ -18,6 +18,7 @@ |
5 | |
6 | from charmhelpers.core.hookenv import ( |
7 | log, |
8 | + DEBUG, |
9 | INFO, |
10 | ) |
11 | |
12 | @@ -173,9 +174,8 @@ |
13 | |
14 | def __call__(self): |
15 | from keystone_utils import ( |
16 | - api_port, set_admin_token, |
17 | - endpoint_url, resolve_address, |
18 | - PUBLIC, ADMIN |
19 | + api_port, set_admin_token, endpoint_url, resolve_address, |
20 | + PUBLIC, ADMIN, PKI_CERTS_DIR, SSH_USER, ensure_permissions, |
21 | ) |
22 | ctxt = {} |
23 | ctxt['token'] = set_admin_token(config('admin-token')) |
24 | @@ -205,6 +205,31 @@ |
25 | enable_pki = config('enable-pki') |
26 | if enable_pki and bool_from_string(enable_pki): |
27 | ctxt['signing'] = True |
28 | + ctxt['token_provider'] = 'pki' |
29 | + |
30 | + if 'token_provider' in ctxt: |
31 | + log("Configuring PKI token cert paths", level=DEBUG) |
32 | + certs = os.path.join(PKI_CERTS_DIR, 'certs') |
33 | + privates = os.path.join(PKI_CERTS_DIR, 'privates') |
34 | + for path in [PKI_CERTS_DIR, certs, privates]: |
35 | + perms = 0o755 |
36 | + if not os.path.isdir(path): |
37 | + mkdir(path=path, owner=SSH_USER, group='keystone', |
38 | + perms=perms) |
39 | + else: |
40 | + # Ensure accessible by ssh user and group (for sync). |
41 | + ensure_permissions(path, user=SSH_USER, |
42 | + group='keystone', perms=perms) |
43 | + |
44 | + signing_paths = {'certfile': os.path.join(certs, |
45 | + 'signing_cert.pem'), |
46 | + 'keyfile': os.path.join(privates, |
47 | + 'signing_key.pem'), |
48 | + 'ca_certs': os.path.join(certs, 'ca.pem'), |
49 | + 'ca_key': os.path.join(certs, 'ca_key.pem')} |
50 | + |
51 | + for key, val in signing_paths.iteritems(): |
52 | + ctxt[key] = val |
53 | |
54 | # Base endpoint URL's which are used in keystone responses |
55 | # to unauthenticated requests to redirect clients to the |
56 | |
57 | === modified file 'hooks/keystone_hooks.py' |
58 | --- hooks/keystone_hooks.py 2015-03-10 12:02:11 +0000 |
59 | +++ hooks/keystone_hooks.py 2015-03-11 14:46:50 +0000 |
60 | @@ -72,6 +72,10 @@ |
61 | is_db_ready, |
62 | clear_ssl_synced_units, |
63 | is_db_initialised, |
64 | + is_pki_enabled, |
65 | + ensure_ssl_dir, |
66 | + ensure_pki_dir_permissions, |
67 | + force_ssl_sync, |
68 | filter_null, |
69 | ) |
70 | |
71 | @@ -115,7 +119,7 @@ |
72 | |
73 | @hooks.hook('config-changed') |
74 | @restart_on_change(restart_map()) |
75 | -@synchronize_ca_if_changed() |
76 | +@synchronize_ca_if_changed(fatal=True) |
77 | def config_changed(): |
78 | if config('prefer-ipv6'): |
79 | setup_ipv6() |
80 | @@ -131,6 +135,9 @@ |
81 | if openstack_upgrade_available('keystone'): |
82 | do_openstack_upgrade(configs=CONFIGS) |
83 | |
84 | + # Ensure ssl dir exists and is unison-accessible |
85 | + ensure_ssl_dir() |
86 | + |
87 | check_call(['chmod', '-R', 'g+wrx', '/var/lib/keystone/']) |
88 | |
89 | # Ensure unison can write to certs dir. |
90 | @@ -143,12 +150,16 @@ |
91 | |
92 | save_script_rc() |
93 | configure_https() |
94 | + |
95 | update_nrpe_config() |
96 | CONFIGS.write_all() |
97 | |
98 | + if is_pki_enabled(): |
99 | + initialise_pki() |
100 | + |
101 | # Update relations since SSL may have been configured. If we have peer |
102 | # units we can rely on the sync to do this in cluster relation. |
103 | - if is_elected_leader(CLUSTER_RES) and not peer_units(): |
104 | + if not peer_units(): |
105 | update_all_identity_relation_units() |
106 | |
107 | for rid in relation_ids('identity-admin'): |
108 | @@ -161,6 +172,22 @@ |
109 | ha_joined(relation_id=r_id) |
110 | |
111 | |
112 | +@synchronize_ca_if_changed(fatal=True) |
113 | +def initialise_pki(): |
114 | + """Create certs and keys required for PKI token signing. |
115 | + |
116 | + NOTE: keystone.conf [signing] section must be up-to-date prior to |
117 | + executing this. |
118 | + """ |
119 | + if is_ssl_cert_master(): |
120 | + log("Ensuring PKI token certs created", level=DEBUG) |
121 | + cmd = ['keystone-manage', 'pki_setup', '--keystone-user', 'keystone', |
122 | + '--keystone-group', 'keystone'] |
123 | + check_call(cmd) |
124 | + |
125 | + ensure_pki_dir_permissions() |
126 | + |
127 | + |
128 | @hooks.hook('shared-db-relation-joined') |
129 | def db_joined(): |
130 | if is_relation_made('pgsql-db'): |
131 | @@ -301,6 +328,7 @@ |
132 | peerdb_settings = filter_null(peerdb_settings) |
133 | if 'service_password' in peerdb_settings: |
134 | relation_set(relation_id=rel_id, **peerdb_settings) |
135 | + |
136 | log('Deferring identity_changed() to service leader.') |
137 | |
138 | if notifications: |
139 | @@ -319,12 +347,20 @@ |
140 | """ |
141 | unit = local_unit().replace('/', '-') |
142 | count = 0 |
143 | - if bool_from_string(config('use-https')): |
144 | + |
145 | + use_https = config('use-https') |
146 | + if use_https and bool_from_string(use_https): |
147 | count += 1 |
148 | |
149 | - if bool_from_string(config('https-service-endpoints')): |
150 | + https_service_endpoints = config('https-service-endpoints') |
151 | + if (https_service_endpoints and |
152 | + bool_from_string(https_service_endpoints)): |
153 | count += 2 |
154 | |
155 | + enable_pki = config('enable-pki') |
156 | + if enable_pki and bool_from_string(enable_pki): |
157 | + count += 3 |
158 | + |
159 | key = 'ssl-sync-required-%s' % (unit) |
160 | settings = {key: count} |
161 | |
162 | @@ -391,23 +427,32 @@ |
163 | |
164 | check_peer_actions() |
165 | |
166 | - if is_elected_leader(CLUSTER_RES) or is_ssl_cert_master(): |
167 | - units = get_ssl_sync_request_units() |
168 | - synced_units = relation_get(attribute='ssl-synced-units', |
169 | - unit=local_unit()) |
170 | - if synced_units: |
171 | - synced_units = json.loads(synced_units) |
172 | - diff = set(units).symmetric_difference(set(synced_units)) |
173 | - |
174 | - if units and (not synced_units or diff): |
175 | - log("New peers joined and need syncing - %s" % |
176 | - (', '.join(units)), level=DEBUG) |
177 | - update_all_identity_relation_units_force_sync() |
178 | - else: |
179 | - update_all_identity_relation_units() |
180 | - |
181 | - for rid in relation_ids('identity-admin'): |
182 | - admin_relation_changed(rid) |
183 | + if is_pki_enabled(): |
184 | + initialise_pki() |
185 | + |
186 | + # Figure out if we need to mandate a sync |
187 | + units = get_ssl_sync_request_units() |
188 | + synced_units = relation_get(attribute='ssl-synced-units', |
189 | + unit=local_unit()) |
190 | + diff = None |
191 | + if synced_units: |
192 | + synced_units = json.loads(synced_units) |
193 | + diff = set(units).symmetric_difference(set(synced_units)) |
194 | + |
195 | + if units and (not synced_units or diff): |
196 | + log("New peers joined and need syncing - %s" % |
197 | + (', '.join(units)), level=DEBUG) |
198 | + update_all_identity_relation_units_force_sync() |
199 | + else: |
200 | + update_all_identity_relation_units() |
201 | + |
202 | + for rid in relation_ids('identity-admin'): |
203 | + admin_relation_changed(rid) |
204 | + |
205 | + if not is_elected_leader(CLUSTER_RES) and is_ssl_cert_master(): |
206 | + # Force and sync and trigger a sync master re-election since we are not |
207 | + # leader anymore. |
208 | + force_ssl_sync() |
209 | else: |
210 | CONFIGS.write_all() |
211 | |
212 | |
213 | === modified file 'hooks/keystone_ssl.py' |
214 | --- hooks/keystone_ssl.py 2015-01-13 11:04:56 +0000 |
215 | +++ hooks/keystone_ssl.py 2015-03-11 14:46:50 +0000 |
216 | @@ -113,15 +113,16 @@ |
217 | |
218 | |
219 | def init_ca(ca_dir, common_name, org_name=ORG_NAME, org_unit_name=ORG_UNIT): |
220 | - print 'Ensuring certificate authority exists at %s.' % ca_dir |
221 | + log('Ensuring certificate authority exists at %s.' % ca_dir, level=DEBUG) |
222 | if not os.path.exists(ca_dir): |
223 | - print 'Initializing new certificate authority at %s' % ca_dir |
224 | + log('Initializing new certificate authority at %s' % ca_dir, |
225 | + level=DEBUG) |
226 | os.mkdir(ca_dir) |
227 | |
228 | for i in ['certs', 'crl', 'newcerts', 'private']: |
229 | d = os.path.join(ca_dir, i) |
230 | if not os.path.exists(d): |
231 | - print 'Creating %s.' % d |
232 | + log('Creating %s.' % d, level=DEBUG) |
233 | os.mkdir(d) |
234 | os.chmod(os.path.join(ca_dir, 'private'), 0o710) |
235 | |
236 | @@ -132,9 +133,11 @@ |
237 | if not os.path.isfile(os.path.join(ca_dir, 'index.txt')): |
238 | with open(os.path.join(ca_dir, 'index.txt'), 'wb') as out: |
239 | out.write('') |
240 | - if not os.path.isfile(os.path.join(ca_dir, 'ca.cnf')): |
241 | - print 'Creating new CA config in %s' % ca_dir |
242 | - with open(os.path.join(ca_dir, 'ca.cnf'), 'wb') as out: |
243 | + |
244 | + conf = os.path.join(ca_dir, 'ca.cnf') |
245 | + if not os.path.isfile(conf): |
246 | + log('Creating new CA config in %s' % ca_dir, level=DEBUG) |
247 | + with open(conf, 'wb') as out: |
248 | out.write(CA_CONFIG % locals()) |
249 | |
250 | |
251 | @@ -144,40 +147,42 @@ |
252 | key = os.path.join(ca_dir, 'private', 'cacert.key') |
253 | for f in [crt, key]: |
254 | if not os.path.isfile(f): |
255 | - print 'Missing %s, will re-initialize cert+key.' % f |
256 | + log('Missing %s, will re-initialize cert+key.' % f, level=DEBUG) |
257 | init = True |
258 | else: |
259 | - print 'Found %s.' % f |
260 | + log('Found %s.' % f, level=DEBUG) |
261 | + |
262 | if init: |
263 | - cmd = ['openssl', 'req', '-config', os.path.join(ca_dir, 'ca.cnf'), |
264 | + conf = os.path.join(ca_dir, 'ca.cnf') |
265 | + cmd = ['openssl', 'req', '-config', conf, |
266 | '-x509', '-nodes', '-newkey', 'rsa', '-days', '21360', |
267 | '-keyout', key, '-out', crt, '-outform', 'PEM'] |
268 | subprocess.check_call(cmd) |
269 | + |
270 | return crt, key |
271 | |
272 | |
273 | def intermediate_ca_csr_key(ca_dir): |
274 | - print 'Creating new intermediate CSR.' |
275 | + log('Creating new intermediate CSR.', level=DEBUG) |
276 | key = os.path.join(ca_dir, 'private', 'cacert.key') |
277 | csr = os.path.join(ca_dir, 'cacert.csr') |
278 | - cmd = ['openssl', 'req', '-config', os.path.join(ca_dir, 'ca.cnf'), |
279 | - '-sha1', '-newkey', 'rsa', '-nodes', '-keyout', key, '-out', |
280 | - csr, '-outform', |
281 | - 'PEM'] |
282 | + conf = os.path.join(ca_dir, 'ca.cnf') |
283 | + cmd = ['openssl', 'req', '-config', conf, '-sha1', '-newkey', 'rsa', |
284 | + '-nodes', '-keyout', key, '-out', csr, '-outform', 'PEM'] |
285 | subprocess.check_call(cmd) |
286 | return csr, key |
287 | |
288 | |
289 | def sign_int_csr(ca_dir, csr, common_name): |
290 | - print 'Signing certificate request %s.' % csr |
291 | - crt = os.path.join(ca_dir, 'certs', |
292 | - '%s.crt' % os.path.basename(csr).split('.')[0]) |
293 | + log('Signing certificate request %s.' % csr, level=DEBUG) |
294 | + crt_name = os.path.basename(csr).split('.')[0] |
295 | + crt = os.path.join(ca_dir, 'certs', '%s.crt' % crt_name) |
296 | subj = '/O=%s/OU=%s/CN=%s' % (ORG_NAME, ORG_UNIT, common_name) |
297 | - cmd = ['openssl', 'ca', '-batch', '-config', |
298 | - os.path.join(ca_dir, 'ca.cnf'), |
299 | - '-extensions', 'ca_extensions', '-days', CA_EXPIRY, '-notext', |
300 | - '-in', csr, '-out', crt, '-subj', subj, '-batch'] |
301 | - print ' '.join(cmd) |
302 | + conf = os.path.join(ca_dir, 'ca.cnf') |
303 | + cmd = ['openssl', 'ca', '-batch', '-config', conf, '-extensions', |
304 | + 'ca_extensions', '-days', CA_EXPIRY, '-notext', '-in', csr, '-out', |
305 | + crt, '-subj', subj, '-batch'] |
306 | + log("Executing: %s" % ' '.join(cmd), level=DEBUG) |
307 | subprocess.check_call(cmd) |
308 | return crt |
309 | |
310 | @@ -187,19 +192,20 @@ |
311 | return root_ca_crt_key(ca_dir) |
312 | |
313 | |
314 | -def init_intermediate_ca(ca_dir, common_name, root_ca_dir, |
315 | - org_name=ORG_NAME, org_unit_name=ORG_UNIT): |
316 | +def init_intermediate_ca(ca_dir, common_name, root_ca_dir, org_name=ORG_NAME, |
317 | + org_unit_name=ORG_UNIT): |
318 | init_ca(ca_dir, common_name) |
319 | if not os.path.isfile(os.path.join(ca_dir, 'cacert.pem')): |
320 | csr, key = intermediate_ca_csr_key(ca_dir) |
321 | crt = sign_int_csr(root_ca_dir, csr, common_name) |
322 | shutil.copy(crt, os.path.join(ca_dir, 'cacert.pem')) |
323 | else: |
324 | - print 'Intermediate CA certificate already exists.' |
325 | + log('Intermediate CA certificate already exists.', level=DEBUG) |
326 | |
327 | - if not os.path.isfile(os.path.join(ca_dir, 'signing.cnf')): |
328 | - print 'Creating new signing config in %s' % ca_dir |
329 | - with open(os.path.join(ca_dir, 'signing.cnf'), 'wb') as out: |
330 | + conf = os.path.join(ca_dir, 'signing.cnf') |
331 | + if not os.path.isfile(conf): |
332 | + log('Creating new signing config in %s' % ca_dir, level=DEBUG) |
333 | + with open(conf, 'wb') as out: |
334 | out.write(SIGNING_CONFIG % locals()) |
335 | |
336 | |
337 | @@ -212,7 +218,7 @@ |
338 | key, '-out', csr, '-subj', subj] |
339 | subprocess.check_call(cmd) |
340 | crt = sign_int_csr(ca_dir, csr, common_name) |
341 | - print 'Signed new CSR, crt @ %s' % crt |
342 | + log('Signed new CSR, crt @ %s' % crt, level=DEBUG) |
343 | return |
344 | |
345 | |
346 | @@ -221,13 +227,14 @@ |
347 | if os.path.isfile(bundle_file): |
348 | current = open(bundle_file, 'r').read().strip() |
349 | if new_bundle == current: |
350 | - print 'CA Bundle @ %s is up to date.' % bundle_file |
351 | + log('CA Bundle @ %s is up to date.' % bundle_file, level=DEBUG) |
352 | return |
353 | - else: |
354 | - print 'Updating CA bundle @ %s.' % bundle_file |
355 | + |
356 | + log('Updating CA bundle @ %s.' % bundle_file, level=DEBUG) |
357 | |
358 | with open(bundle_file, 'wb') as out: |
359 | out.write(new_bundle) |
360 | + |
361 | subprocess.check_call(['update-ca-certificates']) |
362 | |
363 | |
364 | @@ -250,15 +257,19 @@ |
365 | class JujuCA(object): |
366 | |
367 | def __init__(self, name, ca_dir, root_ca_dir, user, group): |
368 | - root_crt, root_key = init_root_ca(root_ca_dir, |
369 | - '%s Certificate Authority' % name) |
370 | - init_intermediate_ca(ca_dir, |
371 | - '%s Intermediate Certificate Authority' % name, |
372 | - root_ca_dir) |
373 | + # Root CA |
374 | + cn = '%s Certificate Authority' % name |
375 | + root_crt, root_key = init_root_ca(root_ca_dir, cn) |
376 | + # Intermediate CA |
377 | + cn = '%s Intermediate Certificate Authority' % name |
378 | + init_intermediate_ca(ca_dir, cn, root_ca_dir) |
379 | + |
380 | + # Create dirs |
381 | cmd = ['chown', '-R', '%s.%s' % (user, group), ca_dir] |
382 | subprocess.check_call(cmd) |
383 | cmd = ['chown', '-R', '%s.%s' % (user, group), root_ca_dir] |
384 | subprocess.check_call(cmd) |
385 | + |
386 | self.ca_dir = ca_dir |
387 | self.root_ca_dir = root_ca_dir |
388 | self.user = user |
389 | @@ -268,8 +279,8 @@ |
390 | def _sign_csr(self, csr, service, common_name): |
391 | subj = '/O=%s/OU=%s/CN=%s' % (ORG_NAME, ORG_UNIT, common_name) |
392 | crt = os.path.join(self.ca_dir, 'certs', '%s.crt' % common_name) |
393 | - cmd = ['openssl', 'ca', '-config', |
394 | - os.path.join(self.ca_dir, 'signing.cnf'), '-extensions', |
395 | + conf = os.path.join(self.ca_dir, 'signing.cnf') |
396 | + cmd = ['openssl', 'ca', '-config', conf, '-extensions', |
397 | 'req_extensions', '-days', '365', '-notext', '-in', csr, |
398 | '-out', crt, '-batch', '-subj', subj] |
399 | subprocess.check_call(cmd) |
400 | @@ -288,10 +299,16 @@ |
401 | log('Signed new CSR, crt @ %s' % crt, level=DEBUG) |
402 | return crt, key |
403 | |
404 | + def get_key_path(self, cn): |
405 | + return os.path.join(self.ca_dir, 'certs', '%s.key' % cn) |
406 | + |
407 | + def get_cert_path(self, cn): |
408 | + return os.path.join(self.ca_dir, 'certs', '%s.crt' % cn) |
409 | + |
410 | def get_cert_and_key(self, common_name): |
411 | log('Getting certificate and key for %s.' % common_name, level=DEBUG) |
412 | - keypath = os.path.join(self.ca_dir, 'certs', '%s.key' % common_name) |
413 | - crtpath = os.path.join(self.ca_dir, 'certs', '%s.crt' % common_name) |
414 | + keypath = self.get_key_path(common_name) |
415 | + crtpath = self.get_cert_path(common_name) |
416 | if os.path.isfile(crtpath): |
417 | log('Found existing certificate for %s.' % common_name, |
418 | level=DEBUG) |
419 | @@ -324,8 +341,24 @@ |
420 | crt, key = self._create_certificate(common_name, common_name) |
421 | return open(crt, 'r').read(), open(key, 'r').read() |
422 | |
423 | + @property |
424 | + def ca_cert_path(self): |
425 | + return os.path.join(self.ca_dir, 'cacert.pem') |
426 | + |
427 | + @property |
428 | + def ca_key_path(self): |
429 | + return os.path.join(self.ca_dir, 'private', 'cacert.key') |
430 | + |
431 | + @property |
432 | + def root_ca_cert_path(self): |
433 | + return os.path.join(self.root_ca_dir, 'cacert.pem') |
434 | + |
435 | + @property |
436 | + def root_ca_key_path(self): |
437 | + return os.path.join(self.root_ca_dir, 'private', 'cacert.key') |
438 | + |
439 | def get_ca_bundle(self): |
440 | - int_cert = open(os.path.join(self.ca_dir, 'cacert.pem')).read() |
441 | - root_cert = open(os.path.join(self.root_ca_dir, 'cacert.pem')).read() |
442 | + int_cert = open(self.ca_cert_path).read() |
443 | + root_cert = open(self.root_ca_cert_path).read() |
444 | # NOTE: ordering of certs in bundle matters! |
445 | return int_cert + root_cert |
446 | |
447 | === modified file 'hooks/keystone_utils.py' |
448 | --- hooks/keystone_utils.py 2015-03-11 11:57:29 +0000 |
449 | +++ hooks/keystone_utils.py 2015-03-11 14:46:50 +0000 |
450 | @@ -137,10 +137,13 @@ |
451 | APACHE_SSL_DIR = '/etc/apache2/ssl/keystone' |
452 | SYNC_FLAGS_DIR = '/var/lib/keystone/juju_sync_flags/' |
453 | SSL_DIR = '/var/lib/keystone/juju_ssl/' |
454 | +PKI_CERTS_DIR = os.path.join(SSL_DIR, 'pki') |
455 | SSL_CA_NAME = 'Ubuntu Cloud' |
456 | CLUSTER_RES = 'grp_ks_vips' |
457 | SSH_USER = 'juju_keystone' |
458 | +CA_CERT_PATH = '/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt' |
459 | SSL_SYNC_SEMAPHORE = threading.Semaphore() |
460 | +SSL_DIRS = [SSL_DIR, APACHE_SSL_DIR, CA_CERT_PATH] |
461 | |
462 | BASE_RESOURCE_MAP = OrderedDict([ |
463 | (KEYSTONE_CONF, { |
464 | @@ -172,8 +175,6 @@ |
465 | }), |
466 | ]) |
467 | |
468 | -CA_CERT_PATH = '/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt' |
469 | - |
470 | valid_services = { |
471 | "nova": { |
472 | "type": "compute", |
473 | @@ -706,7 +707,8 @@ |
474 | return passwd |
475 | |
476 | |
477 | -def ensure_permissions(path, user=None, group=None, perms=None): |
478 | +def ensure_permissions(path, user=None, group=None, perms=None, recurse=False, |
479 | + maxdepth=50): |
480 | """Set chownand chmod for path |
481 | |
482 | Note that -1 for uid or gid result in no change. |
483 | @@ -726,6 +728,16 @@ |
484 | if perms: |
485 | os.chmod(path, perms) |
486 | |
487 | + if recurse: |
488 | + if not maxdepth: |
489 | + log("Max recursion depth reached - skipping further recursion") |
490 | + return |
491 | + |
492 | + paths = glob.glob("%s/*" % (path)) |
493 | + for path in paths: |
494 | + ensure_permissions(path, user=user, group=group, perms=perms, |
495 | + recurse=recurse, maxdepth=maxdepth - 1) |
496 | + |
497 | |
498 | def check_peer_actions(): |
499 | """Honour service action requests from sync master. |
500 | @@ -766,6 +778,9 @@ |
501 | elif action == 'update-ca-certificates': |
502 | log("Running %s" % (action), level=DEBUG) |
503 | subprocess.check_call(['update-ca-certificates']) |
504 | + elif action == 'ensure-pki-permissions': |
505 | + log("Running %s" % (action), level=DEBUG) |
506 | + ensure_pki_dir_permissions() |
507 | else: |
508 | log("Unknown action flag=%s" % (flag), level=WARNING) |
509 | |
510 | @@ -863,8 +878,12 @@ |
511 | |
512 | |
513 | def is_ssl_enabled(): |
514 | - if (bool_from_string(config('use-https')) or |
515 | - bool_from_string(config('https-service-endpoints'))): |
516 | + use_https = config('use-https') |
517 | + https_service_endpoints = config('https-service-endpoints') |
518 | + if ((use_https and bool_from_string(use_https)) or |
519 | + (https_service_endpoints and |
520 | + bool_from_string(https_service_endpoints)) or |
521 | + is_pki_enabled()): |
522 | log("SSL/HTTPS is enabled", level=DEBUG) |
523 | return True |
524 | |
525 | @@ -931,6 +950,20 @@ |
526 | return True |
527 | |
528 | |
529 | +def is_pki_enabled(): |
530 | + enable_pki = config('enable-pki') |
531 | + if enable_pki and bool_from_string(enable_pki): |
532 | + return True |
533 | + |
534 | + return False |
535 | + |
536 | + |
537 | +def ensure_pki_dir_permissions(): |
538 | + # Ensure accessible by unison user and group (for sync). |
539 | + ensure_permissions(PKI_CERTS_DIR, user=SSH_USER, group='keystone', |
540 | + perms=0o755, recurse=True) |
541 | + |
542 | + |
543 | def synchronize_ca(fatal=False): |
544 | """Broadcast service credentials to peers. |
545 | |
546 | @@ -945,12 +978,18 @@ |
547 | Returns a dictionary of settings to be set on the cluster relation. |
548 | """ |
549 | paths_to_sync = [SYNC_FLAGS_DIR] |
550 | + peer_service_actions = [] |
551 | + peer_actions = [] |
552 | |
553 | if bool_from_string(config('https-service-endpoints')): |
554 | log("Syncing all endpoint certs since https-service-endpoints=True", |
555 | level=DEBUG) |
556 | paths_to_sync.append(SSL_DIR) |
557 | paths_to_sync.append(CA_CERT_PATH) |
558 | + # We need to restart peer apache services to ensure they have picked up |
559 | + # new ssl keys. |
560 | + peer_service_actions.append(('restart', ('apache2'))) |
561 | + peer_actions.append('update-ca-certificates') |
562 | |
563 | if bool_from_string(config('use-https')): |
564 | log("Syncing keystone-endpoint certs since use-https=True", |
565 | @@ -958,6 +997,15 @@ |
566 | paths_to_sync.append(SSL_DIR) |
567 | paths_to_sync.append(APACHE_SSL_DIR) |
568 | paths_to_sync.append(CA_CERT_PATH) |
569 | + # We need to restart peer apache services to ensure they have picked up |
570 | + # new ssl keys. |
571 | + peer_service_actions.append(('restart', ('apache2'))) |
572 | + peer_actions.append('update-ca-certificates') |
573 | + |
574 | + if is_pki_enabled(): |
575 | + log("Syncing token certs", level=DEBUG) |
576 | + paths_to_sync.append(PKI_CERTS_DIR) |
577 | + peer_actions.append('ensure-pki-permissions') |
578 | |
579 | # Ensure unique |
580 | paths_to_sync = list(set(paths_to_sync)) |
581 | @@ -969,10 +1017,11 @@ |
582 | if not os.path.isdir(SYNC_FLAGS_DIR): |
583 | mkdir(SYNC_FLAGS_DIR, SSH_USER, 'keystone', 0o775) |
584 | |
585 | - # We need to restart peer apache services to ensure they have picked up |
586 | - # new ssl keys. |
587 | - create_peer_service_actions('restart', ['apache2']) |
588 | - create_peer_actions(['update-ca-certificates']) |
589 | + for action, services in set(peer_service_actions): |
590 | + create_peer_service_actions(action, services) |
591 | + |
592 | + for action in set(peer_actions): |
593 | + create_peer_actions(action) |
594 | |
595 | cluster_rel_settings = {} |
596 | |
597 | @@ -989,11 +1038,11 @@ |
598 | synced_units = [u.replace('/', '-') for u in synced_units] |
599 | cluster_rel_settings['ssl-synced-units'] = \ |
600 | json.dumps(synced_units) |
601 | - except: |
602 | + except Exception as exc: |
603 | if fatal: |
604 | raise |
605 | else: |
606 | - log("Sync failed but fatal=False", level=INFO) |
607 | + log("Sync failed but fatal=False - %s" % (exc), level=INFO) |
608 | return {} |
609 | |
610 | hash2 = hashlib.sha256() |
611 | @@ -1069,21 +1118,19 @@ |
612 | return f(*args, **kwargs) |
613 | |
614 | if not ensure_ssl_cert_master(): |
615 | - log("Not leader - ignoring sync", level=DEBUG) |
616 | + log("Not ssl-cert-master - ignoring sync", level=DEBUG) |
617 | return f(*args, **kwargs) |
618 | |
619 | peer_settings = {} |
620 | if not force: |
621 | - ssl_dirs = [SSL_DIR, APACHE_SSL_DIR, CA_CERT_PATH] |
622 | - |
623 | hash1 = hashlib.sha256() |
624 | - for path in ssl_dirs: |
625 | + for path in SSL_DIRS: |
626 | update_hash_from_path(hash1, path) |
627 | |
628 | ret = f(*args, **kwargs) |
629 | |
630 | hash2 = hashlib.sha256() |
631 | - for path in ssl_dirs: |
632 | + for path in SSL_DIRS: |
633 | update_hash_from_path(hash2, path) |
634 | |
635 | if hash1.hexdigest() != hash2.hexdigest(): |
636 | @@ -1118,15 +1165,33 @@ |
637 | return inner_synchronize_ca_if_changed1 |
638 | |
639 | |
640 | +@synchronize_ca_if_changed(force=True, fatal=True) |
641 | +def force_ssl_sync(): |
642 | + """Force SSL sync to all peers. |
643 | + |
644 | + This is useful if we need to relinquish ssl-cert-master status while |
645 | + making sure that the new master has up-to-date certs. |
646 | + """ |
647 | + return |
648 | + |
649 | + |
650 | +def ensure_ssl_dir(): |
651 | + """Ensure juju ssl dir exists and is unsion read/writable.""" |
652 | + perms = 0o755 |
653 | + if not os.path.isdir(SSL_DIR): |
654 | + mkdir(SSL_DIR, SSH_USER, 'keystone', perms) |
655 | + else: |
656 | + ensure_permissions(SSL_DIR, user=SSH_USER, group='keystone', |
657 | + perms=perms) |
658 | + |
659 | + |
660 | def get_ca(user='keystone', group='keystone'): |
661 | """Initialize a new CA object if one hasn't already been loaded. |
662 | |
663 | This will create a new CA or load an existing one. |
664 | """ |
665 | if not ssl.CA_SINGLETON: |
666 | - if not os.path.isdir(SSL_DIR): |
667 | - os.mkdir(SSL_DIR) |
668 | - |
669 | + ensure_ssl_dir() |
670 | d_name = '_'.join(SSL_CA_NAME.lower().split(' ')) |
671 | ca = ssl.JujuCA(name=SSL_CA_NAME, user=user, group=group, |
672 | ca_dir=os.path.join(SSL_DIR, |
673 | @@ -1134,12 +1199,6 @@ |
674 | root_ca_dir=os.path.join(SSL_DIR, |
675 | '%s_root_ca' % d_name)) |
676 | |
677 | - # SSL_DIR is synchronized via all peers over unison+ssh, need |
678 | - # to ensure permissions. |
679 | - subprocess.check_output(['chown', '-R', '%s.%s' % (user, group), |
680 | - '%s' % SSL_DIR]) |
681 | - subprocess.check_output(['chmod', '-R', 'g+rwx', '%s' % SSL_DIR]) |
682 | - |
683 | # Ensure a master is elected. This should cover the following cases: |
684 | # * single unit == 'oldest' unit is elected as master |
685 | # * multi unit + not clustered == 'oldest' unit is elcted as master |
686 | @@ -1184,9 +1243,13 @@ |
687 | # Some backend services advertise no endpoint but require a |
688 | # hook execution to update auth strategy. |
689 | relation_data = {} |
690 | + rel_only_data = {} |
691 | # Check if clustered and use vip + haproxy ports if so |
692 | - relation_data["auth_host"] = resolve_address(ADMIN) |
693 | - relation_data["service_host"] = resolve_address(PUBLIC) |
694 | + # NOTE(hopem): don't put these on peer relation because racey |
695 | + # leader election causes cluster relation to spin) |
696 | + rel_only_data["auth_host"] = resolve_address(ADMIN) |
697 | + rel_only_data["service_host"] = resolve_address(PUBLIC) |
698 | + |
699 | relation_data["auth_protocol"] = protocol |
700 | relation_data["service_protocol"] = protocol |
701 | relation_data["auth_port"] = config('admin-port') |
702 | @@ -1209,8 +1272,8 @@ |
703 | log("Creating requested role: %s" % role) |
704 | create_role(role) |
705 | |
706 | - peer_store_and_set(relation_id=relation_id, |
707 | - **relation_data) |
708 | + relation_set(relation_id=relation_id, **rel_only_data) |
709 | + peer_store_and_set(relation_id=relation_id, **relation_data) |
710 | return |
711 | else: |
712 | ensure_valid_service(settings['service']) |
713 | @@ -1314,13 +1377,16 @@ |
714 | # service credentials |
715 | service_tenant = config('service-tenant') |
716 | |
717 | + # NOTE(hopem): don't put these on peer relation because racey |
718 | + # leader election causes cluster relation to spin) |
719 | + rel_only_data = {"auth_host": resolve_address(ADMIN), |
720 | + "service_host": resolve_address(PUBLIC)} |
721 | + |
722 | # NOTE(dosaboy): we use __null__ to represent settings that are to be |
723 | # routed to relations via the cluster relation and set to None. |
724 | relation_data = { |
725 | "admin_token": token, |
726 | - "service_host": resolve_address(PUBLIC), |
727 | "service_port": config("service-port"), |
728 | - "auth_host": resolve_address(ADMIN), |
729 | "auth_port": config("admin-port"), |
730 | "service_username": service_username, |
731 | "service_password": service_password, |
732 | @@ -1353,6 +1419,7 @@ |
733 | relation_data['ca_cert'] = b64encode(ca_bundle) |
734 | relation_data['https_keystone'] = 'True' |
735 | |
736 | + relation_set(relation_id=relation_id, **rel_only_data) |
737 | # NOTE(dosaboy): '__null__' settings are for peer relation only so that |
738 | # settings can flushed so we filter them out for non-peer relation. |
739 | filtered = filter_null(relation_data) |
740 | |
741 | === modified file 'templates/icehouse/keystone.conf' |
742 | --- templates/icehouse/keystone.conf 2014-10-07 12:29:11 +0000 |
743 | +++ templates/icehouse/keystone.conf 2015-03-11 14:46:50 +0000 |
744 | @@ -43,7 +43,15 @@ |
745 | |
746 | [token] |
747 | driver = keystone.token.backends.sql.Token |
748 | -provider = keystone.token.providers.uuid.Provider |
749 | +{% if token_provider == 'pki' -%} |
750 | +provider = keystone.token.providers.pki.Provider |
751 | +{% elif token_provider == 'pkiz' -%} |
752 | +provider = keystone.token.providers.pkiz.Provider |
753 | +{% else -%} |
754 | +provider = keystone.token.providers.uuid.Provider |
755 | +{% endif %} |
756 | + |
757 | +{% include "parts/section-signing" %} |
758 | |
759 | [cache] |
760 | |
761 | @@ -58,8 +66,6 @@ |
762 | |
763 | [oauth1] |
764 | |
765 | -[signing] |
766 | - |
767 | [auth] |
768 | methods = external,password,token,oauth1 |
769 | password = keystone.auth.plugins.password.Password |
770 | |
771 | === added directory 'templates/parts' |
772 | === added file 'templates/parts/section-signing' |
773 | --- templates/parts/section-signing 1970-01-01 00:00:00 +0000 |
774 | +++ templates/parts/section-signing 2015-03-11 14:46:50 +0000 |
775 | @@ -0,0 +1,13 @@ |
776 | +[signing] |
777 | +{% if certfile -%} |
778 | +certfile = {{ certfile }} |
779 | +{% endif -%} |
780 | +{% if keyfile -%} |
781 | +keyfile = {{ keyfile }} |
782 | +{% endif -%} |
783 | +{% if ca_certs -%} |
784 | +ca_certs = {{ ca_certs }} |
785 | +{% endif -%} |
786 | +{% if ca_key -%} |
787 | +ca_key = {{ ca_key }} |
788 | +{% endif -%} |
789 | |
790 | === modified file 'unit_tests/test_keystone_hooks.py' |
791 | --- unit_tests/test_keystone_hooks.py 2015-03-10 12:02:11 +0000 |
792 | +++ unit_tests/test_keystone_hooks.py 2015-03-11 14:46:50 +0000 |
793 | @@ -273,6 +273,10 @@ |
794 | |
795 | @patch('keystone_utils.log') |
796 | @patch('keystone_utils.ensure_ssl_cert_master') |
797 | + @patch.object(hooks, 'ensure_pki_dir_permissions') |
798 | + @patch.object(hooks, 'ensure_ssl_dir') |
799 | + @patch.object(hooks, 'is_pki_enabled') |
800 | + @patch.object(hooks, 'is_ssl_cert_master') |
801 | @patch.object(hooks, 'send_ssl_sync_request') |
802 | @patch.object(hooks, 'is_db_initialised') |
803 | @patch.object(hooks, 'is_db_ready') |
804 | @@ -285,13 +289,25 @@ |
805 | @patch.object(hooks, 'CONFIGS') |
806 | @patch.object(hooks, 'identity_changed') |
807 | @patch.object(hooks, 'configure_https') |
808 | - def test_config_changed_no_openstack_upgrade_leader( |
809 | - self, configure_https, identity_changed, |
810 | - configs, get_homedir, ensure_user, cluster_joined, |
811 | - admin_relation_changed, ensure_permissions, mock_peer_units, |
812 | - mock_is_db_ready, mock_is_db_initialised, |
813 | - mock_send_ssl_sync_request, |
814 | - mock_ensure_ssl_cert_master, mock_log): |
815 | + def test_config_changed_no_upgrade_leader(self, configure_https, |
816 | + identity_changed, |
817 | + configs, get_homedir, |
818 | + ensure_user, |
819 | + cluster_joined, |
820 | + admin_relation_changed, |
821 | + ensure_permissions, |
822 | + mock_peer_units, |
823 | + mock_is_db_ready, |
824 | + mock_is_db_initialised, |
825 | + mock_send_ssl_sync_request, |
826 | + mock_is_ssl_cert_master, |
827 | + mock_is_pki_enabled, |
828 | + mock_ensure_ssl_dir, |
829 | + mock_ensure_pki_dir_permissions, |
830 | + mock_ensure_ssl_cert_master, |
831 | + mock_log): |
832 | + mock_is_pki_enabled.return_value = True |
833 | + mock_is_ssl_cert_master.return_value = True |
834 | mock_is_db_initialised.return_value = True |
835 | mock_is_db_ready.return_value = True |
836 | self.openstack_upgrade_available.return_value = False |
837 | @@ -320,6 +336,12 @@ |
838 | |
839 | @patch('keystone_utils.log') |
840 | @patch('keystone_utils.ensure_ssl_cert_master') |
841 | + @patch.object(hooks, 'update_all_identity_relation_units') |
842 | + @patch.object(hooks, 'ensure_pki_dir_permissions') |
843 | + @patch.object(hooks, 'ensure_ssl_dir') |
844 | + @patch.object(hooks, 'is_pki_enabled') |
845 | + @patch.object(hooks, 'peer_units') |
846 | + @patch.object(hooks, 'is_ssl_cert_master') |
847 | @patch.object(hooks, 'ensure_permissions') |
848 | @patch.object(hooks, 'cluster_joined') |
849 | @patch.object(unison, 'ensure_user') |
850 | @@ -327,11 +349,22 @@ |
851 | @patch.object(hooks, 'CONFIGS') |
852 | @patch.object(hooks, 'identity_changed') |
853 | @patch.object(hooks, 'configure_https') |
854 | - def test_config_changed_no_openstack_upgrade_not_leader( |
855 | - self, configure_https, identity_changed, |
856 | - configs, get_homedir, ensure_user, cluster_joined, |
857 | - ensure_permissions, mock_ensure_ssl_cert_master, |
858 | - mock_log): |
859 | + def test_config_changed_no_upgrade_not_leader(self, configure_https, |
860 | + identity_changed, |
861 | + configs, get_homedir, |
862 | + ensure_user, cluster_joined, |
863 | + ensure_permissions, |
864 | + mock_is_ssl_cert_master, |
865 | + mock_peer_units, |
866 | + mock_is_pki_enabled, |
867 | + mock_ensure_ssl_dir, |
868 | + mock_ensure_pki_permissions, |
869 | + mock_update_all_id_rel_units, |
870 | + mock_ensure_ssl_cert_master, |
871 | + mock_log): |
872 | + mock_is_pki_enabled.return_value = True |
873 | + mock_is_ssl_cert_master.return_value = True |
874 | + mock_peer_units.return_value = [] |
875 | self.openstack_upgrade_available.return_value = False |
876 | self.is_elected_leader.return_value = False |
877 | mock_ensure_ssl_cert_master.return_value = False |
878 | @@ -350,6 +383,10 @@ |
879 | |
880 | @patch('keystone_utils.log') |
881 | @patch('keystone_utils.ensure_ssl_cert_master') |
882 | + @patch.object(hooks, 'ensure_pki_dir_permissions') |
883 | + @patch.object(hooks, 'ensure_ssl_dir') |
884 | + @patch.object(hooks, 'is_pki_enabled') |
885 | + @patch.object(hooks, 'is_ssl_cert_master') |
886 | @patch.object(hooks, 'send_ssl_sync_request') |
887 | @patch.object(hooks, 'is_db_initialised') |
888 | @patch.object(hooks, 'is_db_ready') |
889 | @@ -372,8 +409,14 @@ |
890 | mock_is_db_ready, |
891 | mock_is_db_initialised, |
892 | mock_send_ssl_sync_request, |
893 | + mock_is_ssl_cert_master, |
894 | + mock_is_pki_enabled, |
895 | + mock_ensure_ssl_dir, |
896 | + mock_ensure_pki_permissions, |
897 | mock_ensure_ssl_cert_master, |
898 | mock_log): |
899 | + mock_is_pki_enabled.return_value = True |
900 | + mock_is_ssl_cert_master.return_value = True |
901 | mock_is_db_ready.return_value = True |
902 | mock_is_db_initialised.return_value = True |
903 | self.openstack_upgrade_available.return_value = True |
904 | @@ -449,8 +492,11 @@ |
905 | user=self.ssh_user, group='juju_keystone', |
906 | peer_interface='cluster', ensure_local_user=True) |
907 | |
908 | + @patch.object(hooks, 'update_all_identity_relation_units') |
909 | + @patch.object(hooks, 'get_ssl_sync_request_units') |
910 | @patch.object(hooks, 'is_ssl_cert_master') |
911 | @patch.object(hooks, 'peer_units') |
912 | + @patch('keystone_utils.config') |
913 | @patch('keystone_utils.log') |
914 | @patch('keystone_utils.ensure_ssl_cert_master') |
915 | @patch('keystone_utils.synchronize_ca') |
916 | @@ -460,12 +506,29 @@ |
917 | def test_cluster_changed(self, configs, ssh_authorized_peers, |
918 | check_peer_actions, mock_synchronize_ca, |
919 | mock_ensure_ssl_cert_master, |
920 | - mock_log, mock_peer_units, |
921 | - mock_is_ssl_cert_master): |
922 | + mock_log, mock_config, mock_peer_units, |
923 | + mock_is_ssl_cert_master, |
924 | + mock_get_ssl_sync_request_units, |
925 | + mock_update_all_identity_relation_units): |
926 | + |
927 | + relation_settings = {'foo_passwd': '123', |
928 | + 'identity-service:16_foo': 'bar'} |
929 | + |
930 | mock_is_ssl_cert_master.return_value = False |
931 | mock_peer_units.return_value = ['unit/0'] |
932 | mock_ensure_ssl_cert_master.return_value = False |
933 | self.is_elected_leader.return_value = False |
934 | + |
935 | + def fake_rel_get(attribute=None, *args, **kwargs): |
936 | + if not attribute: |
937 | + return relation_settings |
938 | + |
939 | + return relation_settings.get(attribute) |
940 | + |
941 | + self.relation_get.side_effect = fake_rel_get |
942 | + |
943 | + mock_config.return_value = None |
944 | + |
945 | hooks.cluster_changed() |
946 | whitelist = ['_passwd', 'identity-service:', 'ssl-cert-master', |
947 | 'db-initialised'] |
948 | |
949 | === modified file 'unit_tests/test_keystone_utils.py' |
950 | --- unit_tests/test_keystone_utils.py 2015-03-10 12:02:11 +0000 |
951 | +++ unit_tests/test_keystone_utils.py 2015-03-11 14:46:50 +0000 |
952 | @@ -179,18 +179,19 @@ |
953 | self.assertTrue(self.https.called) |
954 | self.assertTrue(self.create_role.called) |
955 | |
956 | - relation_data = {'auth_host': '10.10.10.10', |
957 | - 'service_host': '10.10.10.10', |
958 | - 'auth_protocol': 'https', |
959 | + rel_only_data = {'auth_host': '10.10.10.10', |
960 | + 'service_host': '10.10.10.10'} |
961 | + relation_data = {'auth_protocol': 'https', |
962 | 'service_protocol': 'https', |
963 | 'auth_port': 80, |
964 | 'service_port': 81, |
965 | 'https_keystone': 'True', |
966 | 'ca_cert': 'certificate', |
967 | 'region': 'RegionOne'} |
968 | - self.peer_store_and_set.assert_called_with( |
969 | - relation_id=relation_id, |
970 | - **relation_data) |
971 | + self.relation_set.assert_called_with(relation_id=relation_id, |
972 | + **rel_only_data) |
973 | + self.peer_store_and_set.assert_called_with(relation_id=relation_id, |
974 | + **relation_data) |
975 | |
976 | @patch.object(utils, 'ensure_valid_service') |
977 | @patch.object(utils, 'add_endpoint') |
978 | @@ -236,14 +237,15 @@ |
979 | self.grant_role.assert_called_with('keystone', 'admin', 'tenant') |
980 | self.create_role.assert_called_with('role1', 'keystone', 'tenant') |
981 | |
982 | + rel_only_data = {'auth_host': '10.0.0.3', |
983 | + 'service_host': '10.0.0.3'} |
984 | relation_data = {'admin_token': 'token', 'service_port': 81, |
985 | 'auth_port': 80, 'service_username': 'keystone', |
986 | 'service_password': 'password', |
987 | 'service_tenant': 'tenant', |
988 | 'https_keystone': '__null__', |
989 | 'ssl_cert': '__null__', 'ssl_key': '__null__', |
990 | - 'ca_cert': '__null__', 'auth_host': '10.0.0.3', |
991 | - 'service_host': '10.0.0.3', |
992 | + 'ca_cert': '__null__', |
993 | 'auth_protocol': 'http', 'service_protocol': 'http', |
994 | 'service_tenant_id': 'tenant_id'} |
995 | |
996 | @@ -254,9 +256,11 @@ |
997 | else: |
998 | filtered[k] = v |
999 | |
1000 | - call1 = call(relation_id=relation_id, **filtered) |
1001 | - call2 = call(relation_id='cluster/0', **relation_data) |
1002 | - self.relation_set.assert_has_calls([call1, call2]) |
1003 | + call1 = call(relation_id=relation_id, **rel_only_data) |
1004 | + call2 = call(relation_id=relation_id, **filtered) |
1005 | + call3 = call(relation_id='cluster/0', **relation_data) |
1006 | + self.assertTrue(self.relation_set.called) |
1007 | + self.relation_set.assert_has_calls([call1, call2, call3]) |
1008 | |
1009 | @patch.object(utils, 'ensure_valid_service') |
1010 | @patch.object(utils, 'add_endpoint') |
charm_lint_check #2133 keystone-next for hopem mp249881
LINT OK: passed
Build: http:// 10.245. 162.77: 8080/job/ charm_lint_ check/2133/