aboutsummaryrefslogtreecommitdiffstats
path: root/charms/trusty/ceilometer/charmhelpers/contrib/hardening
diff options
context:
space:
mode:
Diffstat (limited to 'charms/trusty/ceilometer/charmhelpers/contrib/hardening')
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/README.hardening.md38
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/__init__.py15
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/__init__.py19
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/checks/__init__.py31
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/checks/config.py100
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/templates/__init__.py0
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/templates/alias.conf31
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/templates/hardening.conf18
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/audits/__init__.py63
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/audits/apache.py100
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/audits/apt.py105
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/audits/file.py552
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/__init__.py0
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/apache.yaml13
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/apache.yaml.schema9
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/mysql.yaml38
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/mysql.yaml.schema15
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/os.yaml67
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/os.yaml.schema42
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/ssh.yaml49
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/ssh.yaml.schema42
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/harden.py84
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/__init__.py19
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/__init__.py50
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/apt.py39
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/limits.py55
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/login.py67
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/minimize_access.py52
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/pam.py134
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/profile.py45
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/securetty.py39
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/suid_sgid.py131
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/sysctl.py211
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/10.hardcore.conf8
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/99-juju-hardening.conf7
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/__init__.py0
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/login.defs349
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/modules117
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/passwdqc.conf11
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/pinerolo_profile.sh8
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/securetty11
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/tally214
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/__init__.py19
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/checks/__init__.py31
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/checks/config.py89
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/templates/__init__.py0
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/templates/hardening.cnf12
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/__init__.py19
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/checks/__init__.py31
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/checks/config.py394
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/templates/__init__.py0
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/templates/ssh_config70
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/templates/sshd_config159
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/templating.py71
-rw-r--r--charms/trusty/ceilometer/charmhelpers/contrib/hardening/utils.py157
55 files changed, 0 insertions, 3850 deletions
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/README.hardening.md b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/README.hardening.md
deleted file mode 100644
index 91280c0..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/README.hardening.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# Juju charm-helpers hardening library
-
-## Description
-
-This library provides multiple implementations of system and application
-hardening that conform to the standards of http://hardening.io/.
-
-Current implementations include:
-
- * OS
- * SSH
- * MySQL
- * Apache
-
-## Requirements
-
-* Juju Charms
-
-## Usage
-
-1. Synchronise this library into your charm and add the harden() decorator
- (from contrib.hardening.harden) to any functions or methods you want to use
- to trigger hardening of your application/system.
-
-2. Add a config option called 'harden' to your charm config.yaml and set it to
- a space-delimited list of hardening modules you want to run e.g. "os ssh"
-
-3. Override any config defaults (contrib.hardening.defaults) by adding a file
- called hardening.yaml to your charm root containing the name(s) of the
- modules whose settings you want override at root level and then any settings
- with overrides e.g.
-
- os:
- general:
- desktop_enable: True
-
-4. Now just run your charm as usual and hardening will be applied each time the
- hook runs.
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/__init__.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/__init__.py
deleted file mode 100644
index a133532..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/__init__.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/__init__.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/__init__.py
deleted file mode 100644
index 277b8c7..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-from os import path
-
-TEMPLATES_DIR = path.join(path.dirname(__file__), 'templates')
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/checks/__init__.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/checks/__init__.py
deleted file mode 100644
index d130479..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/checks/__init__.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-from charmhelpers.core.hookenv import (
- log,
- DEBUG,
-)
-from charmhelpers.contrib.hardening.apache.checks import config
-
-
-def run_apache_checks():
- log("Starting Apache hardening checks.", level=DEBUG)
- checks = config.get_audits()
- for check in checks:
- log("Running '%s' check" % (check.__class__.__name__), level=DEBUG)
- check.ensure_compliance()
-
- log("Apache hardening checks complete.", level=DEBUG)
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/checks/config.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/checks/config.py
deleted file mode 100644
index 8249ca0..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/checks/config.py
+++ /dev/null
@@ -1,100 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-import os
-import re
-import subprocess
-
-
-from charmhelpers.core.hookenv import (
- log,
- INFO,
-)
-from charmhelpers.contrib.hardening.audits.file import (
- FilePermissionAudit,
- DirectoryPermissionAudit,
- NoReadWriteForOther,
- TemplatedFile,
-)
-from charmhelpers.contrib.hardening.audits.apache import DisabledModuleAudit
-from charmhelpers.contrib.hardening.apache import TEMPLATES_DIR
-from charmhelpers.contrib.hardening import utils
-
-
-def get_audits():
- """Get Apache hardening config audits.
-
- :returns: dictionary of audits
- """
- if subprocess.call(['which', 'apache2'], stdout=subprocess.PIPE) != 0:
- log("Apache server does not appear to be installed on this node - "
- "skipping apache hardening", level=INFO)
- return []
-
- context = ApacheConfContext()
- settings = utils.get_settings('apache')
- audits = [
- FilePermissionAudit(paths='/etc/apache2/apache2.conf', user='root',
- group='root', mode=0o0640),
-
- TemplatedFile(os.path.join(settings['common']['apache_dir'],
- 'mods-available/alias.conf'),
- context,
- TEMPLATES_DIR,
- mode=0o0755,
- user='root',
- service_actions=[{'service': 'apache2',
- 'actions': ['restart']}]),
-
- TemplatedFile(os.path.join(settings['common']['apache_dir'],
- 'conf-enabled/hardening.conf'),
- context,
- TEMPLATES_DIR,
- mode=0o0640,
- user='root',
- service_actions=[{'service': 'apache2',
- 'actions': ['restart']}]),
-
- DirectoryPermissionAudit(settings['common']['apache_dir'],
- user='root',
- group='root',
- mode=0o640),
-
- DisabledModuleAudit(settings['hardening']['modules_to_disable']),
-
- NoReadWriteForOther(settings['common']['apache_dir']),
- ]
-
- return audits
-
-
-class ApacheConfContext(object):
- """Defines the set of key/value pairs to set in a apache config file.
-
- This context, when called, will return a dictionary containing the
- key/value pairs of setting to specify in the
- /etc/apache/conf-enabled/hardening.conf file.
- """
- def __call__(self):
- settings = utils.get_settings('apache')
- ctxt = settings['hardening']
-
- out = subprocess.check_output(['apache2', '-v'])
- ctxt['apache_version'] = re.search(r'.+version: Apache/(.+?)\s.+',
- out).group(1)
- ctxt['apache_icondir'] = '/usr/share/apache2/icons/'
- ctxt['traceenable'] = settings['hardening']['traceenable']
- return ctxt
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/templates/__init__.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/templates/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/templates/__init__.py
+++ /dev/null
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/templates/alias.conf b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/templates/alias.conf
deleted file mode 100644
index e46a58a..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/templates/alias.conf
+++ /dev/null
@@ -1,31 +0,0 @@
-###############################################################################
-# WARNING: This configuration file is maintained by Juju. Local changes may
-# be overwritten.
-###############################################################################
-<IfModule alias_module>
- #
- # Aliases: Add here as many aliases as you need (with no limit). The format is
- # Alias fakename realname
- #
- # Note that if you include a trailing / on fakename then the server will
- # require it to be present in the URL. So "/icons" isn't aliased in this
- # example, only "/icons/". If the fakename is slash-terminated, then the
- # realname must also be slash terminated, and if the fakename omits the
- # trailing slash, the realname must also omit it.
- #
- # We include the /icons/ alias for FancyIndexed directory listings. If
- # you do not use FancyIndexing, you may comment this out.
- #
- Alias /icons/ "{{ apache_icondir }}/"
-
- <Directory "{{ apache_icondir }}">
- Options -Indexes -MultiViews -FollowSymLinks
- AllowOverride None
-{% if apache_version == '2.4' -%}
- Require all granted
-{% else -%}
- Order allow,deny
- Allow from all
-{% endif %}
- </Directory>
-</IfModule>
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/templates/hardening.conf b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/templates/hardening.conf
deleted file mode 100644
index 0794541..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/apache/templates/hardening.conf
+++ /dev/null
@@ -1,18 +0,0 @@
-###############################################################################
-# WARNING: This configuration file is maintained by Juju. Local changes may
-# be overwritten.
-###############################################################################
-
-<Location / >
- <LimitExcept {{ allowed_http_methods }} >
- # http://httpd.apache.org/docs/2.4/upgrading.html
- {% if apache_version > '2.2' -%}
- Require all granted
- {% else -%}
- Order Allow,Deny
- Deny from all
- {% endif %}
- </LimitExcept>
-</Location>
-
-TraceEnable {{ traceenable }}
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/audits/__init__.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/audits/__init__.py
deleted file mode 100644
index 6a7057b..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/audits/__init__.py
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-
-class BaseAudit(object): # NO-QA
- """Base class for hardening checks.
-
- The lifecycle of a hardening check is to first check to see if the system
- is in compliance for the specified check. If it is not in compliance, the
- check method will return a value which will be supplied to the.
- """
- def __init__(self, *args, **kwargs):
- self.unless = kwargs.get('unless', None)
- super(BaseAudit, self).__init__()
-
- def ensure_compliance(self):
- """Checks to see if the current hardening check is in compliance or
- not.
-
- If the check that is performed is not in compliance, then an exception
- should be raised.
- """
- pass
-
- def _take_action(self):
- """Determines whether to perform the action or not.
-
- Checks whether or not an action should be taken. This is determined by
- the truthy value for the unless parameter. If unless is a callback
- method, it will be invoked with no parameters in order to determine
- whether or not the action should be taken. Otherwise, the truthy value
- of the unless attribute will determine if the action should be
- performed.
- """
- # Do the action if there isn't an unless override.
- if self.unless is None:
- return True
-
- # Invoke the callback if there is one.
- if hasattr(self.unless, '__call__'):
- results = self.unless()
- if results:
- return False
- else:
- return True
-
- if self.unless:
- return False
- else:
- return True
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/audits/apache.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/audits/apache.py
deleted file mode 100644
index cf3c987..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/audits/apache.py
+++ /dev/null
@@ -1,100 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-import re
-import subprocess
-
-from six import string_types
-
-from charmhelpers.core.hookenv import (
- log,
- INFO,
- ERROR,
-)
-
-from charmhelpers.contrib.hardening.audits import BaseAudit
-
-
-class DisabledModuleAudit(BaseAudit):
- """Audits Apache2 modules.
-
- Determines if the apache2 modules are enabled. If the modules are enabled
- then they are removed in the ensure_compliance.
- """
- def __init__(self, modules):
- if modules is None:
- self.modules = []
- elif isinstance(modules, string_types):
- self.modules = [modules]
- else:
- self.modules = modules
-
- def ensure_compliance(self):
- """Ensures that the modules are not loaded."""
- if not self.modules:
- return
-
- try:
- loaded_modules = self._get_loaded_modules()
- non_compliant_modules = []
- for module in self.modules:
- if module in loaded_modules:
- log("Module '%s' is enabled but should not be." %
- (module), level=INFO)
- non_compliant_modules.append(module)
-
- if len(non_compliant_modules) == 0:
- return
-
- for module in non_compliant_modules:
- self._disable_module(module)
- self._restart_apache()
- except subprocess.CalledProcessError as e:
- log('Error occurred auditing apache module compliance. '
- 'This may have been already reported. '
- 'Output is: %s' % e.output, level=ERROR)
-
- @staticmethod
- def _get_loaded_modules():
- """Returns the modules which are enabled in Apache."""
- output = subprocess.check_output(['apache2ctl', '-M'])
- modules = []
- for line in output.strip().split():
- # Each line of the enabled module output looks like:
- # module_name (static|shared)
- # Plus a header line at the top of the output which is stripped
- # out by the regex.
- matcher = re.search(r'^ (\S*)', line)
- if matcher:
- modules.append(matcher.group(1))
- return modules
-
- @staticmethod
- def _disable_module(module):
- """Disables the specified module in Apache."""
- try:
- subprocess.check_call(['a2dismod', module])
- except subprocess.CalledProcessError as e:
- # Note: catch error here to allow the attempt of disabling
- # multiple modules in one go rather than failing after the
- # first module fails.
- log('Error occurred disabling module %s. '
- 'Output is: %s' % (module, e.output), level=ERROR)
-
- @staticmethod
- def _restart_apache():
- """Restarts the apache process"""
- subprocess.check_output(['service', 'apache2', 'restart'])
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/audits/apt.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/audits/apt.py
deleted file mode 100644
index e94af03..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/audits/apt.py
+++ /dev/null
@@ -1,105 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-from __future__ import absolute_import # required for external apt import
-from apt import apt_pkg
-from six import string_types
-
-from charmhelpers.fetch import (
- apt_cache,
- apt_purge
-)
-from charmhelpers.core.hookenv import (
- log,
- DEBUG,
- WARNING,
-)
-from charmhelpers.contrib.hardening.audits import BaseAudit
-
-
-class AptConfig(BaseAudit):
-
- def __init__(self, config, **kwargs):
- self.config = config
-
- def verify_config(self):
- apt_pkg.init()
- for cfg in self.config:
- value = apt_pkg.config.get(cfg['key'], cfg.get('default', ''))
- if value and value != cfg['expected']:
- log("APT config '%s' has unexpected value '%s' "
- "(expected='%s')" %
- (cfg['key'], value, cfg['expected']), level=WARNING)
-
- def ensure_compliance(self):
- self.verify_config()
-
-
-class RestrictedPackages(BaseAudit):
- """Class used to audit restricted packages on the system."""
-
- def __init__(self, pkgs, **kwargs):
- super(RestrictedPackages, self).__init__(**kwargs)
- if isinstance(pkgs, string_types) or not hasattr(pkgs, '__iter__'):
- self.pkgs = [pkgs]
- else:
- self.pkgs = pkgs
-
- def ensure_compliance(self):
- cache = apt_cache()
-
- for p in self.pkgs:
- if p not in cache:
- continue
-
- pkg = cache[p]
- if not self.is_virtual_package(pkg):
- if not pkg.current_ver:
- log("Package '%s' is not installed." % pkg.name,
- level=DEBUG)
- continue
- else:
- log("Restricted package '%s' is installed" % pkg.name,
- level=WARNING)
- self.delete_package(cache, pkg)
- else:
- log("Checking restricted virtual package '%s' provides" %
- pkg.name, level=DEBUG)
- self.delete_package(cache, pkg)
-
- def delete_package(self, cache, pkg):
- """Deletes the package from the system.
-
- Deletes the package form the system, properly handling virtual
- packages.
-
- :param cache: the apt cache
- :param pkg: the package to remove
- """
- if self.is_virtual_package(pkg):
- log("Package '%s' appears to be virtual - purging provides" %
- pkg.name, level=DEBUG)
- for _p in pkg.provides_list:
- self.delete_package(cache, _p[2].parent_pkg)
- elif not pkg.current_ver:
- log("Package '%s' not installed" % pkg.name, level=DEBUG)
- return
- else:
- log("Purging package '%s'" % pkg.name, level=DEBUG)
- apt_purge(pkg.name)
-
- def is_virtual_package(self, pkg):
- return pkg.has_provides and not pkg.has_versions
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/audits/file.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/audits/file.py
deleted file mode 100644
index 0fb545a..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/audits/file.py
+++ /dev/null
@@ -1,552 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-import grp
-import os
-import pwd
-import re
-
-from subprocess import (
- CalledProcessError,
- check_output,
- check_call,
-)
-from traceback import format_exc
-from six import string_types
-from stat import (
- S_ISGID,
- S_ISUID
-)
-
-from charmhelpers.core.hookenv import (
- log,
- DEBUG,
- INFO,
- WARNING,
- ERROR,
-)
-from charmhelpers.core import unitdata
-from charmhelpers.core.host import file_hash
-from charmhelpers.contrib.hardening.audits import BaseAudit
-from charmhelpers.contrib.hardening.templating import (
- get_template_path,
- render_and_write,
-)
-from charmhelpers.contrib.hardening import utils
-
-
-class BaseFileAudit(BaseAudit):
- """Base class for file audits.
-
- Provides api stubs for compliance check flow that must be used by any class
- that implemented this one.
- """
-
- def __init__(self, paths, always_comply=False, *args, **kwargs):
- """
- :param paths: string path of list of paths of files we want to apply
- compliance checks are criteria to.
- :param always_comply: if true compliance criteria is always applied
- else compliance is skipped for non-existent
- paths.
- """
- super(BaseFileAudit, self).__init__(*args, **kwargs)
- self.always_comply = always_comply
- if isinstance(paths, string_types) or not hasattr(paths, '__iter__'):
- self.paths = [paths]
- else:
- self.paths = paths
-
- def ensure_compliance(self):
- """Ensure that the all registered files comply to registered criteria.
- """
- for p in self.paths:
- if os.path.exists(p):
- if self.is_compliant(p):
- continue
-
- log('File %s is not in compliance.' % p, level=INFO)
- else:
- if not self.always_comply:
- log("Non-existent path '%s' - skipping compliance check"
- % (p), level=INFO)
- continue
-
- if self._take_action():
- log("Applying compliance criteria to '%s'" % (p), level=INFO)
- self.comply(p)
-
- def is_compliant(self, path):
- """Audits the path to see if it is compliance.
-
- :param path: the path to the file that should be checked.
- """
- raise NotImplementedError
-
- def comply(self, path):
- """Enforces the compliance of a path.
-
- :param path: the path to the file that should be enforced.
- """
- raise NotImplementedError
-
- @classmethod
- def _get_stat(cls, path):
- """Returns the Posix st_stat information for the specified file path.
-
- :param path: the path to get the st_stat information for.
- :returns: an st_stat object for the path or None if the path doesn't
- exist.
- """
- return os.stat(path)
-
-
-class FilePermissionAudit(BaseFileAudit):
- """Implements an audit for file permissions and ownership for a user.
-
- This class implements functionality that ensures that a specific user/group
- will own the file(s) specified and that the permissions specified are
- applied properly to the file.
- """
- def __init__(self, paths, user, group=None, mode=0o600, **kwargs):
- self.user = user
- self.group = group
- self.mode = mode
- super(FilePermissionAudit, self).__init__(paths, user, group, mode,
- **kwargs)
-
- @property
- def user(self):
- return self._user
-
- @user.setter
- def user(self, name):
- try:
- user = pwd.getpwnam(name)
- except KeyError:
- log('Unknown user %s' % name, level=ERROR)
- user = None
- self._user = user
-
- @property
- def group(self):
- return self._group
-
- @group.setter
- def group(self, name):
- try:
- group = None
- if name:
- group = grp.getgrnam(name)
- else:
- group = grp.getgrgid(self.user.pw_gid)
- except KeyError:
- log('Unknown group %s' % name, level=ERROR)
- self._group = group
-
- def is_compliant(self, path):
- """Checks if the path is in compliance.
-
- Used to determine if the path specified meets the necessary
- requirements to be in compliance with the check itself.
-
- :param path: the file path to check
- :returns: True if the path is compliant, False otherwise.
- """
- stat = self._get_stat(path)
- user = self.user
- group = self.group
-
- compliant = True
- if stat.st_uid != user.pw_uid or stat.st_gid != group.gr_gid:
- log('File %s is not owned by %s:%s.' % (path, user.pw_name,
- group.gr_name),
- level=INFO)
- compliant = False
-
- # POSIX refers to the st_mode bits as corresponding to both the
- # file type and file permission bits, where the least significant 12
- # bits (o7777) are the suid (11), sgid (10), sticky bits (9), and the
- # file permission bits (8-0)
- perms = stat.st_mode & 0o7777
- if perms != self.mode:
- log('File %s has incorrect permissions, currently set to %s' %
- (path, oct(stat.st_mode & 0o7777)), level=INFO)
- compliant = False
-
- return compliant
-
- def comply(self, path):
- """Issues a chown and chmod to the file paths specified."""
- utils.ensure_permissions(path, self.user.pw_name, self.group.gr_name,
- self.mode)
-
-
-class DirectoryPermissionAudit(FilePermissionAudit):
- """Performs a permission check for the specified directory path."""
-
- def __init__(self, paths, user, group=None, mode=0o600,
- recursive=True, **kwargs):
- super(DirectoryPermissionAudit, self).__init__(paths, user, group,
- mode, **kwargs)
- self.recursive = recursive
-
- def is_compliant(self, path):
- """Checks if the directory is compliant.
-
- Used to determine if the path specified and all of its children
- directories are in compliance with the check itself.
-
- :param path: the directory path to check
- :returns: True if the directory tree is compliant, otherwise False.
- """
- if not os.path.isdir(path):
- log('Path specified %s is not a directory.' % path, level=ERROR)
- raise ValueError("%s is not a directory." % path)
-
- if not self.recursive:
- return super(DirectoryPermissionAudit, self).is_compliant(path)
-
- compliant = True
- for root, dirs, _ in os.walk(path):
- if len(dirs) > 0:
- continue
-
- if not super(DirectoryPermissionAudit, self).is_compliant(root):
- compliant = False
- continue
-
- return compliant
-
- def comply(self, path):
- for root, dirs, _ in os.walk(path):
- if len(dirs) > 0:
- super(DirectoryPermissionAudit, self).comply(root)
-
-
-class ReadOnly(BaseFileAudit):
- """Audits that files and folders are read only."""
- def __init__(self, paths, *args, **kwargs):
- super(ReadOnly, self).__init__(paths=paths, *args, **kwargs)
-
- def is_compliant(self, path):
- try:
- output = check_output(['find', path, '-perm', '-go+w',
- '-type', 'f']).strip()
-
- # The find above will find any files which have permission sets
- # which allow too broad of write access. As such, the path is
- # compliant if there is no output.
- if output:
- return False
-
- return True
- except CalledProcessError as e:
- log('Error occurred checking finding writable files for %s. '
- 'Error information is: command %s failed with returncode '
- '%d and output %s.\n%s' % (path, e.cmd, e.returncode, e.output,
- format_exc(e)), level=ERROR)
- return False
-
- def comply(self, path):
- try:
- check_output(['chmod', 'go-w', '-R', path])
- except CalledProcessError as e:
- log('Error occurred removing writeable permissions for %s. '
- 'Error information is: command %s failed with returncode '
- '%d and output %s.\n%s' % (path, e.cmd, e.returncode, e.output,
- format_exc(e)), level=ERROR)
-
-
-class NoReadWriteForOther(BaseFileAudit):
- """Ensures that the files found under the base path are readable or
- writable by anyone other than the owner or the group.
- """
- def __init__(self, paths):
- super(NoReadWriteForOther, self).__init__(paths)
-
- def is_compliant(self, path):
- try:
- cmd = ['find', path, '-perm', '-o+r', '-type', 'f', '-o',
- '-perm', '-o+w', '-type', 'f']
- output = check_output(cmd).strip()
-
- # The find above here will find any files which have read or
- # write permissions for other, meaning there is too broad of access
- # to read/write the file. As such, the path is compliant if there's
- # no output.
- if output:
- return False
-
- return True
- except CalledProcessError as e:
- log('Error occurred while finding files which are readable or '
- 'writable to the world in %s. '
- 'Command output is: %s.' % (path, e.output), level=ERROR)
-
- def comply(self, path):
- try:
- check_output(['chmod', '-R', 'o-rw', path])
- except CalledProcessError as e:
- log('Error occurred attempting to change modes of files under '
- 'path %s. Output of command is: %s' % (path, e.output))
-
-
-class NoSUIDSGIDAudit(BaseFileAudit):
- """Audits that specified files do not have SUID/SGID bits set."""
- def __init__(self, paths, *args, **kwargs):
- super(NoSUIDSGIDAudit, self).__init__(paths=paths, *args, **kwargs)
-
- def is_compliant(self, path):
- stat = self._get_stat(path)
- if (stat.st_mode & (S_ISGID | S_ISUID)) != 0:
- return False
-
- return True
-
- def comply(self, path):
- try:
- log('Removing suid/sgid from %s.' % path, level=DEBUG)
- check_output(['chmod', '-s', path])
- except CalledProcessError as e:
- log('Error occurred removing suid/sgid from %s.'
- 'Error information is: command %s failed with returncode '
- '%d and output %s.\n%s' % (path, e.cmd, e.returncode, e.output,
- format_exc(e)), level=ERROR)
-
-
-class TemplatedFile(BaseFileAudit):
- """The TemplatedFileAudit audits the contents of a templated file.
-
- This audit renders a file from a template, sets the appropriate file
- permissions, then generates a hashsum with which to check the content
- changed.
- """
- def __init__(self, path, context, template_dir, mode, user='root',
- group='root', service_actions=None, **kwargs):
- self.context = context
- self.user = user
- self.group = group
- self.mode = mode
- self.template_dir = template_dir
- self.service_actions = service_actions
- super(TemplatedFile, self).__init__(paths=path, always_comply=True,
- **kwargs)
-
- def is_compliant(self, path):
- """Determines if the templated file is compliant.
-
- A templated file is only compliant if it has not changed (as
- determined by its sha256 hashsum) AND its file permissions are set
- appropriately.
-
- :param path: the path to check compliance.
- """
- same_templates = self.templates_match(path)
- same_content = self.contents_match(path)
- same_permissions = self.permissions_match(path)
-
- if same_content and same_permissions and same_templates:
- return True
-
- return False
-
- def run_service_actions(self):
- """Run any actions on services requested."""
- if not self.service_actions:
- return
-
- for svc_action in self.service_actions:
- name = svc_action['service']
- actions = svc_action['actions']
- log("Running service '%s' actions '%s'" % (name, actions),
- level=DEBUG)
- for action in actions:
- cmd = ['service', name, action]
- try:
- check_call(cmd)
- except CalledProcessError as exc:
- log("Service name='%s' action='%s' failed - %s" %
- (name, action, exc), level=WARNING)
-
- def comply(self, path):
- """Ensures the contents and the permissions of the file.
-
- :param path: the path to correct
- """
- dirname = os.path.dirname(path)
- if not os.path.exists(dirname):
- os.makedirs(dirname)
-
- self.pre_write()
- render_and_write(self.template_dir, path, self.context())
- utils.ensure_permissions(path, self.user, self.group, self.mode)
- self.run_service_actions()
- self.save_checksum(path)
- self.post_write()
-
- def pre_write(self):
- """Invoked prior to writing the template."""
- pass
-
- def post_write(self):
- """Invoked after writing the template."""
- pass
-
- def templates_match(self, path):
- """Determines if the template files are the same.
-
- The template file equality is determined by the hashsum of the
- template files themselves. If there is no hashsum, then the content
- cannot be sure to be the same so treat it as if they changed.
- Otherwise, return whether or not the hashsums are the same.
-
- :param path: the path to check
- :returns: boolean
- """
- template_path = get_template_path(self.template_dir, path)
- key = 'hardening:template:%s' % template_path
- template_checksum = file_hash(template_path)
- kv = unitdata.kv()
- stored_tmplt_checksum = kv.get(key)
- if not stored_tmplt_checksum:
- kv.set(key, template_checksum)
- kv.flush()
- log('Saved template checksum for %s.' % template_path,
- level=DEBUG)
- # Since we don't have a template checksum, then assume it doesn't
- # match and return that the template is different.
- return False
- elif stored_tmplt_checksum != template_checksum:
- kv.set(key, template_checksum)
- kv.flush()
- log('Updated template checksum for %s.' % template_path,
- level=DEBUG)
- return False
-
- # Here the template hasn't changed based upon the calculated
- # checksum of the template and what was previously stored.
- return True
-
- def contents_match(self, path):
- """Determines if the file content is the same.
-
- This is determined by comparing hashsum of the file contents and
- the saved hashsum. If there is no hashsum, then the content cannot
- be sure to be the same so treat them as if they are not the same.
- Otherwise, return True if the hashsums are the same, False if they
- are not the same.
-
- :param path: the file to check.
- """
- checksum = file_hash(path)
-
- kv = unitdata.kv()
- stored_checksum = kv.get('hardening:%s' % path)
- if not stored_checksum:
- # If the checksum hasn't been generated, return False to ensure
- # the file is written and the checksum stored.
- log('Checksum for %s has not been calculated.' % path, level=DEBUG)
- return False
- elif stored_checksum != checksum:
- log('Checksum mismatch for %s.' % path, level=DEBUG)
- return False
-
- return True
-
- def permissions_match(self, path):
- """Determines if the file owner and permissions match.
-
- :param path: the path to check.
- """
- audit = FilePermissionAudit(path, self.user, self.group, self.mode)
- return audit.is_compliant(path)
-
- def save_checksum(self, path):
- """Calculates and saves the checksum for the path specified.
-
- :param path: the path of the file to save the checksum.
- """
- checksum = file_hash(path)
- kv = unitdata.kv()
- kv.set('hardening:%s' % path, checksum)
- kv.flush()
-
-
-class DeletedFile(BaseFileAudit):
- """Audit to ensure that a file is deleted."""
- def __init__(self, paths):
- super(DeletedFile, self).__init__(paths)
-
- def is_compliant(self, path):
- return not os.path.exists(path)
-
- def comply(self, path):
- os.remove(path)
-
-
-class FileContentAudit(BaseFileAudit):
- """Audit the contents of a file."""
- def __init__(self, paths, cases, **kwargs):
- # Cases we expect to pass
- self.pass_cases = cases.get('pass', [])
- # Cases we expect to fail
- self.fail_cases = cases.get('fail', [])
- super(FileContentAudit, self).__init__(paths, **kwargs)
-
- def is_compliant(self, path):
- """
- Given a set of content matching cases i.e. tuple(regex, bool) where
- bool value denotes whether or not regex is expected to match, check that
- all cases match as expected with the contents of the file. Cases can be
- expected to pass of fail.
-
- :param path: Path of file to check.
- :returns: Boolean value representing whether or not all cases are
- found to be compliant.
- """
- log("Auditing contents of file '%s'" % (path), level=DEBUG)
- with open(path, 'r') as fd:
- contents = fd.read()
-
- matches = 0
- for pattern in self.pass_cases:
- key = re.compile(pattern, flags=re.MULTILINE)
- results = re.search(key, contents)
- if results:
- matches += 1
- else:
- log("Pattern '%s' was expected to pass but instead it failed"
- % (pattern), level=WARNING)
-
- for pattern in self.fail_cases:
- key = re.compile(pattern, flags=re.MULTILINE)
- results = re.search(key, contents)
- if not results:
- matches += 1
- else:
- log("Pattern '%s' was expected to fail but instead it passed"
- % (pattern), level=WARNING)
-
- total = len(self.pass_cases) + len(self.fail_cases)
- log("Checked %s cases and %s passed" % (total, matches), level=DEBUG)
- return matches == total
-
- def comply(self, *args, **kwargs):
- """NOOP since we just issue warnings. This is to avoid the
- NotImplememtedError.
- """
- log("Not applying any compliance criteria, only checks.", level=INFO)
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/__init__.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/__init__.py
+++ /dev/null
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/apache.yaml b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/apache.yaml
deleted file mode 100644
index e5ada29..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/apache.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
-# NOTE: this file contains the default configuration for the 'apache' hardening
-# code. If you want to override any settings you must add them to a file
-# called hardening.yaml in the root directory of your charm using the
-# name 'apache' as the root key followed by any of the following with new
-# values.
-
-common:
- apache_dir: '/etc/apache2'
-
-hardening:
- traceenable: 'off'
- allowed_http_methods: "GET POST"
- modules_to_disable: [ cgi, cgid ] \ No newline at end of file
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/apache.yaml.schema b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/apache.yaml.schema
deleted file mode 100644
index 227589b..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/apache.yaml.schema
+++ /dev/null
@@ -1,9 +0,0 @@
-# NOTE: this schema must contain all valid keys from it's associated defaults
-# file. It is used to validate user-provided overrides.
-common:
- apache_dir:
- traceenable:
-
-hardening:
- allowed_http_methods:
- modules_to_disable:
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/mysql.yaml b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/mysql.yaml
deleted file mode 100644
index 682d22b..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/mysql.yaml
+++ /dev/null
@@ -1,38 +0,0 @@
-# NOTE: this file contains the default configuration for the 'mysql' hardening
-# code. If you want to override any settings you must add them to a file
-# called hardening.yaml in the root directory of your charm using the
-# name 'mysql' as the root key followed by any of the following with new
-# values.
-
-hardening:
- mysql-conf: /etc/mysql/my.cnf
- hardening-conf: /etc/mysql/conf.d/hardening.cnf
-
-security:
- # @see http://www.symantec.com/connect/articles/securing-mysql-step-step
- # @see http://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_chroot
- chroot: None
-
- # @see http://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_safe-user-create
- safe-user-create: 1
-
- # @see http://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_secure-auth
- secure-auth: 1
-
- # @see http://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_symbolic-links
- skip-symbolic-links: 1
-
- # @see http://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_skip-show-database
- skip-show-database: True
-
- # @see http://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_local_infile
- local-infile: 0
-
- # @see https://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_allow-suspicious-udfs
- allow-suspicious-udfs: 0
-
- # @see https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_automatic_sp_privileges
- automatic-sp-privileges: 0
-
- # @see https://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_secure-file-priv
- secure-file-priv: /tmp
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/mysql.yaml.schema b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/mysql.yaml.schema
deleted file mode 100644
index 2edf325..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/mysql.yaml.schema
+++ /dev/null
@@ -1,15 +0,0 @@
-# NOTE: this schema must contain all valid keys from it's associated defaults
-# file. It is used to validate user-provided overrides.
-hardening:
- mysql-conf:
- hardening-conf:
-security:
- chroot:
- safe-user-create:
- secure-auth:
- skip-symbolic-links:
- skip-show-database:
- local-infile:
- allow-suspicious-udfs:
- automatic-sp-privileges:
- secure-file-priv:
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/os.yaml b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/os.yaml
deleted file mode 100644
index ddd4286..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/os.yaml
+++ /dev/null
@@ -1,67 +0,0 @@
-# NOTE: this file contains the default configuration for the 'os' hardening
-# code. If you want to override any settings you must add them to a file
-# called hardening.yaml in the root directory of your charm using the
-# name 'os' as the root key followed by any of the following with new
-# values.
-
-general:
- desktop_enable: False # (type:boolean)
-
-environment:
- extra_user_paths: []
- umask: 027
- root_path: /
-
-auth:
- pw_max_age: 60
- # discourage password cycling
- pw_min_age: 7
- retries: 5
- lockout_time: 600
- timeout: 60
- allow_homeless: False # (type:boolean)
- pam_passwdqc_enable: True # (type:boolean)
- pam_passwdqc_options: 'min=disabled,disabled,16,12,8'
- root_ttys:
- console
- tty1
- tty2
- tty3
- tty4
- tty5
- tty6
- uid_min: 1000
- gid_min: 1000
- sys_uid_min: 100
- sys_uid_max: 999
- sys_gid_min: 100
- sys_gid_max: 999
- chfn_restrict:
-
-security:
- users_allow: []
- suid_sgid_enforce: True # (type:boolean)
- # user-defined blacklist and whitelist
- suid_sgid_blacklist: []
- suid_sgid_whitelist: []
- # if this is True, remove any suid/sgid bits from files that were not in the whitelist
- suid_sgid_dry_run_on_unknown: False # (type:boolean)
- suid_sgid_remove_from_unknown: False # (type:boolean)
- # remove packages with known issues
- packages_clean: True # (type:boolean)
- packages_list:
- xinetd
- inetd
- ypserv
- telnet-server
- rsh-server
- rsync
- kernel_enable_module_loading: True # (type:boolean)
- kernel_enable_core_dump: False # (type:boolean)
-
-sysctl:
- kernel_secure_sysrq: 244 # 4 + 16 + 32 + 64 + 128
- kernel_enable_sysrq: False # (type:boolean)
- forwarding: False # (type:boolean)
- ipv6_enable: False # (type:boolean)
- arp_restricted: True # (type:boolean)
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/os.yaml.schema b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/os.yaml.schema
deleted file mode 100644
index 88b3966..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/os.yaml.schema
+++ /dev/null
@@ -1,42 +0,0 @@
-# NOTE: this schema must contain all valid keys from it's associated defaults
-# file. It is used to validate user-provided overrides.
-general:
- desktop_enable:
-environment:
- extra_user_paths:
- umask:
- root_path:
-auth:
- pw_max_age:
- pw_min_age:
- retries:
- lockout_time:
- timeout:
- allow_homeless:
- pam_passwdqc_enable:
- pam_passwdqc_options:
- root_ttys:
- uid_min:
- gid_min:
- sys_uid_min:
- sys_uid_max:
- sys_gid_min:
- sys_gid_max:
- chfn_restrict:
-security:
- users_allow:
- suid_sgid_enforce:
- suid_sgid_blacklist:
- suid_sgid_whitelist:
- suid_sgid_dry_run_on_unknown:
- suid_sgid_remove_from_unknown:
- packages_clean:
- packages_list:
- kernel_enable_module_loading:
- kernel_enable_core_dump:
-sysctl:
- kernel_secure_sysrq:
- kernel_enable_sysrq:
- forwarding:
- ipv6_enable:
- arp_restricted:
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/ssh.yaml b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/ssh.yaml
deleted file mode 100644
index cd529bc..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/ssh.yaml
+++ /dev/null
@@ -1,49 +0,0 @@
-# NOTE: this file contains the default configuration for the 'ssh' hardening
-# code. If you want to override any settings you must add them to a file
-# called hardening.yaml in the root directory of your charm using the
-# name 'ssh' as the root key followed by any of the following with new
-# values.
-
-common:
- service_name: 'ssh'
- network_ipv6_enable: False # (type:boolean)
- ports: [22]
- remote_hosts: []
-
-client:
- package: 'openssh-client'
- cbc_required: False # (type:boolean)
- weak_hmac: False # (type:boolean)
- weak_kex: False # (type:boolean)
- roaming: False
- password_authentication: 'no'
-
-server:
- host_key_files: ['/etc/ssh/ssh_host_rsa_key', '/etc/ssh/ssh_host_dsa_key',
- '/etc/ssh/ssh_host_ecdsa_key']
- cbc_required: False # (type:boolean)
- weak_hmac: False # (type:boolean)
- weak_kex: False # (type:boolean)
- allow_root_with_key: False # (type:boolean)
- allow_tcp_forwarding: 'no'
- allow_agent_forwarding: 'no'
- allow_x11_forwarding: 'no'
- use_privilege_separation: 'sandbox'
- listen_to: ['0.0.0.0']
- use_pam: 'no'
- package: 'openssh-server'
- password_authentication: 'no'
- alive_interval: '600'
- alive_count: '3'
- sftp_enable: False # (type:boolean)
- sftp_group: 'sftponly'
- sftp_chroot: '/home/%u'
- deny_users: []
- allow_users: []
- deny_groups: []
- allow_groups: []
- print_motd: 'no'
- print_last_log: 'no'
- use_dns: 'no'
- max_auth_tries: 2
- max_sessions: 10
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/ssh.yaml.schema b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/ssh.yaml.schema
deleted file mode 100644
index d05e054..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/defaults/ssh.yaml.schema
+++ /dev/null
@@ -1,42 +0,0 @@
-# NOTE: this schema must contain all valid keys from it's associated defaults
-# file. It is used to validate user-provided overrides.
-common:
- service_name:
- network_ipv6_enable:
- ports:
- remote_hosts:
-client:
- package:
- cbc_required:
- weak_hmac:
- weak_kex:
- roaming:
- password_authentication:
-server:
- host_key_files:
- cbc_required:
- weak_hmac:
- weak_kex:
- allow_root_with_key:
- allow_tcp_forwarding:
- allow_agent_forwarding:
- allow_x11_forwarding:
- use_privilege_separation:
- listen_to:
- use_pam:
- package:
- password_authentication:
- alive_interval:
- alive_count:
- sftp_enable:
- sftp_group:
- sftp_chroot:
- deny_users:
- allow_users:
- deny_groups:
- allow_groups:
- print_motd:
- print_last_log:
- use_dns:
- max_auth_tries:
- max_sessions:
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/harden.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/harden.py
deleted file mode 100644
index ac7568d..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/harden.py
+++ /dev/null
@@ -1,84 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-import six
-
-from collections import OrderedDict
-
-from charmhelpers.core.hookenv import (
- config,
- log,
- DEBUG,
- WARNING,
-)
-from charmhelpers.contrib.hardening.host.checks import run_os_checks
-from charmhelpers.contrib.hardening.ssh.checks import run_ssh_checks
-from charmhelpers.contrib.hardening.mysql.checks import run_mysql_checks
-from charmhelpers.contrib.hardening.apache.checks import run_apache_checks
-
-
-def harden(overrides=None):
- """Hardening decorator.
-
- This is the main entry point for running the hardening stack. In order to
- run modules of the stack you must add this decorator to charm hook(s) and
- ensure that your charm config.yaml contains the 'harden' option set to
- one or more of the supported modules. Setting these will cause the
- corresponding hardening code to be run when the hook fires.
-
- This decorator can and should be applied to more than one hook or function
- such that hardening modules are called multiple times. This is because
- subsequent calls will perform auditing checks that will report any changes
- to resources hardened by the first run (and possibly perform compliance
- actions as a result of any detected infractions).
-
- :param overrides: Optional list of stack modules used to override those
- provided with 'harden' config.
- :returns: Returns value returned by decorated function once executed.
- """
- def _harden_inner1(f):
- log("Hardening function '%s'" % (f.__name__), level=DEBUG)
-
- def _harden_inner2(*args, **kwargs):
- RUN_CATALOG = OrderedDict([('os', run_os_checks),
- ('ssh', run_ssh_checks),
- ('mysql', run_mysql_checks),
- ('apache', run_apache_checks)])
-
- enabled = overrides or (config("harden") or "").split()
- if enabled:
- modules_to_run = []
- # modules will always be performed in the following order
- for module, func in six.iteritems(RUN_CATALOG):
- if module in enabled:
- enabled.remove(module)
- modules_to_run.append(func)
-
- if enabled:
- log("Unknown hardening modules '%s' - ignoring" %
- (', '.join(enabled)), level=WARNING)
-
- for hardener in modules_to_run:
- log("Executing hardening module '%s'" %
- (hardener.__name__), level=DEBUG)
- hardener()
- else:
- log("No hardening applied to '%s'" % (f.__name__), level=DEBUG)
-
- return f(*args, **kwargs)
- return _harden_inner2
-
- return _harden_inner1
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/__init__.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/__init__.py
deleted file mode 100644
index 277b8c7..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-from os import path
-
-TEMPLATES_DIR = path.join(path.dirname(__file__), 'templates')
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/__init__.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/__init__.py
deleted file mode 100644
index c3bd598..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/__init__.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-from charmhelpers.core.hookenv import (
- log,
- DEBUG,
-)
-from charmhelpers.contrib.hardening.host.checks import (
- apt,
- limits,
- login,
- minimize_access,
- pam,
- profile,
- securetty,
- suid_sgid,
- sysctl
-)
-
-
-def run_os_checks():
- log("Starting OS hardening checks.", level=DEBUG)
- checks = apt.get_audits()
- checks.extend(limits.get_audits())
- checks.extend(login.get_audits())
- checks.extend(minimize_access.get_audits())
- checks.extend(pam.get_audits())
- checks.extend(profile.get_audits())
- checks.extend(securetty.get_audits())
- checks.extend(suid_sgid.get_audits())
- checks.extend(sysctl.get_audits())
-
- for check in checks:
- log("Running '%s' check" % (check.__class__.__name__), level=DEBUG)
- check.ensure_compliance()
-
- log("OS hardening checks complete.", level=DEBUG)
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/apt.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/apt.py
deleted file mode 100644
index 2c221cd..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/apt.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-from charmhelpers.contrib.hardening.utils import get_settings
-from charmhelpers.contrib.hardening.audits.apt import (
- AptConfig,
- RestrictedPackages,
-)
-
-
-def get_audits():
- """Get OS hardening apt audits.
-
- :returns: dictionary of audits
- """
- audits = [AptConfig([{'key': 'APT::Get::AllowUnauthenticated',
- 'expected': 'false'}])]
-
- settings = get_settings('os')
- clean_packages = settings['security']['packages_clean']
- if clean_packages:
- security_packages = settings['security']['packages_list']
- if security_packages:
- audits.append(RestrictedPackages(security_packages))
-
- return audits
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/limits.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/limits.py
deleted file mode 100644
index 8ce9dc2..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/limits.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-from charmhelpers.contrib.hardening.audits.file import (
- DirectoryPermissionAudit,
- TemplatedFile,
-)
-from charmhelpers.contrib.hardening.host import TEMPLATES_DIR
-from charmhelpers.contrib.hardening import utils
-
-
-def get_audits():
- """Get OS hardening security limits audits.
-
- :returns: dictionary of audits
- """
- audits = []
- settings = utils.get_settings('os')
-
- # Ensure that the /etc/security/limits.d directory is only writable
- # by the root user, but others can execute and read.
- audits.append(DirectoryPermissionAudit('/etc/security/limits.d',
- user='root', group='root',
- mode=0o755))
-
- # If core dumps are not enabled, then don't allow core dumps to be
- # created as they may contain sensitive information.
- if not settings['security']['kernel_enable_core_dump']:
- audits.append(TemplatedFile('/etc/security/limits.d/10.hardcore.conf',
- SecurityLimitsContext(),
- template_dir=TEMPLATES_DIR,
- user='root', group='root', mode=0o0440))
- return audits
-
-
-class SecurityLimitsContext(object):
-
- def __call__(self):
- settings = utils.get_settings('os')
- ctxt = {'disable_core_dump':
- not settings['security']['kernel_enable_core_dump']}
- return ctxt
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/login.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/login.py
deleted file mode 100644
index d32c4f6..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/login.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-from six import string_types
-
-from charmhelpers.contrib.hardening.audits.file import TemplatedFile
-from charmhelpers.contrib.hardening.host import TEMPLATES_DIR
-from charmhelpers.contrib.hardening import utils
-
-
-def get_audits():
- """Get OS hardening login.defs audits.
-
- :returns: dictionary of audits
- """
- audits = [TemplatedFile('/etc/login.defs', LoginContext(),
- template_dir=TEMPLATES_DIR,
- user='root', group='root', mode=0o0444)]
- return audits
-
-
-class LoginContext(object):
-
- def __call__(self):
- settings = utils.get_settings('os')
-
- # Octal numbers in yaml end up being turned into decimal,
- # so check if the umask is entered as a string (e.g. '027')
- # or as an octal umask as we know it (e.g. 002). If its not
- # a string assume it to be octal and turn it into an octal
- # string.
- umask = settings['environment']['umask']
- if not isinstance(umask, string_types):
- umask = '%s' % oct(umask)
-
- ctxt = {
- 'additional_user_paths':
- settings['environment']['extra_user_paths'],
- 'umask': umask,
- 'pwd_max_age': settings['auth']['pw_max_age'],
- 'pwd_min_age': settings['auth']['pw_min_age'],
- 'uid_min': settings['auth']['uid_min'],
- 'sys_uid_min': settings['auth']['sys_uid_min'],
- 'sys_uid_max': settings['auth']['sys_uid_max'],
- 'gid_min': settings['auth']['gid_min'],
- 'sys_gid_min': settings['auth']['sys_gid_min'],
- 'sys_gid_max': settings['auth']['sys_gid_max'],
- 'login_retries': settings['auth']['retries'],
- 'login_timeout': settings['auth']['timeout'],
- 'chfn_restrict': settings['auth']['chfn_restrict'],
- 'allow_login_without_home': settings['auth']['allow_homeless']
- }
-
- return ctxt
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/minimize_access.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/minimize_access.py
deleted file mode 100644
index c471064..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/minimize_access.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-from charmhelpers.contrib.hardening.audits.file import (
- FilePermissionAudit,
- ReadOnly,
-)
-from charmhelpers.contrib.hardening import utils
-
-
-def get_audits():
- """Get OS hardening access audits.
-
- :returns: dictionary of audits
- """
- audits = []
- settings = utils.get_settings('os')
-
- # Remove write permissions from $PATH folders for all regular users.
- # This prevents changing system-wide commands from normal users.
- path_folders = {'/usr/local/sbin',
- '/usr/local/bin',
- '/usr/sbin',
- '/usr/bin',
- '/bin'}
- extra_user_paths = settings['environment']['extra_user_paths']
- path_folders.update(extra_user_paths)
- audits.append(ReadOnly(path_folders))
-
- # Only allow the root user to have access to the shadow file.
- audits.append(FilePermissionAudit('/etc/shadow', 'root', 'root', 0o0600))
-
- if 'change_user' not in settings['security']['users_allow']:
- # su should only be accessible to user and group root, unless it is
- # expressly defined to allow users to change to root via the
- # security_users_allow config option.
- audits.append(FilePermissionAudit('/bin/su', 'root', 'root', 0o750))
-
- return audits
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/pam.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/pam.py
deleted file mode 100644
index 383fe28..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/pam.py
+++ /dev/null
@@ -1,134 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-from subprocess import (
- check_output,
- CalledProcessError,
-)
-
-from charmhelpers.core.hookenv import (
- log,
- DEBUG,
- ERROR,
-)
-from charmhelpers.fetch import (
- apt_install,
- apt_purge,
- apt_update,
-)
-from charmhelpers.contrib.hardening.audits.file import (
- TemplatedFile,
- DeletedFile,
-)
-from charmhelpers.contrib.hardening import utils
-from charmhelpers.contrib.hardening.host import TEMPLATES_DIR
-
-
-def get_audits():
- """Get OS hardening PAM authentication audits.
-
- :returns: dictionary of audits
- """
- audits = []
-
- settings = utils.get_settings('os')
-
- if settings['auth']['pam_passwdqc_enable']:
- audits.append(PasswdqcPAM('/etc/passwdqc.conf'))
-
- if settings['auth']['retries']:
- audits.append(Tally2PAM('/usr/share/pam-configs/tally2'))
- else:
- audits.append(DeletedFile('/usr/share/pam-configs/tally2'))
-
- return audits
-
-
-class PasswdqcPAMContext(object):
-
- def __call__(self):
- ctxt = {}
- settings = utils.get_settings('os')
-
- ctxt['auth_pam_passwdqc_options'] = \
- settings['auth']['pam_passwdqc_options']
-
- return ctxt
-
-
-class PasswdqcPAM(TemplatedFile):
- """The PAM Audit verifies the linux PAM settings."""
- def __init__(self, path):
- super(PasswdqcPAM, self).__init__(path=path,
- template_dir=TEMPLATES_DIR,
- context=PasswdqcPAMContext(),
- user='root',
- group='root',
- mode=0o0640)
-
- def pre_write(self):
- # Always remove?
- for pkg in ['libpam-ccreds', 'libpam-cracklib']:
- log("Purging package '%s'" % pkg, level=DEBUG),
- apt_purge(pkg)
-
- apt_update(fatal=True)
- for pkg in ['libpam-passwdqc']:
- log("Installing package '%s'" % pkg, level=DEBUG),
- apt_install(pkg)
-
- def post_write(self):
- """Updates the PAM configuration after the file has been written"""
- try:
- check_output(['pam-auth-update', '--package'])
- except CalledProcessError as e:
- log('Error calling pam-auth-update: %s' % e, level=ERROR)
-
-
-class Tally2PAMContext(object):
-
- def __call__(self):
- ctxt = {}
- settings = utils.get_settings('os')
-
- ctxt['auth_lockout_time'] = settings['auth']['lockout_time']
- ctxt['auth_retries'] = settings['auth']['retries']
-
- return ctxt
-
-
-class Tally2PAM(TemplatedFile):
- """The PAM Audit verifies the linux PAM settings."""
- def __init__(self, path):
- super(Tally2PAM, self).__init__(path=path,
- template_dir=TEMPLATES_DIR,
- context=Tally2PAMContext(),
- user='root',
- group='root',
- mode=0o0640)
-
- def pre_write(self):
- # Always remove?
- apt_purge('libpam-ccreds')
- apt_update(fatal=True)
- apt_install('libpam-modules')
-
- def post_write(self):
- """Updates the PAM configuration after the file has been written"""
- try:
- check_output(['pam-auth-update', '--package'])
- except CalledProcessError as e:
- log('Error calling pam-auth-update: %s' % e, level=ERROR)
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/profile.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/profile.py
deleted file mode 100644
index f744335..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/profile.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-from charmhelpers.contrib.hardening.audits.file import TemplatedFile
-from charmhelpers.contrib.hardening.host import TEMPLATES_DIR
-from charmhelpers.contrib.hardening import utils
-
-
-def get_audits():
- """Get OS hardening profile audits.
-
- :returns: dictionary of audits
- """
- audits = []
-
- settings = utils.get_settings('os')
-
- # If core dumps are not enabled, then don't allow core dumps to be
- # created as they may contain sensitive information.
- if not settings['security']['kernel_enable_core_dump']:
- audits.append(TemplatedFile('/etc/profile.d/pinerolo_profile.sh',
- ProfileContext(),
- template_dir=TEMPLATES_DIR,
- mode=0o0755, user='root', group='root'))
- return audits
-
-
-class ProfileContext(object):
-
- def __call__(self):
- ctxt = {}
- return ctxt
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/securetty.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/securetty.py
deleted file mode 100644
index e33c73c..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/securetty.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-from charmhelpers.contrib.hardening.audits.file import TemplatedFile
-from charmhelpers.contrib.hardening.host import TEMPLATES_DIR
-from charmhelpers.contrib.hardening import utils
-
-
-def get_audits():
- """Get OS hardening Secure TTY audits.
-
- :returns: dictionary of audits
- """
- audits = []
- audits.append(TemplatedFile('/etc/securetty', SecureTTYContext(),
- template_dir=TEMPLATES_DIR,
- mode=0o0400, user='root', group='root'))
- return audits
-
-
-class SecureTTYContext(object):
-
- def __call__(self):
- settings = utils.get_settings('os')
- ctxt = {'ttys': settings['auth']['root_ttys']}
- return ctxt
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/suid_sgid.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/suid_sgid.py
deleted file mode 100644
index 0534689..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/suid_sgid.py
+++ /dev/null
@@ -1,131 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-import subprocess
-
-from charmhelpers.core.hookenv import (
- log,
- INFO,
-)
-from charmhelpers.contrib.hardening.audits.file import NoSUIDSGIDAudit
-from charmhelpers.contrib.hardening import utils
-
-
-BLACKLIST = ['/usr/bin/rcp', '/usr/bin/rlogin', '/usr/bin/rsh',
- '/usr/libexec/openssh/ssh-keysign',
- '/usr/lib/openssh/ssh-keysign',
- '/sbin/netreport',
- '/usr/sbin/usernetctl',
- '/usr/sbin/userisdnctl',
- '/usr/sbin/pppd',
- '/usr/bin/lockfile',
- '/usr/bin/mail-lock',
- '/usr/bin/mail-unlock',
- '/usr/bin/mail-touchlock',
- '/usr/bin/dotlockfile',
- '/usr/bin/arping',
- '/usr/sbin/uuidd',
- '/usr/bin/mtr',
- '/usr/lib/evolution/camel-lock-helper-1.2',
- '/usr/lib/pt_chown',
- '/usr/lib/eject/dmcrypt-get-device',
- '/usr/lib/mc/cons.saver']
-
-WHITELIST = ['/bin/mount', '/bin/ping', '/bin/su', '/bin/umount',
- '/sbin/pam_timestamp_check', '/sbin/unix_chkpwd', '/usr/bin/at',
- '/usr/bin/gpasswd', '/usr/bin/locate', '/usr/bin/newgrp',
- '/usr/bin/passwd', '/usr/bin/ssh-agent',
- '/usr/libexec/utempter/utempter', '/usr/sbin/lockdev',
- '/usr/sbin/sendmail.sendmail', '/usr/bin/expiry',
- '/bin/ping6', '/usr/bin/traceroute6.iputils',
- '/sbin/mount.nfs', '/sbin/umount.nfs',
- '/sbin/mount.nfs4', '/sbin/umount.nfs4',
- '/usr/bin/crontab',
- '/usr/bin/wall', '/usr/bin/write',
- '/usr/bin/screen',
- '/usr/bin/mlocate',
- '/usr/bin/chage', '/usr/bin/chfn', '/usr/bin/chsh',
- '/bin/fusermount',
- '/usr/bin/pkexec',
- '/usr/bin/sudo', '/usr/bin/sudoedit',
- '/usr/sbin/postdrop', '/usr/sbin/postqueue',
- '/usr/sbin/suexec',
- '/usr/lib/squid/ncsa_auth', '/usr/lib/squid/pam_auth',
- '/usr/kerberos/bin/ksu',
- '/usr/sbin/ccreds_validate',
- '/usr/bin/Xorg',
- '/usr/bin/X',
- '/usr/lib/dbus-1.0/dbus-daemon-launch-helper',
- '/usr/lib/vte/gnome-pty-helper',
- '/usr/lib/libvte9/gnome-pty-helper',
- '/usr/lib/libvte-2.90-9/gnome-pty-helper']
-
-
-def get_audits():
- """Get OS hardening suid/sgid audits.
-
- :returns: dictionary of audits
- """
- checks = []
- settings = utils.get_settings('os')
- if not settings['security']['suid_sgid_enforce']:
- log("Skipping suid/sgid hardening", level=INFO)
- return checks
-
- # Build the blacklist and whitelist of files for suid/sgid checks.
- # There are a total of 4 lists:
- # 1. the system blacklist
- # 2. the system whitelist
- # 3. the user blacklist
- # 4. the user whitelist
- #
- # The blacklist is the set of paths which should NOT have the suid/sgid bit
- # set and the whitelist is the set of paths which MAY have the suid/sgid
- # bit setl. The user whitelist/blacklist effectively override the system
- # whitelist/blacklist.
- u_b = settings['security']['suid_sgid_blacklist']
- u_w = settings['security']['suid_sgid_whitelist']
-
- blacklist = set(BLACKLIST) - set(u_w + u_b)
- whitelist = set(WHITELIST) - set(u_b + u_w)
-
- checks.append(NoSUIDSGIDAudit(blacklist))
-
- dry_run = settings['security']['suid_sgid_dry_run_on_unknown']
-
- if settings['security']['suid_sgid_remove_from_unknown'] or dry_run:
- # If the policy is a dry_run (e.g. complain only) or remove unknown
- # suid/sgid bits then find all of the paths which have the suid/sgid
- # bit set and then remove the whitelisted paths.
- root_path = settings['environment']['root_path']
- unknown_paths = find_paths_with_suid_sgid(root_path) - set(whitelist)
- checks.append(NoSUIDSGIDAudit(unknown_paths, unless=dry_run))
-
- return checks
-
-
-def find_paths_with_suid_sgid(root_path):
- """Finds all paths/files which have an suid/sgid bit enabled.
-
- Starting with the root_path, this will recursively find all paths which
- have an suid or sgid bit set.
- """
- cmd = ['find', root_path, '-perm', '-4000', '-o', '-perm', '-2000',
- '-type', 'f', '!', '-path', '/proc/*', '-print']
-
- p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- out, _ = p.communicate()
- return set(out.split('\n'))
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/sysctl.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/sysctl.py
deleted file mode 100644
index 4a76d74..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/checks/sysctl.py
+++ /dev/null
@@ -1,211 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-import os
-import platform
-import re
-import six
-import subprocess
-
-from charmhelpers.core.hookenv import (
- log,
- INFO,
- WARNING,
-)
-from charmhelpers.contrib.hardening import utils
-from charmhelpers.contrib.hardening.audits.file import (
- FilePermissionAudit,
- TemplatedFile,
-)
-from charmhelpers.contrib.hardening.host import TEMPLATES_DIR
-
-
-SYSCTL_DEFAULTS = """net.ipv4.ip_forward=%(net_ipv4_ip_forward)s
-net.ipv6.conf.all.forwarding=%(net_ipv6_conf_all_forwarding)s
-net.ipv4.conf.all.rp_filter=1
-net.ipv4.conf.default.rp_filter=1
-net.ipv4.icmp_echo_ignore_broadcasts=1
-net.ipv4.icmp_ignore_bogus_error_responses=1
-net.ipv4.icmp_ratelimit=100
-net.ipv4.icmp_ratemask=88089
-net.ipv6.conf.all.disable_ipv6=%(net_ipv6_conf_all_disable_ipv6)s
-net.ipv4.tcp_timestamps=%(net_ipv4_tcp_timestamps)s
-net.ipv4.conf.all.arp_ignore=%(net_ipv4_conf_all_arp_ignore)s
-net.ipv4.conf.all.arp_announce=%(net_ipv4_conf_all_arp_announce)s
-net.ipv4.tcp_rfc1337=1
-net.ipv4.tcp_syncookies=1
-net.ipv4.conf.all.shared_media=1
-net.ipv4.conf.default.shared_media=1
-net.ipv4.conf.all.accept_source_route=0
-net.ipv4.conf.default.accept_source_route=0
-net.ipv4.conf.all.accept_redirects=0
-net.ipv4.conf.default.accept_redirects=0
-net.ipv6.conf.all.accept_redirects=0
-net.ipv6.conf.default.accept_redirects=0
-net.ipv4.conf.all.secure_redirects=0
-net.ipv4.conf.default.secure_redirects=0
-net.ipv4.conf.all.send_redirects=0
-net.ipv4.conf.default.send_redirects=0
-net.ipv4.conf.all.log_martians=0
-net.ipv6.conf.default.router_solicitations=0
-net.ipv6.conf.default.accept_ra_rtr_pref=0
-net.ipv6.conf.default.accept_ra_pinfo=0
-net.ipv6.conf.default.accept_ra_defrtr=0
-net.ipv6.conf.default.autoconf=0
-net.ipv6.conf.default.dad_transmits=0
-net.ipv6.conf.default.max_addresses=1
-net.ipv6.conf.all.accept_ra=0
-net.ipv6.conf.default.accept_ra=0
-kernel.modules_disabled=%(kernel_modules_disabled)s
-kernel.sysrq=%(kernel_sysrq)s
-fs.suid_dumpable=%(fs_suid_dumpable)s
-kernel.randomize_va_space=2
-"""
-
-
-def get_audits():
- """Get OS hardening sysctl audits.
-
- :returns: dictionary of audits
- """
- audits = []
- settings = utils.get_settings('os')
-
- # Apply the sysctl settings which are configured to be applied.
- audits.append(SysctlConf())
- # Make sure that only root has access to the sysctl.conf file, and
- # that it is read-only.
- audits.append(FilePermissionAudit('/etc/sysctl.conf',
- user='root',
- group='root', mode=0o0440))
- # If module loading is not enabled, then ensure that the modules
- # file has the appropriate permissions and rebuild the initramfs
- if not settings['security']['kernel_enable_module_loading']:
- audits.append(ModulesTemplate())
-
- return audits
-
-
-class ModulesContext(object):
-
- def __call__(self):
- settings = utils.get_settings('os')
- with open('/proc/cpuinfo', 'r') as fd:
- cpuinfo = fd.readlines()
-
- for line in cpuinfo:
- match = re.search(r"^vendor_id\s+:\s+(.+)", line)
- if match:
- vendor = match.group(1)
-
- if vendor == "GenuineIntel":
- vendor = "intel"
- elif vendor == "AuthenticAMD":
- vendor = "amd"
-
- ctxt = {'arch': platform.processor(),
- 'cpuVendor': vendor,
- 'desktop_enable': settings['general']['desktop_enable']}
-
- return ctxt
-
-
-class ModulesTemplate(object):
-
- def __init__(self):
- super(ModulesTemplate, self).__init__('/etc/initramfs-tools/modules',
- ModulesContext(),
- templates_dir=TEMPLATES_DIR,
- user='root', group='root',
- mode=0o0440)
-
- def post_write(self):
- subprocess.check_call(['update-initramfs', '-u'])
-
-
-class SysCtlHardeningContext(object):
- def __call__(self):
- settings = utils.get_settings('os')
- ctxt = {'sysctl': {}}
-
- log("Applying sysctl settings", level=INFO)
- extras = {'net_ipv4_ip_forward': 0,
- 'net_ipv6_conf_all_forwarding': 0,
- 'net_ipv6_conf_all_disable_ipv6': 1,
- 'net_ipv4_tcp_timestamps': 0,
- 'net_ipv4_conf_all_arp_ignore': 0,
- 'net_ipv4_conf_all_arp_announce': 0,
- 'kernel_sysrq': 0,
- 'fs_suid_dumpable': 0,
- 'kernel_modules_disabled': 1}
-
- if settings['sysctl']['ipv6_enable']:
- extras['net_ipv6_conf_all_disable_ipv6'] = 0
-
- if settings['sysctl']['forwarding']:
- extras['net_ipv4_ip_forward'] = 1
- extras['net_ipv6_conf_all_forwarding'] = 1
-
- if settings['sysctl']['arp_restricted']:
- extras['net_ipv4_conf_all_arp_ignore'] = 1
- extras['net_ipv4_conf_all_arp_announce'] = 2
-
- if settings['security']['kernel_enable_module_loading']:
- extras['kernel_modules_disabled'] = 0
-
- if settings['sysctl']['kernel_enable_sysrq']:
- sysrq_val = settings['sysctl']['kernel_secure_sysrq']
- extras['kernel_sysrq'] = sysrq_val
-
- if settings['security']['kernel_enable_core_dump']:
- extras['fs_suid_dumpable'] = 1
-
- settings.update(extras)
- for d in (SYSCTL_DEFAULTS % settings).split():
- d = d.strip().partition('=')
- key = d[0].strip()
- path = os.path.join('/proc/sys', key.replace('.', '/'))
- if not os.path.exists(path):
- log("Skipping '%s' since '%s' does not exist" % (key, path),
- level=WARNING)
- continue
-
- ctxt['sysctl'][key] = d[2] or None
-
- # Translate for python3
- return {'sysctl_settings':
- [(k, v) for k, v in six.iteritems(ctxt['sysctl'])]}
-
-
-class SysctlConf(TemplatedFile):
- """An audit check for sysctl settings."""
- def __init__(self):
- self.conffile = '/etc/sysctl.d/99-juju-hardening.conf'
- super(SysctlConf, self).__init__(self.conffile,
- SysCtlHardeningContext(),
- template_dir=TEMPLATES_DIR,
- user='root', group='root',
- mode=0o0440)
-
- def post_write(self):
- try:
- subprocess.check_call(['sysctl', '-p', self.conffile])
- except subprocess.CalledProcessError as e:
- # NOTE: on some systems if sysctl cannot apply all settings it
- # will return non-zero as well.
- log("sysctl command returned an error (maybe some "
- "keys could not be set) - %s" % (e),
- level=WARNING)
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/10.hardcore.conf b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/10.hardcore.conf
deleted file mode 100644
index 0014191..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/10.hardcore.conf
+++ /dev/null
@@ -1,8 +0,0 @@
-###############################################################################
-# WARNING: This configuration file is maintained by Juju. Local changes may
-# be overwritten.
-###############################################################################
-{% if disable_core_dump -%}
-# Prevent core dumps for all users. These are usually only needed by developers and may contain sensitive information.
-* hard core 0
-{% endif %} \ No newline at end of file
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/99-juju-hardening.conf b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/99-juju-hardening.conf
deleted file mode 100644
index 101f1e1..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/99-juju-hardening.conf
+++ /dev/null
@@ -1,7 +0,0 @@
-###############################################################################
-# WARNING: This configuration file is maintained by Juju. Local changes may
-# be overwritten.
-###############################################################################
-{% for key, value in sysctl_settings -%}
-{{ key }}={{ value }}
-{% endfor -%}
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/__init__.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/__init__.py
+++ /dev/null
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/login.defs b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/login.defs
deleted file mode 100644
index db137d6..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/login.defs
+++ /dev/null
@@ -1,349 +0,0 @@
-###############################################################################
-# WARNING: This configuration file is maintained by Juju. Local changes may
-# be overwritten.
-###############################################################################
-#
-# /etc/login.defs - Configuration control definitions for the login package.
-#
-# Three items must be defined: MAIL_DIR, ENV_SUPATH, and ENV_PATH.
-# If unspecified, some arbitrary (and possibly incorrect) value will
-# be assumed. All other items are optional - if not specified then
-# the described action or option will be inhibited.
-#
-# Comment lines (lines beginning with "#") and blank lines are ignored.
-#
-# Modified for Linux. --marekm
-
-# REQUIRED for useradd/userdel/usermod
-# Directory where mailboxes reside, _or_ name of file, relative to the
-# home directory. If you _do_ define MAIL_DIR and MAIL_FILE,
-# MAIL_DIR takes precedence.
-#
-# Essentially:
-# - MAIL_DIR defines the location of users mail spool files
-# (for mbox use) by appending the username to MAIL_DIR as defined
-# below.
-# - MAIL_FILE defines the location of the users mail spool files as the
-# fully-qualified filename obtained by prepending the user home
-# directory before $MAIL_FILE
-#
-# NOTE: This is no more used for setting up users MAIL environment variable
-# which is, starting from shadow 4.0.12-1 in Debian, entirely the
-# job of the pam_mail PAM modules
-# See default PAM configuration files provided for
-# login, su, etc.
-#
-# This is a temporary situation: setting these variables will soon
-# move to /etc/default/useradd and the variables will then be
-# no more supported
-MAIL_DIR /var/mail
-#MAIL_FILE .mail
-
-#
-# Enable logging and display of /var/log/faillog login failure info.
-# This option conflicts with the pam_tally PAM module.
-#
-FAILLOG_ENAB yes
-
-#
-# Enable display of unknown usernames when login failures are recorded.
-#
-# WARNING: Unknown usernames may become world readable.
-# See #290803 and #298773 for details about how this could become a security
-# concern
-LOG_UNKFAIL_ENAB no
-
-#
-# Enable logging of successful logins
-#
-LOG_OK_LOGINS yes
-
-#
-# Enable "syslog" logging of su activity - in addition to sulog file logging.
-# SYSLOG_SG_ENAB does the same for newgrp and sg.
-#
-SYSLOG_SU_ENAB yes
-SYSLOG_SG_ENAB yes
-
-#
-# If defined, all su activity is logged to this file.
-#
-#SULOG_FILE /var/log/sulog
-
-#
-# If defined, file which maps tty line to TERM environment parameter.
-# Each line of the file is in a format something like "vt100 tty01".
-#
-#TTYTYPE_FILE /etc/ttytype
-
-#
-# If defined, login failures will be logged here in a utmp format
-# last, when invoked as lastb, will read /var/log/btmp, so...
-#
-FTMP_FILE /var/log/btmp
-
-#
-# If defined, the command name to display when running "su -". For
-# example, if this is defined as "su" then a "ps" will display the
-# command is "-su". If not defined, then "ps" would display the
-# name of the shell actually being run, e.g. something like "-sh".
-#
-SU_NAME su
-
-#
-# If defined, file which inhibits all the usual chatter during the login
-# sequence. If a full pathname, then hushed mode will be enabled if the
-# user's name or shell are found in the file. If not a full pathname, then
-# hushed mode will be enabled if the file exists in the user's home directory.
-#
-HUSHLOGIN_FILE .hushlogin
-#HUSHLOGIN_FILE /etc/hushlogins
-
-#
-# *REQUIRED* The default PATH settings, for superuser and normal users.
-#
-# (they are minimal, add the rest in the shell startup files)
-ENV_SUPATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
-ENV_PATH PATH=/usr/local/bin:/usr/bin:/bin{% if additional_user_paths %}{{ additional_user_paths }}{% endif %}
-
-#
-# Terminal permissions
-#
-# TTYGROUP Login tty will be assigned this group ownership.
-# TTYPERM Login tty will be set to this permission.
-#
-# If you have a "write" program which is "setgid" to a special group
-# which owns the terminals, define TTYGROUP to the group number and
-# TTYPERM to 0620. Otherwise leave TTYGROUP commented out and assign
-# TTYPERM to either 622 or 600.
-#
-# In Debian /usr/bin/bsd-write or similar programs are setgid tty
-# However, the default and recommended value for TTYPERM is still 0600
-# to not allow anyone to write to anyone else console or terminal
-
-# Users can still allow other people to write them by issuing
-# the "mesg y" command.
-
-TTYGROUP tty
-TTYPERM 0600
-
-#
-# Login configuration initializations:
-#
-# ERASECHAR Terminal ERASE character ('\010' = backspace).
-# KILLCHAR Terminal KILL character ('\025' = CTRL/U).
-# UMASK Default "umask" value.
-#
-# The ERASECHAR and KILLCHAR are used only on System V machines.
-#
-# UMASK is the default umask value for pam_umask and is used by
-# useradd and newusers to set the mode of the new home directories.
-# 022 is the "historical" value in Debian for UMASK
-# 027, or even 077, could be considered better for privacy
-# There is no One True Answer here : each sysadmin must make up his/her
-# mind.
-#
-# If USERGROUPS_ENAB is set to "yes", that will modify this UMASK default value
-# for private user groups, i. e. the uid is the same as gid, and username is
-# the same as the primary group name: for these, the user permissions will be
-# used as group permissions, e. g. 022 will become 002.
-#
-# Prefix these values with "0" to get octal, "0x" to get hexadecimal.
-#
-ERASECHAR 0177
-KILLCHAR 025
-UMASK {{ umask }}
-
-# Enable setting of the umask group bits to be the same as owner bits (examples: `022` -> `002`, `077` -> `007`) for non-root users, if the uid is the same as gid, and username is the same as the primary group name.
-# If set to yes, userdel will remove the user´s group if it contains no more members, and useradd will create by default a group with the name of the user.
-USERGROUPS_ENAB yes
-
-#
-# Password aging controls:
-#
-# PASS_MAX_DAYS Maximum number of days a password may be used.
-# PASS_MIN_DAYS Minimum number of days allowed between password changes.
-# PASS_WARN_AGE Number of days warning given before a password expires.
-#
-PASS_MAX_DAYS {{ pwd_max_age }}
-PASS_MIN_DAYS {{ pwd_min_age }}
-PASS_WARN_AGE 7
-
-#
-# Min/max values for automatic uid selection in useradd
-#
-UID_MIN {{ uid_min }}
-UID_MAX 60000
-# System accounts
-SYS_UID_MIN {{ sys_uid_min }}
-SYS_UID_MAX {{ sys_uid_max }}
-
-# Min/max values for automatic gid selection in groupadd
-GID_MIN {{ gid_min }}
-GID_MAX 60000
-# System accounts
-SYS_GID_MIN {{ sys_gid_min }}
-SYS_GID_MAX {{ sys_gid_max }}
-
-#
-# Max number of login retries if password is bad. This will most likely be
-# overriden by PAM, since the default pam_unix module has it's own built
-# in of 3 retries. However, this is a safe fallback in case you are using
-# an authentication module that does not enforce PAM_MAXTRIES.
-#
-LOGIN_RETRIES {{ login_retries }}
-
-#
-# Max time in seconds for login
-#
-LOGIN_TIMEOUT {{ login_timeout }}
-
-#
-# Which fields may be changed by regular users using chfn - use
-# any combination of letters "frwh" (full name, room number, work
-# phone, home phone). If not defined, no changes are allowed.
-# For backward compatibility, "yes" = "rwh" and "no" = "frwh".
-#
-{% if chfn_restrict %}
-CHFN_RESTRICT {{ chfn_restrict }}
-{% endif %}
-
-#
-# Should login be allowed if we can't cd to the home directory?
-# Default in no.
-#
-DEFAULT_HOME {% if allow_login_without_home %} yes {% else %} no {% endif %}
-
-#
-# If defined, this command is run when removing a user.
-# It should remove any at/cron/print jobs etc. owned by
-# the user to be removed (passed as the first argument).
-#
-#USERDEL_CMD /usr/sbin/userdel_local
-
-#
-# Enable setting of the umask group bits to be the same as owner bits
-# (examples: 022 -> 002, 077 -> 007) for non-root users, if the uid is
-# the same as gid, and username is the same as the primary group name.
-#
-# If set to yes, userdel will remove the user´s group if it contains no
-# more members, and useradd will create by default a group with the name
-# of the user.
-#
-USERGROUPS_ENAB yes
-
-#
-# Instead of the real user shell, the program specified by this parameter
-# will be launched, although its visible name (argv[0]) will be the shell's.
-# The program may do whatever it wants (logging, additional authentification,
-# banner, ...) before running the actual shell.
-#
-# FAKE_SHELL /bin/fakeshell
-
-#
-# If defined, either full pathname of a file containing device names or
-# a ":" delimited list of device names. Root logins will be allowed only
-# upon these devices.
-#
-# This variable is used by login and su.
-#
-#CONSOLE /etc/consoles
-#CONSOLE console:tty01:tty02:tty03:tty04
-
-#
-# List of groups to add to the user's supplementary group set
-# when logging in on the console (as determined by the CONSOLE
-# setting). Default is none.
-#
-# Use with caution - it is possible for users to gain permanent
-# access to these groups, even when not logged in on the console.
-# How to do it is left as an exercise for the reader...
-#
-# This variable is used by login and su.
-#
-#CONSOLE_GROUPS floppy:audio:cdrom
-
-#
-# If set to "yes", new passwords will be encrypted using the MD5-based
-# algorithm compatible with the one used by recent releases of FreeBSD.
-# It supports passwords of unlimited length and longer salt strings.
-# Set to "no" if you need to copy encrypted passwords to other systems
-# which don't understand the new algorithm. Default is "no".
-#
-# This variable is deprecated. You should use ENCRYPT_METHOD.
-#
-MD5_CRYPT_ENAB no
-
-#
-# If set to MD5 , MD5-based algorithm will be used for encrypting password
-# If set to SHA256, SHA256-based algorithm will be used for encrypting password
-# If set to SHA512, SHA512-based algorithm will be used for encrypting password
-# If set to DES, DES-based algorithm will be used for encrypting password (default)
-# Overrides the MD5_CRYPT_ENAB option
-#
-# Note: It is recommended to use a value consistent with
-# the PAM modules configuration.
-#
-ENCRYPT_METHOD SHA512
-
-#
-# Only used if ENCRYPT_METHOD is set to SHA256 or SHA512.
-#
-# Define the number of SHA rounds.
-# With a lot of rounds, it is more difficult to brute forcing the password.
-# But note also that it more CPU resources will be needed to authenticate
-# users.
-#
-# If not specified, the libc will choose the default number of rounds (5000).
-# The values must be inside the 1000-999999999 range.
-# If only one of the MIN or MAX values is set, then this value will be used.
-# If MIN > MAX, the highest value will be used.
-#
-# SHA_CRYPT_MIN_ROUNDS 5000
-# SHA_CRYPT_MAX_ROUNDS 5000
-
-################# OBSOLETED BY PAM ##############
-# #
-# These options are now handled by PAM. Please #
-# edit the appropriate file in /etc/pam.d/ to #
-# enable the equivelants of them.
-#
-###############
-
-#MOTD_FILE
-#DIALUPS_CHECK_ENAB
-#LASTLOG_ENAB
-#MAIL_CHECK_ENAB
-#OBSCURE_CHECKS_ENAB
-#PORTTIME_CHECKS_ENAB
-#SU_WHEEL_ONLY
-#CRACKLIB_DICTPATH
-#PASS_CHANGE_TRIES
-#PASS_ALWAYS_WARN
-#ENVIRON_FILE
-#NOLOGINS_FILE
-#ISSUE_FILE
-#PASS_MIN_LEN
-#PASS_MAX_LEN
-#ULIMIT
-#ENV_HZ
-#CHFN_AUTH
-#CHSH_AUTH
-#FAIL_DELAY
-
-################# OBSOLETED #######################
-# #
-# These options are no more handled by shadow. #
-# #
-# Shadow utilities will display a warning if they #
-# still appear. #
-# #
-###################################################
-
-# CLOSE_SESSIONS
-# LOGIN_STRING
-# NO_PASSWORD_CONSOLE
-# QMAIL_DIR
-
-
-
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/modules b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/modules
deleted file mode 100644
index ef0354e..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/modules
+++ /dev/null
@@ -1,117 +0,0 @@
-###############################################################################
-# WARNING: This configuration file is maintained by Juju. Local changes may
-# be overwritten.
-###############################################################################
-# /etc/modules: kernel modules to load at boot time.
-#
-# This file contains the names of kernel modules that should be loaded
-# at boot time, one per line. Lines beginning with "#" are ignored.
-# Parameters can be specified after the module name.
-
-# Arch
-# ----
-#
-# Modules for certains builds, contains support modules and some CPU-specific optimizations.
-
-{% if arch == "x86_64" -%}
-# Optimize for x86_64 cryptographic features
-twofish-x86_64-3way
-twofish-x86_64
-aes-x86_64
-salsa20-x86_64
-blowfish-x86_64
-{% endif -%}
-
-{% if cpuVendor == "intel" -%}
-# Intel-specific optimizations
-ghash-clmulni-intel
-aesni-intel
-kvm-intel
-{% endif -%}
-
-{% if cpuVendor == "amd" -%}
-# AMD-specific optimizations
-kvm-amd
-{% endif -%}
-
-kvm
-
-
-# Crypto
-# ------
-
-# Some core modules which comprise strong cryptography.
-blowfish_common
-blowfish_generic
-ctr
-cts
-lrw
-lzo
-rmd160
-rmd256
-rmd320
-serpent
-sha512_generic
-twofish_common
-twofish_generic
-xts
-zlib
-
-
-# Drivers
-# -------
-
-# Basics
-lp
-rtc
-loop
-
-# Filesystems
-ext2
-btrfs
-
-{% if desktop_enable -%}
-# Desktop
-psmouse
-snd
-snd_ac97_codec
-snd_intel8x0
-snd_page_alloc
-snd_pcm
-snd_timer
-soundcore
-usbhid
-{% endif -%}
-
-# Lib
-# ---
-xz
-
-
-# Net
-# ---
-
-# All packets needed for netfilter rules (ie iptables, ebtables).
-ip_tables
-x_tables
-iptable_filter
-iptable_nat
-
-# Targets
-ipt_LOG
-ipt_REJECT
-
-# Modules
-xt_connlimit
-xt_tcpudp
-xt_recent
-xt_limit
-xt_conntrack
-nf_conntrack
-nf_conntrack_ipv4
-nf_defrag_ipv4
-xt_state
-nf_nat
-
-# Addons
-xt_pknock \ No newline at end of file
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/passwdqc.conf b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/passwdqc.conf
deleted file mode 100644
index f98d14e..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/passwdqc.conf
+++ /dev/null
@@ -1,11 +0,0 @@
-###############################################################################
-# WARNING: This configuration file is maintained by Juju. Local changes may
-# be overwritten.
-###############################################################################
-Name: passwdqc password strength enforcement
-Default: yes
-Priority: 1024
-Conflicts: cracklib
-Password-Type: Primary
-Password:
- requisite pam_passwdqc.so {{ auth_pam_passwdqc_options }}
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/pinerolo_profile.sh b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/pinerolo_profile.sh
deleted file mode 100644
index fd2de79..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/pinerolo_profile.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-###############################################################################
-# WARNING: This configuration file is maintained by Juju. Local changes may
-# be overwritten.
-###############################################################################
-# Disable core dumps via soft limits for all users. Compliance to this setting
-# is voluntary and can be modified by users up to a hard limit. This setting is
-# a sane default.
-ulimit -S -c 0 > /dev/null 2>&1
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/securetty b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/securetty
deleted file mode 100644
index 15b18d4..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/securetty
+++ /dev/null
@@ -1,11 +0,0 @@
-###############################################################################
-# WARNING: This configuration file is maintained by Juju. Local changes may
-# be overwritten.
-###############################################################################
-# A list of TTYs, from which root can log in
-# see `man securetty` for reference
-{% if ttys -%}
-{% for tty in ttys -%}
-{{ tty }}
-{% endfor -%}
-{% endif -%}
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/tally2 b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/tally2
deleted file mode 100644
index d962029..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/host/templates/tally2
+++ /dev/null
@@ -1,14 +0,0 @@
-###############################################################################
-# WARNING: This configuration file is maintained by Juju. Local changes may
-# be overwritten.
-###############################################################################
-Name: tally2 lockout after failed attempts enforcement
-Default: yes
-Priority: 1024
-Conflicts: cracklib
-Auth-Type: Primary
-Auth-Initial:
- required pam_tally2.so deny={{ auth_retries }} onerr=fail unlock_time={{ auth_lockout_time }}
-Account-Type: Primary
-Account-Initial:
- required pam_tally2.so
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/__init__.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/__init__.py
deleted file mode 100644
index 277b8c7..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-from os import path
-
-TEMPLATES_DIR = path.join(path.dirname(__file__), 'templates')
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/checks/__init__.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/checks/__init__.py
deleted file mode 100644
index d4f0ec1..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/checks/__init__.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-from charmhelpers.core.hookenv import (
- log,
- DEBUG,
-)
-from charmhelpers.contrib.hardening.mysql.checks import config
-
-
-def run_mysql_checks():
- log("Starting MySQL hardening checks.", level=DEBUG)
- checks = config.get_audits()
- for check in checks:
- log("Running '%s' check" % (check.__class__.__name__), level=DEBUG)
- check.ensure_compliance()
-
- log("MySQL hardening checks complete.", level=DEBUG)
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/checks/config.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/checks/config.py
deleted file mode 100644
index 3af8b89..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/checks/config.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-import six
-import subprocess
-
-from charmhelpers.core.hookenv import (
- log,
- WARNING,
-)
-from charmhelpers.contrib.hardening.audits.file import (
- FilePermissionAudit,
- DirectoryPermissionAudit,
- TemplatedFile,
-)
-from charmhelpers.contrib.hardening.mysql import TEMPLATES_DIR
-from charmhelpers.contrib.hardening import utils
-
-
-def get_audits():
- """Get MySQL hardening config audits.
-
- :returns: dictionary of audits
- """
- if subprocess.call(['which', 'mysql'], stdout=subprocess.PIPE) != 0:
- log("MySQL does not appear to be installed on this node - "
- "skipping mysql hardening", level=WARNING)
- return []
-
- settings = utils.get_settings('mysql')
- hardening_settings = settings['hardening']
- my_cnf = hardening_settings['mysql-conf']
-
- audits = [
- FilePermissionAudit(paths=[my_cnf], user='root',
- group='root', mode=0o0600),
-
- TemplatedFile(hardening_settings['hardening-conf'],
- MySQLConfContext(),
- TEMPLATES_DIR,
- mode=0o0750,
- user='mysql',
- group='root',
- service_actions=[{'service': 'mysql',
- 'actions': ['restart']}]),
-
- # MySQL and Percona charms do not allow configuration of the
- # data directory, so use the default.
- DirectoryPermissionAudit('/var/lib/mysql',
- user='mysql',
- group='mysql',
- recursive=False,
- mode=0o755),
-
- DirectoryPermissionAudit('/etc/mysql',
- user='root',
- group='root',
- recursive=False,
- mode=0o700),
- ]
-
- return audits
-
-
-class MySQLConfContext(object):
- """Defines the set of key/value pairs to set in a mysql config file.
-
- This context, when called, will return a dictionary containing the
- key/value pairs of setting to specify in the
- /etc/mysql/conf.d/hardening.cnf file.
- """
- def __call__(self):
- settings = utils.get_settings('mysql')
- # Translate for python3
- return {'mysql_settings':
- [(k, v) for k, v in six.iteritems(settings['security'])]}
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/templates/__init__.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/templates/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/templates/__init__.py
+++ /dev/null
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/templates/hardening.cnf b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/templates/hardening.cnf
deleted file mode 100644
index 8242586..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/mysql/templates/hardening.cnf
+++ /dev/null
@@ -1,12 +0,0 @@
-###############################################################################
-# WARNING: This configuration file is maintained by Juju. Local changes may
-# be overwritten.
-###############################################################################
-[mysqld]
-{% for setting, value in mysql_settings -%}
-{% if value == 'True' -%}
-{{ setting }}
-{% elif value != 'None' and value != None -%}
-{{ setting }} = {{ value }}
-{% endif -%}
-{% endfor -%}
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/__init__.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/__init__.py
deleted file mode 100644
index 277b8c7..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-from os import path
-
-TEMPLATES_DIR = path.join(path.dirname(__file__), 'templates')
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/checks/__init__.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/checks/__init__.py
deleted file mode 100644
index b85150d..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/checks/__init__.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-from charmhelpers.core.hookenv import (
- log,
- DEBUG,
-)
-from charmhelpers.contrib.hardening.ssh.checks import config
-
-
-def run_ssh_checks():
- log("Starting SSH hardening checks.", level=DEBUG)
- checks = config.get_audits()
- for check in checks:
- log("Running '%s' check" % (check.__class__.__name__), level=DEBUG)
- check.ensure_compliance()
-
- log("SSH hardening checks complete.", level=DEBUG)
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/checks/config.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/checks/config.py
deleted file mode 100644
index 3fb6ae8..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/checks/config.py
+++ /dev/null
@@ -1,394 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-import os
-
-from charmhelpers.core.hookenv import (
- log,
- DEBUG,
-)
-from charmhelpers.fetch import (
- apt_install,
- apt_update,
-)
-from charmhelpers.core.host import lsb_release
-from charmhelpers.contrib.hardening.audits.file import (
- TemplatedFile,
- FileContentAudit,
-)
-from charmhelpers.contrib.hardening.ssh import TEMPLATES_DIR
-from charmhelpers.contrib.hardening import utils
-
-
-def get_audits():
- """Get SSH hardening config audits.
-
- :returns: dictionary of audits
- """
- audits = [SSHConfig(), SSHDConfig(), SSHConfigFileContentAudit(),
- SSHDConfigFileContentAudit()]
- return audits
-
-
-class SSHConfigContext(object):
-
- type = 'client'
-
- def get_macs(self, allow_weak_mac):
- if allow_weak_mac:
- weak_macs = 'weak'
- else:
- weak_macs = 'default'
-
- default = 'hmac-sha2-512,hmac-sha2-256,hmac-ripemd160'
- macs = {'default': default,
- 'weak': default + ',hmac-sha1'}
-
- default = ('hmac-sha2-512-etm@openssh.com,'
- 'hmac-sha2-256-etm@openssh.com,'
- 'hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,'
- 'hmac-sha2-512,hmac-sha2-256,hmac-ripemd160')
- macs_66 = {'default': default,
- 'weak': default + ',hmac-sha1'}
-
- # Use newer ciphers on Ubuntu Trusty and above
- if lsb_release()['DISTRIB_CODENAME'].lower() >= 'trusty':
- log("Detected Ubuntu 14.04 or newer, using new macs", level=DEBUG)
- macs = macs_66
-
- return macs[weak_macs]
-
- def get_kexs(self, allow_weak_kex):
- if allow_weak_kex:
- weak_kex = 'weak'
- else:
- weak_kex = 'default'
-
- default = 'diffie-hellman-group-exchange-sha256'
- weak = (default + ',diffie-hellman-group14-sha1,'
- 'diffie-hellman-group-exchange-sha1,'
- 'diffie-hellman-group1-sha1')
- kex = {'default': default,
- 'weak': weak}
-
- default = ('curve25519-sha256@libssh.org,'
- 'diffie-hellman-group-exchange-sha256')
- weak = (default + ',diffie-hellman-group14-sha1,'
- 'diffie-hellman-group-exchange-sha1,'
- 'diffie-hellman-group1-sha1')
- kex_66 = {'default': default,
- 'weak': weak}
-
- # Use newer kex on Ubuntu Trusty and above
- if lsb_release()['DISTRIB_CODENAME'].lower() >= 'trusty':
- log('Detected Ubuntu 14.04 or newer, using new key exchange '
- 'algorithms', level=DEBUG)
- kex = kex_66
-
- return kex[weak_kex]
-
- def get_ciphers(self, cbc_required):
- if cbc_required:
- weak_ciphers = 'weak'
- else:
- weak_ciphers = 'default'
-
- default = 'aes256-ctr,aes192-ctr,aes128-ctr'
- cipher = {'default': default,
- 'weak': default + 'aes256-cbc,aes192-cbc,aes128-cbc'}
-
- default = ('chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,'
- 'aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr')
- ciphers_66 = {'default': default,
- 'weak': default + ',aes256-cbc,aes192-cbc,aes128-cbc'}
-
- # Use newer ciphers on ubuntu Trusty and above
- if lsb_release()['DISTRIB_CODENAME'].lower() >= 'trusty':
- log('Detected Ubuntu 14.04 or newer, using new ciphers',
- level=DEBUG)
- cipher = ciphers_66
-
- return cipher[weak_ciphers]
-
- def __call__(self):
- settings = utils.get_settings('ssh')
- if settings['common']['network_ipv6_enable']:
- addr_family = 'any'
- else:
- addr_family = 'inet'
-
- ctxt = {
- 'addr_family': addr_family,
- 'remote_hosts': settings['common']['remote_hosts'],
- 'password_auth_allowed':
- settings['client']['password_authentication'],
- 'ports': settings['common']['ports'],
- 'ciphers': self.get_ciphers(settings['client']['cbc_required']),
- 'macs': self.get_macs(settings['client']['weak_hmac']),
- 'kexs': self.get_kexs(settings['client']['weak_kex']),
- 'roaming': settings['client']['roaming'],
- }
- return ctxt
-
-
-class SSHConfig(TemplatedFile):
- def __init__(self):
- path = '/etc/ssh/ssh_config'
- super(SSHConfig, self).__init__(path=path,
- template_dir=TEMPLATES_DIR,
- context=SSHConfigContext(),
- user='root',
- group='root',
- mode=0o0644)
-
- def pre_write(self):
- settings = utils.get_settings('ssh')
- apt_update(fatal=True)
- apt_install(settings['client']['package'])
- if not os.path.exists('/etc/ssh'):
- os.makedir('/etc/ssh')
- # NOTE: don't recurse
- utils.ensure_permissions('/etc/ssh', 'root', 'root', 0o0755,
- maxdepth=0)
-
- def post_write(self):
- # NOTE: don't recurse
- utils.ensure_permissions('/etc/ssh', 'root', 'root', 0o0755,
- maxdepth=0)
-
-
-class SSHDConfigContext(SSHConfigContext):
-
- type = 'server'
-
- def __call__(self):
- settings = utils.get_settings('ssh')
- if settings['common']['network_ipv6_enable']:
- addr_family = 'any'
- else:
- addr_family = 'inet'
-
- ctxt = {
- 'ssh_ip': settings['server']['listen_to'],
- 'password_auth_allowed':
- settings['server']['password_authentication'],
- 'ports': settings['common']['ports'],
- 'addr_family': addr_family,
- 'ciphers': self.get_ciphers(settings['server']['cbc_required']),
- 'macs': self.get_macs(settings['server']['weak_hmac']),
- 'kexs': self.get_kexs(settings['server']['weak_kex']),
- 'host_key_files': settings['server']['host_key_files'],
- 'allow_root_with_key': settings['server']['allow_root_with_key'],
- 'password_authentication':
- settings['server']['password_authentication'],
- 'use_priv_sep': settings['server']['use_privilege_separation'],
- 'use_pam': settings['server']['use_pam'],
- 'allow_x11_forwarding': settings['server']['allow_x11_forwarding'],
- 'print_motd': settings['server']['print_motd'],
- 'print_last_log': settings['server']['print_last_log'],
- 'client_alive_interval':
- settings['server']['alive_interval'],
- 'client_alive_count': settings['server']['alive_count'],
- 'allow_tcp_forwarding': settings['server']['allow_tcp_forwarding'],
- 'allow_agent_forwarding':
- settings['server']['allow_agent_forwarding'],
- 'deny_users': settings['server']['deny_users'],
- 'allow_users': settings['server']['allow_users'],
- 'deny_groups': settings['server']['deny_groups'],
- 'allow_groups': settings['server']['allow_groups'],
- 'use_dns': settings['server']['use_dns'],
- 'sftp_enable': settings['server']['sftp_enable'],
- 'sftp_group': settings['server']['sftp_group'],
- 'sftp_chroot': settings['server']['sftp_chroot'],
- 'max_auth_tries': settings['server']['max_auth_tries'],
- 'max_sessions': settings['server']['max_sessions'],
- }
- return ctxt
-
-
-class SSHDConfig(TemplatedFile):
- def __init__(self):
- path = '/etc/ssh/sshd_config'
- super(SSHDConfig, self).__init__(path=path,
- template_dir=TEMPLATES_DIR,
- context=SSHDConfigContext(),
- user='root',
- group='root',
- mode=0o0600,
- service_actions=[{'service': 'ssh',
- 'actions':
- ['restart']}])
-
- def pre_write(self):
- settings = utils.get_settings('ssh')
- apt_update(fatal=True)
- apt_install(settings['server']['package'])
- if not os.path.exists('/etc/ssh'):
- os.makedir('/etc/ssh')
- # NOTE: don't recurse
- utils.ensure_permissions('/etc/ssh', 'root', 'root', 0o0755,
- maxdepth=0)
-
- def post_write(self):
- # NOTE: don't recurse
- utils.ensure_permissions('/etc/ssh', 'root', 'root', 0o0755,
- maxdepth=0)
-
-
-class SSHConfigFileContentAudit(FileContentAudit):
- def __init__(self):
- self.path = '/etc/ssh/ssh_config'
- super(SSHConfigFileContentAudit, self).__init__(self.path, {})
-
- def is_compliant(self, *args, **kwargs):
- self.pass_cases = []
- self.fail_cases = []
- settings = utils.get_settings('ssh')
-
- if lsb_release()['DISTRIB_CODENAME'].lower() >= 'trusty':
- if not settings['server']['weak_hmac']:
- self.pass_cases.append(r'^MACs.+,hmac-ripemd160$')
- else:
- self.pass_cases.append(r'^MACs.+,hmac-sha1$')
-
- if settings['server']['weak_kex']:
- self.fail_cases.append(r'^KexAlgorithms\sdiffie-hellman-group-exchange-sha256[,\s]?') # noqa
- self.pass_cases.append(r'^KexAlgorithms\sdiffie-hellman-group14-sha1[,\s]?') # noqa
- self.pass_cases.append(r'^KexAlgorithms\sdiffie-hellman-group-exchange-sha1[,\s]?') # noqa
- self.pass_cases.append(r'^KexAlgorithms\sdiffie-hellman-group1-sha1[,\s]?') # noqa
- else:
- self.pass_cases.append(r'^KexAlgorithms.+,diffie-hellman-group-exchange-sha256$') # noqa
- self.fail_cases.append(r'^KexAlgorithms.*diffie-hellman-group14-sha1[,\s]?') # noqa
-
- if settings['server']['cbc_required']:
- self.pass_cases.append(r'^Ciphers\s.*-cbc[,\s]?')
- self.fail_cases.append(r'^Ciphers\s.*aes128-ctr[,\s]?')
- self.fail_cases.append(r'^Ciphers\s.*aes192-ctr[,\s]?')
- self.fail_cases.append(r'^Ciphers\s.*aes256-ctr[,\s]?')
- else:
- self.fail_cases.append(r'^Ciphers\s.*-cbc[,\s]?')
- self.pass_cases.append(r'^Ciphers\schacha20-poly1305@openssh.com,.+') # noqa
- self.pass_cases.append(r'^Ciphers\s.*aes128-ctr$')
- self.pass_cases.append(r'^Ciphers\s.*aes192-ctr[,\s]?')
- self.pass_cases.append(r'^Ciphers\s.*aes256-ctr[,\s]?')
- else:
- if not settings['client']['weak_hmac']:
- self.fail_cases.append(r'^MACs.+,hmac-sha1$')
- else:
- self.pass_cases.append(r'^MACs.+,hmac-sha1$')
-
- if settings['client']['weak_kex']:
- self.fail_cases.append(r'^KexAlgorithms\sdiffie-hellman-group-exchange-sha256[,\s]?') # noqa
- self.pass_cases.append(r'^KexAlgorithms\sdiffie-hellman-group14-sha1[,\s]?') # noqa
- self.pass_cases.append(r'^KexAlgorithms\sdiffie-hellman-group-exchange-sha1[,\s]?') # noqa
- self.pass_cases.append(r'^KexAlgorithms\sdiffie-hellman-group1-sha1[,\s]?') # noqa
- else:
- self.pass_cases.append(r'^KexAlgorithms\sdiffie-hellman-group-exchange-sha256$') # noqa
- self.fail_cases.append(r'^KexAlgorithms\sdiffie-hellman-group14-sha1[,\s]?') # noqa
- self.fail_cases.append(r'^KexAlgorithms\sdiffie-hellman-group-exchange-sha1[,\s]?') # noqa
- self.fail_cases.append(r'^KexAlgorithms\sdiffie-hellman-group1-sha1[,\s]?') # noqa
-
- if settings['client']['cbc_required']:
- self.pass_cases.append(r'^Ciphers\s.*-cbc[,\s]?')
- self.fail_cases.append(r'^Ciphers\s.*aes128-ctr[,\s]?')
- self.fail_cases.append(r'^Ciphers\s.*aes192-ctr[,\s]?')
- self.fail_cases.append(r'^Ciphers\s.*aes256-ctr[,\s]?')
- else:
- self.fail_cases.append(r'^Ciphers\s.*-cbc[,\s]?')
- self.pass_cases.append(r'^Ciphers\s.*aes128-ctr[,\s]?')
- self.pass_cases.append(r'^Ciphers\s.*aes192-ctr[,\s]?')
- self.pass_cases.append(r'^Ciphers\s.*aes256-ctr[,\s]?')
-
- if settings['client']['roaming']:
- self.pass_cases.append(r'^UseRoaming yes$')
- else:
- self.fail_cases.append(r'^UseRoaming yes$')
-
- return super(SSHConfigFileContentAudit, self).is_compliant(*args,
- **kwargs)
-
-
-class SSHDConfigFileContentAudit(FileContentAudit):
- def __init__(self):
- self.path = '/etc/ssh/sshd_config'
- super(SSHDConfigFileContentAudit, self).__init__(self.path, {})
-
- def is_compliant(self, *args, **kwargs):
- self.pass_cases = []
- self.fail_cases = []
- settings = utils.get_settings('ssh')
-
- if lsb_release()['DISTRIB_CODENAME'].lower() >= 'trusty':
- if not settings['server']['weak_hmac']:
- self.pass_cases.append(r'^MACs.+,hmac-ripemd160$')
- else:
- self.pass_cases.append(r'^MACs.+,hmac-sha1$')
-
- if settings['server']['weak_kex']:
- self.fail_cases.append(r'^KexAlgorithms\sdiffie-hellman-group-exchange-sha256[,\s]?') # noqa
- self.pass_cases.append(r'^KexAlgorithms\sdiffie-hellman-group14-sha1[,\s]?') # noqa
- self.pass_cases.append(r'^KexAlgorithms\sdiffie-hellman-group-exchange-sha1[,\s]?') # noqa
- self.pass_cases.append(r'^KexAlgorithms\sdiffie-hellman-group1-sha1[,\s]?') # noqa
- else:
- self.pass_cases.append(r'^KexAlgorithms.+,diffie-hellman-group-exchange-sha256$') # noqa
- self.fail_cases.append(r'^KexAlgorithms.*diffie-hellman-group14-sha1[,\s]?') # noqa
-
- if settings['server']['cbc_required']:
- self.pass_cases.append(r'^Ciphers\s.*-cbc[,\s]?')
- self.fail_cases.append(r'^Ciphers\s.*aes128-ctr[,\s]?')
- self.fail_cases.append(r'^Ciphers\s.*aes192-ctr[,\s]?')
- self.fail_cases.append(r'^Ciphers\s.*aes256-ctr[,\s]?')
- else:
- self.fail_cases.append(r'^Ciphers\s.*-cbc[,\s]?')
- self.pass_cases.append(r'^Ciphers\schacha20-poly1305@openssh.com,.+') # noqa
- self.pass_cases.append(r'^Ciphers\s.*aes128-ctr$')
- self.pass_cases.append(r'^Ciphers\s.*aes192-ctr[,\s]?')
- self.pass_cases.append(r'^Ciphers\s.*aes256-ctr[,\s]?')
- else:
- if not settings['server']['weak_hmac']:
- self.pass_cases.append(r'^MACs.+,hmac-ripemd160$')
- else:
- self.pass_cases.append(r'^MACs.+,hmac-sha1$')
-
- if settings['server']['weak_kex']:
- self.fail_cases.append(r'^KexAlgorithms\sdiffie-hellman-group-exchange-sha256[,\s]?') # noqa
- self.pass_cases.append(r'^KexAlgorithms\sdiffie-hellman-group14-sha1[,\s]?') # noqa
- self.pass_cases.append(r'^KexAlgorithms\sdiffie-hellman-group-exchange-sha1[,\s]?') # noqa
- self.pass_cases.append(r'^KexAlgorithms\sdiffie-hellman-group1-sha1[,\s]?') # noqa
- else:
- self.pass_cases.append(r'^KexAlgorithms\sdiffie-hellman-group-exchange-sha256$') # noqa
- self.fail_cases.append(r'^KexAlgorithms\sdiffie-hellman-group14-sha1[,\s]?') # noqa
- self.fail_cases.append(r'^KexAlgorithms\sdiffie-hellman-group-exchange-sha1[,\s]?') # noqa
- self.fail_cases.append(r'^KexAlgorithms\sdiffie-hellman-group1-sha1[,\s]?') # noqa
-
- if settings['server']['cbc_required']:
- self.pass_cases.append(r'^Ciphers\s.*-cbc[,\s]?')
- self.fail_cases.append(r'^Ciphers\s.*aes128-ctr[,\s]?')
- self.fail_cases.append(r'^Ciphers\s.*aes192-ctr[,\s]?')
- self.fail_cases.append(r'^Ciphers\s.*aes256-ctr[,\s]?')
- else:
- self.fail_cases.append(r'^Ciphers\s.*-cbc[,\s]?')
- self.pass_cases.append(r'^Ciphers\s.*aes128-ctr[,\s]?')
- self.pass_cases.append(r'^Ciphers\s.*aes192-ctr[,\s]?')
- self.pass_cases.append(r'^Ciphers\s.*aes256-ctr[,\s]?')
-
- if settings['server']['sftp_enable']:
- self.pass_cases.append(r'^Subsystem\ssftp')
- else:
- self.fail_cases.append(r'^Subsystem\ssftp')
-
- return super(SSHDConfigFileContentAudit, self).is_compliant(*args,
- **kwargs)
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/templates/__init__.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/templates/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/templates/__init__.py
+++ /dev/null
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/templates/ssh_config b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/templates/ssh_config
deleted file mode 100644
index 9742d8e..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/templates/ssh_config
+++ /dev/null
@@ -1,70 +0,0 @@
-###############################################################################
-# WARNING: This configuration file is maintained by Juju. Local changes may
-# be overwritten.
-###############################################################################
-# This is the ssh client system-wide configuration file. See
-# ssh_config(5) for more information. This file provides defaults for
-# users, and the values can be changed in per-user configuration files
-# or on the command line.
-
-# Configuration data is parsed as follows:
-# 1. command line options
-# 2. user-specific file
-# 3. system-wide file
-# Any configuration value is only changed the first time it is set.
-# Thus, host-specific definitions should be at the beginning of the
-# configuration file, and defaults at the end.
-
-# Site-wide defaults for some commonly used options. For a comprehensive
-# list of available options, their meanings and defaults, please see the
-# ssh_config(5) man page.
-
-# Restrict the following configuration to be limited to this Host.
-{% if remote_hosts -%}
-Host {{ ' '.join(remote_hosts) }}
-{% endif %}
-ForwardAgent no
-ForwardX11 no
-ForwardX11Trusted yes
-RhostsRSAAuthentication no
-RSAAuthentication yes
-PasswordAuthentication {{ password_auth_allowed }}
-HostbasedAuthentication no
-GSSAPIAuthentication no
-GSSAPIDelegateCredentials no
-GSSAPIKeyExchange no
-GSSAPITrustDNS no
-BatchMode no
-CheckHostIP yes
-AddressFamily {{ addr_family }}
-ConnectTimeout 0
-StrictHostKeyChecking ask
-IdentityFile ~/.ssh/identity
-IdentityFile ~/.ssh/id_rsa
-IdentityFile ~/.ssh/id_dsa
-# The port at the destination should be defined
-{% for port in ports -%}
-Port {{ port }}
-{% endfor %}
-Protocol 2
-Cipher 3des
-{% if ciphers -%}
-Ciphers {{ ciphers }}
-{%- endif %}
-{% if macs -%}
-MACs {{ macs }}
-{%- endif %}
-{% if kexs -%}
-KexAlgorithms {{ kexs }}
-{%- endif %}
-EscapeChar ~
-Tunnel no
-TunnelDevice any:any
-PermitLocalCommand no
-VisualHostKey no
-RekeyLimit 1G 1h
-SendEnv LANG LC_*
-HashKnownHosts yes
-{% if roaming -%}
-UseRoaming {{ roaming }}
-{% endif %}
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/templates/sshd_config b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/templates/sshd_config
deleted file mode 100644
index 5f87298..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/templates/sshd_config
+++ /dev/null
@@ -1,159 +0,0 @@
-###############################################################################
-# WARNING: This configuration file is maintained by Juju. Local changes may
-# be overwritten.
-###############################################################################
-# Package generated configuration file
-# See the sshd_config(5) manpage for details
-
-# What ports, IPs and protocols we listen for
-{% for port in ports -%}
-Port {{ port }}
-{% endfor -%}
-AddressFamily {{ addr_family }}
-# Use these options to restrict which interfaces/protocols sshd will bind to
-{% if ssh_ip -%}
-{% for ip in ssh_ip -%}
-ListenAddress {{ ip }}
-{% endfor %}
-{%- else -%}
-ListenAddress ::
-ListenAddress 0.0.0.0
-{% endif -%}
-Protocol 2
-{% if ciphers -%}
-Ciphers {{ ciphers }}
-{% endif -%}
-{% if macs -%}
-MACs {{ macs }}
-{% endif -%}
-{% if kexs -%}
-KexAlgorithms {{ kexs }}
-{% endif -%}
-# HostKeys for protocol version 2
-{% for keyfile in host_key_files -%}
-HostKey {{ keyfile }}
-{% endfor -%}
-
-# Privilege Separation is turned on for security
-{% if use_priv_sep -%}
-UsePrivilegeSeparation {{ use_priv_sep }}
-{% endif -%}
-
-# Lifetime and size of ephemeral version 1 server key
-KeyRegenerationInterval 3600
-ServerKeyBits 1024
-
-# Logging
-SyslogFacility AUTH
-LogLevel VERBOSE
-
-# Authentication:
-LoginGraceTime 30s
-{% if allow_root_with_key -%}
-PermitRootLogin without-password
-{% else -%}
-PermitRootLogin no
-{% endif %}
-PermitTunnel no
-PermitUserEnvironment no
-StrictModes yes
-
-RSAAuthentication yes
-PubkeyAuthentication yes
-AuthorizedKeysFile %h/.ssh/authorized_keys
-
-# Don't read the user's ~/.rhosts and ~/.shosts files
-IgnoreRhosts yes
-# For this to work you will also need host keys in /etc/ssh_known_hosts
-RhostsRSAAuthentication no
-# similar for protocol version 2
-HostbasedAuthentication no
-# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
-IgnoreUserKnownHosts yes
-
-# To enable empty passwords, change to yes (NOT RECOMMENDED)
-PermitEmptyPasswords no
-
-# Change to yes to enable challenge-response passwords (beware issues with
-# some PAM modules and threads)
-ChallengeResponseAuthentication no
-
-# Change to no to disable tunnelled clear text passwords
-PasswordAuthentication {{ password_authentication }}
-
-# Kerberos options
-KerberosAuthentication no
-KerberosGetAFSToken no
-KerberosOrLocalPasswd no
-KerberosTicketCleanup yes
-
-# GSSAPI options
-GSSAPIAuthentication no
-GSSAPICleanupCredentials yes
-
-X11Forwarding {{ allow_x11_forwarding }}
-X11DisplayOffset 10
-X11UseLocalhost yes
-GatewayPorts no
-PrintMotd {{ print_motd }}
-PrintLastLog {{ print_last_log }}
-TCPKeepAlive no
-UseLogin no
-
-ClientAliveInterval {{ client_alive_interval }}
-ClientAliveCountMax {{ client_alive_count }}
-AllowTcpForwarding {{ allow_tcp_forwarding }}
-AllowAgentForwarding {{ allow_agent_forwarding }}
-
-MaxStartups 10:30:100
-#Banner /etc/issue.net
-
-# Allow client to pass locale environment variables
-AcceptEnv LANG LC_*
-
-# Set this to 'yes' to enable PAM authentication, account processing,
-# and session processing. If this is enabled, PAM authentication will
-# be allowed through the ChallengeResponseAuthentication and
-# PasswordAuthentication. Depending on your PAM configuration,
-# PAM authentication via ChallengeResponseAuthentication may bypass
-# the setting of "PermitRootLogin without-password".
-# If you just want the PAM account and session checks to run without
-# PAM authentication, then enable this but set PasswordAuthentication
-# and ChallengeResponseAuthentication to 'no'.
-UsePAM {{ use_pam }}
-
-{% if deny_users -%}
-DenyUsers {{ deny_users }}
-{% endif -%}
-{% if allow_users -%}
-AllowUsers {{ allow_users }}
-{% endif -%}
-{% if deny_groups -%}
-DenyGroups {{ deny_groups }}
-{% endif -%}
-{% if allow_groups -%}
-AllowGroups allow_groups
-{% endif -%}
-UseDNS {{ use_dns }}
-MaxAuthTries {{ max_auth_tries }}
-MaxSessions {{ max_sessions }}
-
-{% if sftp_enable -%}
-# Configuration, in case SFTP is used
-## override default of no subsystems
-## Subsystem sftp /opt/app/openssh5/libexec/sftp-server
-Subsystem sftp internal-sftp -l VERBOSE
-
-## These lines must appear at the *end* of sshd_config
-Match Group {{ sftp_group }}
-ForceCommand internal-sftp -l VERBOSE
-ChrootDirectory {{ sftp_chroot }}
-{% else -%}
-# Configuration, in case SFTP is used
-## override default of no subsystems
-## Subsystem sftp /opt/app/openssh5/libexec/sftp-server
-## These lines must appear at the *end* of sshd_config
-Match Group sftponly
-ForceCommand internal-sftp -l VERBOSE
-ChrootDirectory /sftpchroot/home/%u
-{% endif %}
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/templating.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/templating.py
deleted file mode 100644
index d2ab7dc..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/templating.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-import os
-
-from charmhelpers.core.hookenv import (
- log,
- DEBUG,
- WARNING,
-)
-
-try:
- from jinja2 import FileSystemLoader, Environment
-except ImportError:
- from charmhelpers.fetch import apt_install
- from charmhelpers.fetch import apt_update
- apt_update(fatal=True)
- apt_install('python-jinja2', fatal=True)
- from jinja2 import FileSystemLoader, Environment
-
-
-# NOTE: function separated from main rendering code to facilitate easier
-# mocking in unit tests.
-def write(path, data):
- with open(path, 'wb') as out:
- out.write(data)
-
-
-def get_template_path(template_dir, path):
- """Returns the template file which would be used to render the path.
-
- The path to the template file is returned.
- :param template_dir: the directory the templates are located in
- :param path: the file path to be written to.
- :returns: path to the template file
- """
- return os.path.join(template_dir, os.path.basename(path))
-
-
-def render_and_write(template_dir, path, context):
- """Renders the specified template into the file.
-
- :param template_dir: the directory to load the template from
- :param path: the path to write the templated contents to
- :param context: the parameters to pass to the rendering engine
- """
- env = Environment(loader=FileSystemLoader(template_dir))
- template_file = os.path.basename(path)
- template = env.get_template(template_file)
- log('Rendering from template: %s' % template.name, level=DEBUG)
- rendered_content = template.render(context)
- if not rendered_content:
- log("Render returned None - skipping '%s'" % path,
- level=WARNING)
- return
-
- write(path, rendered_content.encode('utf-8').strip())
- log('Wrote template %s' % path, level=DEBUG)
diff --git a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/utils.py b/charms/trusty/ceilometer/charmhelpers/contrib/hardening/utils.py
deleted file mode 100644
index a6743a4..0000000
--- a/charms/trusty/ceilometer/charmhelpers/contrib/hardening/utils.py
+++ /dev/null
@@ -1,157 +0,0 @@
-# Copyright 2016 Canonical Limited.
-#
-# This file is part of charm-helpers.
-#
-# charm-helpers is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# charm-helpers is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
-
-import glob
-import grp
-import os
-import pwd
-import six
-import yaml
-
-from charmhelpers.core.hookenv import (
- log,
- DEBUG,
- INFO,
- WARNING,
- ERROR,
-)
-
-
-# Global settings cache. Since each hook fire entails a fresh module import it
-# is safe to hold this in memory and not risk missing config changes (since
-# they will result in a new hook fire and thus re-import).
-__SETTINGS__ = {}
-
-
-def _get_defaults(modules):
- """Load the default config for the provided modules.
-
- :param modules: stack modules config defaults to lookup.
- :returns: modules default config dictionary.
- """
- default = os.path.join(os.path.dirname(__file__),
- 'defaults/%s.yaml' % (modules))
- return yaml.safe_load(open(default))
-
-
-def _get_schema(modules):
- """Load the config schema for the provided modules.
-
- NOTE: this schema is intended to have 1-1 relationship with they keys in
- the default config and is used a means to verify valid overrides provided
- by the user.
-
- :param modules: stack modules config schema to lookup.
- :returns: modules default schema dictionary.
- """
- schema = os.path.join(os.path.dirname(__file__),
- 'defaults/%s.yaml.schema' % (modules))
- return yaml.safe_load(open(schema))
-
-
-def _get_user_provided_overrides(modules):
- """Load user-provided config overrides.
-
- :param modules: stack modules to lookup in user overrides yaml file.
- :returns: overrides dictionary.
- """
- overrides = os.path.join(os.environ['JUJU_CHARM_DIR'],
- 'hardening.yaml')
- if os.path.exists(overrides):
- log("Found user-provided config overrides file '%s'" %
- (overrides), level=DEBUG)
- settings = yaml.safe_load(open(overrides))
- if settings and settings.get(modules):
- log("Applying '%s' overrides" % (modules), level=DEBUG)
- return settings.get(modules)
-
- log("No overrides found for '%s'" % (modules), level=DEBUG)
- else:
- log("No hardening config overrides file '%s' found in charm "
- "root dir" % (overrides), level=DEBUG)
-
- return {}
-
-
-def _apply_overrides(settings, overrides, schema):
- """Get overrides config overlayed onto modules defaults.
-
- :param modules: require stack modules config.
- :returns: dictionary of modules config with user overrides applied.
- """
- if overrides:
- for k, v in six.iteritems(overrides):
- if k in schema:
- if schema[k] is None:
- settings[k] = v
- elif type(schema[k]) is dict:
- settings[k] = _apply_overrides(settings[k], overrides[k],
- schema[k])
- else:
- raise Exception("Unexpected type found in schema '%s'" %
- type(schema[k]), level=ERROR)
- else:
- log("Unknown override key '%s' - ignoring" % (k), level=INFO)
-
- return settings
-
-
-def get_settings(modules):
- global __SETTINGS__
- if modules in __SETTINGS__:
- return __SETTINGS__[modules]
-
- schema = _get_schema(modules)
- settings = _get_defaults(modules)
- overrides = _get_user_provided_overrides(modules)
- __SETTINGS__[modules] = _apply_overrides(settings, overrides, schema)
- return __SETTINGS__[modules]
-
-
-def ensure_permissions(path, user, group, permissions, maxdepth=-1):
- """Ensure permissions for path.
-
- If path is a file, apply to file and return. If path is a directory,
- apply recursively (if required) to directory contents and return.
-
- :param user: user name
- :param group: group name
- :param permissions: octal permissions
- :param maxdepth: maximum recursion depth. A negative maxdepth allows
- infinite recursion and maxdepth=0 means no recursion.
- :returns: None
- """
- if not os.path.exists(path):
- log("File '%s' does not exist - cannot set permissions" % (path),
- level=WARNING)
- return
-
- _user = pwd.getpwnam(user)
- os.chown(path, _user.pw_uid, grp.getgrnam(group).gr_gid)
- os.chmod(path, permissions)
-
- if maxdepth == 0:
- log("Max recursion depth reached - skipping further recursion",
- level=DEBUG)
- return
- elif maxdepth > 0:
- maxdepth -= 1
-
- if os.path.isdir(path):
- contents = glob.glob("%s/*" % (path))
- for c in contents:
- ensure_permissions(c, user=user, group=group,
- permissions=permissions, maxdepth=maxdepth)