~junaidali/charms/trusty/neutron-api-plumgrid/optimal-helpers

« back to all changes in this revision

Viewing changes to hooks/charmhelpers/contrib/hardening/host/checks/sysctl.py

  • Committer: Junaid Ali
  • Date: 2016-04-27 12:17:56 UTC
  • Revision ID: junaidali@plumgrid.com-20160427121756-p3l3mae06r89b27j
Reduced number of helper files

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright 2016 Canonical Limited.
2
 
#
3
 
# This file is part of charm-helpers.
4
 
#
5
 
# charm-helpers is free software: you can redistribute it and/or modify
6
 
# it under the terms of the GNU Lesser General Public License version 3 as
7
 
# published by the Free Software Foundation.
8
 
#
9
 
# charm-helpers is distributed in the hope that it will be useful,
10
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
# GNU Lesser General Public License for more details.
13
 
#
14
 
# You should have received a copy of the GNU Lesser General Public License
15
 
# along with charm-helpers.  If not, see <http://www.gnu.org/licenses/>.
16
 
 
17
 
import os
18
 
import platform
19
 
import re
20
 
import six
21
 
import subprocess
22
 
 
23
 
from charmhelpers.core.hookenv import (
24
 
    log,
25
 
    INFO,
26
 
    WARNING,
27
 
)
28
 
from charmhelpers.contrib.hardening import utils
29
 
from charmhelpers.contrib.hardening.audits.file import (
30
 
    FilePermissionAudit,
31
 
    TemplatedFile,
32
 
)
33
 
from charmhelpers.contrib.hardening.host import TEMPLATES_DIR
34
 
 
35
 
 
36
 
SYSCTL_DEFAULTS = """net.ipv4.ip_forward=%(net_ipv4_ip_forward)s
37
 
net.ipv6.conf.all.forwarding=%(net_ipv6_conf_all_forwarding)s
38
 
net.ipv4.conf.all.rp_filter=1
39
 
net.ipv4.conf.default.rp_filter=1
40
 
net.ipv4.icmp_echo_ignore_broadcasts=1
41
 
net.ipv4.icmp_ignore_bogus_error_responses=1
42
 
net.ipv4.icmp_ratelimit=100
43
 
net.ipv4.icmp_ratemask=88089
44
 
net.ipv6.conf.all.disable_ipv6=%(net_ipv6_conf_all_disable_ipv6)s
45
 
net.ipv4.tcp_timestamps=%(net_ipv4_tcp_timestamps)s
46
 
net.ipv4.conf.all.arp_ignore=%(net_ipv4_conf_all_arp_ignore)s
47
 
net.ipv4.conf.all.arp_announce=%(net_ipv4_conf_all_arp_announce)s
48
 
net.ipv4.tcp_rfc1337=1
49
 
net.ipv4.tcp_syncookies=1
50
 
net.ipv4.conf.all.shared_media=1
51
 
net.ipv4.conf.default.shared_media=1
52
 
net.ipv4.conf.all.accept_source_route=0
53
 
net.ipv4.conf.default.accept_source_route=0
54
 
net.ipv4.conf.all.accept_redirects=0
55
 
net.ipv4.conf.default.accept_redirects=0
56
 
net.ipv6.conf.all.accept_redirects=0
57
 
net.ipv6.conf.default.accept_redirects=0
58
 
net.ipv4.conf.all.secure_redirects=0
59
 
net.ipv4.conf.default.secure_redirects=0
60
 
net.ipv4.conf.all.send_redirects=0
61
 
net.ipv4.conf.default.send_redirects=0
62
 
net.ipv4.conf.all.log_martians=0
63
 
net.ipv6.conf.default.router_solicitations=0
64
 
net.ipv6.conf.default.accept_ra_rtr_pref=0
65
 
net.ipv6.conf.default.accept_ra_pinfo=0
66
 
net.ipv6.conf.default.accept_ra_defrtr=0
67
 
net.ipv6.conf.default.autoconf=0
68
 
net.ipv6.conf.default.dad_transmits=0
69
 
net.ipv6.conf.default.max_addresses=1
70
 
net.ipv6.conf.all.accept_ra=0
71
 
net.ipv6.conf.default.accept_ra=0
72
 
kernel.modules_disabled=%(kernel_modules_disabled)s
73
 
kernel.sysrq=%(kernel_sysrq)s
74
 
fs.suid_dumpable=%(fs_suid_dumpable)s
75
 
kernel.randomize_va_space=2
76
 
"""
77
 
 
78
 
 
79
 
def get_audits():
80
 
    """Get OS hardening sysctl audits.
81
 
 
82
 
    :returns:  dictionary of audits
83
 
    """
84
 
    audits = []
85
 
    settings = utils.get_settings('os')
86
 
 
87
 
    # Apply the sysctl settings which are configured to be applied.
88
 
    audits.append(SysctlConf())
89
 
    # Make sure that only root has access to the sysctl.conf file, and
90
 
    # that it is read-only.
91
 
    audits.append(FilePermissionAudit('/etc/sysctl.conf',
92
 
                                      user='root',
93
 
                                      group='root', mode=0o0440))
94
 
    # If module loading is not enabled, then ensure that the modules
95
 
    # file has the appropriate permissions and rebuild the initramfs
