6.2 KiB
6.2 KiB
name, description, version, author, license, metadata
| name | description | version | author | license | metadata | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| credential-management | Centralized credential management for 9Webs automation scripts — single .env file, Python loader, migration pattern. No more hardcoded passwords in scripts. | 1.0.0 | Hermes Agent | MIT |
|
Credential Management
Centralized credential infrastructure for all 9Webs automation scripts. Scripts read credentials from a single ~/.hermes/credentials.env file via a Python loader module — no hardcoded passwords anywhere.
When to use
- Writing a new automation script that needs AtomK, Ozon, Gitea, Miaoshou, or email credentials
- Migrating an existing hardcoded-credential script to the centralized pattern
- Rotating credentials across all scripts at once
- Debugging a
KeyErrorfromatomk_credentials.get_credential()
Architecture
~/.hermes/
├── credentials.env # Single source of truth (chmod 600, never committed)
└── scripts/
└── atomk_credentials.py # Python loader with typed helpers
credentials.env format
ATOMLISTING_USERNAME=admincao
ATOMLISTING_PASSWORD=actual-value-here
ATOMLISTING_API_BASE=https://www.atomlisting.com
MIAOSHOU_USERNAME=...
MIAOSHOU_PASSWORD=...
OZON1_EMAIL=...
OZON1_PASSWORD=...
GITEA_USERNAME=admin9webs
GITEA_PASSWORD=...
Rules:
chmod 600— owner read/write only- Never committed to Git (add to
.gitignore) FILL_MEplaceholder means the value is not yet set- Override path with
ATOMK_CREDENTIALS_FILEenv var
Python loader API
import sys, os
sys.path.insert(0, os.path.expanduser("~/.hermes/scripts"))
from atomk_credentials import (
get_credential, # key → value
get_atomk_auth, # → (username, password)
get_miaoshou_auth, # → (username, password)
get_ozon_auth, # → (email, password) — store=1 or 2
get_gitea_auth, # → (username, password)
)
The loader caches on first access. get_credential() raises KeyError if the value is unset or still FILL_ME.
Migration pattern
When moving a script from hardcoded credentials to the loader:
Before (BAD):
ATOMK_USERNAME = "admincao"
ATOMK_PASSWORD = "Tt123456!"
After (GOOD):
import sys, os
sys.path.insert(0, os.path.expanduser("~/.hermes/scripts"))
from atomk_credentials import get_atomk_auth
ATOMK_USERNAME, ATOMK_PASSWORD = get_atomk_auth()
Steps for each script:
- Add
import sys, osif not present - Add the
sys.path.insertline before the credential import - Import the appropriate helper function
- Replace hardcoded values with the function call
- Run
python3 -c "import ast; ast.parse(open('script.py').read())"to verify syntax - Test the script with the credential file populated
Adding new credentials
- Add the variable to
~/.hermes/credentials.envwith an initialFILL_MEplaceholder - Add a typed helper function to
atomk_credentials.py(e.g.,get_new_service_auth()) - Fill in the actual value in
credentials.env
Pitfalls
KeyErroron first run — the credential file ships withFILL_MEplaceholders. The user must replace them with real values.ModuleNotFoundError: atomk_credentials— the script doesn't havesys.path.insert(0, ...)before the import. Thescripts/directory is not on Python's default path.- Syntax error after migration — verify with
ast.parse()as shown above. The refactored lines must be valid Python. - Python 3.12+ f-string backslash restriction — if the script uses backslash-escaped quotes inside f-strings (e.g.,
f'{\"embedded\"}'), extract the replacement string to a variable first. This is a Python version constraint, not credential-specific. - Credentials on command line — never pass credentials as command-line arguments. They are visible in
psoutput and shell history. Always read from env or file. - MongoDB URI encoding with special chars — passwords containing
@(%40) and#(%23) can fail authentication when passed via URI string, even afterquote_plus(). Workaround: passusername=andpassword=directly toMongoClient()constructor parameters instead of encoding them into the URI. Seereferences/mongodb-auth-patterns.mdfor detailed examples. - Python venv/PEP 668 — this host enforces externally-managed Python (
--systemflag rejected). Usepython3 -m venv /tmp/venv && /tmp/venv/bin/pip install ...for one-off tool deps (e.g.,pymongo). Do not waste time fightinguv pip install --system.
Related credential stores
- Tencent Cloud / tccli:
~/.tccli/default.credential(INI format). Separate from~/.hermes/credentials.env. Used bytencent-cloud-operationsskill for TAT, Lighthouse, and CVM API access. Managed independently. - Production server .env:
/root/AtomK_Operation_Tools/.envon SG3 (43.134.190.229). Contains MongoDB, MySQL, API keys, and AI service credentials for the running AtomK_Server backend. - premiumproducts MongoDB:
mongodb://root:***@43.134.190.229:27018/premiumproducts?authSource=admin(password contains@and#). New database (2026-07) for premium product management. Use direct constructor params — not URI encoding. Seereferences/mongodb-auth-patterns.md.
Security rules
- Never
print()orlog()a credential value - Never pass credentials on the command line (visible in
ps) - Never commit
credentials.envto Git - After rotating a password, update
credentials.env— no script-level changes needed - The loader checks for
FILL_MEand raisesKeyErrorrather than silently using a placeholder - TAT (Tencent Automation Tools) aggressively masks passwords in remote command output — use
xxdhex dump or char-by-charord()extraction to read credentials from remote.envfiles
Support files
templates/credentials.env— clean template to copy to~/.hermes/credentials.envreferences/audit-findings.md— 2026-06-22 security audit credential exposure summaryscripts/scan_hardcoded_secrets.py— scan a directory for known hardcoded secrets and suspicious patterns