Example #1
0
 def test_settings_cache(self, mock_get_user_provided_overrides):
     mock_get_user_provided_overrides.return_value = {}
     self.assertEqual(utils.__SETTINGS__, {})
     self.assertTrue('sysctl' in utils.get_settings('os'))
     self.assertEqual(sorted(utils.__SETTINGS__.keys()), ['os'])
     self.assertTrue('server' in utils.get_settings('ssh'))
     self.assertEqual(sorted(utils.__SETTINGS__.keys()), ['os', 'ssh'])
Example #2
0
    def __call__(self):
        ctxt = {}
        settings = utils.get_settings("os")

        ctxt["auth_pam_passwdqc_options"] = settings["auth"]["pam_passwdqc_options"]

        return ctxt
    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
Example #4
0
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
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="******", group="root", mode=0o0640),
        TemplatedFile(
            os.path.join(settings["common"]["apache_dir"], "mods-available/alias.conf"),
            context,
            TEMPLATES_DIR,
            mode=0o0755,
            user="******",
            service_actions=[{"service": "apache2", "actions": ["restart"]}],
        ),
        TemplatedFile(
            os.path.join(settings["common"]["apache_dir"], "conf-enabled/hardening.conf"),
            context,
            TEMPLATES_DIR,
            mode=0o0640,
            user="******",
            service_actions=[{"service": "apache2", "actions": ["restart"]}],
        ),
        DirectoryPermissionAudit(settings["common"]["apache_dir"], user="******", group="root", mode=0o640),
        DisabledModuleAudit(settings["hardening"]["modules_to_disable"]),
        NoReadWriteForOther(settings["common"]["apache_dir"]),
    ]

    return audits
Example #6
0
    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
Example #7
0
 def __call__(self):
     settings = utils.get_settings('mysql')
     # Translate for python3
     return {
         'mysql_settings':
         [(k, v) for k, v in six.iteritems(settings['security'])]
     }
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
Example #9
0
    def __call__(self):
        ctxt = {}
        settings = utils.get_settings('os')

        ctxt['auth_pam_passwdqc_options'] = \
            settings['auth']['pam_passwdqc_options']

        return ctxt
Example #10
0
    def __call__(self):
        ctxt = {}
        settings = utils.get_settings('os')

        ctxt['auth_pam_passwdqc_options'] = \
            settings['auth']['pam_passwdqc_options']

        return ctxt
Example #11
0
    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
Example #12
0
    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
Example #13
0
    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
    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/'
        return ctxt
Example #15
0
 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)
Example #16
0
    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/'
        return ctxt
    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
Example #18
0
    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'])]
        }
    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'])]}
Example #20
0
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=os.path.join(
            settings['common']['apache_dir'], 'apache2.conf'),
                            user='******',
                            group='root',
                            mode=0o0640),
        TemplatedFile(os.path.join(settings['common']['apache_dir'],
                                   'mods-available/alias.conf'),
                      context,
                      TEMPLATES_DIR,
                      mode=0o0640,
                      user='******',
                      service_actions=[{
                          'service': 'apache2',
                          'actions': ['restart']
                      }]),
        TemplatedFile(os.path.join(settings['common']['apache_dir'],
                                   'conf-enabled/99-hardening.conf'),
                      context,
                      TEMPLATES_DIR,
                      mode=0o0640,
                      user='******',
                      service_actions=[{
                          'service': 'apache2',
                          'actions': ['restart']
                      }]),
        DirectoryPermissionAudit(settings['common']['apache_dir'],
                                 user='******',
                                 group='root',
                                 mode=0o0750),
        DisabledModuleAudit(settings['hardening']['modules_to_disable']),
        NoReadWriteForOther(settings['common']['apache_dir']),
        DeletedFile(['/var/www/html/index.html'])
    ]

    return audits
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=os.path.join(
                            settings['common']['apache_dir'], 'apache2.conf'),
                            user='******', group='root', mode=0o0640),

        TemplatedFile(os.path.join(settings['common']['apache_dir'],
                                   'mods-available/alias.conf'),
                      context,
                      TEMPLATES_DIR,
                      mode=0o0640,
                      user='******',
                      service_actions=[{'service': 'apache2',
                                        'actions': ['restart']}]),

        TemplatedFile(os.path.join(settings['common']['apache_dir'],
                                   'conf-enabled/99-hardening.conf'),
                      context,
                      TEMPLATES_DIR,
                      mode=0o0640,
                      user='******',
                      service_actions=[{'service': 'apache2',
                                        'actions': ['restart']}]),

        DirectoryPermissionAudit(settings['common']['apache_dir'],
                                 user='******',
                                 group='root',
                                 mode=0o0750),

        DisabledModuleAudit(settings['hardening']['modules_to_disable']),

        NoReadWriteForOther(settings['common']['apache_dir']),

        DeletedFile(['/var/www/html/index.html'])
    ]

    return audits
Example #22
0
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
Example #23
0
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='******',
                            group='root',
                            mode=0o0600),
        TemplatedFile(hardening_settings['hardening-conf'],
                      MySQLConfContext(),
                      TEMPLATES_DIR,
                      mode=0o0750,
                      user='******',
                      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='******',
                                 group='mysql',
                                 recursive=False,
                                 mode=0o755),
        DirectoryPermissionAudit('/etc/mysql',
                                 user='******',
                                 group='root',
                                 recursive=False,
                                 mode=0o700),
    ]

    return audits
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='******', group='root'))
    return audits
Example #25
0
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
Example #26
0
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
Example #27
0
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
Example #28
0
    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
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='******',
                            group='root', mode=0o0600),

        TemplatedFile(hardening_settings['hardening-conf'],
                      MySQLConfContext(),
                      TEMPLATES_DIR,
                      mode=0o0750,
                      user='******',
                      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='******',
                                 group='mysql',
                                 recursive=False,
                                 mode=0o755),

        DirectoryPermissionAudit('/etc/mysql',
                                 user='******',
                                 group='root',
                                 recursive=False,
                                 mode=0o700),
    ]

    return audits
Example #30
0
    def __call__(self):
        settings = utils.get_settings('ssh')
        if settings['common']['network_ipv6_enable']:
            addr_family = 'any'
        else:
            addr_family = 'inet'

        ctxt = {
            'ssh_ip': self.get_listening(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
Example #31
0
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
    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
Example #33
0
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='******',
                          group='root'))
    return audits
Example #34
0
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 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='******',
                                      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
Example #36
0
    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
Example #37
0
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='******', 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='******', group='root', mode=0o0440))
    return audits
Example #38
0
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='******',
                            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
Example #39
0
 def __call__(self):
     settings = utils.get_settings('os')
     ctxt = {'ttys': settings['auth']['root_ttys']}
     return ctxt
Example #40
0
    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\[email protected],.+')  # 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)
Example #41
0
 def __call__(self):
     settings = utils.get_settings('os')
     ctxt = {'ssh_tmout':
             settings['security']['ssh_tmout']}
     return ctxt
Example #42
0
 def __call__(self):
     settings = utils.get_settings('os')
     ctxt = {'disable_core_dump':
             not settings['security']['kernel_enable_core_dump']}
     return ctxt
 def __call__(self):
     settings = utils.get_settings('mysql')
     # Translate for python3
     return {'mysql_settings':
             [(k, v) for k, v in six.iteritems(settings['security'])]}
 def __call__(self):
     settings = utils.get_settings('mysql')
     return {
         'mysql_settings': [(k, v) for k, v in settings['security'].items()]
     }
 def __call__(self):
     settings = utils.get_settings('os')
     ctxt = {'ttys': settings['auth']['root_ttys']}
     return ctxt