This commit is contained in:
deamonkai
2026-01-23 12:11:21 -06:00
commit fc94008530
16494 changed files with 2974672 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
def test_allow_wildcard_warning_colored_when_tty(monkeypatch, tmp_path, capsys):
from certctl import cli
from certctl import keygen
import sys
key_pem = keygen.generate_private_key(kind="rsa", bits=1024)
key_file = tmp_path / "k.pem"
key_file.write_text(key_pem)
# Simulate stderr being a TTY so colored output should be used
monkeypatch.setattr(sys.stderr, "isatty", lambda: True, raising=False)
out = tmp_path / "req.csr"
rc = cli.main(["csr", "create", "--key-file", str(key_file), "--subject", "/C=US/CN=example.com", "--san", "*.example.com", "--allow-wildcard", "--out", str(out)])
captured = capsys.readouterr()
assert rc == 0
# ANSI bold yellow prefix
assert "\033[1;33mWARNING: --allow-wildcard used" in captured.err
# ANSI reset present
assert "\033[0m" in captured.err

View File

@@ -0,0 +1,13 @@
def test_allow_wildcard_warning_prints(monkeypatch, tmp_path, capsys):
from certctl import cli
from certctl import keygen
key_pem = keygen.generate_private_key(kind="rsa", bits=1024)
key_file = tmp_path / "k.pem"
key_file.write_text(key_pem)
out = tmp_path / "req.csr"
rc = cli.main(["csr", "create", "--key-file", str(key_file), "--subject", "/C=US/CN=example.com", "--san", "*.example.com", "--allow-wildcard", "--out", str(out)])
captured = capsys.readouterr()
assert rc == 0
assert "WARNING: --allow-wildcard used" in captured.err

View File

@@ -0,0 +1,21 @@
"""Tests for CLI CSR commands."""
import subprocess
from certctl import cli
def test_cli_csr_create_and_show(monkeypatch, tmp_path):
# Generate a key and write to file
from certctl import keygen
key_pem = keygen.generate_private_key(kind="rsa", bits=1024)
key_file = tmp_path / "k.pem"
key_file.write_text(key_pem)
out = tmp_path / "req.csr"
rc = cli.main(["csr", "create", "--key-file", str(key_file), "--subject", "/C=US/ST=CA/CN=example.com", "--san", "www.example.com", "--san", "10.0.0.1", "--out", str(out)])
assert rc == 0
assert out.exists()
# Show prints text; just call show to ensure no exception
rc2 = cli.main(["csr", "show", "--csr-file", str(out)])
assert rc2 == 0

View File

@@ -0,0 +1,33 @@
"""CLI tests for creating CSR from an existing certificate."""
from certctl import cli, keygen
def test_cli_csr_create_from_cert(tmp_path):
# Generate key
key_pem = keygen.generate_private_key(kind="rsa", bits=1024)
key_file = tmp_path / "k.pem"
key_file.write_text(key_pem)
# Create a cert with SANs
conf = tmp_path / "conf.cnf"
conf.write_text("""[ req ]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[ req_distinguished_name ]
[ v3_req ]
subjectAltName = DNS:www.example.com, IP:10.0.0.1
""")
cert_file = tmp_path / "cert.pem"
subj = "/C=US/ST=CA/CN=example.com"
import subprocess
subprocess.run(["openssl", "req", "-new", "-x509", "-key", str(key_file), "-out", str(cert_file), "-days", "1", "-config", str(conf), "-extensions", "v3_req", "-subj", subj], check=True)
out = tmp_path / "req.csr"
rc = cli.main(["csr", "create", "--key-file", str(key_file), "--from-cert", str(cert_file), "--out", str(out)])
assert rc == 0
assert out.exists()
# Show the CSR to ensure content
rc2 = cli.main(["csr", "show", "--csr-file", str(out)])
assert rc2 == 0

View File

@@ -0,0 +1,12 @@
import pytest
def test_csr_create_help_contains_wildcard(capsys):
from certctl import cli
p = cli.build_parser()
with pytest.raises(SystemExit):
p.parse_args(["csr", "create", "--help"])
captured = capsys.readouterr()
out = captured.out + captured.err
assert '--allow-wildcard' in out
assert 'wildcard' in out.lower()

