From f1d5c07cc10c337766822ddbfbe4b4425492945e Mon Sep 17 00:00:00 2001 From: bunkerity Date: Fri, 13 Aug 2021 16:42:31 +0200 Subject: [PATCH] autoconf - various kubernetes fixes --- autoconf/src/IngressController.py | 4 +- autoconf/src/SwarmController.py | 6 +- docs/integrations.md | 4 +- helpers/autoconf.yml | 39 ++++++++ helpers/kubernetes-ingress.yml | 65 -------------- helpers/kubernetes-nginx.yml | 145 ++++++++++-------------------- helpers/swarm.yml | 67 ++++++++++++++ jobs/main.py | 13 ++- misc/cron-autoconf | 14 +-- 9 files changed, 180 insertions(+), 177 deletions(-) create mode 100644 helpers/autoconf.yml delete mode 100644 helpers/kubernetes-ingress.yml create mode 100644 helpers/swarm.yml diff --git a/autoconf/src/IngressController.py b/autoconf/src/IngressController.py index 6907d3d..d2a1add 100644 --- a/autoconf/src/IngressController.py +++ b/autoconf/src/IngressController.py @@ -86,7 +86,7 @@ class IngressController(Controller.Controller) : for service in services : if service.metadata.annotations != None and "bunkerized-nginx.SERVER_NAME" in service.metadata.annotations : env.update(self.__annotations_to_env(service.metadata.annotations)) - first_servers.append(service.metadata.annotations["SERVER_NAME"]) + first_servers.append(service.metadata.annotations["bunkerized-nginx.SERVER_NAME"]) first_servers = list(dict.fromkeys(first_servers)) if len(first_servers) == 0 : env["SERVER_NAME"] = "" @@ -181,9 +181,11 @@ class IngressController(Controller.Controller) : # Generate first config env = self.get_env() if not self.gen_conf(env) : + self.lock.release() return False, env # Wait for bunkerized-nginx + self.lock.release() return self._config.wait(services), env except : pass diff --git a/autoconf/src/SwarmController.py b/autoconf/src/SwarmController.py index 171e0c2..c7cc974 100644 --- a/autoconf/src/SwarmController.py +++ b/autoconf/src/SwarmController.py @@ -56,8 +56,8 @@ class SwarmController(Controller.Controller) : log("controller", "ERROR", "failed reload") else : log("controller", "ERROR", "can't generate new configuration") - except : - log("controller", "ERROR", "exception while receiving event") + except : + log("controller", "ERROR", "exception while receiving event") self.lock.release() def reload(self) : @@ -74,8 +74,10 @@ class SwarmController(Controller.Controller) : # Generate first config env = self.get_env() if not self.gen_conf(env) : + self.lock.release() return False, env # Wait for nginx + self.lock.release() return self._config.wait(instances), env except : pass diff --git a/docs/integrations.md b/docs/integrations.md index 9cb95de..f6801b1 100644 --- a/docs/integrations.md +++ b/docs/integrations.md @@ -712,6 +712,7 @@ metadata: bunkerized-nginx: "yes" annotations: bunkerized-nginx.SERVER_NAME: "www.example.com" + bunkerized-nginx.AUTO_LETS_ENCRYPT: "yes" bunkerized-nginx.USE_REVERSE_PROXY: "yes" bunkerized-nginx.REVERSE_PROXY_URL: "/" bunkerized-nginx.REVERSE_PROXY_HOST: "http://myapp" @@ -749,8 +750,7 @@ $ curl -fsSL https://TODO -o /tmp/bunkerized-nginx.sh Before executing it, you should also check the signature : ```shell $ curl -fsSL https://TODO -o /tmp/bunkerized-nginx.sh.asc -$ curl -fsSL https://TODO -o /tmp/bunkerized-nginx.key -$ gpg --import /tmp/bunkerized-nginx.key +$ gpg --auto-key-locate hkps://keys.openpgp.org --locate-keys contact@bunkerity.com $ gpg --verify /tmp/bunkerized-nginx.sh.asc /tmp/bunkerized-nginx.sh ``` diff --git a/helpers/autoconf.yml b/helpers/autoconf.yml new file mode 100644 index 0000000..9d83846 --- /dev/null +++ b/helpers/autoconf.yml @@ -0,0 +1,39 @@ +version: '3' + +services: + + mybunkerized: + image: bunkerity/bunkerized-nginx + restart: always + ports: + - 80:8080 + - 443:8443 + volumes: + - ./certs:/etc/letsencrypt + - ./www:/www:ro + - bunkerized-vol:/etc/nginx + environment: + - SERVER_NAME= + - MULTISITE=yes + - AUTO_LETS_ENCRYPT=yes + labels: + - "bunkerized-nginx.AUTOCONF" + networks: + - services-net + + myautoconf: + image: bunkerity/bunkerized-nginx-autoconf + restart: always + volumes_from: + - mybunkerized + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + depends_on: + - mybunkerized + +volumes: + bunkerized-vol: + +networks: + services-net: + name: services-net diff --git a/helpers/kubernetes-ingress.yml b/helpers/kubernetes-ingress.yml deleted file mode 100644 index f3005e4..0000000 --- a/helpers/kubernetes-ingress.yml +++ /dev/null @@ -1,65 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: bunkerized-nginx-ingress - labels: - bunkerized-nginx: "yes" - annotations: - # add any global and default environment variables here as annotations with the "bunkerized-nginx." prefix - # examples : - #bunkerized-nginx.AUTO_LETS_ENCRYPT: "yes" - #bunkerized-nginx.USE_ANTIBOT: "javascript" - #bunkerized-nginx.REDIRECT_HTTP_TO_HTTPS: "yes" - #bunkerized-nginx.app.example.com_REVERSE_PROXY_WS: "yes" - #bunkerized-nginx.app.example.com_USE_MODSECURITY: "no" - -# add "static" routes here (see https://kubernetes.io/docs/concepts/services-networking/ingress/) -# and/or add annotations to your services (see https://github.com/bunkerity/bunkerized-nginx/tree/master/examples/kubernetes) -spec: - tls: - - hosts: - - app.example.com - rules: - - host: "app.example.com" - http: - paths: - - pathType: Prefix - path: "/" - backend: - service: - name: myapp - port: - number: 80 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: myapp - labels: - app: myapp -spec: - replicas: 1 - selector: - matchLabels: - app: myapp - template: - metadata: - labels: - app: myapp - spec: - containers: - - name: myapp - image: containous/whoami ---- -apiVersion: v1 -kind: Service -metadata: - name: myapp -spec: - type: ClusterIP - selector: - app: myapp - ports: - - protocol: TCP - port: 80 - targetPort: 80 diff --git a/helpers/kubernetes-nginx.yml b/helpers/kubernetes-nginx.yml index 8001eec..63c066f 100644 --- a/helpers/kubernetes-nginx.yml +++ b/helpers/kubernetes-nginx.yml @@ -1,71 +1,4 @@ apiVersion: apps/v1 -kind: Deployment -metadata: - name: bunkerized-nginx-ingress-controller - labels: - app: bunkerized-nginx-autoconf -spec: - replicas: 1 - selector: - matchLabels: - app: bunkerized-nginx-autoconf - template: - metadata: - labels: - app: bunkerized-nginx-autoconf - spec: - serviceAccountName: bunkerized-nginx-ingress-controller - containers: - - name: bunkerized-nginx-autoconf - image: bunkerity/bunkerized-nginx-autoconf - #imagePullPolicy: Always - env: - - name: KUBERNETES_MODE - value: "yes" - - name: API_URI - value: "/ChangeMeToSomethingHardToGuess" - volumeMounts: - - name: confs - mountPath: /etc/nginx - - name: letsencrypt - mountPath: /etc/letsencrypt - - name: acme-challenge - mountPath: /acme-challenge - - name: cache - mountPath: /cache - - name: modsec-confs - mountPath: /modsec-confs - readOnly: true - - name: modsec-crs-confs - mountPath: /modsec-crs-confs - 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: cache - hostPath: - path: /shared/cache - type: Directory - - name: modsec-confs - hostPath: - path: /shared/modsec-confs - type: Directory - - name: modsec-crs-confs - hostPath: - path: /shared/modsec-crs-confs - type: Directory ---- -apiVersion: apps/v1 kind: DaemonSet metadata: name: bunkerized-nginx @@ -79,12 +12,12 @@ spec: metadata: labels: name: bunkerized-nginx + # this label is mandatory bunkerized-nginx: "yes" spec: containers: - name: bunkerized-nginx image: bunkerity/bunkerized-nginx - #imagePullPolicy: Always ports: - containerPort: 8080 hostPort: 80 @@ -114,18 +47,6 @@ spec: - name: www mountPath: /www readOnly: true - - name: http-confs - mountPath: /http-confs - readOnly: true - - name: server-confs - mountPath: /server-confs - readOnly: true - - name: modsec-confs - mountPath: /modsec-confs - readOnly: true - - name: modsec-crs-confs - mountPath: /modsec-crs-confs - readOnly: true volumes: - name: confs hostPath: @@ -143,32 +64,64 @@ spec: hostPath: path: /shared/www type: Directory - - name: http-confs - hostPath: - path: /shared/http-confs - type: Directory - - name: server-confs - hostPath: - path: /shared/server-confs - type: Directory - - name: modsec-confs - hostPath: - path: /shared/modsec-confs - type: Directory - - name: modsec-crs-confs - hostPath: - path: /shared/modsec-crs-confs - type: Directory --- apiVersion: v1 kind: Service metadata: name: bunkerized-nginx-service + # this label is mandatory labels: bunkerized-nginx: "yes" + # this annotation is mandatory annotations: bunkerized-nginx.AUTOCONF: "yes" spec: clusterIP: None selector: name: bunkerized-nginx +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: bunkerized-nginx-ingress-controller + labels: + app: bunkerized-nginx-autoconf +spec: + replicas: 1 + selector: + matchLabels: + app: bunkerized-nginx-autoconf + template: + metadata: + labels: + app: bunkerized-nginx-autoconf + spec: + serviceAccountName: bunkerized-nginx-ingress-controller + containers: + - name: bunkerized-nginx-autoconf + image: bunkerity/bunkerized-nginx-autoconf + env: + - name: KUBERNETES_MODE + value: "yes" + - 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 diff --git a/helpers/swarm.yml b/helpers/swarm.yml new file mode 100644 index 0000000..46f8ca7 --- /dev/null +++ b/helpers/swarm.yml @@ -0,0 +1,67 @@ +version: '3.8' + +services: + + nginx: + image: bunkerity/bunkerized-nginx + ports: + - published: 80 + target: 8080 + mode: host + protocol: tcp + - published: 443 + target: 8443 + 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 + - API_URI=/ChangeMeToSomethingHardToGuess # must match API_URI from autoconf + - MULTISITE=yes + - SERVER_NAME= + - AUTO_LETS_ENCRYPT=yes + networks: + - bunkerized-net + - services-net + deploy: + mode: global + placement: + constraints: + - "node.role==worker" + # mandatory label + labels: + - "bunkerized-nginx.AUTOCONF" + + autoconf: + 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 + networks: + - bunkerized-net + deploy: + replicas: 1 + placement: + constraints: + - "node.role==manager" + +# This will create the networks for you +networks: + bunkerized-net: + driver: overlay + attachable: true + name: bunkerized-net + services-net: + driver: overlay + attachable: true + name: services-net diff --git a/jobs/main.py b/jobs/main.py index fa4895a..55fa777 100644 --- a/jobs/main.py +++ b/jobs/main.py @@ -27,6 +27,7 @@ if __name__ == "__main__" : parser = argparse.ArgumentParser(description="job runner for bunkerized-nginx") parser.add_argument("--name", default="", type=str, help="job to run (e.g : abusers or certbot-new or certbot-renew ...)") parser.add_argument("--cache", action="store_true", help="copy data from cache if available") + parser.add_argument("--lock", action="store_true", help="lock access to the configuration") parser.add_argument("--reload", action="store_true", help="reload nginx if necessary and the job is successful") parser.add_argument("--domain", default="", type=str, help="domain(s) for certbot-new job (e.g. : www.example.com or app1.example.com,app2.example.com)") parser.add_argument("--email", default="", type=str, help="email for certbot-new job (e.g. : contact@example.com)") @@ -45,7 +46,8 @@ if __name__ == "__main__" : # Acquire the lock before management = JobManagement() - management.lock() + if args.lock : + management.lock() # Check if we are using redis or not redis_host = None @@ -71,7 +73,8 @@ if __name__ == "__main__" : ret = instance.run() if ret == JobRet.KO : log("job", "ERROR", "error while running job " + job) - management.unlock() + if args.lock : + management.unlock() sys.exit(1) log("job", "INFO", "job " + job + " successfully executed") @@ -80,7 +83,8 @@ if __name__ == "__main__" : ret = management.reload() if ret == ReloadRet.KO : log("job", "ERROR", "error while doing reload operation (job = " + job + ")") - management.unlock() + if args.lock : + management.unlock() sys.exit(1) elif ret == ReloadRet.OK : log("job", "INFO", "reload operation successfully executed (job = " + job + ")") @@ -90,7 +94,8 @@ if __name__ == "__main__" : log("job", "INFO", "skipped reload operation because it's not needed (job = " + job + ")") # Release the lock - management.unlock() + if args.lock : + management.unlock() # Done sys.exit(0) diff --git a/misc/cron-autoconf b/misc/cron-autoconf index 01843ca..72af41e 100644 --- a/misc/cron-autoconf +++ b/misc/cron-autoconf @@ -1,7 +1,7 @@ -15 0 * * * /bin/su -c "/opt/bunkerized-nginx/jobs/main.py --reload --name certbot-renew" nginx >> /var/log/nginx/jobs.log 2>&1 -30 0 * * * /bin/su -c "/opt/bunkerized-nginx/jobs/main.py --reload --name user-agents" nginx >> /var/log/nginx/jobs.log 2>&1 -45 0 * * * /bin/su -c "/opt/bunkerized-nginx/jobs/main.py --reload --name referrers" nginx >> /var/log/nginx/jobs.log 2>&1 -0 1 * * * /bin/su -c "/opt/bunkerized-nginx/jobs/main.py --reload --name abusers" nginx >> /var/log/nginx/jobs.log 2>&1 -0 2 * * * /bin/su -c "/opt/bunkerized-nginx/jobs/main.py --reload --name proxies" nginx >> /var/log/nginx/jobs.log 2>&1 -0 */1 * * * /bin/su -c "/opt/bunkerized-nginx/jobs/main.py --reload --name exit-nodes" nginx >> /var/log/nginx/jobs.log 2>&1 -0 3 2 * * /bin/su -c "/opt/bunkerized-nginx/jobs/main.py --reload --name geoip" nginx >> /var/log/nginx/jobs.log 2>&1 +15 0 * * * /bin/su -c "/opt/bunkerized-nginx/jobs/main.py --reload --lock --name certbot-renew" nginx >> /var/log/nginx/jobs.log 2>&1 +30 0 * * * /bin/su -c "/opt/bunkerized-nginx/jobs/main.py --reload --lock --name user-agents" nginx >> /var/log/nginx/jobs.log 2>&1 +45 0 * * * /bin/su -c "/opt/bunkerized-nginx/jobs/main.py --reload --lock --name referrers" nginx >> /var/log/nginx/jobs.log 2>&1 +0 1 * * * /bin/su -c "/opt/bunkerized-nginx/jobs/main.py --reload --lock --name abusers" nginx >> /var/log/nginx/jobs.log 2>&1 +0 2 * * * /bin/su -c "/opt/bunkerized-nginx/jobs/main.py --reload --lock --name proxies" nginx >> /var/log/nginx/jobs.log 2>&1 +0 */1 * * * /bin/su -c "/opt/bunkerized-nginx/jobs/main.py --reload --lock --name exit-nodes" nginx >> /var/log/nginx/jobs.log 2>&1 +0 3 2 * * /bin/su -c "/opt/bunkerized-nginx/jobs/main.py --reload --lock --name geoip" nginx >> /var/log/nginx/jobs.log 2>&1