Queer European MD passionate about IT
Browse Source

create_certificate script provided

Davte 5 years ago
parent
commit
5eb3d9d874
3 changed files with 140 additions and 24 deletions
  1. 13 23
      README.md
  2. 1 1
      filebridging/__init__.py
  3. 126 0
      filebridging/create_certificate.py

+ 13 - 23
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
-CN = yourdomain.com
 
-[ alt_names ]
-DNS.1 = yourdomain.com
-DNS.2 = 1.111.111.11
+[ dn ]
+CN = yourdomain.com
 ```

+ 1 - 1
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"

+ 126 - 0
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()