96
 
    if not settings['security']['kernel_enable_module_loading']:
97
 
        audits.append(ModulesTemplate())
98
 
 
99
 
    return audits
100
 
 
101
 
 
102
 
class ModulesContext(object):
103
 
 
104
 
    def __call__(self):
105
 
        settings = utils.get_settings('os')
106
 
        with open('/proc/cpuinfo', 'r') as fd:
107
 
            cpuinfo = fd.readlines()
108
 
 
109
 
        for line in cpuinfo:
110
 
            match = re.search(r"^vendor_id\s+:\s+(.+)", line)
111
 
            if match:
112
 
                vendor = match.group(1)
113
 
 
114
 
        if vendor == "GenuineIntel":
115
 
            vendor = "intel"
116
 
        elif vendor == "AuthenticAMD":
117
 
            vendor = "amd"
118
 
 
119
 
        ctxt = {'arch': platform.processor(),
120
 
                'cpuVendor': vendor,
121
 
                'desktop_enable': settings['general']['desktop_enable']}
122
 
 
123
 
        return ctxt
124
 
 
125
 
 
126
 
class ModulesTemplate(object):
127
 
 
128
 
    def __init__(self):
129
 
        super(ModulesTemplate, self).__init__('/etc/initramfs-tools/modules',
130
 
                                              ModulesContext(),
131
 
                                              templates_dir=TEMPLATES_DIR,
132
 
                                              user='root', group='root',
133
 
                                              mode=0o0440)
134
 
 
135
 
    def post_write(self):
136
 
        subprocess.check_call(['update-initramfs', '-u'])
137
 
 
138
 
 
139
 
class SysCtlHardeningContext(object):
140
 
    def __call__(self):
141
 
        settings = utils.get_settings('os')
142
 
        ctxt = {'sysctl': {}}
143
 
 
144
 
        log("Applying sysctl settings", level=INFO)
145
 
        extras = {'net_ipv4_ip_forward': 0,
146
 
                  'net_ipv6_conf_all_forwarding': 0,
147
 
                  'net_ipv6_conf_all_disable_ipv6': 1,
148
 
                  'net_ipv4_tcp_timestamps': 0,
149
 
                  'net_ipv4_conf_all_arp_ignore': 0,
150
 
                  'net_ipv4_conf_all_arp_announce': 0,
151
 
                  'kernel_sysrq': 0,
152
 
                  'fs_suid_dumpable': 0,
153
 
                  'kernel_modules_disabled': 1}
154
 
 
155
 
        if settings['sysctl']['ipv6_enable']:
156
 
            extras['net_ipv6_conf_all_disable_ipv6'] = 0
157
 
 
158
 
        if settings['sysctl']['forwarding']:
159
 
            extras['net_ipv4_ip_forward'] = 1
160
 
            extras['net_ipv6_conf_all_forwarding'] = 1
161
 
 
162
 
        if settings['sysctl']['arp_restricted']:
163
 
            extras['net_ipv4_conf_all_arp_ignore'] = 1
164
 
            extras['net_ipv4_conf_all_arp_announce'] = 2
165
 
 
166
 
        if settings['security']['kernel_enable_module_loading']:
167
 
            extras['kernel_modules_disabled'] = 0
168
 
 
169
 
        if settings['sysctl']['kernel_enable_sysrq']:
170
 
            sysrq_val = settings['sysctl']['kernel_secure_sysrq']
171
 
            extras['kernel_sysrq'] = sysrq_val
172
 
 
173
 
        if settings['security']['kernel_enable_core_dump']:
174
 
            extras['fs_suid_dumpable'] = 1
175
 
 
176
 
        settings.update(extras)
177
 
        for d in (SYSCTL_DEFAULTS % settings).split():
178
 
            d = d.strip().partition('=')
179
 
            key = d[0].strip()
180
 
            path = os.path.join('/proc/sys', key.replace('.', '/'))
181
 
            if not os.path.exists(path):
182
 
                log("Skipping '%s' since '%s' does not exist" % (key, path),
183
 
                    level=WARNING)
184
 
                continue
185
 
 
186
 
            ctxt['sysctl'][key] = d[2] or None
187
 
 
188
 
        # Translate for python3
189
 
        return {'sysctl_settings':
190
 
                [(k, v) for k, v in six.iteritems(ctxt['sysctl'])]}
191
 
 
192
 
 
193
 
class SysctlConf(TemplatedFile):
194
 
    """An audit check for sysctl settings."""
195
 
    def __init__(self):
196
 
        self.conffile = '/etc/sysctl.d/99-juju-hardening.conf'
197
 
        super(SysctlConf, self).__init__(self.conffile,
198
 
                                         SysCtlHardeningContext(),
199
 
                                         template_dir=TEMPLATES_DIR,
200
 
                                         user='root', group='root',
201
 
                                         mode=0o0440)
202
 
 
203
 
    def post_write(self):
204
 
        try:
205
 
            subprocess.check_call(['sysctl', '-p', self.conffile])
206
 
        except subprocess.CalledProcessError as e:
207
 
            # NOTE: on some systems if sysctl cannot apply all settings it
208
 
            #       will return non-zero as well.
209
 
            log("sysctl command returned an error (maybe some "
210
 
                "keys could not be set) - %s" % (e),
211
 
                level=WARNING)