#! /usr/bin/env python
# -*- coding: utf-8 -*-
"""Command line interface to request a URL and get the server cert or cert chain."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import argparse
import cert_human
import sys
[docs]def cli(argv):
"""Parse arguments.
Args:
argv (:obj:`list`): sys.argv or manual list of args to parse.
Returns:
(:obj:`argparse.Namespace`)
"""
fmt = argparse.ArgumentDefaultsHelpFormatter
parser = argparse.ArgumentParser(description=__doc__, formatter_class=fmt)
parser.add_argument(
"host",
metavar="HOST",
action="store",
type=str,
help="Host to get cert or cert chain from",
)
parser.add_argument(
"--port",
default=443,
action="store",
required=False,
type=int,
help="Port on host to connect to",
)
parser.add_argument(
"--method",
dest="method",
action="store",
default="requests",
required=False,
choices=["requests", "socket"],
help="Use requests.get a SSL socket to get cert or cert chain.",
)
parser.add_argument(
"--chain",
dest="chain",
action="store_true",
default=False,
required=False,
help="Print/write the cert chain instead of the cert.",
)
parser.add_argument(
"--print_mode",
dest="print_mode",
action="store",
default="info",
required=False,
choices=["info", "key", "extensions", "all"],
help="When no --write specified, print this type of information for the cert.",
)
parser.add_argument(
"--write",
dest="write",
action="store",
default="",
required=False,
help="File to write cert/cert chain to",
)
parser.add_argument(
"--overwrite",
dest="overwrite",
action="store_true",
default=False,
required=False,
help="When writing to --write and file exists, overwrite.",
)
parser.add_argument(
"--verify",
dest="verify",
action="store",
default="",
required=False,
help="PEM file to verify host, empty will disable verify, for --method requests.",
)
return parser.parse_args(argv)
[docs]def main(cli_args):
"""Process arguments and run the workflows.
Args:
cli_args (:obj:`argparse.Namespace`): Parsed args from sys.argv or list.
"""
if cli_args.chain:
store_cls = cert_human.CertChainStore
store_target = "cert chain"
else:
store_cls = cert_human.CertStore
store_target = "cert"
if cli_args.method == "requests":
verify = False if not cli_args.verify else cli_args.verify
try:
store_obj = store_cls.new_from_host_requests(
host=cli_args.host, port=cli_args.port, verify=verify
)
except cert_human.requests.exceptions.SSLError as exc:
exc = "\n ".join([x.strip() for x in format(exc).split(":")])
m = "SSL Validation Failed:\n {exc}".format(exc=exc)
print(m)
store_obj = None
elif cli_args.method == "socket":
store_obj = store_cls.new_from_host_socket(
host=cli_args.host, port=cli_args.port
)
if store_obj:
if cli_args.write:
store_obj.to_disk(path=cli_args.write, overwrite=cli_args.overwrite)
m = "** Wrote {t} in pem format to: '{p}'"
m = m.format(t=store_target, p=cli_args.write)
print(m)
else:
print_map = {
"info": "dump_str_info",
"key": "dump_str_key",
"all": "dump_str",
"extensions": "dump_str_exts",
}
mode_out = getattr(store_obj, print_map[cli_args.print_mode])
print(mode_out)
if __name__ == "__main__":
cli_args = cli(argv=sys.argv[1:])
main(cli_args)