def secret_token_from_tag(token_tag): "returns token from token_tag" match = re.match(SECRET_TOKEN_TAG_PATTERN, token_tag) if match: _, token, func = match.groups() return token, func else: logger.error('Secret error: token tag not valid: %s', token_tag) raise SecretError()
def secret_gpg_raw_read(secrets_path, token): "load (yaml) and return the content of the secret file for token" _, token_path = secret_token_attributes(token) full_secret_path = os.path.join(secrets_path, token_path) try: with open(full_secret_path) as fp: secret_obj = yaml.load(fp, Loader=YamlLoader) logger.debug("Read raw secret %s at %s", token, full_secret_path) return secret_obj except IOError as ex: if ex.errno == errno.ENOENT: logger.error('Secret error: could not read raw secret %s at %s', token, full_secret_path) raise SecretError()
def reveal_gpg_replace(gpg_obj, secrets_path, match_obj, verify=True, **kwargs): "returns and verifies hash for decrypted secret from token in match_obj" token_tag, token, func = match_obj.groups() if verify: _, token_path, token_hash = secret_token_compiled_attributes(token) secret_raw_obj = secret_gpg_raw_read(secrets_path, token) secret_tag = "%s%s" % (token_path, secret_raw_obj["data"]) secret_hash = hashlib.sha256(secret_tag.encode("UTF-8")).hexdigest() secret_hash = secret_hash[:8] logger.debug("Attempting to reveal token %s with secret hash %s", token, token_hash) if secret_hash != token_hash: logger.error("Secret error: currently stored secret hash: %s does not match compiled secret: %s", secret_hash, token) raise SecretError() logger.debug("Revealing %s", token_tag) return secret_gpg_read(gpg_obj, secrets_path, token, **kwargs)
def secret_token_compiled_attributes(token): "validates and returns backend, path and hash from token" match = re.match(SECRET_TOKEN_COMPILED_ATTR_PATTERN, token) if match: backend, token_path, token_hash = match.groups() logger.debug("Got token attributes %s %s %s", backend, token_path, token_hash) if token_path.startswith("/") or token_path.endswith("/"): raise TokenError("Token path must not start/end with '/' %s" % token_path) split_path = os.path.join(*token_path.split("/")) if backend != 'gpg': raise TokenError('Secret backend is not "gpg": %s' % token) return backend, split_path, token_hash else: logger.error('Secret error: token not valid: %s', token) raise SecretError()
def secret_gpg_read(secrets_path, token, **kwargs): "decrypt and read data for token in secrets_path" _, token_path = secret_token_attributes(token) full_secret_path = os.path.join(secrets_path, token_path) try: with open(full_secret_path) as fp: secret_obj = yaml.load(fp, Loader=YamlLoader) data_decoded = base64.b64decode(secret_obj['data']) dec = secret_gpg_decrypt(data_decoded, **kwargs) logger.debug("Read secret %s at %s", token, full_secret_path) if dec.ok: return dec.data.decode("UTF-8") else: raise GPGError(dec.status) except IOError as ex: if ex.errno == errno.ENOENT: logger.error('Secret error: Could not read secret %s at %s', token, full_secret_path) raise SecretError()