A wheel whose top-level module is `app` collides with anything else in a user's venv, so the package that is about to be published takes the name it is published under. Only the Python package moves; the repo, the Docker WORKDIR and the compose project keep theirs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
43 lines
1.3 KiB
Python
43 lines
1.3 KiB
Python
"""Re-encrypt the secrets store after SECRET_KEY was rotated.
|
|
|
|
The store's encryption key is derived from SECRET_KEY, so a new key leaves
|
|
``secrets.enc`` unreadable. Put the new key in `.env` first, then hand this
|
|
script the previous one:
|
|
|
|
uv run python scripts/rotate_secret_key.py <old-secret-key>
|
|
"""
|
|
|
|
import logging
|
|
import sys
|
|
|
|
from fluksio.core.config import settings
|
|
from fluksio.flow.secrets import SecretsStore, SecretsUnreadable
|
|
|
|
logging.basicConfig(level=logging.INFO)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def main(old_key: str) -> None:
|
|
path = settings.SECRETS_FILE
|
|
if not path.exists():
|
|
sys.exit(f"No secrets store at {path} — nothing to re-encrypt.")
|
|
if old_key == settings.SECRET_KEY:
|
|
sys.exit("Old and new key are identical — set the new SECRET_KEY first.")
|
|
|
|
# The store has no bulk export; reading and writing it whole is the point.
|
|
try:
|
|
data = SecretsStore(path, old_key)._read()
|
|
except SecretsUnreadable:
|
|
sys.exit(f"{path} does not decrypt with that key — refusing to overwrite it.")
|
|
|
|
SecretsStore(path, settings.SECRET_KEY)._write(data)
|
|
logger.info(
|
|
"Re-encrypted %d secret(s) in %s with the current SECRET_KEY", len(data), path
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) != 2:
|
|
sys.exit("usage: rotate_secret_key.py <old-secret-key>")
|
|
main(sys.argv[1])
|