class VaultKeyRetriever: def __init__(self): self.op = OnePassword() vault_keys_doc = self.op.get_item(uuid=os.environ["VAULT_DOC_UUID"]) vault_keys_json = vault_keys_doc["details"]["notesPlain"] self.vault_keys = json.loads(vault_keys_json) def retrieve_key(self, environment, key_type): env_key = f"k8s_operator/{environment}" for e in self.vault_keys: if env_key in e: return e[env_key][key_type]["id"]
def set_up_one_password(): """Set up a mock OnePassword Vault""" domain = "test" email = "*****@*****.**" secret = "test_secret" password = "******" os.environ["HOME"] = 'test_utilities' os.mkdir("test_utilities") with open('test_utilities/.bash_profile', 'w') as f: f.write("") f.close() override_platform = 'Linux' return OnePassword(install_only=True, domain=domain, email=email, secret=secret, password=password, override_platform=override_platform)
def __init__(self, environment, regenerate): super().__init__(environment, regenerate) self.op_secrets = {} self.op = OnePassword() self.parse_vault()
class OnePasswordSecretGenerator(SecretGenerator): def __init__(self, environment, regenerate): super().__init__(environment, regenerate) self.op_secrets = {} self.op = OnePassword() self.parse_vault() def parse_vault(self): items = self.op.list_items("RSP-Vault") for i in items: key = None environments = [] uuid = i["uuid"] doc = self.op.get_item(uuid=uuid) logging.debug(f"Looking at {uuid}") logging.debug(f"{doc}") for section in doc["details"]["sections"]: if "fields" not in section: continue for field in section["fields"]: if field["t"] == "generate_secrets_key": if key is None: key = field["v"] else: raise Exception("Found two generate_secrets_keys for {key}") elif field["t"] == "environment": environments.append(field["v"]) # If we don't find a generate_secrets_key somewhere, then we shouldn't # bother with this document in the vault. if not key: continue # The type of secret is either a note or a password login. # First, check the notes. secret_value = doc["details"]["notesPlain"] # If we don't find anything, pull the password from a login item. if not secret_value: for f in doc["details"]["fields"]: if f["designation"] == "password": secret_value = f["value"] if self.environment in environments: self.op_secrets[key] = secret_value elif not environments and key not in self.op_secrets: self.op_secrets[key] = secret_value def input_field(self, component, name, description): key = f"{component} {name}" if key not in self.op_secrets: raise Exception(f"Did not find entry in 1Password for {key}") self.secrets[component][name] = self.op_secrets[key] def input_file(self, component, name, description): return self.input_field(component, name, description)
class OnePasswordSecretGenerator(SecretGenerator): """A secret generator that syncs 1Password secrets into a secrets directory containing per-component secret export files from Vault (as generated by read_secrets.sh). Parameters ---------- environment : str The name of the environment (the environment's domain name). regenerate : bool If `True`, any secrets that can be generated by the SecretGenerator will be regenerated. """ def __init__(self, environment, regenerate): super().__init__(environment, regenerate) self.op_secrets = {} self.op = OnePassword() self.parse_vault() def parse_vault(self): """Parse the 1Password vault and store secrets applicable to this environment in the `op_secrets` attribute. This method is called automatically when initializing a `OnePasswordSecretGenerator`. """ items = self.op.list_items("RSP-Vault") for i in items: key = None environments = [] uuid = i["uuid"] doc = self.op.get_item(uuid=uuid) logging.debug(f"Looking at {uuid}") logging.debug(f"{doc}") for section in doc["details"]["sections"]: if "fields" not in section: continue for field in section["fields"]: if field["t"] == "generate_secrets_key": if key is None: key = field["v"] else: raise Exception( "Found two generate_secrets_keys for {key}") elif field["t"] == "environment": environments.append(field["v"]) # If we don't find a generate_secrets_key somewhere, then we shouldn't # bother with this document in the vault. if not key: logging.debug( f"Skipping because of no generate_secrets_key, %s", uuid) continue # The type of secret is either a note or a password login. # First, check the notes. secret_value = doc["details"]["notesPlain"] # If we don't find anything, pull the password from a login item. if not secret_value: for f in doc["details"]["fields"]: if f["designation"] == "password": secret_value = f["value"] logging.debug("Environments are %s for %s", environments, uuid) if self.environment in environments: self.op_secrets[key] = secret_value logging.debug("Storing %s (matching environment)", uuid) elif not environments and key not in self.op_secrets: self.op_secrets[key] = secret_value logging.debug("Storing %s (applicable to all envs)", uuid) else: logging.debug("Ignoring %s", uuid) def input_field(self, component, name, description): """Query for a secret's value from 1Password (`op_secrets` attribute). This method overrides `SecretGenerator.input_field`, which prompts a user interactively. """ key = f"{component} {name}" if key not in self.op_secrets: raise Exception(f"Did not find entry in 1Password for {key}") self.secrets[component][name] = self.op_secrets[key] def input_file(self, component, name, description): """Query for a secret file from 1Password (`op_secrets` attribute). This method overrides `SecretGenerator.input_file`, which prompts a user interactively. """ return self.input_field(component, name, description) def generate(self): """Generate secrets, updating the `secrets` attribute. This method first runs `SecretGenerator.generate`, and then automatically generates secrets for any additional components that were identified in 1Password, but do not have a file in the secrets directory yet. """ super().generate() components_in_op = set([k.split()[0] for k in self.op_secrets.keys()]) existing_components = set(self.secrets.keys()) # Add components that may not be present in every environment, # but nonetheless might be 1Password secrets (see conditional # in SecretGenerator.generate) existing_components.update({"ingress-nginx", "cert-manager"}) new_components = components_in_op - existing_components logging.debug("New components: %s", new_components) for component_name in new_components: self._generate_new_op_component(component_name) def _generate_new_op_component(self, component_name): """Generate an entry in the `secrets` attribute for a new component found in 1Password. """ for secret_key in self.op_secrets.keys(): item_component, item_name = secret_key.split() if item_component == component_name: self.input_field(component_name, item_name, "")
def __init__(self): self.op = OnePassword() vault_keys_doc = self.op.get_item(uuid=os.environ["VAULT_DOC_UUID"]) vault_keys_json = vault_keys_doc["details"]["notesPlain"] self.vault_keys = json.loads(vault_keys_json)
from onepassword import OnePassword secret = {"password": "******", "username": "******", "signin_address": "<YOUR-1PASSWORD-ORGNIZATION-ADDRESS>", "secret_key": "<YOUR-1PASSWORD-SECRET-KEY>"} op = OnePassword(secret=secret) documents = op.list("documents") pem_keys = (doc for doc in documents if doc["overview"]["title"].endswith("pem")) first_key = next(pem_keys) key_contents = op.get("document", first_key["uuid"]) print(key_contents)