View File

@@ -0,0 +1,35 @@
"""Tests for the CLI wiring of keygen --save-passphrase flag."""
from certctl import cli
def test_cli_keygen_save_passphrase(monkeypatch, capsys):
called = {}
def fake_gen_rsa(**kwargs):
called.update(kwargs)
return "PEM-KEY"
monkeypatch.setattr("certctl.keygen.generate_rsa_key", fake_gen_rsa)
# Simulate cli args
rc = cli.main(["keygen", "--kind", "rsa", "--bits", "1024", "--passphrase", "fromcli", "--keychain-service", "svc-cli", "--save-passphrase"])
assert rc == 0
assert called["passphrase"] == "fromcli"
assert called["keychain_service"] == "svc-cli"
assert called["save_to_keychain"] is True
def test_cli_keygen_write_file(monkeypatch, tmp_path):
def fake_gen_ec(**kwargs):
return "PEM-EC"
monkeypatch.setattr("certctl.keygen.generate_ec_key", fake_gen_ec)
out = tmp_path / "key.pem"
rc = cli.main(["keygen", "--kind", "ec", "--curve", "prime256v1", "--out", str(out)])
assert rc == 0
assert out.exists()
assert out.read_text() == "PEM-EC"

21
legacy/tests/test_csr.py Normal file
View File

@@ -0,0 +1,21 @@
"""Tests for CSR creation using OpenSSL CLI."""
import tempfile
from certctl import keygen
from certctl import csr
def test_create_csr_with_san(tmp_path):
# Generate a temporary key
key_pem = keygen.generate_private_key(kind="rsa", bits=1024)
key_file = tmp_path / "test.key"
key_file.write_text(key_pem)
subject = {"C": "US", "ST": "CA", "CN": "example.com"}
sans = ["www.example.com", "10.0.0.1"]
csr_pem = csr.create_csr_from_key(str(key_file), subject=subject, sans=sans)
assert csr_pem.startswith("-----BEGIN CERTIFICATE REQUEST-----")
# Ensure SANs are present in the CSR
assert csr.csr_has_san(csr_pem, "DNS:www.example.com")
assert csr.csr_has_san(csr_pem, "IP:10.0.0.1")

View File

@@ -0,0 +1,72 @@
"""Tests for CSR create when wildcard SANs are provided on the CLI."""
from certctl import cli
def test_cli_csr_create_cli_san_wildcard_interactive_confirm_yes(monkeypatch, tmp_path):
from certctl import keygen, csr as csrmod
key_pem = keygen.generate_private_key(kind="rsa", bits=1024)
key_file = tmp_path / "k.pem"
key_file.write_text(key_pem)
# Simulate interactive terminal and confirmation
monkeypatch.setattr("builtins.input", lambda prompt='': "yes")
import sys
monkeypatch.setattr(sys.stdin, "isatty", lambda: True, raising=False)
out = tmp_path / "req.csr"
rc = cli.main(["csr", "create", "--key-file", str(key_file), "--subject", "/C=US/CN=example.com", "--san", "*.example.com", "--out", str(out)])
assert rc == 0
assert out.exists()
csr_pem = out.read_text()
assert csrmod.csr_has_san(csr_pem, "DNS:*.example.com")
def test_cli_csr_create_cli_san_wildcard_interactive_confirm_no(monkeypatch, tmp_path):
from certctl import keygen, csr as csrmod
key_pem = keygen.generate_private_key(kind="rsa", bits=1024)
key_file = tmp_path / "k.pem"
key_file.write_text(key_pem)
# Simulate interactive terminal and decline confirmation
answers = iter(["no"]) # decline wildcard
monkeypatch.setattr("builtins.input", lambda prompt='': next(answers))
import sys
monkeypatch.setattr(sys.stdin, "isatty", lambda: True, raising=False)
out = tmp_path / "req.csr"
rc = cli.main(["csr", "create", "--key-file", str(key_file), "--subject", "/C=US/CN=example.com", "--san", "*.example.com", "--out", str(out)])
assert rc == 0
assert out.exists()
csr_pem = out.read_text()
assert not csrmod.csr_has_san(csr_pem, "DNS:*.example.com")
def test_cli_csr_create_cli_san_wildcard_noninteractive_fails(monkeypatch, tmp_path):
from certctl import keygen
key_pem = keygen.generate_private_key(kind="rsa", bits=1024)
key_file = tmp_path / "k.pem"
key_file.write_text(key_pem)
# Simulate non-interactive (isatty False)
import sys
monkeypatch.setattr(sys.stdin, "isatty", lambda: False, raising=False)
out = tmp_path / "req.csr"
rc = cli.main(["csr", "create", "--key-file", str(key_file), "--san", "*.example.com", "--out", str(out)])
assert rc != 0
def test_cli_csr_create_cli_san_wildcard_allow_flag_noninteractive(monkeypatch, tmp_path):
from certctl import keygen, csr as csrmod
key_pem = keygen.generate_private_key(kind="rsa", bits=1024)
key_file = tmp_path / "k.pem"
key_file.write_text(key_pem)
import sys
monkeypatch.setattr(sys.stdin, "isatty", lambda: False, raising=False)
out = tmp_path / "req.csr"
rc = cli.main(["csr", "create", "--key-file", str(key_file), "--subject", "/C=US/CN=example.com", "--san", "*.example.com", "--allow-wildcard", "--out", str(out)])
assert rc == 0
csr_pem = out.read_text()
assert csrmod.csr_has_san(csr_pem, "DNS:*.example.com")

