diff --git a/openvpncertupdate.py b/openvpncertupdate.py index 6ba541b..57c8d92 100644 --- a/openvpncertupdate.py +++ b/openvpncertupdate.py @@ -1530,7 +1530,7 @@ class CliRunner: print(f"Building certificate for {cn}…", file=sys.stderr) try: build_client_full(EASYRSA_DIR, EASYRSA_PKI_DIR, cn, password, CA_PASSPHRASE, - email=email_addr) + email=email_addr, days=CERT_DAYS) except EasyRSAError as exc: if revoked: print( @@ -1611,6 +1611,9 @@ def _build_parser() -> argparse.ArgumentParser: 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("--days", metavar="N", + help="Certificate lifetime in days for --create/--reissue " + "(overrides CERT_DAYS; omit to use CERT_DAYS)") parser.add_argument("--send-email", dest="send_email", action="store_const", const=True, default=None, help="Send email after issuing cert (default unless --show-eml)") parser.add_argument("--no-send-email", dest="send_email", action="store_const", const=False, @@ -1640,6 +1643,14 @@ def main() -> None: sys.exit(1) globals().update(overrides) + global CERT_DAYS + try: + CERT_DAYS = (resolve_cert_days(args.days, "--days") if args.days is not None + else resolve_cert_days(CERT_DAYS)) + except ConfigError as exc: + print(f"error: {exc}", file=sys.stderr) + sys.exit(1) + if args.list: CliRunner().list_certs(show_all=False) return diff --git a/tests/test_cli.py b/tests/test_cli.py index 72043d4..5714fe2 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -633,3 +633,63 @@ def test_main_show_eml_send_email_override(monkeypatch): runner.create.assert_called_once_with( "alice", "a@b.com", send_email_flag=True, show_eml=True ) + + +# --------------------------------------------------------------------------- +# --days +# --------------------------------------------------------------------------- + +def test_days_flag_parses(): + args = _build_parser().parse_args(["--create", "alice", "--email", "a@b.c", + "--days", "90"]) + assert args.days == "90" + + +def test_days_defaults_to_none_when_absent(): + args = _build_parser().parse_args(["--create", "alice", "--email", "a@b.c"]) + assert args.days is None + + +def test_issue_passes_resolved_days_to_build_client_full(monkeypatch, capsys): + mocks = _patch_issue(monkeypatch) + monkeypatch.setattr("openvpncertupdate.CERT_DAYS", "90") + CliRunner().create("alice", "alice@example.com") + assert mocks["build_client_full"].call_args.kwargs["days"] == "90" + + +def test_issue_passes_empty_days_when_inheriting(monkeypatch, capsys): + mocks = _patch_issue(monkeypatch) + monkeypatch.setattr("openvpncertupdate.CERT_DAYS", "") + CliRunner().create("alice", "alice@example.com") + assert mocks["build_client_full"].call_args.kwargs["days"] == "" + + +def test_main_days_flag_overrides_cert_days(monkeypatch): + import openvpncertupdate + monkeypatch.setattr(sys, "argv", + ["prog", "--create", "alice", "--email", "a@b.c", "--days", "30"]) + monkeypatch.setattr("openvpncertupdate.CERT_DAYS", "default") + monkeypatch.setattr("openvpncertupdate.resolve_ca_passphrase", MagicMock(return_value="")) + runner = MagicMock() + monkeypatch.setattr("openvpncertupdate.CliRunner", MagicMock(return_value=runner)) + main() + assert openvpncertupdate.CERT_DAYS == "30" + + +def test_main_resolves_cert_days_when_no_flag(monkeypatch): + import openvpncertupdate + monkeypatch.setattr(sys, "argv", ["prog", "--create", "alice", "--email", "a@b.c"]) + monkeypatch.setattr("openvpncertupdate.CERT_DAYS", "090") + monkeypatch.setattr("openvpncertupdate.resolve_ca_passphrase", MagicMock(return_value="")) + monkeypatch.setattr("openvpncertupdate.CliRunner", MagicMock(return_value=MagicMock())) + main() + assert openvpncertupdate.CERT_DAYS == "90" + + +def test_main_rejects_bad_days_flag(monkeypatch, capsys): + monkeypatch.setattr(sys, "argv", + ["prog", "--create", "alice", "--email", "a@b.c", "--days", "0"]) + monkeypatch.setattr("openvpncertupdate.resolve_ca_passphrase", MagicMock(return_value="")) + with pytest.raises(SystemExit): + main() + assert "--days" in capsys.readouterr().err