first step to refactor
This commit is contained in:
parent
0a39d8c8b1
commit
c3664b34d3
@ -9,21 +9,24 @@ import os
|
|||||||
from socket import getaddrinfo
|
from socket import getaddrinfo
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
def get_if_available(dict, key, defValue):
|
def get_if_available(dict, key, defValue):
|
||||||
if key in dict:
|
if key in dict:
|
||||||
return dict[key]
|
return dict[key]
|
||||||
else:
|
else:
|
||||||
return defValue
|
return defValue
|
||||||
|
|
||||||
|
|
||||||
def analyse_proxy_data(data):
|
def analyse_proxy_data(data):
|
||||||
"""Extracts the data for the proxy configuration (envrionment variable
|
"""Extracts the data for the proxy configuration (envrionment variable
|
||||||
'PROXY_DATA' and converts it to a dictionary."""
|
'PROXY_DATA' and converts it to a dictionary."""
|
||||||
proxy_data = {}
|
proxy_data = {}
|
||||||
for proxy_var in data['PROXY_DATA'].split(','):
|
for proxy_var in data['PROXY_DATA'].split(','):
|
||||||
t = proxy_var.split(":",1)
|
t = proxy_var.split(":", 1)
|
||||||
proxy_data[t[0]] = t[1]
|
proxy_data[t[0]] = t[1]
|
||||||
return proxy_data
|
return proxy_data
|
||||||
|
|
||||||
|
|
||||||
def analyse_env_vars(inspect_data):
|
def analyse_env_vars(inspect_data):
|
||||||
"""Extracts the environment variables from the given result of an 'inspect
|
"""Extracts the environment variables from the given result of an 'inspect
|
||||||
container' call."""
|
container' call."""
|
||||||
@ -35,6 +38,7 @@ def analyse_env_vars(inspect_data):
|
|||||||
env_data[t[0]] = t[1]
|
env_data[t[0]] = t[1]
|
||||||
return env_data
|
return env_data
|
||||||
|
|
||||||
|
|
||||||
def handle_container(docker_client, id):
|
def handle_container(docker_client, id):
|
||||||
"""This function take a container's id and collects all data required
|
"""This function take a container's id and collects all data required
|
||||||
to create a proper proxy configuration. The configuration is then
|
to create a proper proxy configuration. The configuration is then
|
||||||
@ -47,6 +51,7 @@ def handle_container(docker_client, id):
|
|||||||
return names
|
return names
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def get_resolving_domains_from_containers(docker_client):
|
def get_resolving_domains_from_containers(docker_client):
|
||||||
container_ids = docker_client.containers(quiet=True)
|
container_ids = docker_client.containers(quiet=True)
|
||||||
|
|
||||||
@ -70,8 +75,8 @@ def get_resolving_domains_from_containers(docker_client):
|
|||||||
|
|
||||||
return resolved_domains
|
return resolved_domains
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
client = Client(base_url='unix://var/run/docker.sock', version='1.15')
|
client = Client(base_url='unix://var/run/docker.sock', version='1.15')
|
||||||
|
|
||||||
resolved_domains = get_resolving_domains_from_containers(client)
|
resolved_domains = get_resolving_domains_from_containers(client)
|
||||||
|
113
start.py
113
start.py
@ -12,34 +12,37 @@ import threading
|
|||||||
import list_domains
|
import list_domains
|
||||||
from docker import Client
|
from docker import Client
|
||||||
|
|
||||||
cert_path='/data/haproxy'
|
cert_path = '/data/haproxy'
|
||||||
cert_file='/data/haproxy/cert.pem'
|
cert_file = '/data/haproxy/cert.pem'
|
||||||
pid_file='/haproxy.pid'
|
pid_file = '/haproxy.pid'
|
||||||
|
delay = 10
|
||||||
|
|
||||||
def hash_cert_file():
|
def hash_cert_file():
|
||||||
"""Creates the sha256 hash of the certifcate file for haproxy. If the file
|
"""Creates the sha256 hash of the certificate file for haproxy. If the file
|
||||||
does not exist, an empty string is returned.
|
does not exist, an empty string is returned.
|
||||||
"""
|
"""
|
||||||
if not os.path.isfile(cert_file):
|
if not os.path.isfile(cert_file):
|
||||||
return ''
|
return ''
|
||||||
aFile = open(cert_file, 'rb')
|
file_obj = open(cert_file, 'rb')
|
||||||
hasher = hashlib.sha256()
|
hash_generator = hashlib.sha256()
|
||||||
buf = aFile.read(65536)
|
buf = file_obj.read(65536)
|
||||||
while len(buf) > 0:
|
while len(buf) > 0:
|
||||||
hasher.update(buf)
|
hash_generator.update(buf)
|
||||||
buf = aFile.read(65536)
|
buf = file_obj.read(65536)
|
||||||
return hasher.digest()
|
return hash_generator.digest()
|
||||||
|
|
||||||
|
|
||||||
def setup_logging():
|
def setup_logging():
|
||||||
"""Sets up logging with a nice format"""
|
"""Sets up logging with a nice format"""
|
||||||
logging.basicConfig(format='%(asctime)s [%(levelname)s]: %(message)s', level=logging.INFO)
|
logging.basicConfig(format='%(asctime)s [%(levelname)s]: %(message)s', level=logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
def get_pid():
|
def get_pid():
|
||||||
"""This function reads the process id from the given file and returns as int."""
|
"""This function reads the process id from the given file and returns as int."""
|
||||||
with open(pid_file, 'r') as file:
|
with open(pid_file, 'r') as file:
|
||||||
return int(file.read())
|
return int(file.read())
|
||||||
|
|
||||||
|
|
||||||
def kill_haproxy():
|
def kill_haproxy():
|
||||||
"""Stops the currently running instance of haproxy by issueing a kill signal to its pid."""
|
"""Stops the currently running instance of haproxy by issueing a kill signal to its pid."""
|
||||||
logging.info('killing haproxy')
|
logging.info('killing haproxy')
|
||||||
@ -48,16 +51,19 @@ def kill_haproxy():
|
|||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def start_haproxy_ssl():
|
def start_haproxy_ssl():
|
||||||
logging.info('starting haproxy SSL')
|
logging.info('starting haproxy SSL')
|
||||||
os.system('/usr/sbin/haproxy -f /haproxy_ssl.conf -p /haproxy.pid')
|
os.system('/usr/sbin/haproxy -f /haproxy_ssl.conf -p ' + pid_file)
|
||||||
return is_haproxy_running()
|
return is_haproxy_running()
|
||||||
|
|
||||||
|
|
||||||
def start_haproxy():
|
def start_haproxy():
|
||||||
logging.info('starting haproxy NON SSL')
|
logging.info('starting haproxy NON SSL')
|
||||||
os.system('/usr/sbin/haproxy -f /haproxy.conf -p /haproxy.pid')
|
os.system('/usr/sbin/haproxy -f /haproxy.conf -p ' + pid_file)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def is_haproxy_running():
|
def is_haproxy_running():
|
||||||
try:
|
try:
|
||||||
os.kill(get_pid(), 0)
|
os.kill(get_pid(), 0)
|
||||||
@ -65,6 +71,7 @@ def is_haproxy_running():
|
|||||||
except OSError:
|
except OSError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def ssl_possible():
|
def ssl_possible():
|
||||||
"""Check if a certificate is available."""
|
"""Check if a certificate is available."""
|
||||||
|
|
||||||
@ -73,67 +80,81 @@ def ssl_possible():
|
|||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def create_haproxy_cert():
|
def create_haproxy_cert():
|
||||||
"""Combines the freshly created fullchain.pem and privkey.pem into /data/haproxy/cert.pem"""
|
"""Combines the freshly created fullchain.pem and privkey.pem into /data/haproxy/cert.pem"""
|
||||||
logging.info('updating %s', cert_file)
|
logging.info('updating %s', cert_file)
|
||||||
os.system('DIR=`ls -td /data/config/live/*/ | head -1`; echo ${DIR}; mkdir -p /data/haproxy; cat ${DIR}/fullchain.pem ${DIR}/privkey.pem > /data/haproxy/cert.pem')
|
if not os.path.exists(cert_path):
|
||||||
|
logging.info('creating cert_path path: %s', cert_path)
|
||||||
|
os.mkdir(cert_path)
|
||||||
|
os.system(
|
||||||
|
'DIR=`ls -td /data/config/live/*/ | head -1`; echo ${DIR}; cat ${DIR}/fullchain.pem ${DIR}/privkey.pem > ' + cert_file)
|
||||||
|
|
||||||
|
|
||||||
def create_cert_data_standalone(domains):
|
def create_cert_data_standalone(domains):
|
||||||
domains = " -d ".join(domains)
|
domains = " -d ".join(domains)
|
||||||
os.system('/letsencrypt/letsencrypt-auto --config letencrypt.conf certonly --expand --force-renewal --duplicate --allow-subset-of-names --standalone-supported-challenges http-01 --http-01-port 54321 -d ' + domains)
|
os.system(
|
||||||
|
'/letsencrypt/letsencrypt-auto --config letencrypt.conf certonly --expand --force-renewal --duplicate --allow-subset-of-names --standalone-supported-challenges http-01 --http-01-port 54321 -d ' + domains)
|
||||||
|
|
||||||
|
|
||||||
def cert_watcher():
|
def cert_watcher():
|
||||||
SSL_RUNNING=True
|
ssl_active = ssl_possible() and is_haproxy_running()
|
||||||
cert_file_hash = hash_cert_file()
|
cert_file_hash = hash_cert_file()
|
||||||
while True:
|
while True:
|
||||||
logging.info('ping')
|
logging.info('ping')
|
||||||
time.sleep(60)
|
time.sleep(delay)
|
||||||
if ssl_possible() and not SSL_RUNNING:
|
|
||||||
kill_haproxy()
|
if not ssl_active:
|
||||||
start_haproxy_ssl()
|
if ssl_possible():
|
||||||
if is_haproxy_running():
|
# we should be able to start with SSL, but ...
|
||||||
cert_file_hash = hash_cert_file()
|
kill_haproxy()
|
||||||
logging.info('NON SSL -> SSL')
|
start_haproxy_ssl()
|
||||||
SSL_RUNNING=True
|
if is_haproxy_running():
|
||||||
|
# running with SSL succeeded
|
||||||
|
cert_file_hash = hash_cert_file()
|
||||||
|
logging.info('NON SSL -> SSL')
|
||||||
|
ssl_active = True
|
||||||
|
else:
|
||||||
|
# something went wrong (maybe broken certificate) but without SSL we can run it
|
||||||
|
start_haproxy()
|
||||||
|
logging.info('NON SSL -> NON SSL')
|
||||||
else:
|
else:
|
||||||
start_haproxy()
|
# currently not running with SSL but also no cert, so we do not attempt to start with SSL
|
||||||
SSL_RUNNING=False
|
pass
|
||||||
if SSL_RUNNING and cert_file_hash != hash_cert_file():
|
else:
|
||||||
logging.info('cert has changed')
|
if cert_file_hash != hash_cert_file():
|
||||||
kill_haproxy()
|
# we are running with SSL and the certificate has changed so we need to restart haproxy
|
||||||
start_haproxy_ssl()
|
logging.info('cert has changed')
|
||||||
if is_haproxy_running():
|
kill_haproxy()
|
||||||
|
start_haproxy_ssl()
|
||||||
|
if is_haproxy_running():
|
||||||
|
# restart with SSL succeeded, update hash
|
||||||
|
logging.info('SSL -> SSL')
|
||||||
|
else:
|
||||||
|
# restart with SSL failed, so we start without SSL again
|
||||||
|
start_haproxy()
|
||||||
|
logging.info('SSL -> NON SSL')
|
||||||
|
ssl_active = False
|
||||||
cert_file_hash = hash_cert_file()
|
cert_file_hash = hash_cert_file()
|
||||||
logging.info('SSL -> SSL')
|
|
||||||
SSL_RUNNING=True
|
|
||||||
else:
|
|
||||||
start_haproxy()
|
|
||||||
logging.info('SSL -> NON SSL')
|
|
||||||
SSL_RUNNING=False
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setup_logging()
|
setup_logging()
|
||||||
|
|
||||||
logging.info('starting')
|
logging.info('starting ssl endpoint')
|
||||||
|
|
||||||
if not os.path.exists(cert_path):
|
|
||||||
logging.info('creating cert_path path: %s', cert_path)
|
|
||||||
os.mkdir(cert_path)
|
|
||||||
client = Client(base_url='unix://var/run/docker.sock', version='1.15')
|
client = Client(base_url='unix://var/run/docker.sock', version='1.15')
|
||||||
|
|
||||||
cert_file_hash = hash_cert_file()
|
|
||||||
|
|
||||||
# try to start in SSL mode, no problem if that fails
|
# try to start in SSL mode, no problem if that fails
|
||||||
logging.info('try in SSL mode')
|
logging.info('try in SSL mode')
|
||||||
SSL_RUNNING = start_haproxy_ssl()
|
if not start_haproxy_ssl():
|
||||||
if not SSL_RUNNING:
|
|
||||||
logging.info('SSL mode failed')
|
logging.info('SSL mode failed')
|
||||||
|
|
||||||
if not is_haproxy_running():
|
if not is_haproxy_running():
|
||||||
# tried to start haproxy and this failed, so we need to create a certificate and try again:
|
# tried to start haproxy and this failed, so we need to create a certificate and try again:
|
||||||
# - start non ssl haproxy to be able to get a valid cert
|
# - start non ssl haproxy to be able to get a valid cert
|
||||||
logging.info('try in NON SSL mode')
|
logging.info('try in NON SSL mode')
|
||||||
SSL_RUNNING = start_haproxy()
|
start_haproxy()
|
||||||
# - get all domains
|
# - get all domains
|
||||||
resolved_domains = list_domains.get_resolving_domains_from_containers(client)
|
resolved_domains = list_domains.get_resolving_domains_from_containers(client)
|
||||||
# - create cert
|
# - create cert
|
||||||
|
Loading…
Reference in New Issue
Block a user