View File

@@ -0,0 +1,38 @@
"""Tests for creating CSR from an existing certificate's metadata."""
from certctl import keygen, csr
def test_create_csr_from_cert(tmp_path):
# Generate a key
key_pem = keygen.generate_private_key(kind="rsa", bits=1024)
key_file = tmp_path / "k.pem"
key_file.write_text(key_pem)
# Create a certificate from the key with SANs using a temp OpenSSL config
conf = tmp_path / "conf.cnf"
conf.write_text("""[ req ]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[ req_distinguished_name ]
[ v3_req ]
subjectAltName = DNS:www.example.com, IP:10.0.0.1
""")
cert_file = tmp_path / "cert.pem"
import subprocess
subj = "/C=US/ST=CA/CN=example.com"
subprocess.run(["openssl", "req", "-new", "-x509", "-key", str(key_file), "-out", str(cert_file), "-days", "1", "-config", str(conf), "-extensions", "v3_req", "-subj", subj], check=True)
csr_pem = csr.create_csr_from_cert(str(cert_file), str(key_file))
assert csr_pem.startswith("-----BEGIN CERTIFICATE REQUEST-----")
# Ensure SANs and CN are preserved
assert csr.csr_has_san(csr_pem, "DNS:www.example.com")
assert csr.csr_has_san(csr_pem, "IP:10.0.0.1")
# Check the CN shows up in the CSR subject
import subprocess
p = subprocess.run(["openssl", "req", "-in", "/dev/stdin", "-noout", "-subject"], input=csr_pem.encode("utf-8"), capture_output=True, check=True)
out = p.stdout.decode("utf-8")
import re
assert re.search(r"CN\s*=\s*example\.com", out)

View File

