← Back to team overview

nagios-charmers team mailing list archive

[Merge] ~addyess/charm-nagios:lp1849575-fix_ssl_only_config into charm-nagios:master

 

Adam Dyess has proposed merging ~addyess/charm-nagios:lp1849575-fix_ssl_only_config into charm-nagios:master.

Commit message:
Fix bug associated with ssl=only config

Requested reviews:
  Chris Sanders (chris.sanders)
Related bugs:
  Bug #1849575 in Nagios Charm: "ssl=only does not disable port 80"
  https://bugs.launchpad.net/charm-nagios/+bug/1849575

For more details, see:
https://code.launchpad.net/~addyess/charm-nagios/+git/charm-nagios/+merge/387305
-- 
Your team Nagios Charm developers is subscribed to branch charm-nagios:master.
diff --git a/hooks/templates/ports-cfg.jinja2 b/hooks/templates/ports-cfg.jinja2
new file mode 100644
index 0000000..d638149
--- /dev/null
+++ b/hooks/templates/ports-cfg.jinja2
@@ -0,0 +1,15 @@
+# If you just change the port or add more ports here, you will likely also
+# have to change the VirtualHost statement in
+# /etc/apache2/sites-enabled/000-default.conf
+
+{%if enable_http %}Listen 80{% endif %}
+
+<IfModule ssl_module>
+        Listen 443
+</IfModule>
+
+<IfModule mod_gnutls.c>
+        Listen 443
+</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/hooks/upgrade-charm b/hooks/upgrade-charm
index 05bb384..25ad977 100755
--- a/hooks/upgrade-charm
+++ b/hooks/upgrade-charm
@@ -4,8 +4,8 @@
 # of SSL-Everywhere!
 import base64
 from jinja2 import Template
+import glob
 import os
-# import re
 import pwd
 import grp
 import stat
@@ -29,7 +29,7 @@ pagerduty_path = hookenv.config('pagerduty_path')
 notification_levels = hookenv.config('pagerduty_notification_levels')
 nagios_user = hookenv.config('nagios_user')
 nagios_group = hookenv.config('nagios_group')
-ssl_config = hookenv.config('ssl')
+ssl_config = str(hookenv.config('ssl')).lower()
 charm_dir = os.environ['CHARM_DIR']
 cert_domain = hookenv.unit_get('public-address')
 nagios_cfg = "/etc/nagios3/nagios.cfg"
@@ -40,6 +40,8 @@ password = hookenv.config('password')
 ro_password = hookenv.config('ro-password')
 nagiosadmin = hookenv.config('nagiosadmin') or 'nagiosadmin'
 
+SSL_CONFIGURED = ssl_config in ["on", "only"]
+HTTP_ENABLED = ssl_config not in ["only"]
 
 # Checks the charm relations for legacy relations
 # Inserts warnings into the log about legacy relations, as they will be removed
@@ -216,13 +218,6 @@ def enable_pagerduty_config():
     host.service_reload('nagios3')
 
 
-def ssl_configured():
-    allowed_options = ["on", "only"]
-    if str(ssl_config).lower() in allowed_options:
-        return True
-    return False
-
-
 # Gather local facts for SSL deployment
 deploy_key_path = os.path.join(charm_dir, 'data', '%s.key' % (cert_domain))
 deploy_cert_path = os.path.join(charm_dir, 'data', '%s.crt' % (cert_domain))
@@ -345,12 +340,24 @@ def update_cgi_config():
     host.service_reload('apache2')
 
 
-# Nagios3 is deployed as a global apache application from the archive.
-# We'll get a little funky and add the SSL keys to the default-ssl config
-# which sets our keys, including the self-signed ones, as the host keyfiles.
-# note: i tried to use cheetah, and it barfed, several times. It can go play
-# in a fire. I'm jusing jinja2.
 def update_apache():
