Make certbot compatible with 1.5
This commit is contained in:
parent
aaeda53002
commit
4e96e57e05
|
@ -1,32 +1,46 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import sys, os, traceback
|
||||
from os import getenv, makedirs
|
||||
from os.path import exists
|
||||
from sys import exit as sys_exit, path as sys_path
|
||||
from traceback import format_exc
|
||||
|
||||
sys.path.append("/usr/share/bunkerweb/deps/python")
|
||||
sys.path.append("/usr/share/bunkerweb/utils")
|
||||
sys.path.append("/usr/share/bunkerweb/api")
|
||||
sys_path.append("/usr/share/bunkerweb/deps/python")
|
||||
sys_path.append("/usr/share/bunkerweb/utils")
|
||||
sys_path.append("/usr/share/bunkerweb/api")
|
||||
sys_path.append("/usr/share/bunkerweb/db")
|
||||
|
||||
from Database import Database
|
||||
from logger import setup_logger
|
||||
from API import API
|
||||
|
||||
logger = setup_logger("Lets-encrypt", os.getenv("LOG_LEVEL", "INFO"))
|
||||
logger = setup_logger("Lets-encrypt", getenv("LOG_LEVEL", "INFO"))
|
||||
db = Database(
|
||||
logger,
|
||||
sqlalchemy_string=getenv("DATABASE_URI", None),
|
||||
)
|
||||
status = 0
|
||||
|
||||
try:
|
||||
# Get env vars
|
||||
is_kubernetes_mode = os.getenv("KUBERNETES_MODE") == "yes"
|
||||
is_swarm_mode = os.getenv("SWARM_MODE") == "yes"
|
||||
is_autoconf_mode = os.getenv("AUTOCONF_MODE") == "yes"
|
||||
token = os.getenv("CERTBOT_TOKEN")
|
||||
validation = os.getenv("CERTBOT_VALIDATION")
|
||||
bw_integration = None
|
||||
if getenv("KUBERNETES_MODE") == "yes":
|
||||
bw_integration = "Swarm"
|
||||
elif getenv("SWARM_MODE") == "yes":
|
||||
bw_integration = "Kubernetes"
|
||||
elif getenv("AUTOCONF_MODE") == "yes":
|
||||
bw_integration = "Autoconf"
|
||||
elif exists("/usr/share/bunkerweb/INTEGRATION"):
|
||||
with open("/usr/share/bunkerweb/INTEGRATION", "r") as f:
|
||||
bw_integration = f.read().strip()
|
||||
token = getenv("CERTBOT_TOKEN")
|
||||
validation = getenv("CERTBOT_VALIDATION")
|
||||
|
||||
# Cluster case
|
||||
if is_kubernetes_mode or is_swarm_mode or is_autoconf_mode:
|
||||
for variable, value in os.environ.items():
|
||||
if not variable.startswith("CLUSTER_INSTANCE_"):
|
||||
continue
|
||||
endpoint = value.split(" ")[0]
|
||||
host = value.split(" ")[1]
|
||||
if bw_integration in ("Docker", "Swarm", "Kubernetes", "Autoconf"):
|
||||
for instance in db.get_instances():
|
||||
endpoint = f"http://{instance['hostname']}:{instance['port']}"
|
||||
host = instance["server_name"]
|
||||
api = API(endpoint, host=host)
|
||||
sent, err, status, resp = api.request(
|
||||
"POST",
|
||||
|
@ -49,15 +63,14 @@ try:
|
|||
f"Successfully sent API request to {api.get_endpoint()}/lets-encrypt/challenge",
|
||||
)
|
||||
|
||||
# Docker or Linux case
|
||||
# Linux case
|
||||
else:
|
||||
root_dir = "/var/tmp/bunkerweb/lets-encrypt/.well-known/acme-challenge/"
|
||||
os.makedirs(root_dir, exist_ok=True)
|
||||
with open(root_dir + token, "w") as f:
|
||||
makedirs(root_dir, exist_ok=True)
|
||||
with open(f"{root_dir}{token}", "w") as f:
|
||||
f.write(validation)
|
||||
except:
|
||||
status = 1
|
||||
logger.error("Exception while running certbot-auth.py :")
|
||||
print(traceback.format_exc())
|
||||
logger.error(f"Exception while running certbot-auth.py :\n{format_exc()}")
|
||||
|
||||
sys.exit(status)
|
||||
sys_exit(status)
|
||||
|
|
|
@ -1,31 +1,45 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import sys, os, traceback
|
||||
from os import getenv, remove
|
||||
from os.path import exists, isfile
|
||||
from sys import exit as sys_exit, path as sys_path
|
||||
from traceback import format_exc
|
||||
|
||||
sys.path.append("/usr/share/bunkerweb/deps/python")
|
||||
sys.path.append("/usr/share/bunkerweb/utils")
|
||||
sys.path.append("/usr/share/bunkerweb/api")
|
||||
sys_path.append("/usr/share/bunkerweb/deps/python")
|
||||
sys_path.append("/usr/share/bunkerweb/utils")
|
||||
sys_path.append("/usr/share/bunkerweb/api")
|
||||
sys_path.append("/usr/share/bunkerweb/db")
|
||||
|
||||
from Database import Database
|
||||
from logger import setup_logger
|
||||
from API import API
|
||||
|
||||
logger = setup_logger("Lets-encrypt", os.getenv("LOG_LEVEL", "INFO"))
|
||||
logger = setup_logger("Lets-encrypt", getenv("LOG_LEVEL", "INFO"))
|
||||
db = Database(
|
||||
logger,
|
||||
sqlalchemy_string=getenv("DATABASE_URI", None),
|
||||
)
|
||||
status = 0
|
||||
|
||||
try:
|
||||
# Get env vars
|
||||
is_kubernetes_mode = os.getenv("KUBERNETES_MODE") == "yes"
|
||||
is_swarm_mode = os.getenv("SWARM_MODE") == "yes"
|
||||
is_autoconf_mode = os.getenv("AUTOCONF_MODE") == "yes"
|
||||
token = os.getenv("CERTBOT_TOKEN")
|
||||
bw_integration = None
|
||||
if getenv("KUBERNETES_MODE") == "yes":
|
||||
bw_integration = "Swarm"
|
||||
elif getenv("SWARM_MODE") == "yes":
|
||||
bw_integration = "Kubernetes"
|
||||
elif getenv("AUTOCONF_MODE") == "yes":
|
||||
bw_integration = "Autoconf"
|
||||
elif exists("/usr/share/bunkerweb/INTEGRATION"):
|
||||
with open("/usr/share/bunkerweb/INTEGRATION", "r") as f:
|
||||
bw_integration = f.read().strip()
|
||||
token = getenv("CERTBOT_TOKEN")
|
||||
|
||||
# Cluster case
|
||||
if is_kubernetes_mode or is_swarm_mode or is_autoconf_mode:
|
||||
for variable, value in os.environ.items():
|
||||
if not variable.startswith("CLUSTER_INSTANCE_"):
|
||||
continue
|
||||
endpoint = value.split(" ")[0]
|
||||
host = value.split(" ")[1]
|
||||
if bw_integration in ("Docker", "Swarm", "Kubernetes", "Autoconf"):
|
||||
for instance in db.get_instances():
|
||||
endpoint = f"http://{instance['hostname']}:{instance['port']}"
|
||||
host = instance["server_name"]
|
||||
api = API(endpoint, host=host)
|
||||
sent, err, status, resp = api.request(
|
||||
"DELETE", "/lets-encrypt/challenge", data={"token": token}
|
||||
|
@ -45,17 +59,15 @@ try:
|
|||
logger.info(
|
||||
f"Successfully sent API request to {api.get_endpoint()}/lets-encrypt/challenge",
|
||||
)
|
||||
|
||||
# Docker or Linux case
|
||||
# Linux case
|
||||
else:
|
||||
challenge_path = (
|
||||
f"/var/tmp/bunkerweb/lets-encrypt/.well-known/acme-challenge/{token}"
|
||||
)
|
||||
if os.path.isfile(challenge_path):
|
||||
os.remove(challenge_path)
|
||||
if isfile(challenge_path):
|
||||
remove(challenge_path)
|
||||
except:
|
||||
status = 1
|
||||
logger.error("Exception while running certbot-cleanup.py :")
|
||||
print(traceback.format_exc())
|
||||
logger.error(f"Exception while running certbot-cleanup.py :\n{format_exc()}")
|
||||
|
||||
sys.exit(status)
|
||||
sys_exit(status)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
from io import BytesIO
|
||||
from os import environ, getenv
|
||||
from os import getenv
|
||||
from os.path import exists
|
||||
from subprocess import run, DEVNULL, STDOUT
|
||||
from sys import exit as sys_exit, path as sys_path
|
||||
|
@ -11,13 +11,17 @@ from traceback import format_exc
|
|||
sys_path.append("/usr/share/bunkerweb/deps/python")
|
||||
sys_path.append("/usr/share/bunkerweb/utils")
|
||||
sys_path.append("/usr/share/bunkerweb/api")
|
||||
sys_path.append("/usr/share/bunkerweb/db")
|
||||
|
||||
from docker import DockerClient
|
||||
|
||||
from Database import Database
|
||||
from logger import setup_logger
|
||||
from API import API
|
||||
|
||||
logger = setup_logger("Lets-encrypt", getenv("LOG_LEVEL", "INFO"))
|
||||
db = Database(
|
||||
logger,
|
||||
sqlalchemy_string=getenv("DATABASE_URI", None),
|
||||
)
|
||||
status = 0
|
||||
|
||||
try:
|
||||
|
@ -33,11 +37,11 @@ try:
|
|||
with open("/usr/share/bunkerweb/INTEGRATION", "r") as f:
|
||||
bw_integration = f.read().strip()
|
||||
token = getenv("CERTBOT_TOKEN")
|
||||
|
||||
|
||||
logger.info(f"Certificates renewal for {getenv('RENEWED_DOMAINS')} successful")
|
||||
|
||||
# Cluster case
|
||||
if bw_integration in ("Swarm", "Kubernetes", "Autoconf"):
|
||||
if bw_integration in ("Docker", "Swarm", "Kubernetes", "Autoconf"):
|
||||
# Create tarball of /data/cache/letsencrypt
|
||||
tgz = BytesIO()
|
||||
with tar_open(mode="w:gz", fileobj=tgz) as tf:
|
||||
|
@ -45,11 +49,9 @@ try:
|
|||
tgz.seek(0, 0)
|
||||
files = {"archive.tar.gz": tgz}
|
||||
|
||||
for variable, value in environ.items():
|
||||
if not variable.startswith("CLUSTER_INSTANCE_"):
|
||||
continue
|
||||
endpoint = value.split(" ")[0]
|
||||
host = value.split(" ")[1]
|
||||
for instance in db.get_instances():
|
||||
endpoint = f"http://{instance['hostname']}:{instance['port']}"
|
||||
host = instance["server_name"]
|
||||
api = API(endpoint, host=host)
|
||||
sent, err, status, resp = api.request(
|
||||
"POST", "/lets-encrypt/certificates", files=files
|
||||
|
@ -85,53 +87,13 @@ try:
|
|||
logger.info(
|
||||
f"Successfully sent API request to {api.get_endpoint()}/reload"
|
||||
)
|
||||
|
||||
# Docker or Linux case
|
||||
elif bw_integration == "Docker":
|
||||
docker_client = DockerClient(
|
||||
base_url=getenv("DOCKER_HOST", "unix:///var/run/docker.sock")
|
||||
# Linux case
|
||||
else:
|
||||
proc = run(
|
||||
["nginx", "-s", "reload"],
|
||||
stdin=DEVNULL,
|
||||
stderr=STDOUT,
|
||||
)
|
||||
|
||||
apis = []
|
||||
for instance in docker_client.containers.list(
|
||||
filters={"label": "bunkerweb.INSTANCE"}
|
||||
):
|
||||
api = None
|
||||
|
||||
for var in instance.attrs["Config"]["Env"]:
|
||||
if var.startswith("API_HTTP_PORT="):
|
||||
api = API(
|
||||
f"http://{instance.name}:{var.replace('API_HTTP_PORT=', '', 1)}"
|
||||
)
|
||||
break
|
||||
|
||||
if api:
|
||||
apis.append(api)
|
||||
else:
|
||||
apis.append(
|
||||
API(f"http://{instance.name}:{getenv('API_HTTP_PORT', '5000')}")
|
||||
)
|
||||
|
||||
for api in apis:
|
||||
sent, err, status, resp = api.request("POST", "/reload")
|
||||
if not sent:
|
||||
status = 1
|
||||
logger.error(
|
||||
f"Can't send API request to {api.get_endpoint()}/reload : {err}"
|
||||
)
|
||||
else:
|
||||
if status != 200:
|
||||
status = 1
|
||||
logger.error(
|
||||
f"Error while sending API request to {api.get_endpoint()}/reload : status = {resp['status']}, msg = {resp['msg']}"
|
||||
)
|
||||
else:
|
||||
logger.info(
|
||||
f"Successfully sent API request to {api.get_endpoint()}/reload"
|
||||
)
|
||||
elif bw_integration == "Linux":
|
||||
cmd = "/usr/sbin/nginx -s reload"
|
||||
proc = run(cmd.split(" "), stdin=DEVNULL, stderr=STDOUT)
|
||||
if proc.returncode != 0:
|
||||
status = 1
|
||||
logger.error("Error while reloading nginx")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
from os import environ, getenv
|
||||
from os import environ, getcwd, getenv
|
||||
from os.path import exists
|
||||
from subprocess import DEVNULL, STDOUT, run
|
||||
from sys import exit as sys_exit, path as sys_path
|
||||
|
@ -8,17 +8,42 @@ from traceback import format_exc
|
|||
|
||||
sys_path.append("/usr/share/bunkerweb/deps/python")
|
||||
sys_path.append("/usr/share/bunkerweb/utils")
|
||||
sys_path.append("/usr/share/bunkerweb/db")
|
||||
|
||||
from Database import Database
|
||||
from logger import setup_logger
|
||||
|
||||
logger = setup_logger("LETS-ENCRYPT", getenv("LOG_LEVEL", "INFO"))
|
||||
db = Database(
|
||||
logger,
|
||||
sqlalchemy_string=getenv("DATABASE_URI", None),
|
||||
)
|
||||
status = 0
|
||||
|
||||
|
||||
def certbot_new(domains, email):
|
||||
cmd = f"/usr/share/bunkerweb/deps/python/bin/certbot certonly --manual --preferred-challenges=http --manual-auth-hook /usr/share/bunkerweb/core/letsencrypt/jobs/certbot-auth.py --manual-cleanup-hook /usr/share/bunkerweb/core/letsencrypt/jobs/certbot-cleanup.py -n -d {domains} --email {email} --agree-tos"
|
||||
if getenv("USE_LETS_ENCRYPT_STAGING") == "yes":
|
||||
cmd += " --staging"
|
||||
environ["PYTHONPATH"] = "/usr/share/bunkerweb/deps/python"
|
||||
proc = run(
|
||||
cmd.split(" "),
|
||||
[
|
||||
"/usr/share/bunkerweb/deps/python/bin/certbot certonly",
|
||||
"--manual",
|
||||
"--preferred-challenges=http",
|
||||
"--manual-auth-hook",
|
||||
f"{getcwd()}/certbot-auth.py",
|
||||
"--manual-cleanup-hook",
|
||||
f"{getcwd()}/certbot-cleanup.py",
|
||||
"-n",
|
||||
"-d",
|
||||
domains,
|
||||
"--email",
|
||||
email,
|
||||
"--agree-tos",
|
||||
"--logs-dir",
|
||||
"/var/tmp/bunkerweb",
|
||||
"--work-dir",
|
||||
"/var/lib/bunkerweb",
|
||||
]
|
||||
+ (["--staging"] if getenv("USE_LETS_ENCRYPT_STAGING", "no") == "yes" else []),
|
||||
stdin=DEVNULL,
|
||||
stderr=STDOUT,
|
||||
env=environ,
|
||||
|
@ -26,34 +51,37 @@ def certbot_new(domains, email):
|
|||
return proc.returncode
|
||||
|
||||
|
||||
logger = setup_logger("LETS-ENCRYPT", getenv("LOG_LEVEL", "INFO"))
|
||||
status = 0
|
||||
|
||||
try:
|
||||
|
||||
# Multisite case
|
||||
if getenv("MULTISITE") == "yes":
|
||||
for first_server in getenv("SERVER_NAME").split(" "):
|
||||
if getenv("MULTISITE", "no") == "yes":
|
||||
for first_server in getenv("SERVER_NAME", "").split(" "):
|
||||
if (
|
||||
getenv(f"{first_server}_AUTO_LETS_ENCRYPT", getenv("AUTO_LETS_ENCRYPT"))
|
||||
not first_server
|
||||
or getenv(
|
||||
f"{first_server}_AUTO_LETS_ENCRYPT",
|
||||
getenv("AUTO_LETS_ENCRYPT", "no"),
|
||||
)
|
||||
!= "yes"
|
||||
):
|
||||
continue
|
||||
if first_server == "":
|
||||
continue
|
||||
real_server_name = getenv(f"{first_server}_SERVER_NAME", first_server)
|
||||
domains = real_server_name.replace(" ", ",")
|
||||
|
||||
domains = getenv(f"{first_server}_SERVER_NAME", first_server).replace(
|
||||
" ", ","
|
||||
)
|
||||
|
||||
if exists(f"/etc/letsencrypt/live/{first_server}/cert.pem"):
|
||||
logger.info(
|
||||
f"Certificates already exists for domain(s) {domains}",
|
||||
)
|
||||
continue
|
||||
|
||||
real_email = getenv(
|
||||
f"{first_server}_EMAIL_LETS_ENCRYPT",
|
||||
getenv("EMAIL_LETS_ENCRYPT", f"contact@{first_server}"),
|
||||
)
|
||||
if real_email == "":
|
||||
if not real_email:
|
||||
real_email = f"contact@{first_server}"
|
||||
|
||||
logger.info(
|
||||
f"Asking certificates for domains : {domains} (email = {real_email}) ...",
|
||||
)
|
||||
|
@ -67,16 +95,32 @@ try:
|
|||
f"Certificate generation succeeded for domain(s) : {domains}"
|
||||
)
|
||||
|
||||
if exists(f"/etc/letsencrypt/live/{first_server}/cert.pem"):
|
||||
with open(f"/etc/letsencrypt/live/{first_server}/cert.pem") as f:
|
||||
cert = f.read()
|
||||
|
||||
# Update db
|
||||
err = db.update_job_cache(
|
||||
"letsencrypt",
|
||||
first_server,
|
||||
"cert.pem",
|
||||
cert,
|
||||
)
|
||||
if err:
|
||||
logger.warning(f"Couldn't update db cache: {err}")
|
||||
|
||||
# Singlesite case
|
||||
elif getenv("AUTO_LETS_ENCRYPT") == "yes" and getenv("SERVER_NAME") != "":
|
||||
first_server = getenv("SERVER_NAME").split(" ")[0]
|
||||
domains = getenv("SERVER_NAME").replace(" ", ",")
|
||||
elif getenv("AUTO_LETS_ENCRYPT", "no") == "yes" and getenv("SERVER_NAME", ""):
|
||||
first_server = getenv("SERVER_NAME", "").split(" ")[0]
|
||||
domains = getenv("SERVER_NAME", "").replace(" ", ",")
|
||||
|
||||
if exists(f"/etc/letsencrypt/live/{first_server}/cert.pem"):
|
||||
logger.info(f"Certificates already exists for domain(s) {domains}")
|
||||
else:
|
||||
real_email = getenv("EMAIL_LETS_ENCRYPT", f"contact@{first_server}")
|
||||
if real_email == "":
|
||||
if not real_email:
|
||||
real_email = f"contact@{first_server}"
|
||||
|
||||
logger.info(
|
||||
f"Asking certificates for domain(s) : {domains} (email = {real_email}) ...",
|
||||
)
|
||||
|
@ -88,7 +132,19 @@ try:
|
|||
f"Certificate generation succeeded for domain(s) : {domains}"
|
||||
)
|
||||
|
||||
if exists(f"/etc/letsencrypt/live/{first_server}/cert.pem"):
|
||||
with open(f"/etc/letsencrypt/live/{first_server}/cert.pem") as f:
|
||||
cert = f.read()
|
||||
|
||||
# Update db
|
||||
err = db.update_job_cache(
|
||||
"letsencrypt",
|
||||
first_server,
|
||||
"cert.pem",
|
||||
cert,
|
||||
)
|
||||
if err:
|
||||
logger.warning(f"Couldn't update db cache: {err}")
|
||||
except:
|
||||
status = 1
|
||||
logger.error(f"Exception while running certbot-new.py :\n{format_exc()}")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
from os import environ, getenv
|
||||
from os import environ, getcwd, getenv
|
||||
from os.path import exists
|
||||
from subprocess import DEVNULL, STDOUT, run
|
||||
from sys import exit as sys_exit, path as sys_path
|
||||
|
@ -13,10 +13,16 @@ from logger import setup_logger
|
|||
|
||||
|
||||
def renew(domain):
|
||||
cmd = f"/usr/share/bunkerweb/deps/python/bin/certbot renew --cert-name {domain} --deploy-hook /usr/share/bunkerweb/core/letsencrypt/jobs/certbot-deploy.py"
|
||||
environ["PYTHONPATH"] = "/usr/share/bunkerweb/deps/python"
|
||||
proc = run(
|
||||
cmd.split(" "),
|
||||
[
|
||||
"/usr/share/bunkerweb/deps/python/bin/certbot",
|
||||
"renew",
|
||||
"--cert-name",
|
||||
domain,
|
||||
"--deploy-hook",
|
||||
f"{getcwd()}/certbot-deploy.py",
|
||||
],
|
||||
stdin=DEVNULL,
|
||||
stderr=STDOUT,
|
||||
env=environ,
|
||||
|
@ -30,23 +36,25 @@ status = 0
|
|||
try:
|
||||
if getenv("MULTISITE") == "yes":
|
||||
for first_server in getenv("SERVER_NAME").split(" "):
|
||||
if first_server == "":
|
||||
continue
|
||||
if (
|
||||
getenv(f"{first_server}_AUTO_LETS_ENCRYPT", getenv("AUTO_LETS_ENCRYPT"))
|
||||
not first_server
|
||||
or getenv(
|
||||
f"{first_server}_AUTO_LETS_ENCRYPT",
|
||||
getenv("AUTO_LETS_ENCRYPT", "no"),
|
||||
)
|
||||
!= "yes"
|
||||
or not exists(f"/etc/letsencrypt/live/{first_server}/cert.pem")
|
||||
):
|
||||
continue
|
||||
if not exists(f"/etc/letsencrypt/live/{first_server}/cert.pem"):
|
||||
continue
|
||||
|
||||
ret = renew(first_server)
|
||||
if ret != 0:
|
||||
status = 2
|
||||
logger.error(
|
||||
f"Certificates renewal for {first_server} failed",
|
||||
)
|
||||
elif getenv("AUTO_LETS_ENCRYPT") == "yes" and getenv("SERVER_NAME") != "":
|
||||
first_server = getenv("SERVER_NAME").split(" ")[0]
|
||||
elif getenv("AUTO_LETS_ENCRYPT", "no") == "yes" and not getenv("SERVER_NAME", ""):
|
||||
first_server = getenv("SERVER_NAME", "").split(" ")[0]
|
||||
if exists(f"/etc/letsencrypt/live/{first_server}/cert.pem"):
|
||||
ret = renew(first_server)
|
||||
if ret != 0:
|
||||
|
|
|
@ -80,7 +80,7 @@ class JobScheduler(ApiCaller):
|
|||
if self.__integration == "Linux":
|
||||
self.__logger.info("Reloading nginx ...")
|
||||
proc = run(
|
||||
["/usr/sbin/nginx", "-s", "reload"],
|
||||
["nginx", "-s", "reload"],
|
||||
stdin=DEVNULL,
|
||||
stderr=PIPE,
|
||||
env=self.__env,
|
||||
|
@ -111,6 +111,8 @@ class JobScheduler(ApiCaller):
|
|||
stdin=DEVNULL,
|
||||
stderr=STDOUT,
|
||||
env=self.__env,
|
||||
user=101,
|
||||
group=101,
|
||||
)
|
||||
except BaseException:
|
||||
with self.__thread_lock:
|
||||
|
|
Loading…
Reference in New Issue