# -*- coding: utf-8 -*-
from setuphelpers import *
def install():
import re
import nginxparser
import jinja2
import datetime
import subprocess
from waptcrypto import SSLCertificate, SSLPrivateKey
try:
import grp
except:
raise Exception("This package have to be installed on Linux")
def generate_dhparam(NGINX_GID):
dh_filename = "/etc/ssl/certs/dhparam.pem"
if not os.path.exists(dh_filename):
print(run("openssl dhparam -out %s 2048" % dh_filename))
os.chown(dh_filename, 0, NGINX_GID) # pylint: disable=no-member
os.chmod(dh_filename, 0o640) # pylint: disable=no-member
def selinux_rules(local_repo):
"""SELinux httpd security rules"""
run("setsebool -P httpd_can_network_connect 1")
run("setsebool -P httpd_setrlimit on")
for sepath in ("wapt", "wapt-host", "waptwua", "wads"):
path = makepath(local_repo, sepath)
mkdirs(path)
try:
run('semanage fcontext -a -t httpd_sys_content_t "%s(/.*)?"' % (path))
except:
run('semanage fcontext -m -t httpd_sys_content_t "%s(/.*)?"' % (path))
run("restorecon -R -v %s" % (path))
def nginx_set_worker_limit(nginx_conf):
already_set = False
for entries in nginx_conf:
if entries[0] == "worker_rlimit_nofile":
print("Nginx - worker_rlimit_nofile already set")
already_set = True
if not already_set:
nginx_conf.insert(3, ["worker_rlimit_nofile", "32768"])
return nginx_conf
def make_httpd_config(waptservice_dir, fqdn, local_repo):
ssl_dir = makepath(waptservice_dir, "nginx", "ssl")
scripts_dir = makepath(waptservice_dir, "scripts")
wapt_ssl_key_file = makepath(ssl_dir, "key.pem")
wapt_ssl_cert_file = makepath(ssl_dir, "cert.pem")
# write the apache configuration fragment
jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(scripts_dir))
template = jinja_env.get_template("wapt.nginxconfig.template")
template_vars = {
"wapt_repository_path": local_repo,
"windows": False,
"debian": type_debian(),
"redhat": type_redhat(),
"force_https": False,
"wapt_ssl_key_file": wapt_ssl_key_file,
"wapt_ssl_cert_file": wapt_ssl_cert_file,
"fqdn": fqdn,
"use_ssl_client_auth": False,
"clients_signing_certificate": False,
"server_tokens": "off",
}
print("Nginx - creating wapt.conf virtualhost")
config_string = template.render(template_vars)
if type_debian():
dst_file_path = "/etc/nginx/sites-available/wapt.conf"
if not os.path.exists("/etc/nginx/sites-enabled/wapt.conf"):
print(run("ln -s /etc/nginx/sites-available/wapt.conf /etc/nginx/sites-enabled/wapt.conf"))
if os.path.exists("/etc/nginx/sites-enabled/default"):
os.unlink("/etc/nginx/sites-enabled/default")
elif type_redhat():
dst_file_path = "/etc/nginx/conf.d/wapt.conf"
with open(dst_file_path, "wt") as dst_file:
dst_file.write(config_string)
# create keys for https:// access
if not os.path.exists(wapt_ssl_key_file) or not os.path.exists(wapt_ssl_cert_file):
print("Nginx - generate self-signed certs")
key = SSLPrivateKey(wapt_ssl_key_file)
if not os.path.isfile(wapt_ssl_key_file):
print("Create SSL RSA Key %s" % wapt_ssl_key_file)
key.create()
key.save_as_pem()
if os.path.isfile(wapt_ssl_cert_file):
crt = SSLCertificate(wapt_ssl_cert_file)
if crt.cn != fqdn:
os.rename(wapt_ssl_cert_file, "%s-%s.old" % (wapt_ssl_cert_file, "{:%Y%m%d-%Hh%Mm%Ss}".format(datetime.datetime.now())))
crt = key.build_sign_certificate(cn=fqdn, dnsname=fqdn, is_code_signing=False)
print("Create X509 cert %s" % wapt_ssl_cert_file)
crt.save_as_pem(wapt_ssl_cert_file)
else:
crt = key.build_sign_certificate(cn=fqdn, dnsname=fqdn, is_code_signing=False)
print("Create X509 cert %s" % wapt_ssl_cert_file)
crt.save_as_pem(wapt_ssl_cert_file)
def nginx_clean_default_vhost(nginx_conf):
for entry in nginx_conf:
if entry[0] == ["http"]:
for subentry in entry[1]:
if subentry[0] == ["server"]:
print("Nginx - removing default vhost")
entry[1].remove(subentry)
return nginx_conf
def enable_nginx():
print(run("systemctl enable nginx"))
def restart_nginx():
print(run("systemctl restart nginx"))
def nginx_cleanup():
with open("/etc/nginx/nginx.conf", "r") as read_conf:
nginx_conf = nginxparser.load(read_conf)
nginx_conf = nginx_set_worker_limit(nginx_conf)
nginx_conf = nginx_clean_default_vhost(nginx_conf)
with open("/etc/nginx/nginx.conf", "w") as nginx_conf_file:
nginx_conf_file.write(nginxparser.dumps(nginx_conf))
def setup_firewall():
"""Add permanent rules for firewalld"""
if type_redhat():
output = run("firewall-cmd --list-ports")
if "443/tcp" in output and "80/tcp" in output:
print("Firewall already configured, skipping firewalld configuration")
elif subprocess.call(["firewall-cmd", "--state"], stdout=open(os.devnull, "w")) == 0:
run("firewall-cmd --permanent --add-port=443/tcp")
run("firewall-cmd --permanent --add-port=80/tcp")
run("firewall-cmd --reload")
else:
run("firewall-offline-cmd --add-port=443/tcp")
run("firewall-offline-cmd --add-port=80/tcp")
print("Install nginx to permit WAPTAgent to become a repository")
if type_debian():
install_apt("nginx")
NGINX_GID = grp.getgrnam("www-data").gr_gid
elif type_redhat():
install_yum("nginx")
NGINX_GID = grp.getgrnam("nginx").gr_gid
else:
raise Exception("Distribution not supported yet")
print("Create WAPTService directories for nginx")
for dirname in ["nginx", "scripts"]:
mkdirs(makepath(WAPT.wapt_base_dir, "waptservice", dirname))
for dirname in ["ssl"]:
mkdirs(makepath(WAPT.wapt_base_dir, "waptservice", "nginx", dirname))
copytree2("scripts", makepath(WAPT.wapt_base_dir, "waptservice", "scripts"), onreplace=default_overwrite)
local_repo = inifile_readstring(WAPT.config_filename, "repo-sync", "local_repo_path") or makepath(WAPT.wapt_base_dir, "repository")
# SELinux rules for CentOS/RedHat
if type_redhat():
if re.match("^SELinux status:.*enabled", run("sestatus")):
print("Redhat/Centos detected, tweaking SELinux rules")
selinux_rules(local_repo)
print("Nginx - SELinux correctly configured for Nginx reverse proxy")
fqdn = get_fqdn()
# Nginx configuration
generate_dhparam(NGINX_GID)
nginx_cleanup()
make_httpd_config(makepath(WAPT.wapt_base_dir, "waptservice"), fqdn, local_repo)
print("Testing NGINX configuration")
run("nginx -t")
enable_nginx()
restart_nginx()
try:
setup_firewall()
except:
pass