From f575613bc4c97a2df1c7a4e36c386195c85a8920 Mon Sep 17 00:00:00 2001 From: Olof-Joachim Frahm Date: Sat, 10 Jan 2015 20:53:01 +0000 Subject: [PATCH] Create GnuPG and OpenSSH keys; usage notes. --- README.md | 21 ++++++- crypto-install.py | 164 +++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 142 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index b44b229..eef6c8a 100644 --- a/README.md +++ b/README.md @@ -2,5 +2,22 @@ crypto-install.py # USAGE -Run the script to install a baseline setup. Existing files are detected -and not touched in the process, so running it is always safe to do. +Run the script to install a baseline setup for both GnuPG and OpenSSH. + +Existing files are detected and not touched in the process, so running +it is always safe to do. + +# INSTALLATION + +Until I set up a better routine: + + git clone https://github.com/Ferada/crypto-install.git + # or + git clone git@github.com:Ferada/crypto-install.git + + cd crypto-install + make + cp build/crypto-install.py ~/bin # or wherever + +Simply copy the built file into your path and possibly ensure execution +permissions. diff --git a/crypto-install.py b/crypto-install.py index 0aff602..9715441 100755 --- a/crypto-install.py +++ b/crypto-install.py @@ -2,17 +2,35 @@ # -*- mode: python; coding: utf-8-unix; -*- -import argparse, ConfigParser, os, sys, textwrap +import argparse, errno, os, readline, subprocess, sys, tempfile, textwrap -def print_version (): - print ("crypto-install.py GIT-TAG (GIT-COMMIT/GIT-BRANCH)") +if sys.version_info[0] == 2: + def input_string (prompt=""): + return raw_input (prompt) +elif sys.version_info[0] > 2: + def input_string (prompt=""): + return input (prompt) +else: + raise Exception ("Unsupported Python version {}".format (sys.version_info)) -def input_string (prompt=""): - if sys.version_info[0] == 2: - return raw_input(prompt) - return input(prompt) +def dedented (text): + return textwrap.dedent (text).strip () + + +def filled (text): + return textwrap.fill (dedented (text), width = 72) + + +def read_input_string (prompt="", default=""): + if default != "": + readline.set_startup_hook (lambda: readline.insert_text (default)) + + try: + return input_string(prompt) + finally: + readline.set_startup_hook() def parse_arguments (): @@ -20,71 +38,135 @@ def parse_arguments (): parser.add_argument ( "-v", "--version", dest = "version", - action = "store_true", + action = "version", + version = "crypto-install.py version GIT-TAG (GIT-COMMIT/GIT-BRANCH)", help = "Display version.") - parser.add_argument ( + gnupg_group = parser.add_argument_group ("GnuPG", + "Options related to the GnuPG setup.") + gnupg_group.add_argument ( "--no-gpg", dest = "gnupg", action = "store_false", help = "Disable GnuPG setup.") - parser.add_argument ( + gnupg_group.add_argument ( + "--gpg-home", + dest = "gnupg_home", + default = "~/.gnupg", + metavar = "PATH", + help = "Default directory for GnuPG files.") + openssh_group = parser.add_argument_group ("OpenSSH", + "Options related to the OpenSSH setup.") + openssh_group.add_argument ( "--no-ssh", dest = "openssh", action = "store_false", help = "Disable OpenSSH setup.") - parser.add_argument ( - "--ssh-config", - dest = "openssh_config", - default = "~/.ssh/config", - help = "Set path for OpenSSH configuration file.") + openssh_group.add_argument ( + "--ssh-home", + dest = "openssh_home", + default = "~/.ssh", + metavar = "PATH", + help = "Default directory for OpenSSH files.") return parser.parse_args () -def gnupg_setup (): - if False: - print("Default GnuPG key already exists.") +def gnupg_setup (arguments): + gnupg_home = os.path.expanduser (arguments.gnupg_home) + gnupg_secring = os.path.join (gnupg_home, "secring.gpg") + + if os.path.exists (gnupg_secring): + print ("GnuPG secret keyring already exists at {!r}." + .format (gnupg_secring)) return - print (textwrap.fill (textwrap.dedent("""\ + print (filled (""" No default GnuPG key available. Please enter your information to - create a new key."""), width = 80)) + create a new key.""")) + + default_name = os.getenv ("FULLNAME") + name = read_input_string ("What is your name? ", default_name) + + default_email = os.getenv ("EMAIL") + email = read_input_string ("What is your email address? ", default_email) + + comment = read_input_string ("What is your comment phrase, if any (e.g. 'key for 2014')? ") + + if not os.path.exists (gnupg_home): + ensure_directories (gnupg_home, 0o700) - name = input_string("What is your name? (Max Mustermann) ") - email = input_string("What is your email address? (max@example.de) ") - motto = input_string("What is your motto phrase, if any? (Schlüssel für 2014) ") + with tempfile.NamedTemporaryFile () as tmp: + batch_key = dedented (""" + %ask-passphrase + Key-Type: DSA + Key-Length: 2048 + Subkey-Type: ELG-E + Subkey-Length: 2048 + Name-Real: {} + Name-Email: {} + Expire-Date: 0 + """).format (name, email) + + if comment != "": + batch_key += "\nName-Comment: {}\n".format (comment) + + tmp.write (batch_key) + tmp.flush () + + batch_env = dict(os.environ) + del batch_env["DISPLAY"] + + gnupg_process = subprocess.Popen (["gpg2", "--homedir", gnupg_home, "--batch", "--gen-key", tmp.name], + env = batch_env) + gnupg_process.wait () + + if gnupg_process.returncode != 0: + raise Exception ("Couldn't create GnuPG key.") + + +def ensure_directories (path, mode = 0o777): + try: + os.makedirs (path, mode) + except OSError as exception: + if exception.errno != errno.EEXIST: + raise def openssh_setup (arguments): - if not os.path.exists(arguments.openssh_config): - with open(arguments.openssh_config, "w") as ssh_config: - ssh_config.write(textwrap.dedent("""\ + openssh_home = os.path.expanduser (arguments.openssh_home) + openssh_config = os.path.join (openssh_home, "config") + + if not os.path.exists (openssh_config): + ensure_directories (openssh_home, 0o700) + + with open (openssh_config, "w") as config: + config.write (dedented (""" ForwardAgent yes ForwardX11 yes """)) - if os.path.exists (os.path.expanduser ("~/.ssh/id_rsa")) \ - or os.path.exists (os.path.expanduser ("~/.ssh/id_dsa")): - print("OpenSSH key already exists.") + openssh_key = os.path.join (openssh_home, "id_rsa") + + if os.path.exists (openssh_key): + print("OpenSSH key already exists at {!r}.".format (openssh_key)) return - print (textwrap.fill (textwrap.dedent("""\ - No OpenSSH key available. Generating new key."""), width = 80)) + print (filled ("No OpenSSH key available. Generating new key.")) - os.system ("ssh-keygen") + openssh_process = subprocess.Popen (["ssh-keygen", "-f", openssh_key]) + openssh_process.wait () + if openssh_process.returncode != 0: + raise Exception ("Couldn't create OpenSSH key.") -def main (): - args = parse_arguments () - if args.version: - print_version () - sys.exit () +def main (): + arguments = parse_arguments () - if args.gnupg: - gnupg_setup () + if arguments.gnupg: + gnupg_setup (arguments) - if args.openssh: - openssh_setup (args) + if arguments.openssh: + openssh_setup (arguments) if __name__ == "__main__": -- 1.7.10.4