feat: app orchestrator, entry point, CLAUDE.md — implementation complete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Vlad Doloman
2026-06-24 00:24:30 +03:00
parent ca6fe9f525
commit 1b2f4d2bdc
2 changed files with 243 additions and 2 deletions

57
CLAUDE.md Normal file
View File

@@ -0,0 +1,57 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## What this is
`openvpncertupdate` is a single-file Python + curses TUI tool for managing OpenVPN user certificates via EasyRSA 3.2.x. It lists expiring/expired certs, re-issues them with fresh keys, creates new certs, and delivers configs via Cryptgeon (one-time password URL) and email.
## Running
```bash
pip install -r requirements.txt # just: cryptography>=41
python3 openvpncertupdate.py
```
Edit the `SETTINGS` block at the top of `openvpncertupdate.py` before first run.
## Tests
```bash
python3 -m pytest tests/ -v
python3 -m pytest tests/test_password.py -v # single file
python3 -m pytest tests/test_pki.py::test_sorted_ascending -v # single test
```
## File layout — sections inside `openvpncertupdate.py`
| Section | Key symbols |
|---|---|
| SETTINGS | all-caps constants |
| PKI | `CertInfo`, `load_expiring_certs()`, `_parse_index_line()` |
| PASSWORD | `generate_password()` |
| EASYRSA | `EasyRSAError`, `revoke_issued()`, `build_client_full()`, `gen_crl()`, `copy_crl()` |
| METADATA | `load_metadata()`, `save_email()`, `get_email()` |
| CONFIG | `build_ovpn()``vpn-configs/<CN>_<date>/<CONFIG_NAME>` |
| CRYPTGEON | `CryptgeonError`, `create_note()` |
| MAILER | `send_email()` |
| TUI WIDGETS | `InputField`, `clamp()`, `draw_box()`, `init_colors()`, `COLOR_*` |
| TUI DIALOGS | `show_confirm()`, `show_cert_form()`, `CertFormResult` |
| TUI SCREEN | `show_main_screen()`, `Action`, `ScreenResult` |
| APP | `CursesApp` |
| ENTRY POINT | `main()` |
## Re-issue workflow
1. `revoke-issued <CN>` — archives old key + CSR to `pki/revoked/`
2. `build-client-full <CN> --passout=pass:<pw>` — generates new key + cert
3. CRL **not** auto-updated during renewal; use "Regenerate CRL" menu item or `r` hotkey
## Key constraints
- EasyRSA called with `--batch`; `--passin=pass:<CA_PASSPHRASE>` omitted when `CA_PASSPHRASE=""`
- Cryptgeon: `raw_key=os.urandom(32)`, `aes_key=SHA-256(raw_key)`, AES-256-GCM, URL fragment=`base64url(raw_key)`
- `copy_crl()` does `chmod 644` after copy
- Password: pos 1=uppercase, pos 2=lowercase (no j), pos 3-27=alphanumeric, pos 28=lowercase (no j); `oO01lI` banned everywhere
- Inline file path: `<PKI_DIR>/inline/private/<CN>.inline`
- User emails stored in `<PKI_DIR>/openvpncertupdate-metadata.json`