~alexlist/charms/trusty/keystone/mojo-is-swift-ha

« back to all changes in this revision

Viewing changes to hooks/lib/apache_utils.py

  • Committer: James Page
  • Date: 2014-04-16 08:20:08 UTC
  • mfrom: (52.2.30 keystone)
  • Revision ID: james.page@canonical.com-20140416082008-34w0nyak0y571tfp
[james-page,ivoks,hazmat,yolanda.robla,r=james-page,t=*]

Redux to used charm helpers
Support for Icehouse on 12.04 and 14.04
Support for Active/Active and SSL RabbitMQ
Support for SSL MySQL
Support for SSL endpoints
Support for PostgreSQL

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#
2
 
# Copyright 2012 Canonical Ltd.
3
 
#
4
 
# This file is sourced from lp:openstack-charm-helpers
5
 
#
6
 
# Authors:
7
 
#  James Page <james.page@ubuntu.com>
8
 
#  Adam Gandelman <adamg@ubuntu.com>
9
 
#
10
 
 
11
 
from lib.utils import (
12
 
    relation_ids,
13
 
    relation_list,
14
 
    relation_get,
15
 
    render_template,
16
 
    juju_log,
17
 
    config_get,
18
 
    install,
19
 
    get_host_ip,
20
 
    restart
21
 
    )
22
 
from lib.cluster_utils import https
23
 
 
24
 
import os
25
 
import subprocess
26
 
from base64 import b64decode
27
 
 
28
 
APACHE_SITE_DIR = "/etc/apache2/sites-available"
29
 
SITE_TEMPLATE = "apache2_site.tmpl"
30
 
RELOAD_CHECK = "To activate the new configuration"
31
 
 
32
 
 
33
 
def get_cert():
34
 
    cert = config_get('ssl_cert')
35
 
    key = config_get('ssl_key')
36
 
    if not (cert and key):
37
 
        juju_log('INFO',
38
 
                 "Inspecting identity-service relations for SSL certificate.")
39
 
        cert = key = None
40
 
        for r_id in relation_ids('identity-service'):
41
 
            for unit in relation_list(r_id):
42
 
                if not cert:
43
 
                    cert = relation_get('ssl_cert',
44
 
                                        rid=r_id, unit=unit)
45
 
                if not key:
46
 
                    key = relation_get('ssl_key',
47
 
                                       rid=r_id, unit=unit)
48
 
    return (cert, key)
49
 
 
50
 
 
51
 
def get_ca_cert():
52
 
    ca_cert = None
53
 
    juju_log('INFO',
54
 
             "Inspecting identity-service relations for CA SSL certificate.")
55
 
    for r_id in relation_ids('identity-service'):
56
 
        for unit in relation_list(r_id):
57
 
            if not ca_cert:
58
 
                ca_cert = relation_get('ca_cert',
59
 
                                       rid=r_id, unit=unit)
60
 
    return ca_cert
61
 
 
62
 
 
63
 
def install_ca_cert(ca_cert):
64
 
    if ca_cert:
65
 
        with open('/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt',
66
 
                  'w') as crt:
67
 
            crt.write(ca_cert)
68
 
        subprocess.check_call(['update-ca-certificates', '--fresh'])
69
 
 
70
 
 
71
 
def enable_https(port_maps, namespace, cert, key, ca_cert=None):
72
 
    '''
73
 
    For a given number of port mappings, configures apache2
74
 
    HTTPs local reverse proxying using certficates and keys provided in
75
 
    either configuration data (preferred) or relation data.  Assumes ports
76
 
    are not in use (calling charm should ensure that).
77
 
 
78
 
    port_maps: dict: external to internal port mappings
79
 
    namespace: str: name of charm
80
 
    '''
81
 
    def _write_if_changed(path, new_content):
82
 
        content = None
83
 
        if os.path.exists(path):
84
 
            with open(path, 'r') as f:
85
 
                content = f.read().strip()
86
 
        if content != new_content:
87
 
            with open(path, 'w') as f:
88
 
                f.write(new_content)
89
 
            return True
90
 
        else:
91
 
            return False
92
 
 
93
 
    juju_log('INFO', "Enabling HTTPS for port mappings: {}".format(port_maps))
94
 
    http_restart = False
