initial commit after bringing over cleaned up code and testing some examples

This commit is contained in:
Blake J. Harnden 2017-04-25 08:45:34 -07:00
parent c4858e6e0d
commit 00f4ebf5a9
93 changed files with 15189 additions and 13083 deletions

View file

@ -1,24 +1,22 @@
#
# CORE
# Copyright (c)2010-2014 the Boeing Company.
# See the LICENSE file included in this distribution.
#
# author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
#
'''
utility.py: defines miscellaneous utility services.
'''
"""
utility.py: defines miscellaneous utility services.
"""
import os
import subprocess
from core import constants
from core.misc import utils
from core.misc.ipaddress import Ipv4Prefix
from core.misc.ipaddress import Ipv6Prefix
from core.service import CoreService
from core.service import ServiceManager
from core.service import CoreService, addservice
from core.misc.ipaddr import IPv4Prefix, IPv6Prefix
from core.misc.utils import *
from core.constants import *
class UtilService(CoreService):
''' Parent class for utility services.
'''
"""
Parent class for utility services.
"""
_name = "UtilityProcess"
_group = "Utility"
_depends = ()
@ -29,15 +27,16 @@ class UtilService(CoreService):
_shutdown = ()
@classmethod
def generateconfig(cls, node, filename, services):
def generateconfig(cls, node, filename, services):
return ""
class IPForwardService(UtilService):
_name = "IPForward"
_configs = ("ipforward.sh", )
_configs = ("ipforward.sh",)
_startindex = 5
_startup = ("sh ipforward.sh", )
_startup = ("sh ipforward.sh",)
@classmethod
def generateconfig(cls, node, filename, services):
if os.uname()[0] == "Linux":
@ -60,13 +59,13 @@ class IPForwardService(UtilService):
%(sysctl)s -w net.ipv4.conf.default.send_redirects=0
%(sysctl)s -w net.ipv4.conf.all.rp_filter=0
%(sysctl)s -w net.ipv4.conf.default.rp_filter=0
""" % {'sysctl': SYSCTL_BIN}
""" % {'sysctl': constants.SYSCTL_BIN}
for ifc in node.netifs():
name = sysctldevname(ifc.name)
cfg += "%s -w net.ipv4.conf.%s.forwarding=1\n" % (SYSCTL_BIN, name)
name = utils.sysctldevname(ifc.name)
cfg += "%s -w net.ipv4.conf.%s.forwarding=1\n" % (constants.SYSCTL_BIN, name)
cfg += "%s -w net.ipv4.conf.%s.send_redirects=0\n" % \
(SYSCTL_BIN, name)
cfg += "%s -w net.ipv4.conf.%s.rp_filter=0\n" % (SYSCTL_BIN, name)
(constants.SYSCTL_BIN, name)
cfg += "%s -w net.ipv4.conf.%s.rp_filter=0\n" % (constants.SYSCTL_BIN, name)
return cfg
@classmethod
@ -78,9 +77,8 @@ class IPForwardService(UtilService):
%s -w net.inet6.ip6.forwarding=1
%s -w net.inet.icmp.bmcastecho=1
%s -w net.inet.icmp.icmplim=0
""" % (SYSCTL_BIN, SYSCTL_BIN, SYSCTL_BIN, SYSCTL_BIN)
""" % (constants.SYSCTL_BIN, constants.SYSCTL_BIN, constants.SYSCTL_BIN, constants.SYSCTL_BIN)
addservice(IPForwardService)
class DefaultRouteService(UtilService):
_name = "DefaultRoute"
@ -92,21 +90,21 @@ class DefaultRouteService(UtilService):
cfg = "#!/bin/sh\n"
cfg += "# auto-generated by DefaultRoute service (utility.py)\n"
for ifc in node.netifs():
if hasattr(ifc, 'control') and ifc.control == True:
if hasattr(ifc, 'control') and ifc.control is True:
continue
cfg += "\n".join(map(cls.addrstr, ifc.addrlist))
cfg += "\n"
return cfg
@staticmethod
def addrstr(x):
if x.find(":") >= 0:
net = IPv6Prefix(x)
net = Ipv6Prefix(x)
fam = "inet6 ::"
else:
net = IPv4Prefix(x)
net = Ipv4Prefix(x)
fam = "inet 0.0.0.0"
if net.maxaddr() == net.minaddr():
if net.max_addr() == net.min_addr():
return ""
else:
if os.uname()[0] == "Linux":
@ -115,9 +113,8 @@ class DefaultRouteService(UtilService):
rtcmd = "route add -%s" % fam
else:
raise Exception, "unknown platform"
return "%s %s" % (rtcmd, net.minaddr())
addservice(DefaultRouteService)
return "%s %s" % (rtcmd, net.min_addr())
class DefaultMulticastRouteService(UtilService):
_name = "DefaultMulticastRoute"
@ -144,8 +141,7 @@ class DefaultMulticastRouteService(UtilService):
cfg += "\n"
break
return cfg
addservice(DefaultMulticastRouteService)
class StaticRouteService(UtilService):
_name = "StaticRoute"
@ -160,23 +156,23 @@ class StaticRouteService(UtilService):
cfg += "# NOTE: this service must be customized to be of any use\n"
cfg += "# Below are samples that you can uncomment and edit.\n#\n"
for ifc in node.netifs():
if hasattr(ifc, 'control') and ifc.control == True:
if hasattr(ifc, 'control') and ifc.control is True:
continue
cfg += "\n".join(map(cls.routestr, ifc.addrlist))
cfg += "\n"
return cfg
@staticmethod
def routestr(x):
if x.find(":") >= 0:
net = IPv6Prefix(x)
net = Ipv6Prefix(x)
fam = "inet6"
dst = "3ffe:4::/64"
else:
net = IPv4Prefix(x)
net = Ipv4Prefix(x)
fam = "inet"
dst = "10.9.8.0/24"
if net.maxaddr() == net.minaddr():
if net.max_addr() == net.min_addr():
return ""
else:
if os.uname()[0] == "Linux":
@ -185,9 +181,8 @@ class StaticRouteService(UtilService):
rtcmd = "#/sbin/route add -%s %s" % (fam, dst)
else:
raise Exception, "unknown platform"
return "%s %s" % (rtcmd, net.minaddr())
return "%s %s" % (rtcmd, net.min_addr())
addservice(StaticRouteService)
class SshService(UtilService):
_name = "SSH"
@ -200,12 +195,13 @@ class SshService(UtilService):
_startup = ("sh startsshd.sh",)
_shutdown = ("killall sshd",)
_validate = ()
@classmethod
def generateconfig(cls, node, filename, services):
''' Use a startup script for launching sshd in order to wait for host
key generation.
'''
"""
Use a startup script for launching sshd in order to wait for host
key generation.
"""
if os.uname()[0] == "FreeBSD":
sshcfgdir = node.nodedir
sshstatedir = node.nodedir
@ -264,7 +260,6 @@ UsePAM yes
UseDNS no
""" % (sshcfgdir, sshstatedir, sshlibdir)
addservice(SshService)
class DhcpService(UtilService):
_name = "DHCP"
@ -273,12 +268,13 @@ class DhcpService(UtilService):
_startup = ("dhcpd",)
_shutdown = ("killall dhcpd",)
_validate = ("pidof dhcpd",)
@classmethod
def generateconfig(cls, node, filename, services):
''' Generate a dhcpd config file using the network address of
each interface.
'''
"""
Generate a dhcpd config file using the network address of
each interface.
"""
cfg = """\
# auto-generated by DHCP service (utility.py)
# NOTE: move these option lines into the desired pool { } block(s) below
@ -294,25 +290,26 @@ max-lease-time 7200;
ddns-update-style none;
"""
for ifc in node.netifs():
if hasattr(ifc, 'control') and ifc.control == True:
if hasattr(ifc, 'control') and ifc.control is True:
continue
cfg += "\n".join(map(cls.subnetentry, ifc.addrlist))
cfg += "\n"
return cfg
@staticmethod
def subnetentry(x):
''' Generate a subnet declaration block given an IPv4 prefix string
for inclusion in the dhcpd3 config file.
'''
"""
Generate a subnet declaration block given an IPv4 prefix string
for inclusion in the dhcpd3 config file.
"""
if x.find(":") >= 0:
return ""
else:
addr = x.split("/")[0]
net = IPv4Prefix(x)
net = Ipv4Prefix(x)
# divide the address space in half
rangelow = net.addr(net.numaddr() / 2)
rangehigh = net.maxaddr()
rangelow = net.addr(net.num_addr() / 2)
rangehigh = net.max_addr()
return """
subnet %s netmask %s {
pool {
@ -321,23 +318,24 @@ subnet %s netmask %s {
option routers %s;
}
}
""" % (net.prefixstr(), net.netmaskstr(), rangelow, rangehigh, addr)
""" % (net.prefix_str(), net.netmask_str(), rangelow, rangehigh, addr)
addservice(DhcpService)
class DhcpClientService(UtilService):
''' Use a DHCP client for all interfaces for addressing.
'''
"""
Use a DHCP client for all interfaces for addressing.
"""
_name = "DHCPClient"
_configs = ("startdhcpclient.sh",)
_startup = ("sh startdhcpclient.sh",)
_shutdown = ("killall dhclient",)
_validate = ("pidof dhclient",)
@classmethod
def generateconfig(cls, node, filename, services):
''' Generate a script to invoke dhclient on all interfaces.
'''
"""
Generate a script to invoke dhclient on all interfaces.
"""
cfg = "#!/bin/sh\n"
cfg += "# auto-generated by DHCPClient service (utility.py)\n"
cfg += "# uncomment this mkdir line and symlink line to enable client-"
@ -350,25 +348,26 @@ class DhcpClientService(UtilService):
cfg += "#ln -s /var/run/resolvconf/interface/%s.dhclient" % ifc.name
cfg += " /var/run/resolvconf/resolv.conf\n"
cfg += "/sbin/dhclient -nw -pf /var/run/dhclient-%s.pid" % ifc.name
cfg += " -lf /var/run/dhclient-%s.lease %s\n" % (ifc.name, ifc.name)
cfg += " -lf /var/run/dhclient-%s.lease %s\n" % (ifc.name, ifc.name)
return cfg
addservice(DhcpClientService)
class FtpService(UtilService):
''' Start a vsftpd server.
'''
"""
Start a vsftpd server.
"""
_name = "FTP"
_configs = ("vsftpd.conf",)
_dirs = ("/var/run/vsftpd/empty", "/var/ftp",)
_startup = ("vsftpd ./vsftpd.conf",)
_shutdown = ("killall vsftpd",)
_validate = ("pidof vsftpd",)
@classmethod
def generateconfig(cls, node, filename, services):
''' Generate a vsftpd.conf configuration file.
'''
"""
Generate a vsftpd.conf configuration file.
"""
return """\
# vsftpd.conf auto-generated by FTP service (utility.py)
listen=YES
@ -384,26 +383,27 @@ secure_chroot_dir=/var/run/vsftpd/empty
anon_root=/var/ftp
"""
addservice(FtpService)
class HttpService(UtilService):
''' Start an apache server.
'''
"""
Start an apache server.
"""
_name = "HTTP"
_configs = ("/etc/apache2/apache2.conf", "/etc/apache2/envvars",
"/var/www/index.html",)
_dirs = ("/etc/apache2", "/var/run/apache2", "/var/log/apache2",
"/run/lock", "/var/lock/apache2", "/var/www", )
"/run/lock", "/var/lock/apache2", "/var/www",)
_startup = ("chown www-data /var/lock/apache2", "apache2ctl start",)
_shutdown = ("apache2ctl stop",)
_validate = ("pidof apache2",)
APACHEVER22, APACHEVER24 = (22, 24)
@classmethod
def generateconfig(cls, node, filename, services):
''' Generate an apache2.conf configuration file.
'''
"""
Generate an apache2.conf configuration file.
"""
if filename == cls._configs[0]:
return cls.generateapache2conf(node, filename, services)
elif filename == cls._configs[1]:
@ -415,43 +415,45 @@ class HttpService(UtilService):
@classmethod
def detectversionfromcmd(cls):
''' Detect the apache2 version using the 'a2query' command.
'''
"""
Detect the apache2 version using the 'a2query' command.
"""
try:
status, result = cmdresult(['a2query', '-v'])
except Exception:
status, result = utils.cmdresult(['a2query', '-v'])
except subprocess.CalledProcessError:
status = -1
if status == 0 and result[:3] == '2.4':
return cls.APACHEVER24
return cls.APACHEVER22
return cls.APACHEVER22
@classmethod
def generateapache2conf(cls, node, filename, services):
lockstr = { cls.APACHEVER22:
'LockFile ${APACHE_LOCK_DIR}/accept.lock\n',
cls.APACHEVER24:
'Mutex file:${APACHE_LOCK_DIR} default\n', }
mpmstr = { cls.APACHEVER22: '', cls.APACHEVER24:
'LoadModule mpm_worker_module /usr/lib/apache2/modules/mod_mpm_worker.so\n', }
lockstr = {cls.APACHEVER22:
'LockFile ${APACHE_LOCK_DIR}/accept.lock\n',
cls.APACHEVER24:
'Mutex file:${APACHE_LOCK_DIR} default\n', }
mpmstr = {cls.APACHEVER22: '', cls.APACHEVER24:
'LoadModule mpm_worker_module /usr/lib/apache2/modules/mod_mpm_worker.so\n', }
permstr = { cls.APACHEVER22:
' Order allow,deny\n Deny from all\n Satisfy all\n',
cls.APACHEVER24:
' Require all denied\n', }
permstr = {cls.APACHEVER22:
' Order allow,deny\n Deny from all\n Satisfy all\n',
cls.APACHEVER24:
' Require all denied\n', }
authstr = { cls.APACHEVER22:
'LoadModule authz_default_module /usr/lib/apache2/modules/mod_authz_default.so\n',
cls.APACHEVER24:
'LoadModule authz_core_module /usr/lib/apache2/modules/mod_authz_core.so\n', }
authstr = {cls.APACHEVER22:
'LoadModule authz_default_module /usr/lib/apache2/modules/mod_authz_default.so\n',
cls.APACHEVER24:
'LoadModule authz_core_module /usr/lib/apache2/modules/mod_authz_core.so\n', }
permstr2 = { cls.APACHEVER22:
'\t\tOrder allow,deny\n\t\tallow from all\n',
permstr2 = {cls.APACHEVER22:
'\t\tOrder allow,deny\n\t\tallow from all\n',
cls.APACHEVER24:
'\t\tRequire all granted\n', }
'\t\tRequire all granted\n', }
version = cls.detectversionfromcmd()
cfg ="# apache2.conf generated by utility.py:HttpService\n"
cfg = "# apache2.conf generated by utility.py:HttpService\n"
cfg += lockstr[version]
cfg += """\
PidFile ${APACHE_PID_FILE}
@ -474,7 +476,7 @@ KeepAliveTimeout 5
<IfModule mpm_worker_module>
StartServers 2
MinSpareThreads 25
MaxSpareThreads 75
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxClients 150
@ -484,7 +486,7 @@ KeepAliveTimeout 5
<IfModule mpm_event_module>
StartServers 2
MinSpareThreads 25
MaxSpareThreads 75
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxClients 150
@ -590,16 +592,16 @@ export LANG
for ifc in node.netifs():
if hasattr(ifc, 'control') and ifc.control == True:
continue
body += "<li>%s - %s</li>\n" % (ifc.name, ifc.addrlist)
body += "<li>%s - %s</li>\n" % (ifc.name, ifc.addrlist)
return "<html><body>%s</body></html>" % body
addservice(HttpService)
class PcapService(UtilService):
''' Pcap service for logging packets.
'''
"""
Pcap service for logging packets.
"""
_name = "pcap"
_configs = ("pcap.sh", )
_configs = ("pcap.sh",)
_dirs = ()
_startindex = 1
_startup = ("sh pcap.sh start",)
@ -609,8 +611,9 @@ class PcapService(UtilService):
@classmethod
def generateconfig(cls, node, filename, services):
''' Generate a startpcap.sh traffic logging script.
'''
"""
Generate a startpcap.sh traffic logging script.
"""
cfg = """
#!/bin/sh
# set tcpdump options here (see 'man tcpdump' for help)
@ -625,7 +628,7 @@ if [ "x$1" = "xstart" ]; then
cfg += '# '
redir = "< /dev/null"
cfg += "tcpdump ${DUMPOPTS} -w %s.%s.pcap -i %s %s &\n" % \
(node.name, ifc.name, ifc.name, redir)
(node.name, ifc.name, ifc.name, redir)
cfg += """
elif [ "x$1" = "xstop" ]; then
@ -635,7 +638,6 @@ fi;
"""
return cfg
addservice(PcapService)
class RadvdService(UtilService):
_name = "radvd"
@ -644,12 +646,13 @@ class RadvdService(UtilService):
_startup = ("radvd -C /etc/radvd/radvd.conf -m logfile -l /var/log/radvd.log",)
_shutdown = ("pkill radvd",)
_validate = ("pidof radvd",)
@classmethod
def generateconfig(cls, node, filename, services):
''' Generate a RADVD router advertisement daemon config file
"""
Generate a RADVD router advertisement daemon config file
using the network address of each interface.
'''
"""
cfg = "# auto-generated by RADVD service (utility.py)\n"
for ifc in node.netifs():
if hasattr(ifc, 'control') and ifc.control == True:
@ -679,29 +682,30 @@ interface %s
""" % prefix
cfg += "};\n"
return cfg
@staticmethod
def subnetentry(x):
''' Generate a subnet declaration block given an IPv6 prefix string
for inclusion in the RADVD config file.
'''
"""
Generate a subnet declaration block given an IPv6 prefix string
for inclusion in the RADVD config file.
"""
if x.find(":") >= 0:
net = IPv6Prefix(x)
net = Ipv6Prefix(x)
return str(net)
else:
return ""
addservice(RadvdService)
class AtdService(UtilService):
''' Atd service for scheduling at jobs
'''
"""
Atd service for scheduling at jobs
"""
_name = "atd"
_configs = ("startatd.sh",)
_dirs = ("/var/spool/cron/atjobs", "/var/spool/cron/atspool")
_startup = ("sh startatd.sh", )
_shutdown = ("pkill atd", )
_startup = ("sh startatd.sh",)
_shutdown = ("pkill atd",)
@classmethod
def generateconfig(cls, node, filename, services):
return """
@ -711,14 +715,28 @@ chown -R daemon /var/spool/cron/*
chmod -R 700 /var/spool/cron/*
atd
"""
addservice(AtdService)
class UserDefinedService(UtilService):
''' Dummy service allowing customization of anything.
'''
"""
Dummy service allowing customization of anything.
"""
_name = "UserDefined"
_startindex = 50
_meta = "Customize this service to do anything upon startup."
addservice(UserDefinedService)
def load_services():
ServiceManager.add(IPForwardService)
ServiceManager.add(DefaultRouteService)
ServiceManager.add(DefaultMulticastRouteService)
ServiceManager.add(StaticRouteService)
ServiceManager.add(SshService)
ServiceManager.add(DhcpService)
ServiceManager.add(DhcpClientService)
ServiceManager.add(FtpService)
ServiceManager.add(HttpService)
ServiceManager.add(PcapService)
ServiceManager.add(RadvdService)
ServiceManager.add(AtdService)
ServiceManager.add(UserDefinedService)