diff options
Diffstat (limited to 'charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/checks')
-rw-r--r-- | charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/checks/__init__.py | 31 | ||||
-rw-r--r-- | charms/trusty/ceilometer/charmhelpers/contrib/hardening/ssh/checks/config.py | 394 |
2 files changed, 0 insertions, 425 deletions
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) |