Initial YakPanel commit
This commit is contained in:
333
class/sewer/cli.py
Normal file
333
class/sewer/cli.py
Normal file
@@ -0,0 +1,333 @@
|
||||
import os
|
||||
import logging
|
||||
import argparse
|
||||
|
||||
from . import Client
|
||||
from . import __version__ as sewer_version
|
||||
from .config import ACME_DIRECTORY_URL_STAGING, ACME_DIRECTORY_URL_PRODUCTION
|
||||
|
||||
|
||||
def main():
|
||||
r"""
|
||||
Usage:
|
||||
1. To get a new certificate:
|
||||
CLOUDFLARE_EMAIL=example@example.com \
|
||||
CLOUDFLARE_API_KEY=api-key \
|
||||
sewer \
|
||||
--model cloudflare \
|
||||
--domain example.com \
|
||||
--action run
|
||||
|
||||
2. To renew a certificate:
|
||||
CLOUDFLARE_EMAIL=example@example.com \
|
||||
CLOUDFLARE_API_KEY=api-key \
|
||||
sewer \
|
||||
--account_key /path/to/your/account.key \
|
||||
--model cloudflare \
|
||||
--domain example.com \
|
||||
--action renew
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="sewer",
|
||||
description=r"""Sewer is a Let's Encrypt(ACME) client.
|
||||
Example usage::
|
||||
CLOUDFLARE_EMAIL=example@example.com \
|
||||
CLOUDFLARE_API_KEY=api-key \
|
||||
sewer \
|
||||
--model cloudflare \
|
||||
--domain example.com \
|
||||
--action run""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--version",
|
||||
action="version",
|
||||
version="%(prog)s {version}".format(version=sewer_version.__version__),
|
||||
help="The currently installed sewer version.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--account_key",
|
||||
type=argparse.FileType("r"),
|
||||
required=False,
|
||||
help="The path to your letsencrypt/acme account key. \
|
||||
eg: --account_key /home/myaccount.key",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--certificate_key",
|
||||
type=argparse.FileType("r"),
|
||||
required=False,
|
||||
help="The path to your certificate key. \
|
||||
eg: --certificate_key /home/mycertificate.key",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--model",
|
||||
type=str,
|
||||
required=True,
|
||||
choices=[
|
||||
"cloudflare",
|
||||
"aurora",
|
||||
"acmedns",
|
||||
"aliyun",
|
||||
"hurricane",
|
||||
"rackspace",
|
||||
"dnspod",
|
||||
"duckdns",
|
||||
],
|
||||
help="The name of the model provider that you want to use.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--domain",
|
||||
type=str,
|
||||
required=True,
|
||||
help="The domain/subdomain name for which \
|
||||
you want to get/renew certificate for. \
|
||||
wildcards are also supported \
|
||||
eg: --domain example.com",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--alt_domains",
|
||||
type=str,
|
||||
required=False,
|
||||
default=[],
|
||||
nargs="*",
|
||||
help="A list of alternative domain/subdomain name/s(if any) for which \
|
||||
you want to get/renew certificate for. \
|
||||
eg: --alt_domains www.example.com blog.example.com",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--bundle_name",
|
||||
type=str,
|
||||
required=False,
|
||||
help="The name to use for certificate \
|
||||
certificate key and account key. Default is name of domain.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--endpoint",
|
||||
type=str,
|
||||
required=False,
|
||||
default="production",
|
||||
choices=["production", "staging"],
|
||||
help="Whether to use letsencrypt/acme production/live endpoints \
|
||||
or staging endpoints. production endpoints are used by default. \
|
||||
eg: --endpoint staging",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--email",
|
||||
type=str,
|
||||
required=False,
|
||||
help="Email to be used for registration and recovery. \
|
||||
eg: --email me@example.com",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--action",
|
||||
type=str,
|
||||
required=True,
|
||||
choices=["run", "renew"],
|
||||
help="The action that you want to perform. \
|
||||
Either run (get a new certificate) or renew (renew a certificate). \
|
||||
eg: --action run",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--out_dir",
|
||||
type=str,
|
||||
required=False,
|
||||
default=os.getcwd(),
|
||||
help="""The dir where the certificate and keys file will be stored.
|
||||
default: The directory you run sewer command.
|
||||
eg: --out_dir /data/ssl/
|
||||
""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--loglevel",
|
||||
type=str,
|
||||
required=False,
|
||||
default="INFO",
|
||||
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
|
||||
help="The log level to output log messages at. \
|
||||
eg: --loglevel DEBUG",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
dns_provider = args.dns
|
||||
domain = args.domain
|
||||
alt_domains = args.alt_domains
|
||||
action = args.action
|
||||
account_key = args.account_key
|
||||
certificate_key = args.certificate_key
|
||||
bundle_name = args.bundle_name
|
||||
endpoint = args.endpoint
|
||||
email = args.email
|
||||
loglevel = args.loglevel
|
||||
out_dir = args.out_dir
|
||||
|
||||
# Make sure the output dir user specified is writable
|
||||
if not os.access(out_dir, os.W_OK):
|
||||
raise OSError("The dir '{0}' is not writable".format(out_dir))
|
||||
|
||||
logger = logging.getLogger()
|
||||
handler = logging.StreamHandler()
|
||||
formatter = logging.Formatter("%(message)s")
|
||||
handler.setFormatter(formatter)
|
||||
if not logger.handlers:
|
||||
logger.addHandler(handler)
|
||||
logger.setLevel(loglevel)
|
||||
|
||||
if account_key:
|
||||
account_key = account_key.read()
|
||||
if certificate_key:
|
||||
certificate_key = certificate_key.read()
|
||||
if bundle_name:
|
||||
file_name = bundle_name
|
||||
else:
|
||||
file_name = "{0}".format(domain)
|
||||
if endpoint == "staging":
|
||||
ACME_DIRECTORY_URL = ACME_DIRECTORY_URL_STAGING
|
||||
else:
|
||||
ACME_DIRECTORY_URL = ACME_DIRECTORY_URL_PRODUCTION
|
||||
|
||||
if dns_provider == "cloudflare":
|
||||
from . import CloudFlareDns
|
||||
|
||||
try:
|
||||
CLOUDFLARE_EMAIL = os.environ["CLOUDFLARE_EMAIL"]
|
||||
CLOUDFLARE_API_KEY = os.environ["CLOUDFLARE_API_KEY"]
|
||||
|
||||
dns_class = CloudFlareDns(
|
||||
CLOUDFLARE_EMAIL=CLOUDFLARE_EMAIL, CLOUDFLARE_API_KEY=CLOUDFLARE_API_KEY
|
||||
)
|
||||
logger.info("chosen_dns_provider. Using {0} as model provider.".format(dns_provider))
|
||||
except KeyError as e:
|
||||
logger.error("ERROR:: Please supply {0} as an environment variable.".format(str(e)))
|
||||
raise
|
||||
|
||||
elif dns_provider == "aurora":
|
||||
from . import AuroraDns
|
||||
|
||||
try:
|
||||
AURORA_API_KEY = os.environ["AURORA_API_KEY"]
|
||||
AURORA_SECRET_KEY = os.environ["AURORA_SECRET_KEY"]
|
||||
|
||||
dns_class = AuroraDns(
|
||||
AURORA_API_KEY=AURORA_API_KEY, AURORA_SECRET_KEY=AURORA_SECRET_KEY
|
||||
)
|
||||
logger.info("chosen_dns_provider. Using {0} as model provider.".format(dns_provider))
|
||||
except KeyError as e:
|
||||
logger.error("ERROR:: Please supply {0} as an environment variable.".format(str(e)))
|
||||
raise
|
||||
|
||||
elif dns_provider == "acmedns":
|
||||
from . import AcmeDnsDns
|
||||
|
||||
try:
|
||||
ACME_DNS_API_USER = os.environ["ACME_DNS_API_USER"]
|
||||
ACME_DNS_API_KEY = os.environ["ACME_DNS_API_KEY"]
|
||||
ACME_DNS_API_BASE_URL = os.environ["ACME_DNS_API_BASE_URL"]
|
||||
|
||||
dns_class = AcmeDnsDns(
|
||||
ACME_DNS_API_USER=ACME_DNS_API_USER,
|
||||
ACME_DNS_API_KEY=ACME_DNS_API_KEY,
|
||||
ACME_DNS_API_BASE_URL=ACME_DNS_API_BASE_URL,
|
||||
)
|
||||
logger.info("chosen_dns_provider. Using {0} as model provider.".format(dns_provider))
|
||||
except KeyError as e:
|
||||
logger.error("ERROR:: Please supply {0} as an environment variable.".format(str(e)))
|
||||
raise
|
||||
elif dns_provider == "aliyun":
|
||||
from . import AliyunDns
|
||||
|
||||
try:
|
||||
aliyun_ak = os.environ["ALIYUN_AK_ID"]
|
||||
aliyun_secret = os.environ["ALIYUN_AK_SECRET"]
|
||||
aliyun_endpoint = os.environ.get("ALIYUN_ENDPOINT", "cn-beijing")
|
||||
dns_class = AliyunDns(aliyun_ak, aliyun_secret, aliyun_endpoint)
|
||||
logger.info("chosen_dns_provider. Using {0} as model provider.".format(dns_provider))
|
||||
except KeyError as e:
|
||||
logger.error("ERROR:: Please supply {0} as an environment variable.".format(str(e)))
|
||||
raise
|
||||
elif dns_provider == "hurricane":
|
||||
from . import HurricaneDns
|
||||
|
||||
try:
|
||||
he_username = os.environ["HURRICANE_USERNAME"]
|
||||
he_password = os.environ["HURRICANE_PASSWORD"]
|
||||
dns_class = HurricaneDns(he_username, he_password)
|
||||
logger.info("chosen_dns_provider. Using {0} as model provider.".format(dns_provider))
|
||||
except KeyError as e:
|
||||
logger.error("ERROR:: Please supply {0} as an environment variable.".format(str(e)))
|
||||
raise
|
||||
elif dns_provider == "rackspace":
|
||||
from . import RackspaceDns
|
||||
|
||||
try:
|
||||
RACKSPACE_USERNAME = os.environ["RACKSPACE_USERNAME"]
|
||||
RACKSPACE_API_KEY = os.environ["RACKSPACE_API_KEY"]
|
||||
dns_class = RackspaceDns(RACKSPACE_USERNAME, RACKSPACE_API_KEY)
|
||||
logger.info("chosen_dns_prover. Using {0} as model provider. ".format(dns_provider))
|
||||
except KeyError as e:
|
||||
logger.error("ERROR:: Please supply {0} as an environment variable.".format(str(e)))
|
||||
raise
|
||||
elif dns_provider == "dnspod":
|
||||
from . import DNSPodDns
|
||||
|
||||
try:
|
||||
DNSPOD_ID = os.environ["DNSPOD_ID"]
|
||||
DNSPOD_API_KEY = os.environ["DNSPOD_API_KEY"]
|
||||
dns_class = DNSPodDns(DNSPOD_ID, DNSPOD_API_KEY)
|
||||
logger.info("chosen_dns_prover. Using {0} as model provider. ".format(dns_provider))
|
||||
except KeyError as e:
|
||||
logger.error("ERROR:: Please supply {0} as an environment variable.".format(str(e)))
|
||||
raise
|
||||
elif dns_provider == "duckdns":
|
||||
from . import DuckDNSDns
|
||||
|
||||
try:
|
||||
duckdns_token = os.environ["DUCKDNS_TOKEN"]
|
||||
|
||||
dns_class = DuckDNSDns(duckdns_token=duckdns_token)
|
||||
logger.info("chosen_dns_provider. Using {0} as model provider.".format(dns_provider))
|
||||
except KeyError as e:
|
||||
logger.error("ERROR:: Please supply {0} as an environment variable.".format(str(e)))
|
||||
raise
|
||||
else:
|
||||
raise ValueError("The model provider {0} is not recognised.".format(dns_provider))
|
||||
|
||||
client = Client(
|
||||
domain_name=domain,
|
||||
dns_class=dns_class,
|
||||
domain_alt_names=alt_domains,
|
||||
contact_email=email,
|
||||
account_key=account_key,
|
||||
certificate_key=certificate_key,
|
||||
ACME_DIRECTORY_URL=ACME_DIRECTORY_URL,
|
||||
LOG_LEVEL=loglevel,
|
||||
)
|
||||
certificate_key = client.certificate_key
|
||||
account_key = client.account_key
|
||||
|
||||
# prepare file path
|
||||
account_key_file_path = os.path.join(out_dir, "{0}.account.key".format(file_name))
|
||||
crt_file_path = os.path.join(out_dir, "{0}.crt".format(file_name))
|
||||
crt_key_file_path = os.path.join(out_dir, "{0}.key".format(file_name))
|
||||
|
||||
# write out account_key in out_dir directory
|
||||
with open(account_key_file_path, "w") as account_file:
|
||||
account_file.write(account_key)
|
||||
logger.info("account key succesfully written to {0}.".format(account_key_file_path))
|
||||
|
||||
if action == "renew":
|
||||
message = "Certificate Succesfully renewed. The certificate, certificate key and account key have been saved in the current directory"
|
||||
certificate = client.renew()
|
||||
else:
|
||||
message = "Certificate Succesfully issued. The certificate, certificate key and account key have been saved in the current directory"
|
||||
certificate = client.cert()
|
||||
|
||||
# write out certificate and certificate key in out_dir directory
|
||||
with open(crt_file_path, "w") as certificate_file:
|
||||
certificate_file.write(certificate)
|
||||
with open(crt_key_file_path, "w") as certificate_key_file:
|
||||
certificate_key_file.write(certificate_key)
|
||||
|
||||
logger.info("certificate succesfully written to {0}.".format(crt_file_path))
|
||||
logger.info("certificate key succesfully written to {0}.".format(crt_key_file_path))
|
||||
|
||||
logger.info("the_end. {0}".format(message))
|
||||
Reference in New Issue
Block a user