integration - continue work on storageless config for k8s and swarm
This commit is contained in:
parent
e55dff8128
commit
062fa3e78a
|
@ -16,6 +16,7 @@ chmod ugo+x /opt/bunkerized-nginx/entrypoint/* /opt/bunkerized-nginx/scripts/*
|
|||
chmod ugo+x /opt/bunkerized-nginx/gen/main.py
|
||||
chmod ugo+x /opt/bunkerized-nginx/jobs/main.py
|
||||
chmod ugo+x /opt/bunkerized-nginx/jobs/reload.py
|
||||
chmod ugo+x /opt/bunkerized-nginx/jobs/certbot-*.sh
|
||||
chmod 770 /opt/bunkerized-nginx
|
||||
chmod 440 /opt/bunkerized-nginx/settings.json
|
||||
|
||||
|
|
|
@ -6,6 +6,15 @@ import Controller
|
|||
|
||||
from logger import log
|
||||
|
||||
CONFIGS = {
|
||||
"conf": "/etc/nginx",
|
||||
"letsencrypt": "/etc/letsencrypt",
|
||||
"http": "/http-confs",
|
||||
"server": "/server-confs",
|
||||
"modsec": "/modsec-confs",
|
||||
"modsec-crs": "/modsec-crs-confs"
|
||||
}
|
||||
|
||||
class Config :
|
||||
|
||||
def __init__(self, type, api_uri, http_port="8080") :
|
||||
|
@ -64,12 +73,32 @@ class Config :
|
|||
instance.kill("SIGHUP")
|
||||
except :
|
||||
ret = False
|
||||
elif self.__type == Controller.Type.SWARM :
|
||||
ret = self.__api_call(instances, "/reload")
|
||||
elif self.__type == Controller.Type.KUBERNETES :
|
||||
elif self.__type == Controller.Type.SWARM or self.__type == Controller.Type.KUBERNETES :
|
||||
ret = self.__api_call(instances, "/reload")
|
||||
return ret
|
||||
|
||||
def send(self, instances) :
|
||||
ret = True
|
||||
if self.__type == Controller.Type.DOCKER :
|
||||
return ret
|
||||
elif self.__type == Controller.Type.SWARM or self.__type == Controller.Type.KUBERNERTES :
|
||||
fail = False
|
||||
for name, path in CONFIGS.items() :
|
||||
file = self.__tarball(path)
|
||||
if not self.__api_call(instances, "/" + name, file=file) :
|
||||
log("config", "ERROR", "can't send config " + name + " to instance(s)")
|
||||
fail = True
|
||||
file.close()
|
||||
if fail :
|
||||
ret = False
|
||||
return ret
|
||||
|
||||
def __tarball(path) :
|
||||
file = io.BytesIO()
|
||||
with tarfile.open(mode="w:gz", fileobj=file) as tar :
|
||||
tar.add(path, arcname=".")
|
||||
return file
|
||||
|
||||
def __ping(self, instances) :
|
||||
return self.__api_call(instances, "/ping")
|
||||
|
||||
|
@ -120,7 +149,7 @@ class Config :
|
|||
log("config", "ERROR", "exception while waiting for bunkerized-nginx instances : " + traceback.format_exc())
|
||||
return False
|
||||
|
||||
def __api_call(self, instances, path) :
|
||||
def __api_call(self, instances, path, file=None) :
|
||||
ret = True
|
||||
nb = 0
|
||||
urls = []
|
||||
|
@ -146,7 +175,10 @@ class Config :
|
|||
for url in urls :
|
||||
req = None
|
||||
try :
|
||||
req = requests.post(url)
|
||||
if file == None :
|
||||
req = requests.post(url)
|
||||
else :
|
||||
req = requests.post(url, {'file': file})
|
||||
except :
|
||||
pass
|
||||
if req and req.status_code == 200 and req.text == "ok" :
|
||||
|
|
|
@ -51,3 +51,10 @@ class Controller(ABC) :
|
|||
except :
|
||||
ret = False
|
||||
return ret
|
||||
|
||||
def _send(self, instances) :
|
||||
try :
|
||||
ret = self._config.send(instances)
|
||||
except :
|
||||
ret = False
|
||||
return ret
|
||||
|
|
|
@ -96,9 +96,9 @@ class IngressController(Controller.Controller) :
|
|||
|
||||
def process_events(self, current_env) :
|
||||
self.__old_env = current_env
|
||||
t_pod = Thread(target=self.__watch_pod)
|
||||
t_ingress = Thread(target=self.__watch_ingress)
|
||||
t_service = Thread(target=self.__watch_service)
|
||||
t_pod = Thread(target=self.__watch, args=("pod",))
|
||||
t_ingress = Thread(target=self.__watch, args=("ingress",))
|
||||
t_service = Thread(target=self.__watch, args=("service",))
|
||||
t_pod.start()
|
||||
t_ingress.start()
|
||||
t_service.start()
|
||||
|
@ -106,63 +106,38 @@ class IngressController(Controller.Controller) :
|
|||
t_ingress.join()
|
||||
t_service.join()
|
||||
|
||||
def __watch_pod(self) :
|
||||
def __watch(self, type) :
|
||||
w = watch.Watch()
|
||||
for event in w.stream(self.__api.list_pod_for_all_namespaces, label_selector="bunkerized-nginx") :
|
||||
what = None
|
||||
if type == "pod" :
|
||||
what = self.__api.list_pod_for_all_namespaces
|
||||
elif type == "ingress" :
|
||||
what = self.__extensions_api.list_ingress_for_all_namespaces
|
||||
elif type == "service" :
|
||||
what = self.__api.list_service_for_all_namespaces
|
||||
for event in w.stream(what, label_selector="bunkerized-nginx") :
|
||||
self.lock.acquire()
|
||||
new_env = self.get_env()
|
||||
if new_env != self.__old_env :
|
||||
try :
|
||||
if self.gen_conf(new_env) :
|
||||
self.__old_env = new_env.copy()
|
||||
log("CONTROLLER", "INFO", "successfully generated new configuration")
|
||||
if self.reload() :
|
||||
log("controller", "INFO", "successful reload")
|
||||
else :
|
||||
log("controller", "ERROR", "failed reload")
|
||||
except :
|
||||
log("controller", "ERROR", "exception while receiving event")
|
||||
self.lock.release()
|
||||
|
||||
def __watch_ingress(self) :
|
||||
w = watch.Watch()
|
||||
for event in w.stream(self.__extensions_api.list_ingress_for_all_namespaces, label_selector="bunkerized-nginx") :
|
||||
self.lock.acquire()
|
||||
new_env = self.get_env()
|
||||
if new_env != self.__old_env :
|
||||
try :
|
||||
if self.gen_conf(new_env) :
|
||||
self.__old_env = new_env.copy()
|
||||
log("CONTROLLER", "INFO", "successfully generated new configuration")
|
||||
if self.reload() :
|
||||
log("controller", "INFO", "successful reload")
|
||||
else :
|
||||
log("controller", "ERROR", "failed reload")
|
||||
except :
|
||||
log("controller", "ERROR", "exception while receiving event")
|
||||
self.lock.release()
|
||||
|
||||
def __watch_service(self) :
|
||||
w = watch.Watch()
|
||||
for event in w.stream(self.__api.list_service_for_all_namespaces, label_selector="bunkerized-nginx") :
|
||||
self.lock.acquire()
|
||||
new_env = self.get_env()
|
||||
if new_env != self.__old_env :
|
||||
try :
|
||||
if self.gen_conf(new_env) :
|
||||
self.__old_env = new_env.copy()
|
||||
log("CONTROLLER", "INFO", "successfully generated new configuration")
|
||||
if self.reload() :
|
||||
log("controller", "INFO", "successful reload")
|
||||
else :
|
||||
log("controller", "ERROR", "failed reload")
|
||||
except :
|
||||
log("controller", "ERROR", "exception while receiving event")
|
||||
if not self.gen_conf(new_env) :
|
||||
raise Exception("can't generate configuration")
|
||||
if not self.send() :
|
||||
raise Exception("can't send configuration")
|
||||
if not self.reload() :
|
||||
raise Exception("can't reload configuration")
|
||||
self.__old_env = new_env.copy()
|
||||
log("CONTROLLER", "INFO", "successfully loaded new configuration")
|
||||
except Exception as e :
|
||||
log("controller", "ERROR", "error while computing new event : " + str(e))
|
||||
self.lock.release()
|
||||
|
||||
def reload(self) :
|
||||
return self._reload(self.__get_services(autoconf=True))
|
||||
|
||||
def send(self) :
|
||||
return self._send(self.__get_services(autoconf=True))
|
||||
|
||||
def wait(self) :
|
||||
self.lock.acquire()
|
||||
try :
|
||||
|
|
|
@ -46,23 +46,24 @@ class SwarmController(Controller.Controller) :
|
|||
if new_env != old_env :
|
||||
self.lock.acquire()
|
||||
try :
|
||||
log("controller", "INFO", "generating new configuration")
|
||||
if self.gen_conf(new_env) :
|
||||
old_env = new_env.copy()
|
||||
log("controller", "INFO", "successfully generated new configuration")
|
||||
if self.reload() :
|
||||
log("controller", "INFO", "successful reload")
|
||||
else :
|
||||
log("controller", "ERROR", "failed reload")
|
||||
else :
|
||||
log("controller", "ERROR", "can't generate new configuration")
|
||||
except :
|
||||
log("controller", "ERROR", "exception while receiving event")
|
||||
if not self.gen_conf(new_env) :
|
||||
raise Exception("can't generate configuration")
|
||||
if not self.send() :
|
||||
raise Exception("can't send configuration")
|
||||
if not self.reload() :
|
||||
raise Exception("can't reload configuration")
|
||||
self.__old_env = new_env.copy()
|
||||
log("CONTROLLER", "INFO", "successfully loaded new configuration")
|
||||
except Exception as e :
|
||||
log("controller", "ERROR", "error while computing new event : " + str(e))
|
||||
self.lock.release()
|
||||
|
||||
def reload(self) :
|
||||
return self._reload(self.__get_instances())
|
||||
|
||||
def send(self) :
|
||||
return self._send(self.__get_instances())
|
||||
|
||||
def wait(self) :
|
||||
self.lock.acquire()
|
||||
try :
|
||||
|
|
|
@ -820,6 +820,7 @@ do_and_check_cmd chmod 750 /opt/bunkerized-nginx/entrypoint/*
|
|||
do_and_check_cmd chmod 750 /opt/bunkerized-nginx/gen/main.py
|
||||
do_and_check_cmd chmod 750 /opt/bunkerized-nginx/jobs/main.py
|
||||
do_and_check_cmd chmod 750 /opt/bunkerized-nginx/jobs/reload.py
|
||||
do_and_check_cmd chmod 750 /opt/bunkerized-nginx/jobs/certbot-*.sh
|
||||
# Set permissions for /usr/local/bin/bunkerized-nginx
|
||||
do_and_check_cmd chown root:root /usr/local/bin/bunkerized-nginx
|
||||
do_and_check_cmd chmod 750 /usr/local/bin/bunkerized-nginx
|
||||
|
|
|
@ -37,31 +37,10 @@ spec:
|
|||
- name: MULTISITE
|
||||
value: "yes"
|
||||
volumeMounts:
|
||||
- name: confs
|
||||
mountPath: /etc/nginx
|
||||
readOnly: true
|
||||
- name: letsencrypt
|
||||
mountPath: /etc/letsencrypt
|
||||
readOnly: true
|
||||
- name: acme-challenge
|
||||
mountPath: /acme-challenge
|
||||
readOnly: true
|
||||
- name: www
|
||||
mountPath: /www
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: confs
|
||||
hostPath:
|
||||
path: /shared/confs
|
||||
type: Directory
|
||||
- name: letsencrypt
|
||||
hostPath:
|
||||
path: /shared/letsencrypt
|
||||
type: Directory
|
||||
- name: acme-challenge
|
||||
hostPath:
|
||||
path: /shared/acme-challenge
|
||||
type: Directory
|
||||
- name: www
|
||||
hostPath:
|
||||
path: /shared/www
|
||||
|
@ -108,22 +87,10 @@ spec:
|
|||
- name: API_URI
|
||||
value: "/ChangeMeToSomethingHardToGuess"
|
||||
volumeMounts:
|
||||
- name: confs
|
||||
mountPath: /etc/nginx
|
||||
- name: letsencrypt
|
||||
mountPath: /etc/letsencrypt
|
||||
- name: acme-challenge
|
||||
mountPath: /acme-challenge
|
||||
volumes:
|
||||
- name: confs
|
||||
hostPath:
|
||||
path: /shared/confs
|
||||
type: Directory
|
||||
- name: letsencrypt
|
||||
hostPath:
|
||||
path: /shared/letsencrypt
|
||||
type: Directory
|
||||
- name: acme-challenge
|
||||
hostPath:
|
||||
path: /shared/acme-challenge
|
||||
type: Directory
|
||||
|
|
|
@ -14,10 +14,7 @@ services:
|
|||
mode: host
|
||||
protocol: tcp
|
||||
volumes:
|
||||
- /shared/confs:/etc/nginx:ro
|
||||
- /shared/www:/www:ro
|
||||
- /shared/letsencrypt:/etc/letsencrypt:ro
|
||||
- /shared/acme-challenge:/acme-challenge:ro
|
||||
environment:
|
||||
- SWARM_MODE=yes
|
||||
- USE_API=yes
|
||||
|
@ -41,9 +38,7 @@ services:
|
|||
image: bunkerity/bunkerized-nginx-autoconf
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- /shared/confs:/etc/nginx
|
||||
- /shared/letsencrypt:/etc/letsencrypt
|
||||
- /shared/acme-challenge:/acme-challenge
|
||||
environment:
|
||||
- SWARM_MODE=yes
|
||||
- API_URI=/ChangeMeToSomethingHardToGuess # must match API_URI from nginx
|
||||
|
|
|
@ -6,7 +6,7 @@ class CertbotNew(Job) :
|
|||
|
||||
def __init__(self, redis_host=None, copy_cache=False, domain="", email="", staging=False) :
|
||||
name = "certbot-new"
|
||||
data = ["certbot", "certonly", "--webroot", "-w", "/opt/bunkerized-nginx/acme-challenge", "-n", "-d", domain, "--email", email, "--agree-tos"]
|
||||
data = ["certbot", "certonly", "--manual", "--preferred-challenges=http", "--manual-auth-hook", "/opt/bunkerized-nginx/jobs/certbot-auth.sh", "--manual-cleanup-hook", "/opt/bunkerized-nginx/jobs/certbot-cleanup.sh", "-n", "-d", domain, "--email", email, "--agree-tos"]
|
||||
if staging :
|
||||
data.append("--staging")
|
||||
type = "exec"
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo $CERTBOT_VALIDATION > /opt/bunkerized-nginx/acme-challenge/.well-known/acme-challenge/$CERTBOT_TOKEN
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
rm -f /opt/bunkerized-nginx/acme-challenge/.well-known/acme-challenge/$CERTBOT_TOKEN
|
10
lua/api.lua
10
lua/api.lua
|
@ -41,6 +41,13 @@ api_list["^/letsencrypt$"] = function ()
|
|||
return M.extract_file("/tmp/letsencrypt.tar.gz", "/etc/letsencrypt/")
|
||||
end
|
||||
|
||||
api_list["^/acme$"] = function ()
|
||||
if not M.save_file("/tmp/acme.tar.gz") then
|
||||
return false
|
||||
end
|
||||
return M.extract_file("/tmp/acme.tar.gz", "/acme-challenge")
|
||||
end
|
||||
|
||||
api_list["^/http$"] = function ()
|
||||
if not M.save_file("/tmp/http.tar.gz") then
|
||||
return false
|
||||
|
@ -75,7 +82,7 @@ function M.save_file (name)
|
|||
return false
|
||||
end
|
||||
form:set_timeout(1000)
|
||||
file = io.open(name, "a")
|
||||
file = io.open(name, "w")
|
||||
while true do
|
||||
local typ, res, err = form:read()
|
||||
if not typ then
|
||||
|
@ -89,6 +96,7 @@ function M.save_file (name)
|
|||
file:write(res)
|
||||
end
|
||||
end
|
||||
file:flush()
|
||||
file:close()
|
||||
return true
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue