Skip to content

Commit

Permalink
Implement GET /api/v1/node/{name}/configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
jschlyter committed Dec 19, 2024
1 parent 2e8b85d commit 834ce90
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 6 deletions.
14 changes: 12 additions & 2 deletions nodeman/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@
from pydantic.types import AwareDatetime

from .db_models import TapirNode
from .jose import PrivateJwk, PrivateSymmetric, PublicJwk, PublicJwks, public_key_factory
from .jose import (
PrivateJwk,
PrivateSymmetric,
PublicJwk,
PublicJwks,
public_key_factory,
)
from .settings import MqttUrl

MAX_REQUEST_AGE = 300
Expand Down Expand Up @@ -81,7 +87,7 @@ def validate_pem_bundle(cls, v: str):
return v


class NodeConfiguration(NodeCertificate):
class NodeConfiguration(BaseModel):
name: str = Field(title="Node name", examples=["node.example.com"])
mqtt_broker: MqttUrl = Field(title="MQTT Broker", examples=["mqtts://broker.example.com"])
mqtt_topics: dict[str, str] = Field(
Expand All @@ -90,3 +96,7 @@ class NodeConfiguration(NodeCertificate):
examples=[{"edm": "configuration/node.example.com/edm", "pop": "configuration/node.example.com/pop"}],
)
trusted_jwks: PublicJwks = Field(title="Trusted JWKS")


class NodeEnrollmentResult(NodeConfiguration, NodeCertificate):
pass
36 changes: 33 additions & 3 deletions nodeman/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
NodeCertificate,
NodeCollection,
NodeConfiguration,
NodeEnrollmentResult,
NodeInformation,
PublicKeyFormat,
RenewalRequest,
Expand Down Expand Up @@ -199,7 +200,7 @@ def delete_node(name: str, username: Annotated[str, Depends(get_current_username
@router.post(
"/api/v1/node/{name}/enroll",
responses={
status.HTTP_200_OK: {"model": NodeConfiguration},
status.HTTP_200_OK: {"model": NodeEnrollmentResult},
status.HTTP_404_NOT_FOUND: {},
},
tags=["client"],
Expand All @@ -208,7 +209,7 @@ def delete_node(name: str, username: Annotated[str, Depends(get_current_username
async def enroll_node(
name: str,
request: Request,
) -> NodeConfiguration:
) -> NodeEnrollmentResult:
"""Enroll new node"""

node = find_node(name)
Expand Down Expand Up @@ -269,7 +270,7 @@ async def enroll_node(

nodes_enrolled.add(1)

return NodeConfiguration(
return NodeEnrollmentResult(
name=name,
mqtt_broker=request.app.settings.nodes.mqtt_broker,
mqtt_topics=request.app.settings.nodes.mqtt_topics,
Expand Down Expand Up @@ -332,3 +333,32 @@ async def renew_node(
nodes_renewed.add(1)

return res


@router.get(
"/api/v1/node/{name}/configuration",
responses={
status.HTTP_200_OK: {"model": NodeConfiguration},
status.HTTP_404_NOT_FOUND: {},
},
tags=["client"],
response_model_exclude_none=True,
)
async def get_node_configuration(
name: str,
request: Request,
) -> NodeConfiguration:
"""Enroll new node"""

node = find_node(name)

if not node.activated:
logging.debug("Node %s not activated", name, extra={"nodename": name})
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail="Node not activated")

return NodeConfiguration(
name=name,
mqtt_broker=request.app.settings.nodes.mqtt_broker,
mqtt_topics=request.app.settings.nodes.mqtt_topics,
trusted_jwks=request.app.trusted_jwks,
)
16 changes: 15 additions & 1 deletion tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@
from nodeman.models import PublicKeyFormat
from nodeman.server import NodemanServer
from nodeman.settings import Settings
from nodeman.x509 import RSA_EXPONENT, CertificateAuthorityClient, generate_ca_certificate, generate_x509_csr
from nodeman.x509 import (
RSA_EXPONENT,
CertificateAuthorityClient,
generate_ca_certificate,
generate_x509_csr,
)

ADMIN_TEST_NODE_COUNT = 100
BACKEND_CREDENTIALS = ("username", "password")
Expand Down Expand Up @@ -140,6 +145,15 @@ def _test_enroll(data_key: JWK, x509_key: PrivateKey, requested_name: str | None
assert node_information["name"] == name
assert node_information["activated"] is not None

#########################
# Get node configuration

response = client.get(f"{node_url}/configuration")
assert response.status_code == status.HTTP_200_OK
node_information = response.json()
print(json.dumps(node_information, indent=4))
assert node_information["name"] == name

#####################
# Get node public key

Expand Down

0 comments on commit 834ce90

Please sign in to comment.