@@ -0,0 +1,102 @@
"""Tests for interactive CSR prompting."""
from certctl import csr
def test_prompt_for_subject_and_sans(monkeypatch):
answers = iter([
"US", # C
"CA", # ST
"", # L
"Example Org", # O
"", # OU
"example.com", # CN
"www.example.com", # SAN 1
"10.0.0.1", # SAN 2
"" # finish
])
monkeypatch.setattr("builtins.input", lambda prompt='': next(answers))
subj, sans = csr.prompt_for_subject_and_sans()
assert subj["C"] == "US"
assert subj["ST"] == "CA"
assert subj["O"] == "Example Org"
assert subj["CN"] == "example.com"
# prompt now returns normalized SANs like DNS:... or IP:...
assert "DNS:www.example.com" in sans
assert "IP:10.0.0.1" in sans
def test_cli_csr_create_interactive(monkeypatch, tmp_path):
# Generate a key
from certctl import keygen, cli
key_pem = keygen.generate_private_key(kind="rsa", bits=1024)
key_file = tmp_path / "k.pem"
key_file.write_text(key_pem)
# Simulate interactive inputs (subject fields + SANs)
answers = iter([
"US", # C
"CA", # ST
"", # L
"Example Org", # O
"", # OU
"example.com", # CN
"www.example.com", # SAN 1
"10.0.0.1", # SAN 2
"" # finish
])
monkeypatch.setattr("builtins.input", lambda prompt='': next(answers))
out = tmp_path / "req.csr"
rc = cli.main(["csr", "create", "--key-file", str(key_file), "--out", str(out)])
assert rc == 0
assert out.exists()
# Target SAN should be present
from certctl import csr as csrmod
csr_pem = out.read_text()
assert csrmod.csr_has_san(csr_pem, "DNS:www.example.com")
assert csrmod.csr_has_san(csr_pem, "IP:10.0.0.1")
def test_prompt_for_subject_and_sans_wildcard_confirm_yes(monkeypatch):
answers = iter([
"US", # C
"CA", # ST
"", # L
"Example Org", # O
"", # OU
"example.com", # CN
"*.example.com", # SAN 1 (wildcard)
"yes", # confirm wildcard
"", # finish
])
monkeypatch.setattr("builtins.input", lambda prompt='': next(answers))
subj, sans = csr.prompt_for_subject_and_sans()
assert subj["C"] == "US"
assert any(s.startswith("DNS:*.example.com") for s in sans)
def test_prompt_for_subject_and_sans_wildcard_confirm_no(monkeypatch):
answers = iter([
"US", # C
"CA", # ST
"", # L
"Example Org", # O
"", # OU
"example.com", # CN
"*.example.com", # SAN 1 (wildcard)
"no", # do not confirm
"www.example.com", # SAN 2
"", # finish
])
monkeypatch.setattr("builtins.input", lambda prompt='': next(answers))
subj, sans = csr.prompt_for_subject_and_sans()
assert subj["C"] == "US"
assert not any(s.startswith("DNS:*.example.com") for s in sans)
assert any(s.startswith("DNS:www.example.com") for s in sans)

View File

@@ -0,0 +1,37 @@
"""Tests for CSR submit flow using the Mock CA adapter."""
from certctl import cli
from certctl.ca.mock import MockCA
def test_csr_submit_mock(tmp_path):
# Create a key and a CSR
from certctl import keygen, csr
key_pem = keygen.generate_private_key(kind="rsa", bits=1024)
key_file = tmp_path / "k.pem"
key_file.write_text(key_pem)
csr_pem = csr.create_csr_from_key(str(key_file), subject={"C": "US", "CN": "test.local"}, sans=["www.test.local"])
csr_file = tmp_path / "r.csr"
csr_file.write_text(csr_pem)
# Submit via CLI using mock adapter
rc = cli.main(["csr", "submit", "--csr-file", str(csr_file), "--ca", "mock", "--name", "testreq", "--wait"])
assert rc == 0
def test_csr_submit_reject_wildcard(tmp_path):
from certctl import keygen, csr
key_pem = keygen.generate_private_key(kind="rsa", bits=1024)
key_file = tmp_path / "k.pem"
key_file.write_text(key_pem)
csr_pem = csr.create_csr_from_key(str(key_file), subject={"C": "US", "CN": "test.local"}, sans=["*.example.com"])
csr_file = tmp_path / "r.csr"
csr_file.write_text(csr_pem)
rc = cli.main(["csr", "submit", "--csr-file", str(csr_file), "--ca", "mock", "--name", "testreq"])
assert rc != 0
# Allow wildcard
rc2 = cli.main(["csr", "submit", "--csr-file", str(csr_file), "--ca", "mock", "--name", "testreq", "--allow-wildcard", "--wait"])
assert rc2 == 0

View File

@@ -0,0 +1,6 @@
def test_docs_mention_wildcard():
import pathlib
p = pathlib.Path(__file__).resolve().parents[1] / 'docs' / 'USAGE.md'
txt = p.read_text()
assert 'wildcard' in txt.lower()
assert '--allow-wildcard' in txt

View File

