61 lines
2.1 KiB
Python
61 lines
2.1 KiB
Python
"""Restricted interactive owner-account provisioning command."""
|
|||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import argparse
|
||
|
|
import getpass
|
||
|
|
import os
|
||
|
|
import sys
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
import pyotp
|
||
|
|
|
||
|
|
from gewu.adapters.sqlite_identity import SQLiteIdentityStore
|
||
|
|
|
||
|
|
|
||
|
|
def main() -> int:
|
||
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
||
|
|
parser.add_argument("principal_id")
|
||
|
|
parser.add_argument(
|
||
|
|
"--project", action="append", dest="project_ids", required=True, metavar="PROJECT_ID"
|
||
|
|
)
|
||
|
|
arguments = parser.parse_args()
|
||
|
|
if not sys.stdin.isatty() or not sys.stdout.isatty():
|
||
|
|
parser.error("owner provisioning requires an interactive terminal")
|
||
|
|
data_root = Path(os.environ.get("GEWU_DATA_ROOT", "./.data/gewu")).expanduser().absolute()
|
||
|
|
encryption_key = os.environ.get("GEWU_OWNER_ENCRYPTION_KEY")
|
||
|
|
if encryption_key is None:
|
||
|
|
parser.error("GEWU_OWNER_ENCRYPTION_KEY must be configured outside the database")
|
||
|
|
password = getpass.getpass("Owner password: ")
|
||
|
|
confirmation = getpass.getpass("Confirm owner password: ")
|
||
|
|
if password != confirmation:
|
||
|
|
parser.error("owner passwords did not match")
|
||
|
|
secret = pyotp.random_base32()
|
||
|
|
store = SQLiteIdentityStore(
|
||
|
|
data_root / "identity.sqlite3",
|
||
|
|
authority_lock_path=data_root / "workflow/locks/canonical-writer.lock",
|
||
|
|
owner_encryption_key=encryption_key.encode("ascii"),
|
||
|
|
)
|
||
|
|
try:
|
||
|
|
store.provision_owner(
|
||
|
|
principal_id=arguments.principal_id,
|
||
|
|
password=password,
|
||
|
|
totp_secret=secret,
|
||
|
|
project_ids=tuple(arguments.project_ids),
|
||
|
|
)
|
||
|
|
except (ValueError, RuntimeError) as error:
|
||
|
|
parser.error(str(error))
|
||
|
|
finally:
|
||
|
|
password = ""
|
||
|
|
confirmation = ""
|
||
|
|
enrollment_uri = pyotp.TOTP(secret).provisioning_uri(
|
||
|
|
name=arguments.principal_id, issuer_name="GEWU"
|
||
|
|
)
|
||
|
|
print("Add this one-time enrollment URI to the owner authenticator:")
|
||
|
|
print(enrollment_uri)
|
||
|
|
print("The URI contains the TOTP seed. Store it securely; it will not be shown again.")
|
||
|
|
return 0
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
raise SystemExit(main())
|