+    """
+    Nagios3 is deployed as a global apache application from the archive.
+    We'll get a little funky and add the SSL keys to the default-ssl config
+    which sets our keys, including the self-signed ones, as the host keyfiles.
+    """
+
+    # Start by Setting the ports.conf
+
+    with open('hooks/templates/ports-cfg.jinja2', 'r') as f:
+        templateDef = f.read()
+    t = Template(templateDef)
+    ports_conf = '/etc/apache2/ports.conf'
+
+    with open(ports_conf, 'w') as f:
+        f.write(t.render({'enable_http': HTTP_ENABLED}))
+
+    # Next setup the default-ssl.conf
     if os.path.exists(chain_file) and os.path.getsize(chain_file) > 0:
         ssl_chain = chain_file
     else:
@@ -361,34 +368,61 @@ def update_apache():
     with open('hooks/templates/default-ssl.tmpl', 'r') as f:
         templateDef = f.read()
 
+    t = Template(templateDef)
+    ssl_conf = '/etc/apache2/sites-available/default-ssl.conf'
+    with open(ssl_conf, 'w') as f:
+        f.write(t.render(template_values))
+
     # Create directory for extra *.include files installed by subordinates
     try:
         os.makedirs('/etc/apache2/vhost.d/')
     except OSError:
         pass
 
-    t = Template(templateDef)
-    with open('/etc/apache2/sites-available/default-ssl.conf', 'w') as f:
-        f.write(t.render(template_values))
-    print("Value of ssl is %s" % ssl)
-    if ssl_config == "only":
-        subprocess.call(['a2dissite', 'default'])
-        hookenv.close_port(80)
-        subprocess.call(['a2ensite', 'default-ssl'])
-        subprocess.call(['a2enmod', 'ssl'])
-    elif ssl_config == "on":
-        subprocess.call(['a2ensite', 'default-ssl'])
-        subprocess.call(['a2enmod', 'ssl'])
-        hookenv.open_port(443)
-    else:
-        subprocess.call(['a2dissite', 'default-ssl'])
-        hookenv.close_port(443)
-        subprocess.call(['a2ensite', 'default'])
-        hookenv.open_port(80)
+    # Configure the behavior of http sites
+    sites = glob.glob("/etc/apache2/sites-available/*.conf")
+    non_ssl = set(sites) - {ssl_conf}
+    for each in non_ssl:
+        site = os.path.basename(each).strip('.conf')
+        Apache2Site(site).action(enabled=HTTP_ENABLED)
 
+    # Configure the behavior of https site
+    Apache2Site("default-ssl").action(enabled=SSL_CONFIGURED)
+
+    # Finally, restart apache2
     host.service_reload('apache2')
 
 
+class Apache2Site:
+    def __init__(self, site):
+        self.site = site
+        self.is_ssl = 'ssl' in site.lower()
+        self.port = 443 if self.is_ssl else 80
+
+    def action(self, enabled):
+        fn = self._enable if enabled else self._disable
+        return fn()
+
+    def _call(self, args):
+        try:
+            subprocess.check_output(args, stderr=subprocess.STDOUT)
+        except subprocess.CalledProcessError as e:
+            hookenv.log("Apache2Site: `{}`, returned {}, stdout:\n{}"
+                        .format(e.cmd, e.returncode, e.output), "ERROR")
+
+    def _enable(self):
+        hookenv.log("Apache2Site: Enabling %s..." % self.site, "INFO")
+        self._call(['a2ensite', self.site])
+        if self.port == 443:
+            self._call(['a2enmod', 'ssl'])
+        hookenv.open_port(self.port)
+
+    def _disable(self):
+        hookenv.log("Apache2Site: Disabling %s..." % self.site, "INFO")
+        self._call(['a2dissite', self.site])
+        hookenv.close_port(self.port)
+
+
 def update_password(account, password):
     """Update the charm and Apache's record of the password for the supplied account."""
     account_file = ''.join(['/var/lib/juju/nagios.', account, '.passwd'])
@@ -411,7 +445,7 @@ write_extra_config()
 update_config()
 enable_livestatus_config()
 enable_pagerduty_config()
-if ssl_configured():
+if SSL_CONFIGURED:
     enable_ssl()
 update_apache()
 update_localhost()

Follow ups