@@ -0,0 +1,39 @@
"""Tests for OpenSSL-based key generation helpers."""
import re
from certctl.keygen import generate_rsa_key, generate_ec_key, generate_private_key
# We accept PKCS#1 (RSA PRIVATE KEY), PKCS#8 (PRIVATE KEY) or encrypted forms.
PEM_PRIV_RE = re.compile(r"-----BEGIN [A-Z0-9 -]*PRIVATE KEY-----")
def test_generate_rsa_unencrypted():
pem = generate_rsa_key(bits=2048)
assert pem.strip().startswith("-----BEGIN")
# basic sanity checks for PEM content
assert "PRIVATE KEY" in pem or "RSA PRIVATE KEY" in pem
assert "BEGIN" in pem and "END" in pem
def test_generate_rsa_encrypted():
pem = generate_rsa_key(bits=2048, passphrase="s3cr3t")
assert "ENCRYPTED" in pem or "ENCRYPTED PRIVATE KEY" in pem or "Proc-Type: 4,ENCRYPTED" in pem
def test_generate_ec_unencrypted():
pem = generate_ec_key(curve="prime256v1")
assert pem.strip().startswith("-----BEGIN")
assert "PRIVATE KEY" in pem and "BEGIN" in pem and "END" in pem
def test_generate_ec_encrypted():
pem = generate_ec_key(curve="secp384r1", passphrase="s3cr3t")
assert "ENCRYPTED" in pem or "ENCRYPTED PRIVATE KEY" in pem
def test_generate_private_key_helper():
pem = generate_private_key(kind="rsa", bits=2048)
assert PEM_PRIV_RE.search(pem)
pem2 = generate_private_key(kind="ec", curve="prime256v1")
assert PEM_PRIV_RE.search(pem2)

View File

@@ -0,0 +1,29 @@
"""Integration tests to verify keygen resolves passphrases from keychain."""
from certctl import keygen
def test_generate_rsa_using_keychain(monkeypatch):
# Return a known passphrase from keychain and ensure result is encrypted
monkeypatch.setattr(keygen, "_openssl_bin", lambda: "/usr/bin/openssl")
def fake_keychain_get(service):
assert service == "svc1"
return "from-keychain"
monkeypatch.setattr("certctl.storage.keychain_get", fake_keychain_get)
pem = keygen.generate_rsa_key(bits=1024, passphrase=None, keychain_service="svc1")
assert "ENCRYPTED" in pem or "ENCRYPTED PRIVATE KEY" in pem
def test_generate_ec_using_keychain(monkeypatch):
monkeypatch.setattr(keygen, "_openssl_bin", lambda: "/usr/bin/openssl")
def fake_keychain_get(service):
assert service == "svc2"
return "from-keychain"
monkeypatch.setattr("certctl.storage.keychain_get", fake_keychain_get)
pem = keygen.generate_ec_key(curve="prime256v1", passphrase=None, keychain_service="svc2")
assert "ENCRYPTED" in pem or "ENCRYPTED PRIVATE KEY" in pem

View File

@@ -0,0 +1,43 @@
"""Tests verifying passphrase save-to-keychain behavior for keygen."""
from certctl import keygen
def test_save_rsa_passphrase_to_keychain(monkeypatch):
# stub openssl path to avoid requiring a specific binary
monkeypatch.setattr(keygen, "_openssl_bin", lambda: "/usr/bin/openssl")
called = {}
def fake_set(service, password, account="certctl"):
called['service'] = service
called['password'] = password
called['account'] = account
return True
monkeypatch.setattr("certctl.storage.keychain_set", fake_set)
# Provide passphrase and request save to keychain
pem = keygen.generate_rsa_key(bits=1024, passphrase="savetest", keychain_service="svc-save", save_to_keychain=True, keychain_account="acct1")
assert called['service'] == "svc-save"
assert called['password'] == "savetest"
assert called['account'] == "acct1"
def test_save_ec_passphrase_to_keychain(monkeypatch):
monkeypatch.setattr(keygen, "_openssl_bin", lambda: "/usr/bin/openssl")
called = {}
def fake_set(service, password, account="certctl"):
called['service'] = service
called['password'] = password
called['account'] = account
return True
monkeypatch.setattr("certctl.storage.keychain_set", fake_set)
pem = keygen.generate_ec_key(curve="prime256v1", passphrase="ecsave", keychain_service="svc-save-ec", save_to_keychain=True)
assert called['service'] == "svc-save-ec"
assert called['password'] == "ecsave"

