**Approach (brief)**Authenticate using a Vault token (env var), read the secret at secret/data/app/api, generate a new credential (placeholder function), write it back with proper KV v2 payload, and print a concise change summary. Handle HTTP errors, missing keys, and ensure idempotency by checking if the new value differs before writing.python
import os, requests, json
VAULT_ADDR = os.environ.get("VAULT_ADDR", "https://vault.example.com")
VAULT_TOKEN = os.environ["VAULT_TOKEN"] # fail fast if missing
SECRET_PATH = "secret/data/app/api" # KV v2 path
def generate_new_credential() -> str:
# Placeholder: implement secure random generation elsewhere
raise NotImplementedError
def vault_request(method, path, **kwargs):
url = f"{VAULT_ADDR}/v1/{path}"
headers = {"X-Vault-Token": VAULT_TOKEN}
resp = requests.request(method, url, headers=headers, timeout=10, **kwargs)
resp.raise_for_status()
return resp.json()
def rotate_api_credential():
try:
current = vault_request("GET", SECRET_PATH)
cur_value = current["data"]["data"].get("api_key")
except requests.HTTPError as e:
print("Error fetching secret:", e); return
new_value = generate_new_credential()
if new_value == cur_value:
print("No change needed (idempotent)."); return
payload = {"data": {"api_key": new_value}}
try:
vault_request("POST", "secret/data/app/api", json=payload)
print(f"Rotated api_key: old_present={bool(cur_value)}, new_length={len(new_value)}")
except requests.HTTPError as e:
print("Error writing secret:", e)
if __name__ == "__main__":
rotate_api_credential()
**Error handling**- Use exceptions from requests; print/log and exit gracefully- Validate JSON structure and missing keys- Timeouts and retries can be added for transient failures**Idempotency**- Script checks existing value and skips write if identical- Safe to run repeatedly; avoid unnecessary version churn in Vault by not writing identical secrets