|
| 1 | +#!/usr/bin/python3 |
| 2 | +import argparse |
| 3 | +import csv |
| 4 | +import json |
| 5 | +import subprocess |
| 6 | +import sys |
| 7 | +import time |
| 8 | + |
| 9 | +parser = argparse.ArgumentParser( |
| 10 | + "Create a 1Password vault for each name in a list of vault names provided as a plaintext file using the --file flag.", |
| 11 | + "By default, you will have full permissions on each vault created by this script." |
| 12 | + "User the --remove-me flag if you'd like to revoke your own access to the vault after it is created. Members of the Owners and Administrators groups will still be able to manage this vault.", |
| 13 | +) |
| 14 | +parser.add_argument( |
| 15 | + "--file", |
| 16 | + action="store", |
| 17 | + dest="filepath", |
| 18 | + help="Specify the path to a CSV file containing the required input data.", |
| 19 | + required=True, |
| 20 | +) |
| 21 | + |
| 22 | +parser.add_argument( |
| 23 | + "--remove-me", |
| 24 | + action="store_true", |
| 25 | + dest="removeMe", |
| 26 | + help="Remove yourself from the vaults created by this script. To avoid rate limiting, this aggressively throttles the script and each vault will take 11 seconds to process.", |
| 27 | +) |
| 28 | + |
| 29 | +args = parser.parse_args() |
| 30 | + |
| 31 | + |
| 32 | +# Get the User UUID of the person running the script. This is required for other parts of the script. |
| 33 | +def getMyUUID() -> str: |
| 34 | + print("Ensuring you're signed into 1Password and obtaining your User ID.\n") |
| 35 | + r = subprocess.run(["op", "whoami", "--format=json"], capture_output=True) |
| 36 | + |
| 37 | + # Catch error and kill process |
| 38 | + if r.returncode != 0: |
| 39 | + sys.exit( |
| 40 | + f"🔴 Unable to get your user UUID. Make sure you are are signed into the 1Password CLI. Error: {r.stderr.decode('utf-8')}" |
| 41 | + ) |
| 42 | + print(f"🟢 Obtained your User ID: {json.loads(r.stdout)['user_uuid']} \n") |
| 43 | + return json.loads(r.stdout)["user_uuid"] |
| 44 | + |
| 45 | + |
| 46 | +# Grants the group access to the corrosponding vault with defined permissions. |
| 47 | +def createVaultWithName(vault: str): |
| 48 | + retries = 0 |
| 49 | + maxRetries = 3 |
| 50 | + print(f"\t⌛ Attempting to create vault called {vault}.") |
| 51 | + while retries < maxRetries: |
| 52 | + r = subprocess.run( |
| 53 | + [ |
| 54 | + "op", |
| 55 | + "vault", |
| 56 | + "create", |
| 57 | + vault, |
| 58 | + ], |
| 59 | + capture_output=True, |
| 60 | + ) |
| 61 | + # time.sleep(11) |
| 62 | + # Handle rate limit error |
| 63 | + if "rate-limited" in r.stderr.decode("utf-8"): |
| 64 | + # Retry after waiting for 60 seconds |
| 65 | + print(r.stderr.decode("utf-8")) |
| 66 | + print("💤 Sleeping for 10 minutes, go grab a coffee.") |
| 67 | + time.sleep(600) |
| 68 | + retries += 1 |
| 69 | + # Catch error but continue |
| 70 | + elif r.returncode != 0 and "rate-limited" not in r.stderr.decode("utf-8"): |
| 71 | + print( |
| 72 | + f"\t🔴 Unable to create vault named '{vault}'. Error: ", |
| 73 | + r.stderr.decode("utf-8"), |
| 74 | + ) |
| 75 | + break |
| 76 | + else: |
| 77 | + print(f"\t🟢 Successfully created '{vault}'") |
| 78 | + break |
| 79 | + |
| 80 | + |
| 81 | +# Revokes vault access for the person running the script. |
| 82 | +def removeCreatorPermissionsFor(vault: str, userID: str): |
| 83 | + retries = 0 |
| 84 | + maxRetries = 3 |
| 85 | + print(f"\t⌛ Attempting to remove your access to the newly created vault {vault}.") |
| 86 | + while retries < maxRetries: |
| 87 | + r = subprocess.run( |
| 88 | + ["op", "vault", "user", "revoke", f"--user={userID}", f"--vault={vault}"], |
| 89 | + capture_output=True, |
| 90 | + ) |
| 91 | + time.sleep(11) |
| 92 | + # Handle rate limit error |
| 93 | + if "rate-limited" in r.stderr.decode("utf-8"): |
| 94 | + # Retry after waiting for 60 seconds |
| 95 | + print(r.stderr.decode("utf-8")) |
| 96 | + print("💤 Sleeping for 10 minutes, go grab a coffee.") |
| 97 | + time.sleep(600) |
| 98 | + retries += 1 |
| 99 | + # Catch error but continue |
| 100 | + elif r.returncode != 0 and "rate-limited" not in r.stderr.decode("utf-8"): |
| 101 | + print( |
| 102 | + f"\t🔴 There was an issue removing your access to the vault {vault}. Error: ", |
| 103 | + r.stderr.decode("utf-8"), |
| 104 | + ) |
| 105 | + return |
| 106 | + print(f"\t🟢 Succeeded in removing your access to vault {vault}.\n\n") |
| 107 | + return |
| 108 | + |
| 109 | + |
| 110 | +def main(): |
| 111 | + myUUID: str = getMyUUID() |
| 112 | + # Open the csv passed via the --file flag |
| 113 | + with open(args.filepath, "r", newline="", encoding="utf-8") as inputFile: |
| 114 | + csvReader = csv.reader(inputFile, skipinitialspace=True) |
| 115 | + for row in csvReader: |
| 116 | + vault: str = row[0].strip() |
| 117 | + createVaultWithName(vault) |
| 118 | + |
| 119 | + # If --remove-me flag was used, remove the script-runner's permission |
| 120 | + if args.removeMe: |
| 121 | + removeCreatorPermissionsFor(vault, myUUID) |
| 122 | + |
| 123 | + |
| 124 | +main() |
0 commit comments