Merge lp:~openstack-charmers/charms/precise/cinder/ssl-everywhere into lp:~openstack-charmers-archive/charms/precise/cinder/trunk

Proposed by Kapil Thangavelu
Status: Merged
Merged at revision: 33
Proposed branch: lp:~openstack-charmers/charms/precise/cinder/ssl-everywhere
Merge into: lp:~openstack-charmers-archive/charms/precise/cinder/trunk
Diff against target: 391 lines (+130/-41)
9 files modified
charm-helpers.yaml (+1/-1)
config.yaml (+5/-0)
hooks/charmhelpers/contrib/hahelpers/apache.py (+9/-8)
hooks/charmhelpers/contrib/openstack/context.py (+88/-23)
hooks/charmhelpers/contrib/openstack/templates/ceph.conf (+3/-0)
hooks/charmhelpers/contrib/storage/linux/ceph.py (+6/-2)
hooks/cinder_utils.py (+5/-4)
templates/cinder.conf (+10/-3)
templates/havana/api-paste.ini (+3/-0)
To merge this branch: bzr merge lp:~openstack-charmers/charms/precise/cinder/ssl-everywhere
Reviewer Review Type Date Requested Status
Marco Ceppi Pending
Edward Hope-Morley Pending
Review via email: mp+209300@code.launchpad.net

Description of the change

SSL client support for mysql and rabbitmq

Sync of charm helpers and config template changes

