feat: add show-admin-password and reset-admin-password make targets
make show-admin-password — prints the admin password from the initial setup file if the API hasn't consumed it yet; otherwise prompts to reset make reset-admin-password — generates a strong random password, updates auth_users.json directly, writes it back to the setup file, and prints it prominently so it's easy to copy Also enhances reset_admin_password.py with --show, --generate flags and a clear banner output, and adds both targets to make help. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
test-integration test-integration-readonly \
|
||||
test-e2e-deps test-e2e-api test-e2e-ui test-e2e-wg test-e2e \
|
||||
reset-test-admin-pass \
|
||||
show-admin-password reset-admin-password \
|
||||
show-routes add-peer list-peers
|
||||
|
||||
# Detect docker compose command (v2 plugin preferred, fallback to v1 standalone)
|
||||
@@ -54,6 +55,8 @@ help:
|
||||
@echo " backup - Backup config + data to backups/"
|
||||
@echo " restore - List available backups"
|
||||
@echo " clean - Remove containers and volumes (keeps config/data dirs)"
|
||||
@echo " show-admin-password - Print the admin password (reads setup file or prompts to reset)"
|
||||
@echo " reset-admin-password - Generate a new random admin password and print it"
|
||||
@echo ""
|
||||
@echo "Tests:"
|
||||
@echo " test - Run all tests"
|
||||
@@ -271,6 +274,14 @@ ifndef PIC_TEST_ADMIN_PASS
|
||||
endif
|
||||
python3 scripts/reset_admin_password.py "$(PIC_TEST_ADMIN_PASS)"
|
||||
|
||||
# ── Admin password management ──────────────────────────────────────────────────
|
||||
|
||||
show-admin-password:
|
||||
@python3 scripts/reset_admin_password.py --show
|
||||
|
||||
reset-admin-password:
|
||||
@python3 scripts/reset_admin_password.py --generate
|
||||
|
||||
test-phase1:
|
||||
cd api && python3 -m pytest tests/test_network_manager.py tests/test_phase1_endpoints.py -v
|
||||
|
||||
|
||||
@@ -1,27 +1,102 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Reset admin password directly in auth_users.json — for test environments only."""
|
||||
"""
|
||||
Admin password management utility.
|
||||
|
||||
Usage:
|
||||
reset_admin_password.py --generate # generate a random password and set it
|
||||
reset_admin_password.py <new_password> # set a specific password
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
import secrets
|
||||
import string
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'api'))
|
||||
|
||||
ROOT = os.path.join(os.path.dirname(__file__), '..')
|
||||
INIT_PW_FILE = os.path.normpath(os.path.join(ROOT, 'data', 'api', '.admin_initial_password'))
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: reset_admin_password.py <new_password>", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
new_password = sys.argv[1]
|
||||
|
||||
def _generate_password(length: int = 20) -> str:
|
||||
alphabet = string.ascii_letters + string.digits + '!@#$%^&*'
|
||||
while True:
|
||||
pw = ''.join(secrets.choice(alphabet) for _ in range(length))
|
||||
# Ensure at least one of each character class required by the validator
|
||||
if (any(c.isupper() for c in pw)
|
||||
and any(c.islower() for c in pw)
|
||||
and any(c.isdigit() for c in pw)
|
||||
and any(c in '!@#$%^&*' for c in pw)):
|
||||
return pw
|
||||
|
||||
|
||||
def _set_password(new_password: str) -> None:
|
||||
from auth_manager import AuthManager
|
||||
data_dir = os.path.join(os.path.dirname(__file__), '..', 'data', 'api')
|
||||
data_dir = os.path.normpath(os.path.join(ROOT, 'data', 'api'))
|
||||
os.makedirs(data_dir, exist_ok=True)
|
||||
mgr = AuthManager(data_dir=data_dir, config_dir='/tmp')
|
||||
if mgr.set_password_admin('admin', new_password):
|
||||
print(f"[OK] Admin password reset successfully.")
|
||||
print('[OK] Admin password updated in auth_users.json')
|
||||
else:
|
||||
print("[WARN] Admin user not found — creating admin user.")
|
||||
print('[WARN] Admin user not found — creating it now')
|
||||
mgr.create_user('admin', new_password, 'admin')
|
||||
print(f"[OK] Admin user created with provided password.")
|
||||
print('[OK] Admin user created')
|
||||
|
||||
|
||||
def _print_banner(password: str) -> None:
|
||||
border = '=' * 60
|
||||
print(border)
|
||||
print(' ADMIN PASSWORD')
|
||||
print(border)
|
||||
print(f' Username : admin')
|
||||
print(f' Password : {password}')
|
||||
print(border)
|
||||
print(' Save this password — it will NOT be shown again.')
|
||||
print(border)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
if len(sys.argv) < 2:
|
||||
print(__doc__, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
arg = sys.argv[1]
|
||||
|
||||
if arg == '--show':
|
||||
# Show the initial password file if the API hasn't consumed it yet
|
||||
if os.path.exists(INIT_PW_FILE):
|
||||
pw = open(INIT_PW_FILE).read().strip()
|
||||
_print_banner(pw)
|
||||
print()
|
||||
print(f' (file: {INIT_PW_FILE})')
|
||||
print(' The API will delete this file on first start.')
|
||||
else:
|
||||
print('Initial password file not found.')
|
||||
print('The API has already consumed it, or setup has not been run.')
|
||||
print()
|
||||
print('To set a new password run:')
|
||||
print(' make reset-admin-password')
|
||||
return
|
||||
|
||||
if arg == '--generate':
|
||||
password = _generate_password()
|
||||
else:
|
||||
password = arg
|
||||
|
||||
if len(password) < 10:
|
||||
print('Error: password must be at least 10 characters', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
_set_password(password)
|
||||
|
||||
# Also update the initial password file so show-admin-password works
|
||||
os.makedirs(os.path.dirname(INIT_PW_FILE), exist_ok=True)
|
||||
with open(INIT_PW_FILE, 'w') as f:
|
||||
f.write(password)
|
||||
|
||||
_print_banner(password)
|
||||
print(f'\n Also saved to: {INIT_PW_FILE}')
|
||||
print(' Restart the API container for the change to take effect:')
|
||||
print(' docker restart cell-api')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
Reference in New Issue
Block a user