95
 
 
96
 
    if cert:
97
 
        cert = b64decode(cert)
98
 
    if key:
99
 
        key = b64decode(key)
100
 
    if ca_cert:
101
 
        ca_cert = b64decode(ca_cert)
102
 
 
103
 
    if not cert and not key:
104
 
        juju_log('ERROR',
105
 
                 "Expected but could not find SSL certificate data, not "
106
 
                 "configuring HTTPS!")
107
 
        return False
108
 
 
109
 
    install('apache2')
110
 
    if RELOAD_CHECK in subprocess.check_output(['a2enmod', 'ssl',
111
 
                                                'proxy', 'proxy_http']):
112
 
        http_restart = True
113
 
 
114
 
    ssl_dir = os.path.join('/etc/apache2/ssl', namespace)
115
 
    if not os.path.exists(ssl_dir):
116
 
        os.makedirs(ssl_dir)
117
 
 
118
 
    if (_write_if_changed(os.path.join(ssl_dir, 'cert'), cert)):
119
 
        http_restart = True
120
 
    if (_write_if_changed(os.path.join(ssl_dir, 'key'), key)):
121
 
        http_restart = True
122
 
    os.chmod(os.path.join(ssl_dir, 'key'), 0600)
123
 
 
124
 
    install_ca_cert(ca_cert)
125
 
 
126
 
    sites_dir = '/etc/apache2/sites-available'
127
 
    for ext_port, int_port in port_maps.items():
128
 
        juju_log('INFO',
129
 
                 'Creating apache2 reverse proxy vhost'
130
 
                 ' for {}:{}'.format(ext_port,
131
 
                                     int_port))
132
 
        site = "{}_{}".format(namespace, ext_port)
133
 
        site_path = os.path.join(sites_dir, site)
134
 
        with open(site_path, 'w') as fsite:
135
 
            context = {
136
 
                "ext": ext_port,
137
 
                "int": int_port,
138
 
                "namespace": namespace,
139
 
                "private_address": get_host_ip()
140
 
                }
141
 
            fsite.write(render_template(SITE_TEMPLATE,
142
 
                                        context))
143
 
 
144
 
        if RELOAD_CHECK in subprocess.check_output(['a2ensite', site]):
145
 
            http_restart = True
146
 
 
147
 
    if http_restart:
148
 
        restart('apache2')
149
 
 
150
 
    return True
151
 
 
152
 
 
153
 
def disable_https(port_maps, namespace):
154
 
    '''
155
 
    Ensure HTTPS reverse proxying is disables for given port mappings
156
 
 
157
 
    port_maps: dict: of ext -> int port mappings
158
 
    namespace: str: name of chamr
159
 
    '''
160
 
    juju_log('INFO', 'Ensuring HTTPS disabled for {}'.format(port_maps))
161
 
 
162
 
    if (not os.path.exists('/etc/apache2') or
163
 
        not os.path.exists(os.path.join('/etc/apache2/ssl', namespace))):
164
 
        return
165
 
 
166
 
    http_restart = False
167
 
    for ext_port in port_maps.keys():
168
 
        if os.path.exists(os.path.join(APACHE_SITE_DIR,
169
 
                                       "{}_{}".format(namespace,
170
 
                                                      ext_port))):
171
 
            juju_log('INFO',
172
 
                     "Disabling HTTPS reverse proxy"
173
 
                     " for {} {}.".format(namespace,
174
 
                                          ext_port))
175
 
            if (RELOAD_CHECK in
176
 
                subprocess.check_output(['a2dissite',
177
 
                                         '{}_{}'.format(namespace,
178
 
                                                        ext_port)])):
179
 
                http_restart = True
180
 
 
181
 
    if http_restart:
182
 
        restart(['apache2'])
183
 
 
184
 
 
185
 
def setup_https(port_maps, namespace, cert, key, ca_cert=None):
186
 
    '''
187
 
    Ensures HTTPS is either enabled or disabled for given port
188
 
    mapping.
189
 
 
190
 
    port_maps: dict: of ext -> int port mappings
191
 
    namespace: str: name of charm
192
 
    '''
193
 
    if not https:
194
 
        disable_https(port_maps, namespace)
195
 
    else:
196
 
        enable_https(port_maps, namespace, cert, key, ca_cert)