Add NPM endpoint verification

This commit is contained in:
Lyncoln
2026-09-20 00:40:12 -04:00
parent 2b4a6eea79
commit 939d51d661
2 changed files with 323 additions and 63 deletions
+134 -60
View File
@@ -6,9 +6,11 @@ from ...adapters import (
Capability,
CapabilityOperation,
DiscoveredObject,
NormalizedObject,
ObjectReference,
)
from ...npm_client import NpmClient
from ...object_normalizer import normalize_discovered_object
_PROXY_HOST_FIELDS = (
@@ -36,10 +38,18 @@ class Plugin:
PROXY_HOSTS,
CapabilityOperation.DISCOVER,
),
Capability(
PROXY_HOSTS,
CapabilityOperation.VERIFY,
),
Capability(
CERTIFICATES,
CapabilityOperation.DISCOVER,
),
Capability(
CERTIFICATES,
CapabilityOperation.VERIFY,
),
}
)
@@ -74,92 +84,156 @@ class Plugin:
f"object type {object_type!r}"
)
def _discover_proxy_hosts(self) -> list[DiscoveredObject]:
discovered: list[DiscoveredObject] = []
def _proxy_host_from_row(
self,
row: dict[str, Any],
) -> DiscoveredObject:
payload = {
field: row.get(field)
for field in _PROXY_HOST_FIELDS
}
for row in self.client.proxy_hosts():
payload = {
field: row.get(field)
for field in _PROXY_HOST_FIELDS
}
certificate_id = row.get("certificate_id")
certificate_id = row.get("certificate_id")
if certificate_id in (None, "", 0, "0"):
references = ()
else:
if isinstance(certificate_id, bool):
raise RuntimeError(
"NPM proxy host has invalid certificate_id"
)
certificate_local_key = str(
certificate_id
).strip()
if not certificate_local_key:
raise RuntimeError(
"NPM proxy host has invalid certificate_id"
)
references = (
ObjectReference(
relation="certificate",
object_type=CERTIFICATES,
local_key=certificate_local_key,
),
if certificate_id in (None, "", 0, "0"):
references = ()
else:
if isinstance(certificate_id, bool):
raise RuntimeError(
"NPM proxy host has invalid certificate_id"
)
discovered.append(
DiscoveredObject(
object_type=PROXY_HOSTS,
local_key=self._local_key(row, "proxy host"),
payload=payload,
references=references,
certificate_local_key = str(
certificate_id
).strip()
if not certificate_local_key:
raise RuntimeError(
"NPM proxy host has invalid certificate_id"
)
references = (
ObjectReference(
relation="certificate",
object_type=CERTIFICATES,
local_key=certificate_local_key,
),
)
return discovered
return DiscoveredObject(
object_type=PROXY_HOSTS,
local_key=self._local_key(
row,
"proxy host",
),
payload=payload,
references=references,
)
def _discover_certificates(self) -> list[DiscoveredObject]:
discovered: list[DiscoveredObject] = []
def _certificate_from_row(
self,
row: dict[str, Any],
) -> DiscoveredObject:
meta = row.get("meta")
if not isinstance(meta, dict):
meta = {}
for row in self.client.certificates():
meta = row.get("meta")
if not isinstance(meta, dict):
meta = {}
payload = {
return DiscoveredObject(
object_type=CERTIFICATES,
local_key=self._local_key(
row,
"certificate",
),
payload={
"domain_names": list(
row.get("domain_names") or []
),
"provider": str(row.get("provider") or ""),
"nice_name": str(row.get("nice_name") or ""),
"provider": str(
row.get("provider") or ""
),
"nice_name": str(
row.get("nice_name") or ""
),
"valid_from": row.get("valid_from"),
"expires_on": row.get("expires_on"),
"cluster_managed": (
meta.get("cluster_managed") is True
),
"acme_renew": meta.get("acme_renew") is True,
"acme_renew": (
meta.get("acme_renew") is True
),
"dns_challenge": (
meta.get("dns_challenge") is True
),
}
discovered.append(
DiscoveredObject(
object_type=CERTIFICATES,
local_key=self._local_key(row, "certificate"),
payload=payload,
)
)
},
)
return discovered
def _discover_proxy_hosts(self) -> list[DiscoveredObject]:
return [
self._proxy_host_from_row(row)
for row in self.client.proxy_hosts()
]
def _discover_certificates(self) -> list[DiscoveredObject]:
return [
self._certificate_from_row(row)
for row in self.client.certificates()
]
def apply(self, action):
raise RuntimeError(
f"{self.endpoint.identity} does not support apply yet"
)
def verify(self, object):
def verify(self, object: NormalizedObject) -> bool:
if object.local_key is None:
return False
if object.object_type == PROXY_HOSTS:
row = self.client.proxy_host(
object.local_key
)
actual = normalize_discovered_object(
self._proxy_host_from_row(row)
)
return actual == object
if object.object_type == CERTIFICATES:
row = self.client.certificate(
object.local_key
)
actual = normalize_discovered_object(
self._certificate_from_row(row)
)
if actual.local_key != object.local_key:
return False
if actual.logical_key != object.logical_key:
return False
# Provider, display name, and renewal flags describe how
# this NPM endpoint manages the certificate. They are not
# portable certificate identity. A copied Let's Encrypt
# certificate becomes provider="other" on the recipient.
#
# The portable verification state is the domain identity
# plus the certificate validity period exposed by NPM.
for field in (
"domain_names",
"valid_from",
"expires_on",
):
if (
actual.payload.get(field)
!= object.payload.get(field)
):
return False
return True
raise RuntimeError(
f"{self.endpoint.identity} does not support verify yet"
f"{self.endpoint.identity} cannot verify "
f"object type {object.object_type!r}"
)