Coverage for mcpgateway / utils / hash_password.py: 100%

25 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-09 03:05 +0000

1#!/usr/bin/env python3 

2# -*- coding: utf-8 -*- 

3"""Location: ./mcpgateway/utils/hash_password.py 

4Copyright 2026 

5SPDX-License-Identifier: Apache-2.0 

6 

7Generate Argon2id password hashes for emergency admin recovery operations. 

8""" 

9 

10# Standard 

11import argparse 

12import asyncio 

13import getpass 

14import sys 

15 

16# First-Party 

17from mcpgateway.services.argon2_service import Argon2PasswordService 

18 

19 

20async def _generate_hash(password: str) -> str: 

21 """Generate an Argon2id hash for a plaintext password. 

22 

23 Args: 

24 password: Plaintext password. 

25 

26 Returns: 

27 str: Argon2id encoded hash. 

28 """ 

29 service = Argon2PasswordService() 

30 return await service.hash_password_async(password) 

31 

32 

33def main() -> int: 

34 """Run CLI entrypoint for generating password hashes. 

35 

36 Returns: 

37 int: Process exit code (`0` success, non-zero on validation failure). 

38 """ 

39 parser = argparse.ArgumentParser(description="Generate an Argon2id password hash for ContextForge users.") 

40 parser.add_argument("--password", help="Password value. If omitted, a secure prompt is used.") 

41 args = parser.parse_args() 

42 

43 password = args.password 

44 if not password: 

45 password = getpass.getpass("Password: ") 

46 confirm = getpass.getpass("Confirm password: ") 

47 if password != confirm: 

48 print("Passwords do not match.", file=sys.stderr) 

49 return 1 

50 

51 if not password: 

52 print("Password cannot be empty.", file=sys.stderr) 

53 return 1 

54 

55 password_hash = asyncio.run(_generate_hash(password)) 

56 print(password_hash) 

57 return 0 

58 

59 

60if __name__ == "__main__": 

61 raise SystemExit(main())