Remove obsolete NPM certificate repository
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
@@ -15,21 +14,3 @@ class CertificateIdentity:
|
|||||||
@property
|
@property
|
||||||
def key(self) -> str:
|
def key(self) -> str:
|
||||||
return ",".join(self.domains)
|
return ",".join(self.domains)
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
|
||||||
class CertificateState:
|
|
||||||
"""
|
|
||||||
Non-secret certificate state suitable for discovery, comparison, and logs.
|
|
||||||
"""
|
|
||||||
|
|
||||||
identity: CertificateIdentity
|
|
||||||
local_id: int
|
|
||||||
provider: str
|
|
||||||
nice_name: str
|
|
||||||
valid_from: datetime | None
|
|
||||||
expires_on: datetime | None
|
|
||||||
cluster_managed: bool
|
|
||||||
acme_renew: bool
|
|
||||||
dns_challenge: bool
|
|
||||||
source: str
|
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
from typing import Any
|
|
||||||
|
|
||||||
from ..npm_client import NpmClient
|
|
||||||
from .models import CertificateState
|
|
||||||
from .normalizer import (
|
|
||||||
normalize_certificate_domains,
|
|
||||||
parse_npm_datetime,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class NpmCertificateRepository:
|
|
||||||
"""
|
|
||||||
Read-only NPM certificate repository.
|
|
||||||
|
|
||||||
This milestone intentionally discovers metadata only.
|
|
||||||
Certificate/private-key material is not requested or logged.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, config):
|
|
||||||
self.config = config
|
|
||||||
self.client = NpmClient(config)
|
|
||||||
|
|
||||||
def _rows(self) -> list[dict[str, Any]]:
|
|
||||||
data = self.client.certificates()
|
|
||||||
|
|
||||||
if not isinstance(data, list):
|
|
||||||
raise RuntimeError(
|
|
||||||
"NPM certificate response was not a list"
|
|
||||||
)
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
def discover(self) -> list[CertificateState]:
|
|
||||||
certificates: list[CertificateState] = []
|
|
||||||
|
|
||||||
for row in self._rows():
|
|
||||||
local_id = row.get("id")
|
|
||||||
|
|
||||||
if not isinstance(local_id, int):
|
|
||||||
raise RuntimeError(
|
|
||||||
f"NPM certificate has invalid id: {local_id!r}"
|
|
||||||
)
|
|
||||||
|
|
||||||
meta = row.get("meta")
|
|
||||||
if not isinstance(meta, dict):
|
|
||||||
meta = {}
|
|
||||||
|
|
||||||
certificates.append(
|
|
||||||
CertificateState(
|
|
||||||
identity=normalize_certificate_domains(
|
|
||||||
row.get("domain_names")
|
|
||||||
),
|
|
||||||
local_id=local_id,
|
|
||||||
provider=str(
|
|
||||||
row.get("provider") or ""
|
|
||||||
),
|
|
||||||
nice_name=str(
|
|
||||||
row.get("nice_name") or ""
|
|
||||||
),
|
|
||||||
valid_from=parse_npm_datetime(
|
|
||||||
row.get("valid_from")
|
|
||||||
),
|
|
||||||
expires_on=parse_npm_datetime(
|
|
||||||
row.get("expires_on")
|
|
||||||
),
|
|
||||||
cluster_managed=(
|
|
||||||
meta.get("cluster_managed") is True
|
|
||||||
),
|
|
||||||
acme_renew=(
|
|
||||||
meta.get("acme_renew") is True
|
|
||||||
),
|
|
||||||
dns_challenge=(
|
|
||||||
meta.get("dns_challenge") is True
|
|
||||||
),
|
|
||||||
source=self.config.proxy_url,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
return certificates
|
|
||||||
@@ -107,13 +107,6 @@ class AppConfig:
|
|||||||
domain: str | None
|
domain: str | None
|
||||||
include_disabled: bool = False
|
include_disabled: bool = False
|
||||||
|
|
||||||
@property
|
|
||||||
def proxy_url(self) -> str:
|
|
||||||
return (
|
|
||||||
f"{self.proxy_api_scheme}://"
|
|
||||||
f"{self.npm_endpoints[0].address}"
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_env(cls, include_disabled: bool = False) -> "AppConfig":
|
def from_env(cls, include_disabled: bool = False) -> "AppConfig":
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ class AppConfigEndpointTests(unittest.TestCase):
|
|||||||
tuple(endpoint.identity for endpoint in config.npm_endpoints),
|
tuple(endpoint.identity for endpoint in config.npm_endpoints),
|
||||||
("npm://192.168.1.101:81",),
|
("npm://192.168.1.101:81",),
|
||||||
)
|
)
|
||||||
self.assertEqual(config.proxy_url, "http://192.168.1.101:81")
|
|
||||||
self.assertEqual(config.target_ip, "192.168.1.101")
|
self.assertEqual(config.target_ip, "192.168.1.101")
|
||||||
|
|
||||||
def test_endpoint_list_controls_api_and_proxy_ip_remains_target(self):
|
def test_endpoint_list_controls_api_and_proxy_ip_remains_target(self):
|
||||||
@@ -84,7 +83,6 @@ class AppConfigEndpointTests(unittest.TestCase):
|
|||||||
"npm://192.168.1.5:81",
|
"npm://192.168.1.5:81",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
self.assertEqual(config.proxy_url, "http://192.168.1.3:81")
|
|
||||||
self.assertEqual(config.target_ip, "192.168.1.101")
|
self.assertEqual(config.target_ip, "192.168.1.101")
|
||||||
|
|
||||||
def test_explicit_dns_target_supports_multiple_endpoints(self):
|
def test_explicit_dns_target_supports_multiple_endpoints(self):
|
||||||
@@ -98,7 +96,6 @@ class AppConfigEndpointTests(unittest.TestCase):
|
|||||||
):
|
):
|
||||||
config = AppConfig.from_env()
|
config = AppConfig.from_env()
|
||||||
|
|
||||||
self.assertEqual(config.proxy_url, "http://192.168.1.3:81")
|
|
||||||
self.assertEqual(config.target_ip, "192.168.1.101")
|
self.assertEqual(config.target_ip, "192.168.1.101")
|
||||||
|
|
||||||
def test_multiple_endpoints_require_target_without_proxy_ip(self):
|
def test_multiple_endpoints_require_target_without_proxy_ip(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user