View File

@@ -0,0 +1,16 @@
import pathlib
def test_no_direct_stderr_writes():
root = pathlib.Path(__file__).resolve().parents[1]
# Only check package sources and the top-level script(s); ignore virtualenv and tests
py_files = list((root / 'certctl').rglob('*.py'))
main_script = root / 'nscertkeycreate.py'
if main_script.exists():
py_files.append(main_script)
offending = []
for p in py_files:
txt = p.read_text()
if 'sys.stderr.write' in txt or 'file=sys.stderr' in txt:
offending.append(str(p))
assert not offending, f"Found direct stderr writes in: {offending}"

View File

@@ -0,0 +1,9 @@
"""Verify `bin/certctl` wrapper exists and is executable."""
import os
def test_nsctl_exists_and_executable():
path = os.path.join(os.path.dirname(__file__), "..", "bin", "certctl")
path = os.path.abspath(path)
assert os.path.exists(path)
assert os.access(path, os.X_OK)

View File

@@ -0,0 +1,7 @@
"""Test verifying `pyproject.toml` exposes `certctl` script entry."""
def test_pyproject_has_nsctl_entry():
content = open("pyproject.toml").read()
assert "certctl" in content
assert "certctl.cli:main" in content

View File

@@ -0,0 +1,31 @@
"""Tests for SAN validation and CLI rejection of invalid SANs."""
import pytest
from certctl.csr import normalize_and_validate_san
def test_normalize_dns():
assert normalize_and_validate_san("www.example.com") == "DNS:www.example.com"
assert normalize_and_validate_san("DNS:www.example.com") == "DNS:www.example.com"
def test_normalize_ip():
assert normalize_and_validate_san("10.2.3.4") == "IP:10.2.3.4"
assert normalize_and_validate_san("IP:10.2.3.4") == "IP:10.2.3.4"
def test_invalid_san_raises():
with pytest.raises(ValueError):
normalize_and_validate_san("*invalid_hostname*")
def test_cli_rejects_bad_san(tmp_path):
# Generate a key
from certctl import keygen, cli
key_pem = keygen.generate_private_key(kind="rsa", bits=1024)
key_file = tmp_path / "k.pem"
key_file.write_text(key_pem)
out = tmp_path / "req.csr"
rc = cli.main(["csr", "create", "--key-file", str(key_file), "--subject", "/C=US/CN=example.com", "--san", "bad@@@", "--out", str(out)])
assert rc != 0
assert not out.exists()

View File

@@ -0,0 +1,50 @@
"""Tests for macOS Keychain helpers in `certctl.storage`.
These tests stub out `subprocess.run` and `getpass.getpass` to simulate
macOS behavior.
"""
import subprocess
from certctl import storage
class DummyCompleted:
def __init__(self, out=b""):
self.stdout = out
def test_keychain_get_found(monkeypatch):
def fake_run(args, check, capture_output):
return DummyCompleted(out=b"s3cr3t\n")
monkeypatch.setattr(subprocess, "run", fake_run)
assert storage.keychain_get("svc-1") == "s3cr3t"
def test_keychain_get_not_found(monkeypatch):
def fake_run(args, check, capture_output):
raise subprocess.CalledProcessError(1, args)
monkeypatch.setattr(subprocess, "run", fake_run)
assert storage.keychain_get("svc-missing") is None
def test_get_or_prompt_passphrase_stores(monkeypatch):
# Simulate nothing in keychain, then interactive prompt, then store called
def fake_run_find(args, check, capture_output):
raise subprocess.CalledProcessError(1, args)
stored = {}
def fake_set(service, password, account="certctl"):
stored[service] = password
return True
monkeypatch.setattr(subprocess, "run", fake_run_find)
monkeypatch.setattr(storage, "keychain_set", fake_set)
monkeypatch.setattr("getpass.getpass", lambda prompt: "typed-pass")
val = storage.get_or_prompt_passphrase("myservice", prompt="enter:")
assert val == "typed-pass"
assert stored.get("myservice") == "typed-pass"

