diff --git a/openvpncertupdate.py b/openvpncertupdate.py index e20f068..cc6ecaa 100644 --- a/openvpncertupdate.py +++ b/openvpncertupdate.py @@ -1410,6 +1410,10 @@ def _build_parser() -> argparse.ArgumentParser: group.add_argument("--reissue", metavar="CN", help="Revoke and reissue certificate for CN") group.add_argument("--revoke", metavar="CN", help="Revoke certificate for CN and regenerate CRL") group.add_argument("--gen-crl", action="store_true", help="Regenerate and copy CRL") + group.add_argument("--list", action="store_true", + help="List recently-expired/soon-to-expire CNs " + "(per DAYS_PAST/DAYS_AHEAD) with email") + group.add_argument("--list-all", action="store_true", help="List all CNs with email") parser.add_argument("--email", metavar="EMAIL", help="Email address (required for --create; optional for --reissue)") parser.add_argument("--send-email", dest="send_email", action="store_const", const=True, @@ -1441,6 +1445,13 @@ def main() -> None: sys.exit(1) globals().update(overrides) + if args.list: + CliRunner().list_certs(show_all=False) + return + if args.list_all: + CliRunner().list_certs(show_all=True) + return + global CA_PASSPHRASE CA_PASSPHRASE = resolve_ca_passphrase(CA_PASSPHRASE, EASYRSA_PKI_DIR) diff --git a/tests/test_cli.py b/tests/test_cli.py index 7e33dc8..acf2850 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -292,6 +292,40 @@ def test_main_dispatches_gen_crl(monkeypatch): runner.regen_crl.assert_called_once_with() +def test_main_dispatches_list(monkeypatch): + monkeypatch.setattr(sys, "argv", ["prog", "--list"]) + runner = MagicMock() + monkeypatch.setattr("openvpncertupdate.CliRunner", lambda: runner) + main() + runner.list_certs.assert_called_once_with(show_all=False) + + +def test_main_dispatches_list_all(monkeypatch): + monkeypatch.setattr(sys, "argv", ["prog", "--list-all"]) + runner = MagicMock() + monkeypatch.setattr("openvpncertupdate.CliRunner", lambda: runner) + main() + runner.list_certs.assert_called_once_with(show_all=True) + + +def test_main_list_skips_ca_passphrase_resolution(monkeypatch): + monkeypatch.setattr(sys, "argv", ["prog", "--list"]) + monkeypatch.setattr("openvpncertupdate.CliRunner", lambda: MagicMock()) + mock_resolve = MagicMock() + monkeypatch.setattr("openvpncertupdate.resolve_ca_passphrase", mock_resolve) + main() + mock_resolve.assert_not_called() + + +def test_main_list_all_skips_ca_passphrase_resolution(monkeypatch): + monkeypatch.setattr(sys, "argv", ["prog", "--list-all"]) + monkeypatch.setattr("openvpncertupdate.CliRunner", lambda: MagicMock()) + mock_resolve = MagicMock() + monkeypatch.setattr("openvpncertupdate.resolve_ca_passphrase", mock_resolve) + main() + mock_resolve.assert_not_called() + + def test_main_no_args_launches_tui(monkeypatch): monkeypatch.setattr(sys, "argv", ["prog"]) app = MagicMock()