Skip to content

Commit

Permalink
Add option to create node with custom name (#10)
Browse files Browse the repository at this point in the history
* add option to create node with custom name

* rename
  • Loading branch information
jschlyter authored Dec 2, 2024
1 parent 3425d47 commit f802310
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 6 deletions.
12 changes: 10 additions & 2 deletions nodeman/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,18 @@ def get_current_username(
tags=["backend"],
)
async def create_node(
request: Request, username: Annotated[str, Depends(get_current_username)]
request: Request, username: Annotated[str, Depends(get_current_username)], name: str | None = None
) -> NodeBootstrapInformation:
secret = JWK.generate(kty="oct", size=256).k
node = TapirNode.create_next_node(domain=request.app.settings.nodes.domain)
domain = request.app.settings.nodes.domain
if name is None:
node = TapirNode.create_next_node(domain=request.app.settings.nodes.domain)
elif name.endswith(f".{domain}"):
logging.debug("Explicit node name %s requested", name)
node = TapirNode(name=name, domain=domain).save()
else:
logging.warning("Explicit node name %s not acceptable", name)
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail="Invalid node name")
logging.debug("Created node %s", node.name)
node_secret = TapirNodeSecret(name=node.name, secret=secret).save()
return NodeBootstrapInformation(name=node.name, secret=node_secret.secret)
Expand Down
2 changes: 1 addition & 1 deletion tests/test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
server = "mongomock://localhost/nodes"

[nodes]
domain = "dev.dnstapir.se"
domain = "test.dnstapir.se"
#trusted_keys = "trusted_keys.json"
mqtt_broker = "mqtts://localhost"

Expand Down
34 changes: 31 additions & 3 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import uuid
from urllib.parse import urljoin

import pytest
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import ec, rsa
from cryptography.hazmat.primitives.asymmetric.ed448 import Ed448PrivateKey
Expand All @@ -23,18 +24,24 @@
ADMIN_TEST_NODE_COUNT = 100
BACKEND_CREDENTIALS = ("username", "password")

PrivateKey = ec.EllipticCurvePrivateKey | rsa.RSAPublicKey | Ed25519PrivateKey | Ed448PrivateKey

Settings.model_config = SettingsConfigDict(toml_file="tests/test.toml")
settings = Settings()


def get_test_client() -> TestClient:
settings = Settings()
app = NodemanServer(settings)
app.ca_client = CaTestClient()
app.connect_mongodb()
return TestClient(app)


def _test_enroll(data_key, x509_key) -> None:
class FailedToCreateNode(RuntimeError):
pass


def _test_enroll(data_key: JWK, x509_key: PrivateKey, requested_name: str | None = None) -> None:
client = get_test_client()

admin_client = get_test_client()
Expand All @@ -45,11 +52,17 @@ def _test_enroll(data_key, x509_key) -> None:
logging.basicConfig(level=logging.DEBUG)
logging.debug("Testing enrollment")

response = admin_client.post(urljoin(server, "/api/v1/node"))
response = admin_client.post(
urljoin(server, "/api/v1/node"), params={"name": requested_name} if requested_name else None
)
if response.status_code != 201:
raise FailedToCreateNode
assert response.status_code == 201
create_response = response.json()
name = create_response["name"]
secret = create_response["secret"]
if requested_name:
assert name == requested_name
logging.info("Got name=%s secret=%s", name, secret)

node_url = urljoin(server, f"/api/v1/node/{name}")
Expand Down Expand Up @@ -145,6 +158,21 @@ def test_enroll_rsa() -> None:
_test_enroll(data_key=data_key, x509_key=x509_key)


def test_enroll_p256_named_node() -> None:
data_key = JWK.generate(kty="EC", crv="P-256")
x509_key = ec.generate_private_key(ec.SECP256R1())
requested_name = ".".join(["xyzzy", settings.nodes.domain])
_test_enroll(data_key=data_key, x509_key=x509_key, requested_name=requested_name)


def test_enroll_p256_bad_named_node() -> None:
data_key = JWK.generate(kty="EC", crv="P-256")
x509_key = ec.generate_private_key(ec.SECP256R1())
requested_name = "xyzzy.example.com"
with pytest.raises(FailedToCreateNode):
_test_enroll(data_key=data_key, x509_key=x509_key, requested_name=requested_name)


def test_enroll_bad_hmac_signature() -> None:
client = get_test_client()
server = ""
Expand Down

0 comments on commit f802310

Please sign in to comment.