View File

@@ -0,0 +1,22 @@
def test_term_error_and_info_format(monkeypatch):
from certctl import term
class Fake:
def isatty(self):
return True
written = ''
def write(self, s):
Fake.written += s
fake = Fake()
# error
e = term.format_error('danger', stream=fake)
assert '\033[1;31m' in e and '\033[0m' in e
term.print_error('err', stream=fake)
assert '\033[1;31m' in Fake.written
# info
i = term.format_info('ok', stream=fake)
assert '\033[1;32m' in i and '\033[0m' in i
term.print_info('info', stream=fake)
assert '\033[1;32m' in Fake.written

View File

@@ -0,0 +1,25 @@
def test_term_format_and_print(monkeypatch):
import sys
from certctl import term
class Fake:
def isatty(self):
return False
def write(self, s):
Fake.written = getattr(Fake, 'written', '') + s
fake = Fake()
# plain
assert term.format_warning('w', stream=fake) == 'w'
term.print_warning('x', stream=fake)
assert 'x' in Fake.written
# TTY
class FakeTTY(Fake):
def isatty(self):
return True
fty = FakeTTY()
out = term.format_warning('z', stream=fty)
assert '\033[1;33m' in out and '\033[0m' in out
term.print_warning('y', stream=fty)
# ensure it wrote the ANSI code
assert '\033[1;33m' in Fake.written or '\033[1;33m' in fty.write('')

View File

@@ -0,0 +1,63 @@
"""Tests for certctl.utils.extract_pem_from_json"""
from certctl.utils import extract_pem_from_json
from certctl.netscaler import extract_csr_text
def test_extract_from_ns_ssl_csr():
resp = {
"ns_ssl_csr": [
{
"file_name": "app1.csr",
"csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIIC123...\n-----END CERTIFICATE REQUEST-----",
"errorcode": 0,
}
],
"errorcode": 0,
}
pem = extract_pem_from_json(resp)
assert pem is not None
assert pem.startswith("-----BEGIN CERTIFICATE REQUEST-----")
# netscaler-specific helper should prefer the ns_ssl_csr field
pem2 = extract_csr_text(resp)
assert pem2 == pem
def test_extract_from_ns_command_stdout():
resp = {
"ns_command": {
"commands": [
{
"command": "shell cat /nsconfig/ssl/app1.csr",
"stdout": "-----BEGIN CERTIFICATE REQUEST-----\nMIIC_STDOUT...\n-----END CERTIFICATE REQUEST-----",
"response": None,
}
],
"errorcode": 0,
}
}
pem = extract_pem_from_json(resp)
assert pem is not None
assert "MIIC_STDOUT" in pem
def test_extract_from_rows_array():
resp = {
"ns_command": {
"commands": [
{"command": "cat ...", "rows": ["-----BEGIN CERTIFICATE REQUEST-----", "MIIC_ROWS...", "-----END CERTIFICATE REQUEST-----"]}
]
}
}
pem = extract_pem_from_json(resp)
assert pem is not None
assert "MIIC_ROWS" in pem
def test_no_pem_returns_none():
resp = {"foo": "bar", "nested": {"x": [1, 2, {"y": "nothing here"}]}}
assert extract_pem_from_json(resp) is None

View File

@@ -0,0 +1,38 @@
def test_format_warning_colored_and_plain(monkeypatch, capsys):
import sys
from certctl import utils
# Non-tty stream -> plain
class Fake:
def isatty(self):
return False
def write(self, s):
pass
fake = Fake()
out_plain = utils.format_warning("test", stream=fake)
assert out_plain == "test"
# TTY stream -> colored
class FakeTTY(Fake):
def isatty(self):
return True
fty = FakeTTY()
out_colored = utils.format_warning("test", stream=fty)
assert "\033[1;33mtest\033[0m" == out_colored
def test_print_warning_writes(monkeypatch, capsys):
import sys
from certctl import utils
class FakeTTY:
def isatty(self):
return True
written = ""
def write(self, s):
# accumulate
FakeTTY.written += s
f = FakeTTY()
utils.print_warning("hello", stream=f)
assert "hello" in FakeTTY.written
assert "\033[1;33m" in FakeTTY.written