Guest User

Untitled

a guest
Feb 23rd, 2018
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.37 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. """
  3. Command line utility for making passwords. Requires ansible for keeping
  4. an encrypted log file of past invocations (pip install ansible).
  5. If you don't like the security implications of maintaining a log,
  6. you probably don't want this.
  7.  
  8. Installation:
  9. Requires Python 3.6 or higher.
  10. chmod u+x this file and put it somewhere in your path
  11.  
  12. Usage:
  13.  
  14. * initialize ansible vault password for the password log
  15.  
  16. $ password init
  17.  
  18. * make a password
  19.  
  20. $ password create
  21. random password: oUjrqEnKWaLGFHelHFpCLj2jMePa2qzQ
  22.  
  23. * view previously created passwords when you lost one
  24.  
  25. $ password logs
  26.  
  27. """
  28. import os
  29. import sys
  30. import time
  31. import string
  32. import random
  33. import subprocess
  34. from pathlib import Path
  35.  
  36. HOME = f"{Path.home()}"
  37. VAULT_FILE = f"{HOME}/.vault_password"
  38. PASSWORD_FILE = f"{HOME}/.passwords"
  39. HELP_TEXT = """usage: password <command>
  40.  
  41. commands:
  42. init makes a vault for storing password log
  43. make makes a 32 character cryptographically random password
  44. logs open previously created passwords in less
  45. """
  46.  
  47.  
  48. def help_text():
  49. """Prints help text."""
  50. print(HELP_TEXT, file=sys.stderr)
  51.  
  52.  
  53. def generate(n: int) -> str:
  54. """Generates an n character random password"""
  55. choices = set(
  56. string.ascii_uppercase + string.ascii_lowercase + string.digits)
  57. # remove ambiguous characters
  58. readable = list(choices - set(['O', '0', 'o']))
  59. pw = ''.join(random.SystemRandom().choice(readable) for _ in range(n))
  60. return pw
  61.  
  62.  
  63. def run(cmd: str) -> subprocess.CompletedProcess:
  64. """ Runs a shell command."""
  65. out = subprocess.run(
  66. cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  67. return out
  68.  
  69.  
  70. def parse_args() -> str:
  71. """Validates user input."""
  72. try:
  73. cmd = sys.argv[1]
  74. except IndexError:
  75. help_text()
  76. sys.exit(1)
  77.  
  78. if cmd not in ["init", "make", "logs", "help", "h"]:
  79. print("error: invald command", file=sys.stderr)
  80. help_text()
  81. sys.exit(1)
  82.  
  83. if cmd in ["help", "h"]:
  84. help_text()
  85. sys.exit(1)
  86.  
  87. return cmd
  88.  
  89.  
  90. if __name__ == "__main__":
  91.  
  92. cmd = parse_args()
  93.  
  94. if cmd == "make":
  95. # decrypt log
  96. run(f"ansible-vault --vault-password-file {VAULT_FILE} decrypt {PASSWORD_FILE}"
  97. )
  98. # make the password and append to log
  99. pw = generate(32)
  100. with open(f"{PASSWORD_FILE}", "a+") as f:
  101. now = time.strftime("%Y-%m-%d %H:%M")
  102. f.write(f"{now}: {pw}\n")
  103.  
  104. print("password:", pw)
  105. # encrypt log
  106. run(f"ansible-vault --vault-password-file {VAULT_FILE} encrypt {PASSWORD_FILE}")
  107.  
  108. if cmd == "init":
  109. # ensure there's not an existing log or password file
  110. for f in [VAULT_FILE, PASSWORD_FILE]:
  111. if os.path.exists(f):
  112. print(f"error: found previous version of {f}; skipping\n",
  113. file=sys.stderr)
  114. help_text()
  115. sys.exit(1)
  116.  
  117. with open(VAULT_FILE, "w") as f:
  118. # make password store
  119. pw = generate(32)
  120. f.write(pw)
  121.  
  122. run(f"touch {PASSWORD_FILE}")
  123. print("vault created")
  124.  
  125. if cmd == "logs":
  126. run(f"ansible-vault --vault-password-file {VAULT_FILE} decrypt {PASSWORD_FILE}"
  127. )
  128. subprocess.call(["less", PASSWORD_FILE])
  129. run(f"ansible-vault --vault-password-file {VAULT_FILE} encrypt {PASSWORD_FILE}"
  130. )
Add Comment
Please, Sign In to add comment