def retrieve_from_server(remote_server, remote_path, local_path, verify_local=None): """ This function uses scp with syco root login to retrieve a directory or file from a remote server to the local machine. It will automatically wait for root login and verify the files locally after the copy if a list of files is specified with the verify_local keyword argument """ wait_for_server_root_login(remote_server) while True: _scp_from(remote_server, remote_path, local_path) if not verify_local: # Assume success break if not _do_files_exist(verify_local): app.print_verbose( "Waiting for files to be successfully copied from %s%s" % ( remote_server, remote_path ) ) else: break
def disable_usb(): # TODO Currently need usb dvd reader for installation. return app.print_verbose("Disable usb") scOpen("/etc/modprobe.d/syco.conf").replace_add( "^blacklist usb-storage$", "blacklist usb-storage" )
def handle_subprocess(p, output): stdout="" stderr="" while (True): for txt in p.stdout: # Only write caption once. if (output == X_OUTPUT_ALL): if (stdout==""): app.print_verbose("---- Result ----", 2) app.print_verbose(txt, 2, new_line=False) stdout+=txt for txt in p.stderr: stderr += txt if (p.poll() != None): break if (stderr and output == X_OUTPUT_ALL): app.print_error(stderr.strip()) # # Error messages is enough to print. A failure doesn't always mean a failure. # For example [ -f '/etc/cron.allow' ] && chmod og-rwx /etc/cron.allow # will return returncode 1, when the file doesn't exist. # if (p.returncode and output == X_OUTPUT_ALL): # app.print_error("Invalid returncode %d" % p.returncode) # An extra line break for the looks. if ((stdout or stderr) and app.options.verbose >=2 and output == X_OUTPUT_ALL): print("\n"), return stdout + str(stderr)
def install_ssh_key(self): ''' Install ssh keys on a remote server. Raise Exception if any error. ''' app.print_verbose("Install ssh key") self._check_alive() if (self._is_sshkey_installed()): return self._generate_ssh_keys() # Install key on remote host. self.ssh_exec( "mkdir -p .ssh;" + "chmod 700 .ssh;" + "touch .ssh/authorized_keys;" + "chmod 640 .ssh/authorized_keys;" + "echo '" + self._get_public_key() + "' >> .ssh/authorized_keys; " + "restorecon -R -v .ssh" ) # Raise exception if the installation of the cert failed. if (not self._is_sshkey_installed()): raise SettingsError("Failed to install cert on " + self.server)
def setup_clam_and_freshclam(): # # Setup clamav and freshclam # app.print_verbose("Setup clamav and freshclam") app.print_verbose(" Setup config files.") clamd = scOpen("/usr/local/etc/clamd.conf") clamd.replace("^[#]\?Example.*", "#Example") clamd.replace("^[#]\?LogFileMaxSize.*", "LogFileMaxSize 100M") clamd.replace("^[#]\?LogFile.*", "LogFile /var/log/clamav/clamd.log") clamd.replace("^[#]\?LogTime.*", "LogTime yes") clamd.replace("^[#]\?LogSyslog.*", "LogSyslog yes") clamd.replace("^[#]\?TCPSocket.*", "TCPSocket 3310") clamd.replace("^[#]\?TCPAddr.*", "TCPAddr 127.0.0.1") clamd.replace("^[#]\?ExcludePath.*/proc.*", "ExcludePath ^/proc") clamd.replace("^[#]\?ExcludePath.*/sys.*", "ExcludePath ^/sys") clamd.replace("^[#]\?User.*", "User clamav") clamd.replace("^[#]\?LocalSocket.*", "LocalSocket /var/run/clamav/clamd.socket") clamd.replace("^[#]\?PidFile.*", "PidFile /var/run/clamav/clamd.pid") freshclam = scOpen("/usr/local/etc/freshclam.conf") freshclam.replace("^[#]\?Example.*", "#Example") freshclam.replace("^[#]\?LogFileMaxSize.*", "LogFileMaxSize 100M") freshclam.replace("^[#]\?LogTime.*", "LogTime yes") freshclam.replace("^[#]\?LogSyslog.*", "LogSyslog yes") freshclam.replace("^[#]\?DatabaseOwner.*", "DatabaseOwner clamav") freshclam.replace("^[#]\?PidFile.*", "PidFile /var/run/clamav/freshclam.pid") freshclam.replace("^[#]\?DatabaseMirror.*", "DatabaseMirror database.clamav.net") freshclam.replace("^[#]\?UpdateLogFile.*", "UpdateLogFile /var/log/clamav/freshclam.log")
def add_nfs_chain(): del_nfs_chain() app.print_verbose("Add iptables chain for nfs") iptables("-N nfs_export") iptables("-A syco_input -p ALL -j nfs_export") iptables("-A syco_output -p ALL -j nfs_export") iptables("-A nfs_export -m state --state NEW -p tcp --dport 32803 -j allowed_tcp") iptables("-A nfs_export -m state --state NEW -p tcp --dport 32769 -j allowed_tcp") iptables("-A nfs_export -m state --state NEW -p tcp --dport 892 -j allowed_tcp") iptables("-A nfs_export -m state --state NEW -p tcp --dport 875 -j allowed_tcp") iptables("-A nfs_export -m state --state NEW -p tcp --dport 662 -j allowed_tcp") iptables("-A nfs_export -m state --state NEW -p tcp --dport 2020 -j allowed_tcp") iptables("-A nfs_export -m state --state NEW -p tcp --dport 2049 -j allowed_tcp") iptables("-A nfs_export -m state --state NEW -p tcp --dport 111 -j allowed_tcp") iptables("-A nfs_export -m state --state NEW -p udp --dport 32803 -j allowed_udp") iptables("-A nfs_export -m state --state NEW -p udp --dport 32769 -j allowed_udp") iptables("-A nfs_export -m state --state NEW -p udp --dport 892 -j allowed_udp") iptables("-A nfs_export -m state --state NEW -p udp --dport 875 -j allowed_udp") iptables("-A nfs_export -m state --state NEW -p udp --dport 662 -j allowed_udp") iptables("-A nfs_export -m state --state NEW -p udp --dport 2020 -j allowed_udp") iptables("-A nfs_export -m state --state NEW -p udp --dport 2049 -j allowed_udp") iptables("-A nfs_export -m state --state NEW -p udp --dport 111 -j allowed_udp")
def add_icinga_chain(): del_icinga_chain() if (not os.path.exists("/etc/icinga/icinga.cfg")): return app.print_verbose("Add iptables chain for Icinga") iptables("-N icinga_output") iptables("-A syco_output -p ALL -j icinga_output") # Output rule for NRPE-queries icinga_ports = "5666" icinga_server_hostname = config.general.get_monitor_server_hostname() icinga_server_ip = config.host(config.general.get_monitor_server()).get_front_ip() app.print_verbose("Chain for NRPE output".format(icinga_server_hostname)) iptables("-A icinga_output -p TCP -m multiport -s " + icinga_server_ip + " --dports " + icinga_ports + " -m state --state NEW -j allowed_tcp") # Output rule for SNMP-queries snmp_port = "161" switch_hostname_list = config.get_switches() #For every switch for host in config.get_switches(): host_ip = config.host(host).get_back_ip() iptables("-A icinga_output -p udp --dport " + snmp_port + " -d " + host_ip + " -m state --state NEW -j allowed_udp")
def setup_syco_chains(device=False): ''' Setup input/output/forward chains that are used by all syco installed services. This is so it's easier to remove/rebuild iptables rules for a specific service. And easier to trace what rules that are used for a specific service. ''' app.print_verbose("Create syco input, output, forward chain") # Input chain iptables("-N syco_input") input_device = (" -i " + str(device) if device else "") iptables("-A INPUT {0} -p ALL -j syco_input".format(input_device)) # Output chain output_device = (" -o " + str(device) if device else "") iptables("-N syco_output") iptables("-A OUTPUT {0} -p ALL -j syco_output".format(output_device)) # Forward chain should not be installed on main firewall. # Cant use a single device for forward if not device: iptables("-N syco_forward") iptables("-A FORWARD -p ALL -j syco_forward") iptables("-t nat -N syco_nat_postrouting") iptables("-t nat -A POSTROUTING -p ALL -j syco_nat_postrouting")
def _setup_gpg_rules(): ''' Allow GPG to talk to keyserver.ubuntu.com:11371 ''' app.print_verbose("Setup GPG output rule.") iptables("-A syco_output -p tcp -d keyserver.ubuntu.com --dport 11371 -j allowed_tcp")
def install_openldap(args): ''' Install openldap on current host. ''' app.print_verbose("Install openldap script-version: %d" % SCRIPT_VERSION) version_obj = version.Version("InstallOpenLdap", SCRIPT_VERSION) version_obj.check_executed() initialize_passwords() # Do the installation. enable_selinux() install_packages() store_logs_on_file() configure_openldap() configure_sudo_in_ldap() create_modules() add_auditlog_overlay() add_pwdpolicy_overlay() add_user_domain() create_certs() enable_ssl() require_highest_security_from_clients() # Let clients connect to the server through the firewall. This is done after # everything else is done, so we are sure that the server is secure before # letting somebody in. #iptables.add_ldap_chain() #iptables.save() _install_web_page()
def save(): ''' Save all current iptable rules to file, so it will be reloaded after reboot. ''' app.print_verbose("Save current iptables rules to /etc/sysconfig/iptables.") x("/sbin/iptables-save > /etc/sysconfig/iptables")
def del_haproxy_chain(): app.print_verbose("Delete iptables chain for haproxy") iptables("-D syco_input -p tcp -j haproxy_inout", general.X_OUTPUT_CMD) iptables("-D syco_output -p tcp -j haproxy_inout", general.X_OUTPUT_CMD) iptables("-F haproxy_inout", general.X_OUTPUT_CMD) iptables("-X haproxy_inout", general.X_OUTPUT_CMD)
def _create_cert(hostname): ''' Create certificate for one rsyslog client. ''' fqdn = "{0}.{1}".format(hostname, config.general.get_resolv_domain()) app.print_verbose("Create cert for host: {0}".format(fqdn)) template_server = "{0}template.{1}".format(get_install_dir(), fqdn) x("cp -f /opt/syco/var/rsyslog/template.server {0}".format(template_server)) _replace_tags(template_server, fqdn) # Create key x("certtool --generate-privkey " + "--outfile /etc/pki/rsyslog/{0}.key".format(fqdn) ) # Create cert x("certtool --generate-request " + "--load-privkey /etc/pki/rsyslog/{0}.key ".format(fqdn) + "--outfile /etc/pki/rsyslog/{0}.csr ".format(fqdn) + "--template {0}".format(template_server) ) # Sign cert x("certtool --generate-certificate " + "--load-request /etc/pki/rsyslog/{0}.csr ".format(fqdn) + "--outfile /etc/pki/rsyslog/{0}.crt ".format(fqdn) + "--load-ca-certificate /etc/pki/rsyslog/ca.crt " + "--load-ca-privkey /etc/pki/rsyslog/ca.key " + "--template {0}".format(template_server) )
def disable_services(): config = ConfigParser.SafeConfigParser() config.read("%s/hardening/config.cfg" % app.SYCO_VAR_PATH) for service in config.options("service"): app.print_verbose("Disabling service %s " % service) if os.path.exists("/etc/xinetd.d/%s" % service): disable_service(service)
def _gen_and_copy_cert(args): """ Generate certs if they don't exist or if cert regen was requested with "force-new-certs" """ crt_dir = "/etc/pki/rsyslog/" x("mkdir -p {0}".format(crt_dir)) fqdn = "{0}.{1}".format(net.get_hostname(), config.general.get_resolv_domain()) srv = config.general.get_log_server_hostname1() cert_files = [ "{0}{1}.crt".format(crt_dir, fqdn), "{0}{1}.key".format(crt_dir, fqdn), "{0}/ca.crt".format(crt_dir) ] # Determine whether to generate and copy rsyslog certificates if 'force-new-certs' in args or not _all_files_exist(cert_files): # Generate the certs on the remote machine general.wait_for_server_root_login(srv) general.run_remote_command(srv, "/etc/pki/rsyslog/syco-gen-rsyslog-client-keys.sh {0}".format(fqdn)) # Retrieve the certs general.retrieve_from_server(srv, "/etc/pki/rsyslog/ca.crt", crt_dir) general.retrieve_from_server(srv, "/etc/pki/rsyslog/{0}*".format(net.get_hostname()), crt_dir, verify_local=cert_files, remove_remote_files=True) x("restorecon -r /etc/pki/rsyslog") x("chmod 600 /etc/pki/rsyslog/*") x("chown root:root /etc/pki/rsyslog/*") else: app.print_verbose("Found all certs and force-new-certs was not specified so not updating certificates")
def _print_install_stat(self): ''' Display information about the servers that are being installed. ''' print("\n\n\n") app.print_verbose(str(self._servers_left_to_install()) + " server(s) left to install.") app.print_verbose(str(threading.activeCount()) + " thread(s) are running.") app.print_verbose(" " + "SERVER NAME".ljust(30) + "IP".ljust(15) + "ALIVE".ljust(6) + "VALID CONFIG".ljust(13) + "INSTALLED".ljust(10) + "ABORT ERROR".ljust(20) ) app.print_verbose(" " + ("-" * 29).ljust(30) + ("-" * 14).ljust(15) + ("-" * 5).ljust(6) + ("-" * 12).ljust(13) + ("-" * 9).ljust(10) + ("-" * 20).ljust(21) ) for hostname in self.servers: app.print_verbose(" " + hostname.ljust(30) + config.host(hostname).get_back_ip().ljust(15) + self._get_alive(hostname).ljust(6) + self._get_invalid_config(hostname).ljust(13) + self._get_installed(hostname).ljust(10) + self._get_abort_errors(hostname) ) print("\n\n\n")
def download_file(src, dst=None, user="", remote_user=None, remote_password=None, cookie=None, md5=None): ''' Download a file using wget, and place in the installation tmp folder. download_file("http://www.example.com/file.gz", "file.gz") ''' app.print_verbose("Download: " + src) if (not dst): dst = os.path.basename(src) create_install_dir() if (not os.access(app.INSTALL_DIR + dst, os.F_OK)): cmd = "-O " + app.INSTALL_DIR + dst if (remote_user): cmd += " --user="******" --password=\"" + remote_password + "\"" if (cookie): cmd += ' --no-cookies --header "Cookie: %s"' % cookie shell_exec("wget -U syco " + cmd + " " + src, user=user) # Looks like the file is not flushed to disk immediatley, # making the script not able to read the file immediatley after it's # downloaded. A sleep fixes this. time.sleep(2) if (not os.access(app.INSTALL_DIR + dst, os.F_OK)): raise Exception("Couldn't download: " + dst) if md5 != None and md5checksum(app.INSTALL_DIR + dst) != md5: raise Exception("MD5 Checksum dont match for " + dst)
def httpd_rotate(): if not os.path.exists('/etc/init.d/httpd'): return app.print_verbose("Adding httpd logrotate") x("mkdir -p /var/log/httpd/archive") x("cp %svar/logrotate/httpd /etc/logrotate.d/" % app.SYCO_PATH)
def uninstall_redis(args): """ Remove Redis from the server """ app.print_verbose("Uninstall Redis") os.chdir("/") _chkconfig("redis", "off") _service("redis", "stop") _chkconfig("keepalived", "on") _service("keepalived", "restart") x("yum -y remove redis keepalived") x("rm -rf {0}redis.conf".format(REDIS_CONF_DIR)) x("rm -rf {0}redis.conf.rpmsave".format(REDIS_CONF_DIR)) x("rm -rf {0}*".format(KEEPALIVED_CONF_DIR)) iptables.iptables("-D syco_input -p tcp -m multiport --dports 6379 -j allowed_tcp") iptables.iptables("-D syco_output -p tcp -m multiport --dports 6379 -j allowed_tcp") iptables.iptables("-D multicast_packets -d 224.0.0.0/8 -j ACCEPT") iptables.iptables("-D multicast_packets -s 224.0.0.0/8 -j ACCEPT") iptables.iptables("-D syco_input -p 112 -i eth1 -j ACCEPT") iptables.iptables("-D syco_output -p 112 -o eth1 -j ACCEPT") iptables.iptables("-A multicast_packets -s 224.0.0.0/4 -j DROP") iptables.iptables("-A multicast_packets -d 224.0.0.0/4 -j DROP") iptables.save() version_obj = version.Version("InstallRedis", script_version) version_obj.mark_uninstalled()
def yum_update(): ''' yum update is the first thing that is done when hardening the server, to minimize the risk that an updated package revert any hardening mods. ''' app.print_verbose("Update with yum") x("yum update -y")
def main(): """ Used to control the command line options, and the execution of the script. First function called when using the script. """ # Module variables cmd_list = Commands() usage = "usage: %prog [options] command\n\n" usage += "Commands:\n" usage += cmd_list.get_help() app.parser = OptionParser(usage=usage, version="System Console " + app.version, add_help_option=True) app.parser.add_option("-v", "--verbose", action="store_const", const=2, dest="verbose", default=1, help="Show more output.") app.parser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbose", help="Show no output.") app.parser.add_option("-f", "--force", action="store_const", const=1, dest="force", default=0, help="Ignore version.cfg.") (app.options, args) = app.parser.parse_args() app.print_verbose(app.parser.get_version()) if len(args) < 1 and 2 > len(args): app.parser.print_help() else: try: cmd_list.execute(args) except version.VersionException, e: app.print_error(repr(e.args))
def install_sssd(args): ''' Install ldap client on current host and connect to networks ldap server. ''' app.print_verbose("Install sssd script-version: %d" % SCRIPT_VERSION) version_obj = version.Version("InstallSssd", SCRIPT_VERSION) version_obj.check_executed() # Get all passwords from installation user at the start of the script. app.get_ldap_sssd_password() install_packages() installOpenLdap.setup_hosts() iptables.add_ldap_chain() iptables.save() ip = config.general.get_ldap_server_ip() general.wait_for_server_to_start(ip, "636") install_certs() # For some reason it needs to be executed twice. authconfig() authconfig() installOpenLdap.configure_client_cert_for_ldaptools() configured_sssd() configured_sudo() version_obj.mark_executed()
def install_mysql_replication(args): ''' Setup and start the database replication in master-master mode. This function should be executed on the secondary master, after the primary master has been configured. ''' app.print_verbose("Install mysql replication version: %d" % SCRIPT_VERSION) version_obj = version.Version("install-mysql-replication", SCRIPT_VERSION) version_obj.check_executed() general.wait_for_server_to_start(config.general.get_mysql_primary_master_ip(), "3306") repl_password=general.generate_password(20) for ip in [config.general.get_mysql_primary_master_ip(), config.general.get_mysql_secondary_master_ip()]: mysql_exec("stop slave;", True, ip) mysql_exec("delete from mysql.user where User = '******';", True, ip) mysql_exec("flush privileges;", True, ip) mysql_exec("GRANT REPLICATION SLAVE ON *.* TO 'repl'@'" + config.general.get_mysql_primary_master_ip() + "' IDENTIFIED BY '" + repl_password + "';", True, ip) mysql_exec("GRANT REPLICATION SLAVE ON *.* TO 'repl'@'" + config.general.get_mysql_secondary_master_ip() + "' IDENTIFIED BY '" + repl_password + "';", True, ip) if (ip==config.general.get_mysql_primary_master_ip()): mysql_exec("CHANGE MASTER TO MASTER_HOST='" + config.general.get_mysql_secondary_master_ip() + "', MASTER_USER='******', MASTER_PASSWORD='******'", True, ip) else: mysql_exec("CHANGE MASTER TO MASTER_HOST='" + config.general.get_mysql_primary_master_ip() + "', MASTER_USER='******', MASTER_PASSWORD='******'", True, ip) mysql_exec("start slave;", True, ip) version_obj.mark_executed()
def download_and_install(): # # Download and extract clamav # app.print_verbose("Download and extract clamav") dst_path = urlretrive(CLAM_AV_URL, "clamav_latest.tar.gz") x("tar -C %s -zxf %s" % (app.INSTALL_DIR, dst_path)) compile_dir = "%scompile-clamav" % app.INSTALL_DIR x("mkdir -p %s" % compile_dir) x("mv %s/clamav-*/* %s" % (app.INSTALL_DIR, compile_dir)) # # Install packages required for compiling # x("yum -y install gcc make gcc-c++ zlib-devel bzip2-devel ncurses-devel file") # # Build and install clamav and freshclam # app.print_verbose("Build and install clamav and freshclam") x("chown -R root:root %s" % compile_dir) x("./configure", cwd=compile_dir) x("make", cwd=compile_dir) x("make install", cwd=compile_dir) x("ldconfig") # # Remove packages needed for compilation. # x ( "yum remove zlib-devel bzip2-devel ncurses-devel " + "gcc make cloog-ppl cpp glibc-devel glibc-headers kernel-headers "+ "libgomp mpfr ppl gcc-c++ libstdc++-devel" )
def add_openvpn_chain(): del_openvpn_chain() if (not os.path.exists('/etc/init.d/openvpn')): return app.print_verbose("Add iptables chain for openvpn") network = config.general.get_openvpn_network() iptables("-N openvpn_input") iptables("-N openvpn_forward") iptables("-t nat -N openvpn_postrouting") iptables("-A syco_input -p ALL -j openvpn_input") iptables("-A syco_forward -p ALL -j openvpn_forward") iptables("-t nat -A syco_nat_postrouting -p ALL -j openvpn_postrouting") #Accept connections on 1194 for vpn access from clients iptables("-A openvpn_input -p udp --dport 1194 -j allowed_udp") iptables("-A openvpn_input -p tcp --dport 1194 -j allowed_tcp") #Apply forwarding for OpenVPN Tunneling iptables("-A openvpn_forward -m state --state RELATED,ESTABLISHED -j ACCEPT") iptables("-A openvpn_forward -s %s/24 -j ACCEPT" % network) # iptables("-A openvpn_forward -p tcp -m state --state NEW -m multiport --dports 22,34,53,80,443,4848,8080,8181,6048,6080,6081,7048,7080,7081 -j allowed_tcp") iptables("-A openvpn_forward -j REJECT") iptables("-t nat -A openvpn_postrouting -s %s/24 -o eth0 -j MASQUERADE" % network) iptables("-t nat -A openvpn_postrouting -s %s/24 -o eth1 -j MASQUERADE" % network)
def install_git_server(args): app.print_verbose("Install Git-Server version: %d" % SCRIPT_VERSION) version_obj = version.Version("InstallGit", SCRIPT_VERSION) version_obj.check_executed() # Get all passwords from installation user at the start of the script. app.get_ldap_sssd_password() x("yum -y install git") setup_git_user() setup_repo_folder() create_empty_test_repo() set_permission_on_repos() # Deny user git to login on SSH x("usermod --shell /usr/bin/git-shell git") install_gitweb() install_cgit() # Configure apache x("cp " + app.SYCO_PATH + "var/git/git.conf /etc/httpd/conf.d/git.conf") _install_httpd_certificates() _setup_ldap_auth() x("/etc/init.d/httpd restart") # Install startpage shutil.copy(app.SYCO_PATH + "var/git/index.html", "/var/www/html/index.html") version_obj.mark_executed()
def install_keepalived(args): global SYCO_PLUGIN_PATH, ACCEPTED_KA_ENV, ka_env SYCO_PLUGIN_PATH = app.get_syco_plugin_paths("/var/keepalived/").next() ACCEPTED_KA_ENV = get_environments() if len(args) != 2: print_killmessage() else: ka_env = args[1] if ka_env.lower() not in ACCEPTED_KA_ENV: print_killmessage() app.print_verbose("Install Keepalived version: %d" % script_version) version_obj = version.Version("InstallKeepalived", script_version) version_obj.check_executed() os.chdir("/") install_packages("keepalived") _configure_keepalived() # Adding iptables rules iptables_setup() save() version_obj.mark_executed()
def install_ossec_client(args): ''' Install OSSEC Client on the server ''' if os.path.exists('/var/ossec/bin/manage_agents'): app.print_error("Not insalling OSSEC client since OSSEC server detected") return app.print_verbose("Install ossec client.") version_obj = version.Version("InstallOssec", SCRIPT_VERSION) version_obj.check_executed() # Initialize all passwords used by the script app.init_mysql_passwords() build_ossec('preloaded-vars-client.conf') _setup_conf() _setup_keys() # Enabling syslog logging x('/var/ossec/bin/ossec-control enable client-syslog') # Adding iptables rules iptables.add_ossec_chain() iptables.save() # Restaring OSSEC server x("service ossec restart") x('yum remove gcc perl-Time-HiRes -y') version_obj.mark_executed()
def install_docker(args): """Install and configure docker on the local host.""" app.print_verbose("Install docker version: %d" % SCRIPT_VERSION) version_obj = version.Version("Installdocker", SCRIPT_VERSION) version_obj.check_executed() proxy_host = config.general.get_proxy_host() proxy_port = config.general.get_proxy_port() x("cp %s/docker/docker.repo /etc/yum.repos.d/docker.repo" % app.SYCO_VAR_PATH) general.install_packages("docker-engine") x("cp %s/docker/docker /etc/sysconfig/docker" % app.SYCO_VAR_PATH) # http://stackoverflow.com/questions/23111631/cannot-download-docker-images-behind-a-proxy docker_conf = scOpen(filename="/etc/sysconfig/docker") if proxy_host and proxy_port: docker_conf.replace("%HTTP_PROXY%", 'export HTTP_PROXY="http://%s:%s"' % (proxy_host, proxy_port)) docker_conf.replace("%HTTPS_PROXY%", 'export HTTPS_PROXY="https://%s:%s"' % (proxy_host, proxy_port)) else: docker_conf.replace("%HTTP_PROXY%", "") docker_conf.replace("%HTTPS_PROXY%", "") x("chkconfig docker on") x("service docker start") version_obj.mark_executed() # FW rule needed to access container through ports # Sleep for docker to start completely before setting rule x("sleep 10 && iptables -A syco_output -j DOCKER") x("service iptables save") version_obj.mark_executed()
def install_bind_client(args): """ Setup current server to use syco dns server as recursive name server. """ app.print_verbose("Install bind client.") version_obj = version.Version("InstallBindClient", SCRIPT_VERSION) version_obj.check_executed() # Iptables is already configured with iptables._setup_dns_resolver_rules general.wait_for_server_to_start(config.general.get_nameserver_server_ip(), "53") # Set what resolver to use (this will be rewritten by networkmanager at # reboot) resolv = scOpen("/etc/resolv.conf") resolv.remove("nameserver.*") for ip in config.general.get_nameserver_server_ips(): resolv.add("nameserver {0} ".format(ip)) # Change config files for networkmanager. x(""" grep -irl dns ifcfg*|xargs \ sed -i 's/.*\(dns.*\)[=].*/\\1={0}/ig'""".format( config.general.get_nameserver_server_ip() ), cwd = "/etc/sysconfig/network-scripts" ) version_obj.mark_executed()
def root_console_lockdown(): ''' Root is only allowed to login on tty1. ''' app.print_verbose("CIS 6.4 Restrict root Login to System Console") app.print_verbose(" Root is only allowed to login on tty1.") copyfile("/etc/securetty", "/etc/securetty.sycobak") changefile = open("/etc/securetty", 'w') changefile.write("tty1")
def delete_install_dir(): ''' Delete the folder where installation files are stored during installation. ''' if (os.access(app.INSTALL_DIR, os.W_OK | os.X_OK)): app.print_verbose("Delete " + app.INSTALL_DIR + " used during installation.") os.chdir("/tmp") x("rm -rf " + app.INSTALL_DIR)
def del_ossec_chain(): app.print_verbose("Delete iptables chain for Ossec") iptables("-D syco_input -p udp -j ossec_in", general.X_OUTPUT_CMD) iptables("-F ossec_in", general.X_OUTPUT_CMD) iptables("-X ossec_in", general.X_OUTPUT_CMD) iptables("-D syco_output -p udp -j ossec_out", general.X_OUTPUT_CMD) iptables("-F ossec_out", general.X_OUTPUT_CMD) iptables("-X ossec_out", general.X_OUTPUT_CMD)
def del_rabbitmq_chain(): app.print_verbose("Delete iptables chain for RabbitMQ") iptables("-D syco_input -p tcp -j rabbitmq_in", general.X_OUTPUT_CMD) iptables("-F rabbitmq_in", general.X_OUTPUT_CMD) iptables("-X rabbitmq_in", general.X_OUTPUT_CMD) iptables("-D syco_output -p tcp -j rabbitmq_out", general.X_OUTPUT_CMD) iptables("-F rabbitmq_out", general.X_OUTPUT_CMD) iptables("-X rabbitmq_out", general.X_OUTPUT_CMD)
def uninstall_sssd(args): app.print_verbose("Uninstall sssd script-version: %d" % SCRIPT_VERSION) x("yum -y remove openldap-clients sssd") x("rm -rf /var/lib/sss/") iptables.del_ldap_chain() iptables.save() version_obj = version.Version("InstallSssd", SCRIPT_VERSION) version_obj.mark_uninstalled()
def del_bind_chain(): app.print_verbose("Delete iptables chain for bind") iptables("-D syco_input -j bind_input", general.X_OUTPUT_CMD) iptables("-D syco_output -j bind_output", general.X_OUTPUT_CMD) iptables("-F bind_input", general.X_OUTPUT_CMD) iptables("-F bind_output", general.X_OUTPUT_CMD) iptables("-X bind_input", general.X_OUTPUT_CMD) iptables("-X bind_output", general.X_OUTPUT_CMD)
def add_module(name): ''' Add module to the beginning of IPTABLES_MODULES in /etc/sysconfig/iptables-config ''' app.print_verbose("Add module " + name) x('sed -i "/IPTABLES_MODULES=/s/\\"/\\"' + name + ' /;' + '/IPTABLES_MODULES=/s/ \\"/\\"/g' + '" /etc/sysconfig/iptables-config') x("modprobe " + name)
def install_icinga(args): ''' Installs the icinga poller and web-interface. ''' app.print_verbose("Installing icinga") version_obj = version.Version("installIcinga", SCRIPT_VERSION) version_obj.check_executed() _install_icinga(args) version_obj.mark_executed()
def setup_dns_resolver_rules(): ''' Allow this server to communicate with all syco approved dns resolvers. ''' app.print_verbose("Setup DNS resolver INPUT/OUTPUT rule.") for resolver_ip in config.general.get_dns_resolvers(): if resolver_ip and resolver_ip.lower() != "none": iptables("-A syco_output -p udp --sport 1024:65535 -d " + resolver_ip + " --dport 53 -m state --state NEW -j allowed_udp") iptables("-A syco_output -p tcp --sport 1024:65535 -d " + resolver_ip + " --dport 53 -m state --state NEW -j allowed_tcp")
def uninstall_rsyslogd(args): """ Remove Rsyslogd server from the server """ app.print_verbose("Uninstall Rsyslogd SERVER") x("yum erase rsyslog rsyslog-gnutls gnutls-utils") x("rm -rf /etc/pki/rsyslog") version_obj = version.Version("InstallRsyslogd", SCRIPT_VERSION) version_obj.mark_uninstalled()
def _get_icinga_web_version(): ''' Checks what package version of icinga is installed (package version comes after "-" i) ''' # Since repoforge may be updated, check insalled version of icinga. icingaversion = x( "yum list installed | grep icinga-web.noarch").split()[1].split("-")[0] app.print_verbose(icingaversion) return icingaversion
def ldap_dump(args): ''' Dump ldap database to file for backup in ldif format. File will be stored in ~/dump.ldif ''' print_verbose("Dump LDAP database.") remove_file() dump_database()
def add_rsyslog_chain(context=None): ''' Rsyslog IPtables rules Rsyslog Server Servers in network -> IN -> tcp -> 514 -> Rsyslog Server Rsyslog Client Rsyslog Server <- OUT <- tcp <- 514 <- Rsyslog Client ''' del_rsyslog_chain() import installRsyslog import installRsyslogd server_version_obj = version.Version("InstallRsyslogd", installRsyslogd.SCRIPT_VERSION) client_version_obj = version.Version("InstallRsyslogdClient", installRsyslog.SCRIPT_VERSION) if server_version_obj.is_executed() or client_version_obj.is_executed( ) or context in ["server", "client"]: app.print_verbose("Add iptables chain for rsyslog") iptables("-N rsyslog_in") iptables("-N rsyslog_out") iptables("-A syco_input -p all -j rsyslog_in") iptables("-A syco_output -p all -j rsyslog_out") # On rsyslog server if server_version_obj.is_executed() or context is "server": back_subnet = config.general.get_back_subnet() front_subnet = config.general.get_front_subnet() iptables( " -A rsyslog_in -m state --state NEW -p tcp -s %s --dport 514 -j allowed_tcp" % back_subnet) iptables( " -A rsyslog_in -m state --state NEW -p tcp -s %s --dport 514 -j allowed_tcp" % front_subnet) iptables( " -A rsyslog_in -m state --state NEW -p udp -s %s --dport 514 -j allowed_udp" % back_subnet) iptables( " -A rsyslog_in -m state --state NEW -p udp -s %s --dport 514 -j allowed_udp" % front_subnet) # On rsyslog client elif client_version_obj.is_executed() or context is "client": iptables( "-A rsyslog_out -m state --state NEW -p tcp -d %s --dport 514 -j allowed_tcp" % config.general.get_log_server_hostname1()) iptables( "-A rsyslog_out -m state --state NEW -p tcp -d %s --dport 514 -j allowed_tcp" % config.general.get_log_server_hostname2())
def add_kibana_chain(): del_kibana_chain() if (not os.path.exists('/etc/init.d/kibana')): return app.print_verbose("Add iptables chain for kibana") iptables("-N kibana") iptables("-A syco_input -p ALL -j kibana_input") iptables("-A syco_output -p ALL -j kibana_output") iptables("-A kiban_input -p TCP --dport 5601 -j allowed_tcp")
def disable_ip6_support(): app.print_verbose("Disable IP6 support") modprobe = scOpen("/etc/modprobe.d/syco.conf") modprobe.replace_add("^options ipv6.*", "options ipv6 disable=1") modprobe.replace_add("^alias net-pf-10 off$", "alias net-pf-10 off") network = scOpen("/etc/sysconfig/network") network.replace_add("^NETWORKING_IPV6=.*$", "NETWORKING_IPV6=no") x("/sbin/sysctl -w net.ipv6.conf.default.disable_ipv6=1") x("/sbin/sysctl -w net.ipv6.conf.all.disable_ipv6=1")
def setup_crontab(): # # Setup crontab # app.print_verbose("Setup crontab") x("cp %s/clam/viruscan.sh /etc/cron.daily/" % app.SYCO_VAR_PATH) scOpen("/etc/cron.daily/viruscan.sh").replace( "${ADMIN_EMAIL}", config.general.get_admin_email()) # https://redmine.fareoffice.com/issues/61041 x("/bin/chmod 0755 /etc/cron.daily/viruscan.sh")
def _import_repos(): if (os.access("/var/www/cobbler/ks_mirror/centos-x86_64", os.F_OK)): app.print_verbose("Centos-x86_64 already imported") else: x('cobbler import --path=rsync://ftp.sunet.se/pub/Linux/distributions/centos/6/os/x86_64/ --name=centos --arch=x86_64') if (os.access("/var/www/cobbler/repo_mirror/centos-updates-x86_64", os.F_OK)): app.print_verbose("Centos-updates-x86_64 repo already imported") else: x("cobbler repo add --arch=x86_64 --name=centos-updates-x86_64 --mirror=rsync://ftp.sunet.se/pub/Linux/distributions/centos/6/updates/x86_64/") x("cobbler repo add --arch=x86_64 --name=epel-x86_64 --mirror=rsync://ftp.df.lth.se/pub/fedora-epel/6/x86_64")
def uninstall_glassfish(args): ''' The main function the glassfish uninstallation. ''' app.print_verbose("Uninstall " + GLASSFISH_VERSION + " version: %d" % SCRIPT_VERSION) if (os.access(GLASSFISH_INSTALL_PATH, os.F_OK)): os.chdir("/tmp") x("/etc/init.d/" + GLASSFISH_VERSION + " stop -an") x("rm -rf " + GLASSFISH_INSTALL_PATH) x("/sbin/chkconfig --del " + GLASSFISH_VERSION) x("rm " + "/etc/init.d/" + GLASSFISH_VERSION) if (_is_glassfish_user_installed()): # Change dir if some of the rm commands fails, so not everythig will # be deleted by mistake. x("rm -rf /home/glassfish") x("userdel glassfish") x("groupdel glassfishadm") if (os.access("/usr/java/jdk1.6.0_22", os.F_OK)): x("rpm -e sun-javadb-core-10.5.3-0.2") x("rpm -e sun-javadb-client-10.5.3-0.2") x("rpm -e sun-javadb-demo-10.5.3-0.2") x("rpm -e sun-javadb-docs-10.5.3-0.2") x("rpm -e sun-javadb-javadoc-10.5.3-0.2") x("rpm -e sun-javadb-common-10.5.3-0.2") x("rpm -e jdk-1.6.0_22-fcs") if (os.access("/usr/java/jdk1.6.0_24", os.F_OK)): x("rpm -e sun-javadb-core-10.6.2-1.1.i386") x("rpm -e sun-javadb-client-10.6.2-1.1.i386") x("rpm -e sun-javadb-demo-10.6.2-1.1.i386") x("rpm -e sun-javadb-docs-10.6.2-1.1.i386") x("rpm -e sun-javadb-javadoc-10.6.2-1.1.i386") x("rpm -e sun-javadb-common-10.6.2-1.1.i386") x("rpm -e jdk-1.6.0_24-fcs") x("rpm -e jdk-6u24-linux-amd64") if (os.access("/usr/java/jdk1.6.0_29", os.F_OK)): x("rpm -e sun-javadb-javadoc-10.6.2-1.1.i386") x("rpm -e sun-javadb-docs-10.6.2-1.1.i386") x("rpm -e sun-javadb-demo-10.6.2-1.1.i386") x("rpm -e sun-javadb-client-10.6.2-1.1.i386") x("rpm -e sun-javadb-core-10.6.2-1.1.i386") x("rpm -e sun-javadb-common-10.6.2-1.1.i386") x("rpm -e jdk-6u29-linux-amd64") iptables.del_glassfish_chain() iptables.save() version_obj = version.Version("Install" + GLASSFISH_VERSION, SCRIPT_VERSION) version_obj.mark_uninstalled()
def del_mail_relay_chain(): app.print_verbose("Delete iptables chain for mail_relay") iptables("-D syco_input -p tcp -j incoming_mail", general.X_OUTPUT_CMD) iptables("-D syco_output -p tcp -j outgoing_mail", general.X_OUTPUT_CMD) iptables("-F incoming_mail", general.X_OUTPUT_CMD) iptables("-F outgoing_mail", general.X_OUTPUT_CMD) iptables("-X incoming_mail", general.X_OUTPUT_CMD) iptables("-X outgoing_mail", general.X_OUTPUT_CMD)
def expect_loop(self, searcher, timeout=-1, searchwindowsize=-1): ''' Using print_verbose, to get realtime output. Everything else is from pexpect.expect_loop. ''' self.searcher = searcher if timeout == -1: timeout = self.timeout if timeout is not None: end_time = time.time() + timeout if searchwindowsize == -1: searchwindowsize = self.searchwindowsize try: incoming = self.buffer freshlen = len(incoming) while True: # Keep reading until exception or return. app.print_verbose(incoming[-freshlen:], self.verbose_level, new_line=False, enable_caption=False) index = searcher.search(incoming, freshlen, searchwindowsize) if index >= 0: self.buffer = incoming[searcher.end:] self.before = incoming[:searcher.start] self.after = incoming[searcher.start:searcher.end] self.match = searcher.match self.match_index = index return self.match_index # No match at this point if timeout < 0 and timeout is not None: raise pexpect.TIMEOUT('Timeout exceeded in expect_any().') # Still have time left, so read more data c = self.read_nonblocking(self.maxread, timeout) freshlen = len(c) time.sleep(0.0001) incoming = incoming + c if timeout is not None: timeout = end_time - time.time() except pexpect.EOF, e: self.buffer = '' self.before = incoming self.after = pexpect.EOF index = searcher.eof_index if index >= 0: self.match = pexpect.EOF self.match_index = index return self.match_index else: self.match = None self.match_index = None raise pexpect.EOF(str(e) + '\n' + str(self))
def wait_for_procesess_to_finish(name): while (True): num_of_processes = subprocess.Popen( "ps aux | grep " + name, stdout=subprocess.PIPE, shell=True).communicate()[0].count("\n") if num_of_processes <= 2: break app.print_verbose( str(num_of_processes - 2) + " processes running, wait 10 more sec.") time.sleep(10)
def remove_file(path): ''' Remove file(s) in path, can use wildcard. Example remove_file('/var/log/libvirt/qemu/%s.log*') ''' for file_name in glob.glob(path): app.print_verbose('Remove file %s' % file_name) os.remove('%s' % file_name)
def add_rsync_chain(): del_rsync_chain() app.print_verbose("Add iptables chain for rsync") iptables("-N rsync_input") iptables("-N rsync_output") iptables("-A syco_input -p ALL -j rsync_input") iptables("-A syco_output -p ALL -j rsync_output") #iptables("-A rsync_output -p TCP -m multiport --dports 873 -j allowed_tcp") iptables("-A rsync_output -p TCP --dport 873 -j allowed_tcp")
def install_freeradius(args): ''' Install and configure the mysql-server on the local host. ''' app.print_verbose("Install FreeRadius version: %d" % SCRIPT_VERSION) version_obj = version.Version("InstallFreeRadius", SCRIPT_VERSION) version_obj.check_executed() # Install the mysql-server packages. if (not os.access("/usr/sbin/radiusd", os.W_OK | os.X_OK)): x("yum -y install freeradius-utils freeradius-ldap") x("/sbin/chkconfig radiusd on ") if (not os.access("/usr/sbin/radiusd", os.F_OK)): raise Exception("Couldn't install FreeRadius") # Configure iptables iptables.add_freeradius_chain() iptables.save() app.print_verbose("Copying config") ldapconf = scOpen("/etc/raddb/modules/ldap") ldapconf.replace( "\\t*server =.*", "\\tserver=\"ldaps://%s\"" % config.general.get_ldap_hostname()) ldapconf.replace("\\t#password = .*", "\\tpassword =%s" % app.get_ldap_admin_password()) ldapconf.replace( "\\t#identity = .*", "\\tidentity = \"cn=Manager,%s\"" % config.general.get_ldap_dn()) ldapconf.replace("\\t#base_filter = .*", "\\tbase_filter = \"(employeeType=Sysop)\"") ldapconf.replace("\\tfilter = .*", "\\tfilter =\"(uid=%u)\"") ldapconf.replace("\\tbasedn = .*", "\\tbasedn =\"%s\"" % config.general.get_ldap_dn()) #Deal with certs ldapconf.replace("\\t\\t# cacertfile.*=.*", "\\t\\tcacertfile\\t= /etc/openldap/cacerts/ca.crt") ldapconf.replace("\\t\\t# certfile.*=.*", "\\t\\tcertfile\\t= /etc/openldap/cacerts/client.crt") ldapconf.replace("\\t\\t# keyfile.*=.*", "\\t\\tkeyfile\\t= /etc/openldap/cacerts/client.key") x("/usr/bin/awk '/^[#]\\tldap/{c++;if(c==1){sub(\"^[#]\\tldap\",\"\\tldap\")}}1' %s" % "/etc/raddb/sites-enabled/default > /etc/raddb/sites-enabled/default.tmp" ) x("cp /etc/raddb/sites-enabled/default.tmp /etc/raddb/sites-enabled/default" ) x("rm /etc/raddb/sites-enabled/default.tmp") version_obj.mark_executed()
def chmod_files(): ''' Set permissions on file from config file. ''' app.print_verbose("Set permissions on file from config file..") config = ConfigParser.SafeConfigParser() config.read('%s/hardening/config.cfg' % app.SYCO_VAR_PATH) for setting in config.options('chmod_f'): name = config.get('chmod_f', setting) if os.path.isfile(name): x("chmod %s %s" % (setting, name))
def del_cobbler_chain(): app.print_verbose("Delete iptables chain for cobbler") iptables("-D syco_input -p ALL -j cobbler", general.X_OUTPUT_CMD) iptables("-D syco_output -p ALL -j cobbler", general.X_OUTPUT_CMD) iptables("-F cobbler", general.X_OUTPUT_CMD) iptables("-X cobbler", general.X_OUTPUT_CMD) iptables("-D syco_input -p ALL -j cobbler_output", general.X_OUTPUT_CMD) iptables("-F cobbler_output", general.X_OUTPUT_CMD) iptables("-X cobbler_output", general.X_OUTPUT_CMD) del_module("nf_conntrack_tftp")
def install_clam(args): app.print_verbose("Install antivirus (clamav and freshclam).") version_obj = version.Version("InstallClamAntiVirus", SCRIPT_VERSION) version_obj.check_executed() prepare_installation() download_and_install() setup_clam_and_freshclam() setup_crontab() setup_autostart_and_start() version_obj.mark_executed()
def setup_ssh_rules(): ''' Can SSH to this and any other computer internal and/or external. ''' app.print_verbose("Setup ssh INPUT/OUTPUT rule.") iptables( "-A syco_input -p tcp -m multiport --dports 22,34,8022 -j allowed_tcp" ) iptables( "-A syco_output -p tcp -m multiport --dports 22,34,8022 -j allowed_tcp" )
def wait_until_alive(self): '''Wait until the remote server becomes alive.''' if (not self.is_alive()): app.print_verbose("Wait for remote host " + self.server + " to become alive.", new_line=False) while (not self.is_alive()): if (app.options.verbose >= 1): sys.stdout.write(".") sys.stdout.flush() time.sleep(5) app.print_verbose("\n", new_line=False)
def setup_network(): ''' Help kernel to prevent certain kinds of attacks ''' app.print_verbose("Setup network (Settings from CIS benchmark)") setup_kernel() disable_ip6_support() configure_resolv_conf() configure_localhost() restart_network()