https://codereview.appspot.com/68100043/

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'charm-helpers.yaml'
2--- charm-helpers.yaml 2013-10-17 21:48:08 +0000
3+++ charm-helpers.yaml 2014-03-04 16:53:59 +0000
4@@ -1,4 +1,4 @@
5-branch: lp:charm-helpers
6+branch: lp:~openstack-charmers/charm-helpers/ssl-everywhere
7 destination: hooks/charmhelpers
8 include:
9 - core
10
11=== modified file 'config.yaml'
12--- config.yaml 2014-02-03 10:44:24 +0000
13+++ config.yaml 2014-03-04 16:53:59 +0000
14@@ -121,6 +121,11 @@
15 ssl_key:
16 type: string
17 description: SSL key to use with certificate specified as ssl_cert.
18+ ssl_ca:
19+ type: string
20+ description: |
21+ SSL CA to use with the certificate and key provided - this is only
22+ required if you are providing a privately signed ssl_cert and ssl_key.
23 config-flags:
24 type: string
25 description: Comma separated list of key=value config flags to be set in cinder.conf.
26
27=== modified file 'hooks/charmhelpers/contrib/hahelpers/apache.py'
28--- hooks/charmhelpers/contrib/hahelpers/apache.py 2013-10-17 21:48:08 +0000
29+++ hooks/charmhelpers/contrib/hahelpers/apache.py 2014-03-04 16:53:59 +0000
30@@ -39,14 +39,15 @@
31
32
33 def get_ca_cert():
34- ca_cert = None
35- log("Inspecting identity-service relations for CA SSL certificate.",
36- level=INFO)
37- for r_id in relation_ids('identity-service'):
38- for unit in relation_list(r_id):
39- if not ca_cert:
40- ca_cert = relation_get('ca_cert',
41- rid=r_id, unit=unit)
42+ ca_cert = config_get('ssl_ca')
43+ if ca_cert is None:
44+ log("Inspecting identity-service relations for CA SSL certificate.",
45+ level=INFO)
46+ for r_id in relation_ids('identity-service'):
47+ for unit in relation_list(r_id):
48+ if ca_cert is None:
49+ ca_cert = relation_get('ca_cert',
50+ rid=r_id, unit=unit)
51 return ca_cert
52
53
54
55=== modified file 'hooks/charmhelpers/contrib/openstack/context.py'
56--- hooks/charmhelpers/contrib/openstack/context.py 2014-02-19 10:44:30 +0000
57+++ hooks/charmhelpers/contrib/openstack/context.py 2014-03-04 16:53:59 +0000
58@@ -1,5 +1,6 @@
59 import json
60 import os
61+import time
62
63 from base64 import b64decode
64
65@@ -29,6 +30,7 @@
66 determine_apache_port,
67 determine_api_port,
68 https,
69+ is_clustered
70 )
71
72 from charmhelpers.contrib.hahelpers.apache import (
73@@ -112,7 +114,8 @@
74 class SharedDBContext(OSContextGenerator):
75 interfaces = ['shared-db']
76
77- def __init__(self, database=None, user=None, relation_prefix=None):
78+ def __init__(self,
79+ database=None, user=None, relation_prefix=None, ssl_dir=None):
80 '''
81 Allows inspecting relation for settings prefixed with relation_prefix.
82 This is useful for parsing access for multiple databases returned via
83@@ -121,6 +124,7 @@
84 self.relation_prefix = relation_prefix
85 self.database = database
86 self.user = user
87+ self.ssl_dir = ssl_dir
88
89 def __call__(self):
90 self.database = self.database or config('database')
91@@ -138,19 +142,44 @@
92
93 for rid in relation_ids('shared-db'):
94 for unit in related_units(rid):
95- passwd = relation_get(password_setting, rid=rid, unit=unit)
96+ rdata = relation_get(rid=rid, unit=unit)
97 ctxt = {
98- 'database_host': relation_get('db_host', rid=rid,
99- unit=unit),
100+ 'database_host': rdata.get('db_host'),
101 'database': self.database,
102 'database_user': self.user,
103- 'database_password': passwd,
104+ 'database_password': rdata.get(password_setting)
105 }
106 if context_complete(ctxt):
107+ db_ssl(rdata, ctxt, self.ssl_dir)
108 return ctxt
109 return {}
110
111
112+def db_ssl(rdata, ctxt, ssl_dir):
113+ if 'ssl_ca' in rdata and ssl_dir:
114+ ca_path = os.path.join(ssl_dir, 'db-client.ca')
115+ with open(ca_path, 'w') as fh:
116+ fh.write(b64decode(rdata['ssl_ca']))
117+ ctxt['database_ssl_ca'] = ca_path
118+ elif 'ssl_ca' in rdata:
119+ log("Charm not setup for ssl support but ssl ca found")
120+ return ctxt
121+ if 'ssl_cert' in rdata:
122+ cert_path = os.path.join(
123+ ssl_dir, 'db-client.cert')
124+ if not os.path.exists(cert_path):
125+ log("Waiting 1m for ssl client cert validity")
126+ time.sleep(60)
127+ with open(cert_path, 'w') as fh:
128+ fh.write(b64decode(rdata['ssl_cert']))
129+ ctxt['database_ssl_cert'] = cert_path
130+ key_path = os.path.join(ssl_dir, 'db-client.key')
131+ with open(key_path, 'w') as fh:
132+ fh.write(b64decode(rdata['ssl_key']))
133+ ctxt['database_ssl_key'] = key_path
134+ return ctxt
135+
136+
137 class IdentityServiceContext(OSContextGenerator):
138 interfaces = ['identity-service']
139
140@@ -160,22 +189,19 @@
141
142 for rid in relation_ids('identity-service'):
143 for unit in related_units(rid):
144+ rdata = relation_get(rid=rid, unit=unit)
145 ctxt = {
146- 'service_port': relation_get('service_port', rid=rid,
147- unit=unit),
148- 'service_host': relation_get('service_host', rid=rid,
149- unit=unit),
150- 'auth_host': relation_get('auth_host', rid=rid, unit=unit),
151- 'auth_port': relation_get('auth_port', rid=rid, unit=unit),
152- 'admin_tenant_name': relation_get('service_tenant',
153- rid=rid, unit=unit),
154- 'admin_user': relation_get('service_username', rid=rid,
155- unit=unit),
156- 'admin_password': relation_get('service_password', rid=rid,
157- unit=unit),
158- # XXX: Hard-coded http.
159- 'service_protocol': 'http',
160- 'auth_protocol': 'http',
161+ 'service_port': rdata.get('service_port'),
162+ 'service_host': rdata.get('service_host'),
163+ 'auth_host': rdata.get('auth_host'),
164+ 'auth_port': rdata.get('auth_port'),
165+ 'admin_tenant_name': rdata.get('service_tenant'),
166+ 'admin_user': rdata.get('service_username'),
167+ 'admin_password': rdata.get('service_password'),
168+ 'service_protocol':
169+ rdata.get('service_protocol') or 'http',
170+ 'auth_protocol':
171+ rdata.get('auth_protocol') or 'http',
172 }
173 if context_complete(ctxt):
174 return ctxt
175@@ -185,6 +211,9 @@
176 class AMQPContext(OSContextGenerator):
177 interfaces = ['amqp']
178
179+ def __init__(self, ssl_dir=None):
180+ self.ssl_dir = ssl_dir
181+
182 def __call__(self):
183 log('Generating template context for amqp')
184 conf = config()
185@@ -195,7 +224,6 @@
186 log('Could not generate shared_db context. '
187 'Missing required charm config options: %s.' % e)
188 raise OSContextError
189-
190 ctxt = {}
191 for rid in relation_ids('amqp'):
192 for unit in related_units(rid):
193@@ -212,7 +240,24 @@
194 unit=unit),
195 'rabbitmq_virtual_host': vhost,
196 })
197+ ssl_port = relation_get('ssl_port', rid=rid, unit=unit)
198+ if ssl_port:
199+ ctxt['rabbit_ssl_port'] = ssl_port
200+ ssl_ca = relation_get('ssl_ca', rid=rid, unit=unit)
201+ if ssl_ca:
202+ ctxt['rabbit_ssl_ca'] = ssl_ca
203+
204 if context_complete(ctxt):
205+ if 'rabbit_ssl_ca' in ctxt:
206+ if not self.ssl_dir:
207+ log(("Charm not setup for ssl support "
208+ "but ssl ca found"))
209+ break
210+ ca_path = os.path.join(
211+ self.ssl_dir, 'rabbit-client-ca.pem')
212+ with open(ca_path, 'w') as fh:
213+ fh.write(b64decode(ctxt['rabbit_ssl_ca']))
214+ ctxt['rabbit_ssl_ca'] = ca_path
215 # Sufficient information found = break out!
216 break
217 # Used for active/active rabbitmq >= grizzly
218@@ -240,10 +285,13 @@
219 '''This generates context for /etc/ceph/ceph.conf templates'''
220 if not relation_ids('ceph'):
221 return {}
222+
223 log('Generating template context for ceph')
224+
225 mon_hosts = []
226 auth = None
227 key = None
228+ use_syslog = str(config('use-syslog')).lower()
229 for rid in relation_ids('ceph'):
230 for unit in related_units(rid):
231 mon_hosts.append(relation_get('private-address', rid=rid,
232@@ -255,6 +303,7 @@
233 'mon_hosts': ' '.join(mon_hosts),
234 'auth': auth,
235 'key': key,
236+ 'use_syslog': use_syslog
237 }
238
239 if not os.path.isdir('/etc/ceph'):
240@@ -391,7 +440,7 @@
241 return ctxt
242
243
244-class NeutronContext(object):
245+class NeutronContext(OSContextGenerator):
246 interfaces = []
247
248 @property
249@@ -452,6 +501,22 @@
250
251 return nvp_ctxt
252
253+ def neutron_ctxt(self):
254+ if https():
255+ proto = 'https'
256+ else:
257+ proto = 'http'
258+ if is_clustered():
259+ host = config('vip')
260+ else:
261+ host = unit_get('private-address')
262+ url = '%s://%s:%s' % (proto, host, '9292')
263+ ctxt = {
264+ 'network_manager': self.network_manager,
265+ 'neutron_url': url,
266+ }
267+ return ctxt
268+
269 def __call__(self):
270 self._ensure_packages()
271
272@@ -461,7 +526,7 @@
273 if not self.plugin:
274 return {}
275
276- ctxt = {'network_manager': self.network_manager}
277+ ctxt = self.neutron_ctxt()
278
279 if self.plugin == 'ovs':
280 ctxt.update(self.ovs_ctxt())
281
282=== modified file 'hooks/charmhelpers/contrib/openstack/templates/ceph.conf'
283--- hooks/charmhelpers/contrib/openstack/templates/ceph.conf 2013-10-17 21:48:08 +0000
284+++ hooks/charmhelpers/contrib/openstack/templates/ceph.conf 2014-03-04 16:53:59 +0000
285@@ -9,3 +9,6 @@
286 keyring = /etc/ceph/$cluster.$name.keyring
287 mon host = {{ mon_hosts }}
288 {% endif -%}
289+log to syslog = {{ use_syslog }}
290+err to syslog = {{ use_syslog }}
291+clog to syslog = {{ use_syslog }}
292
293=== modified file 'hooks/charmhelpers/contrib/storage/linux/ceph.py'
294--- hooks/charmhelpers/contrib/storage/linux/ceph.py 2013-11-06 03:53:17 +0000
295+++ hooks/charmhelpers/contrib/storage/linux/ceph.py 2014-03-04 16:53:59 +0000
296@@ -49,6 +49,9 @@
297 auth supported = {auth}
298 keyring = {keyring}
299 mon host = {mon_hosts}
300+ log to syslog = {use_syslog}
301+ err to syslog = {use_syslog}
302+ clog to syslog = {use_syslog}
303 """
304
305
306@@ -194,7 +197,7 @@
307 return hosts
308
309
310-def configure(service, key, auth):
311+def configure(service, key, auth, use_syslog):
312 ''' Perform basic configuration of Ceph '''
313 create_keyring(service, key)
314 create_key_file(service, key)
315@@ -202,7 +205,8 @@
316 with open('/etc/ceph/ceph.conf', 'w') as ceph_conf:
317 ceph_conf.write(CEPH_CONF.format(auth=auth,
318 keyring=_keyring_path(service),
319- mon_hosts=",".join(map(str, hosts))))
320+ mon_hosts=",".join(map(str, hosts)),
321+ use_syslog=use_syslog))
322 modprobe('rbd')
323
324
325
326=== modified file 'hooks/cinder_utils.py'
327--- hooks/cinder_utils.py 2014-02-17 07:53:12 +0000
328+++ hooks/cinder_utils.py 2014-03-04 16:53:59 +0000
329@@ -83,8 +83,9 @@
330 class CinderCharmError(Exception):
331 pass
332
333-CINDER_CONF = '/etc/cinder/cinder.conf'
334-CINDER_API_CONF = '/etc/cinder/api-paste.ini'
335+CINDER_CONF_DIR = "/etc/cinder"
336+CINDER_CONF = '%s/cinder.conf' % CINDER_CONF_DIR
337+CINDER_API_CONF = '%s/api-paste.ini' % CINDER_CONF_DIR
338 CEPH_CONF = '/etc/ceph/ceph.conf'
339 HAPROXY_CONF = '/etc/haproxy/haproxy.cfg'
340 APACHE_SITE_CONF = '/etc/apache2/sites-available/openstack_https_frontend'
341@@ -96,8 +97,8 @@
342 # with file in restart_on_changes()'s service map.
343 CONFIG_FILES = OrderedDict([
344 (CINDER_CONF, {
345- 'hook_contexts': [context.SharedDBContext(),
346- context.AMQPContext(),
347+ 'hook_contexts': [context.SharedDBContext(ssl_dir=CINDER_CONF_DIR),
348+ context.AMQPContext(ssl_dir=CINDER_CONF_DIR),
349 context.ImageServiceContext(),
350 context.OSConfigFlagContext(),
351 context.SyslogContext(),
352
353=== modified file 'templates/cinder.conf'
354--- templates/cinder.conf 2014-02-03 10:44:24 +0000
355+++ templates/cinder.conf 2014-03-04 16:53:59 +0000
356@@ -16,11 +16,18 @@
357 lock_path = /var/lock/cinder
358 volumes_dir = /var/lib/cinder/volumes
359 {% if database_host -%}
360-sql_connection = mysql://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }}
361-{% endif -%}
362-{% if rabbitmq_host -%}
363+sql_connection = mysql://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }}{% if database_ssl_ca %}?ssl_ca={{ database_ssl_ca }}{% if database_ssl_cert %}&ssl_cert={{ database_ssl_cert }}&ssl_key={{ database_ssl_key }}{% endif %}{% endif %}
364+{% endif %}
365+{% if rabbitmq_host %}
366 notification_driver = cinder.openstack.common.notifier.rabbit_notifier
367 control_exchange = cinder
368+{% if rabbit_ssl_port %}
369+rabbit_use_ssl=True
370+rabbit_port={{ rabbit_ssl_port }}
371+{% if rabbit_ssl_ca %}
372+kombu_ssl_ca_certs={{rabbit_ssl_ca}}
373+{% endif %}
374+{% endif %}
375 rabbit_host = {{ rabbitmq_host }}
376 rabbit_userid = {{ rabbitmq_user }}
377 rabbit_password = {{ rabbitmq_password }}
378
379=== modified file 'templates/havana/api-paste.ini'
380--- templates/havana/api-paste.ini 2013-10-17 21:48:08 +0000
381+++ templates/havana/api-paste.ini 2014-03-04 16:53:59 +0000
382@@ -58,6 +58,9 @@
383 [filter:authtoken]
384 paste.filter_factory = keystoneclient.middleware.auth_token:filter_factory
385 {% if service_host -%}
386+service_protocol = {{ service_protocol }}
387+service_host = {{ service_host }}
388+service_port = {{ service_port }}
389 auth_host = {{ auth_host }}
390 auth_port = {{ auth_port }}
391 auth_protocol = {{ auth_protocol }}

Subscribers

People subscribed via source and target branches

to all changes: