Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python3
- """
- Command line utility for making passwords. Requires ansible for keeping
- an encrypted log file of past invocations (pip install ansible).
- If you don't like the security implications of maintaining a log,
- you probably don't want this.
- Installation:
- Requires Python 3.6 or higher.
- chmod u+x this file and put it somewhere in your path
- Usage:
- * initialize ansible vault password for the password log
- $ password init
- * make a password
- $ password create
- random password: oUjrqEnKWaLGFHelHFpCLj2jMePa2qzQ
- * view previously created passwords when you lost one
- $ password logs
- """
- import os
- import sys
- import time
- import string
- import random
- import subprocess
- from pathlib import Path
- HOME = f"{Path.home()}"
- VAULT_FILE = f"{HOME}/.vault_password"
- PASSWORD_FILE = f"{HOME}/.passwords"
- HELP_TEXT = """usage: password <command>
- commands:
- init makes a vault for storing password log
- make makes a 32 character cryptographically random password
- logs open previously created passwords in less
- """
- def help_text():
- """Prints help text."""
- print(HELP_TEXT, file=sys.stderr)
- def generate(n: int) -> str:
- """Generates an n character random password"""
- choices = set(
- string.ascii_uppercase + string.ascii_lowercase + string.digits)
- # remove ambiguous characters
- readable = list(choices - set(['O', '0', 'o']))
- pw = ''.join(random.SystemRandom().choice(readable) for _ in range(n))
- return pw
- def run(cmd: str) -> subprocess.CompletedProcess:
- """ Runs a shell command."""
- out = subprocess.run(
- cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- return out
- def parse_args() -> str:
- """Validates user input."""
- try:
- cmd = sys.argv[1]
- except IndexError:
- help_text()
- sys.exit(1)
- if cmd not in ["init", "make", "logs", "help", "h"]:
- print("error: invald command", file=sys.stderr)
- help_text()
- sys.exit(1)
- if cmd in ["help", "h"]:
- help_text()
- sys.exit(1)
- return cmd
- if __name__ == "__main__":
- cmd = parse_args()
- if cmd == "make":
- # decrypt log
- run(f"ansible-vault --vault-password-file {VAULT_FILE} decrypt {PASSWORD_FILE}"
- )
- # make the password and append to log
- pw = generate(32)
- with open(f"{PASSWORD_FILE}", "a+") as f:
- now = time.strftime("%Y-%m-%d %H:%M")
- f.write(f"{now}: {pw}\n")
- print("password:", pw)
- # encrypt log
- run(f"ansible-vault --vault-password-file {VAULT_FILE} encrypt {PASSWORD_FILE}")
- if cmd == "init":
- # ensure there's not an existing log or password file
- for f in [VAULT_FILE, PASSWORD_FILE]:
- if os.path.exists(f):
- print(f"error: found previous version of {f}; skipping\n",
- file=sys.stderr)
- help_text()
- sys.exit(1)
- with open(VAULT_FILE, "w") as f:
- # make password store
- pw = generate(32)
- f.write(pw)
- run(f"touch {PASSWORD_FILE}")
- print("vault created")
- if cmd == "logs":
- run(f"ansible-vault --vault-password-file {VAULT_FILE} decrypt {PASSWORD_FILE}"
- )
- subprocess.call(["less", PASSWORD_FILE])
- run(f"ansible-vault --vault-password-file {VAULT_FILE} encrypt {PASSWORD_FILE}"
- )
Add Comment
Please, Sign In to add comment