From 5eb3d9d8749289f25f7e7c99cf807d165237542b Mon Sep 17 00:00:00 2001 From: Davte Date: Sun, 19 Apr 2020 00:06:05 +0200 Subject: [PATCH] create_certificate script provided --- README.md | 34 +++----- filebridging/__init__.py | 2 +- filebridging/create_certificate.py | 126 +++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+), 23 deletions(-) create mode 100644 filebridging/create_certificate.py diff --git a/README.md b/README.md index 0eb0e15..7eb701f 100644 --- a/README.md +++ b/README.md @@ -60,40 +60,30 @@ python -m filebridging.client --help ## Generating SSL certificates +You may use `filebridging.create_certificate.py` script or use openssl from the command line. +###Via script +```bash +python -m filebridging.create_certificate --name example --domain example.com --force +``` + +### Via command line Store configuration in file `mycert.csr.cnf` and run the following command to generate a self-signed SSL certificate. ```bash -openssl req -newkey rsa:2048 -nodes -keyout ./mycert.key \ +openssl req -newkey rsa:4096 -nodes -keyout ./mycert.key \ -x509 -days 365 -out ./mycert.crt \ - -config <( cat mycert.csr.cnf ) + -config mycert.csr.cnf ``` **mycert.csr.cnf** ```text -[req] -default_bits = 2048 +[ req ] +default_bits = 4096 prompt = no default_md = sha256 distinguished_name = dn -req_extensions = v3_req -subjectAltName = @alt_names -[ v3_req ] -basicConstraints = CA:FALSE -keyUsage = nonRepudiation, digitalSignature, keyEncipherment -subjectAltName = @alt_names - -[dn] -C=US -ST=YourState -L=YourTown -O=FileBridging -OU=filebridging -emailAddress=filebridging@yourdomain.com +[ dn ] CN = yourdomain.com - -[ alt_names ] -DNS.1 = yourdomain.com -DNS.2 = 1.111.111.11 ``` \ No newline at end of file diff --git a/filebridging/__init__.py b/filebridging/__init__.py index b69174c..9e9439e 100644 --- a/filebridging/__init__.py +++ b/filebridging/__init__.py @@ -13,6 +13,6 @@ __author__ = "Davide Testa" __email__ = "davide@davte.it" __credits__ = [] __license__ = "GNU General Public License v3.0" -__version__ = "0.0.6" +__version__ = "0.0.7" __maintainer__ = "Davide Testa" __contact__ = "t.me/davte" diff --git a/filebridging/create_certificate.py b/filebridging/create_certificate.py new file mode 100644 index 0000000..2f4b3f2 --- /dev/null +++ b/filebridging/create_certificate.py @@ -0,0 +1,126 @@ +"""Create a SSL certificate. + +Requirements: OpenSSL. +""" + +import argparse +import logging +import os +import subprocess + + +def get_paths(path): + """""" + return [ + os.path.abspath(path) + string + for string in (".crt", ".key", "csr.cnf") + ] + + +def main(): + # noinspection SpellCheckingInspection + log_formatter = logging.Formatter( + "%(asctime)s [%(module)-15s %(levelname)-8s] %(message)s", + style='%' + ) + root_logger = logging.getLogger() + root_logger.setLevel(logging.DEBUG) + + console_handler = logging.StreamHandler() + console_handler.setFormatter(log_formatter) + console_handler.setLevel(logging.DEBUG) + root_logger.addHandler(console_handler) + + cli_parser = argparse.ArgumentParser(description='Create SSL certificate', + allow_abbrev=False) + cli_parser.add_argument('-n', '--name', + type=str, + default=None, + required=False, + help='Certificate, key and configuration file name') + cli_parser.add_argument('-d', '--domain', + type=str, + default=None, + required=False, + help='Server domain (e.g. example.com)') + cli_parser.add_argument('-f', '--force', '--overwrite', + action='store_true', + help='Overwrite certificate and key if they exist') + arguments = vars(cli_parser.parse_args()) + name = arguments['name'] + if name is None: + try: + from config import name + except ImportError: + name = None + while not name or not os.access(os.path.dirname(os.path.abspath(name)), + os.W_OK): + try: + name = input( + "Enter a valid file name for certificate, key and " + "configuration file. Directory must be writeable.\n" + "\t\t" + ) + except KeyboardInterrupt: + print() + logging.error("Aborting...") + return + certificate_path, key_path, configuration_path = get_paths( + name + ) + if not os.access(os.path.dirname(certificate_path), os.W_OK): + logging.error(f"Invalid path `{certificate_path}`!") + return + if any( + os.path.isfile(path) + for path in (certificate_path, key_path, configuration_path) + ) and not arguments['force'] and not input( + "Do you want to overwrite existing certificate, key and " + "configuration file?" + "\n[Y]es or [N]o\t\t\t\t" + ).lower().startswith('y'): + logging.error("Interrupted. Provide a different --name.") + return + domain = arguments['domain'] + if domain is None: + try: + from config import domain + except ImportError: + domain = None + while not domain: + domain = input("Enter server domain (e.g. example.com)\n\t\t") + with open(configuration_path, 'w') as configuration_file: + logging.info("Writing configuration file...") + configuration_file.write( + "[req]\n" + "default_bits = 4096\n" + "prompt = no\n" + "default_md = sha256\n" + "distinguished_name = dn\n" + "\n" + "[dn]\n" + f"CN = {domain}\n" + ) + logging.info("Generating certificate and key...") + subprocess.run( + [ + f"openssl req -newkey rsa:4096 -nodes " + f"-keyout \"{key_path}\" -x509 -days 365 " + f"-out \"{certificate_path}\" " + f"-config \"{configuration_path}\"" + ], + capture_output=True, + text=True, + shell=True + ) + with open(certificate_path, 'r') as certificate_file: + logging.info( + "Certificate:\n\n{certificate}".format( + certificate=''.join(certificate_file.readlines()) + ), + ) + logging.info("Done!") + + +if __name__ == '__main__': + main()