Skip to content

Commit

Permalink
Add domain name to core-api
Browse files Browse the repository at this point in the history
  • Loading branch information
olekoliinyk committed Oct 15, 2024
1 parent a4b7a4a commit 9643480
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 73 deletions.
Empty file.
9 changes: 9 additions & 0 deletions nat-lab/bin/core-api
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash

set -e

SERVER_NAME=api.nordvpn.com

openssl req -new -x509 -keyout /etc/ssl/server_certificate/server.pem -out /etc/ssl/server_certificate/server.pem -days 365 -nodes -subj "/CN=${SERVER_NAME}"

python3 /opt/bin/core-api.py
8 changes: 7 additions & 1 deletion nat-lab/bin/core-api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import json
import paho.mqtt.client as mqtt # type: ignore # pylint: disable=import-error
import ssl
from dataclasses import asdict, dataclass
from enum import Enum
from http import HTTPStatus
Expand Down Expand Up @@ -129,6 +130,8 @@ def do_GET(self):
elif self.path.split("/")[-1] == "map":
machine_id = self.path.split("/")[-2]
self.handle_get_machine_map(machine_id)
elif self.path == "/v1/health":
self.handle_root_path()

def do_HEAD(self):
self._set_headers()
Expand Down Expand Up @@ -271,9 +274,12 @@ def get_meshmap(self, machine_id):
}


def run(mqttc, port=8080):
def run(mqttc, port=443):
server_address = ("", port)
httpd = CoreServer(server_address, CoreApiHandler, mqttc)
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain(certfile="/etc/ssl/server_certificate/server.pem")
httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
print("Starting httpd...")
httpd.serve_forever()

Expand Down
1 change: 1 addition & 0 deletions nat-lab/bin/dns-server
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ KNOWN = {
b"google.com": dns.Record_A(address="142.250.179.206"),
b"www.google.com": dns.Record_A(address="142.250.179.206"),
b"error-with-noerror-return-code.com": None,
b"api.nordvpn.com": dns.Record_A(address="10.0.80.86"),
},
dns.CNAME: {
b"www.microsoft.com": dns.Record_CNAME(name="www.microsoft.com-c-3.edgekey.net.")
Expand Down
25 changes: 23 additions & 2 deletions nat-lab/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,22 @@ services:
ipv4_address: 192.168.102.54
environment:
CLIENT_GATEWAY_PRIMARY: 192.168.102.254
cone-client-03:
hostname: cone-client-03
<<: *common-client
entrypoint: /opt/bin/client
networks:
cone-net-03:
ipv4_address: 192.168.107.54
environment:
CLIENT_GATEWAY_PRIMARY: 192.168.107.254
dns:
- 10.0.80.82
- 10.0.80.83
volumes:
- ../:/libtelio
- ./data/teliod:/etc/teliod
- server-certificate:/etc/ssl/server_certificate
# Client that shares two cone networks on different interfaces
shared-client-01:
hostname: shared-client-01
Expand Down Expand Up @@ -601,18 +617,20 @@ services:
core-api:
hostname: core-api
image: nat-lab:base
entrypoint: /opt/bin/core-api.py
entrypoint: /opt/bin/core-api
environment:
PYTHONUNBUFFERED: 1
healthcheck:
test: "curl http://localhost:8080" # Here the port comes directly from the source code of api server where it is hardcoded
test: "curl -k https://localhost/v1/health"
networks:
internet:
ipv4_address: 10.0.80.86
ipv6_address: 2001:db8:85a4::adda:edde:b
depends_on:
mqtt-broker:
condition: service_healthy
volumes:
- server-certificate:/etc/ssl/server_certificate

networks:
# Network representing public internet,
Expand Down Expand Up @@ -725,3 +743,6 @@ networks:
driver: default
config:
- subnet: 192.168.111.0/24

volumes:
server-certificate:
3 changes: 3 additions & 0 deletions nat-lab/tests/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,6 @@ def get_root_path(path: str) -> str:
LIBDROP_PORT = 49111

LINUX_INTERFACE_NAME = "tun10"

CORE_API_URL = "https://api.nordvpn.com"
CORE_API_CA_CERTIFICATE_PATH = "/etc/ssl/server_certificate/server.pem"
28 changes: 28 additions & 0 deletions nat-lab/tests/helpers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import asyncio
import itertools
import json
import pytest
from config import WG_SERVERS
from contextlib import AsyncExitStack, asynccontextmanager
Expand Down Expand Up @@ -421,3 +422,30 @@ async def ping_between_all_nodes(env: Environment) -> None:
)
if not client.is_node(node)
])


async def send_https_request(
connection, endpoint, method, ca_cert_path, data=None, expect_response=True
):
curl_command = [
"curl",
"--cacert",
ca_cert_path,
"-X",
method,
endpoint,
"-H",
"Content-Type: application/json",
]

if data:
curl_command.extend(["-d", data])

process = await connection.create_process(curl_command).execute()
response = process.get_stdout()
if expect_response:
try:
return json.loads(response)
except json.JSONDecodeError:
assert False, f"Expected JSON response but got: {response}"
return None
91 changes: 42 additions & 49 deletions nat-lab/tests/test_core_api.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import json
import pytest
from config import CORE_API_CA_CERTIFICATE_PATH, CORE_API_URL
from contextlib import AsyncExitStack
from dataclasses import dataclass
from enum import Enum
from helpers import send_https_request
from utils.connection_util import ConnectionTag, new_connection_by_tag
from uuid import UUID

Expand Down Expand Up @@ -83,41 +85,20 @@ def verify_uuid(uuid_to_test, version=4):
assert str(uuid_obj) == uuid_to_test, "Not a valid UUID"


async def send_http_request(
connection, endpoint, method, data=None, expect_response=True
):
curl_command = [
"curl",
"-X",
method,
endpoint,
"-H",
"Content-Type: application/json",
]

if data:
curl_command.extend(["-d", data])

process = await connection.create_process(curl_command).execute()
response = process.get_stdout()
if expect_response:
try:
return json.loads(response)
except json.JSONDecodeError:
assert False, f"Expected JSON response but got: {response}"
return None


async def clean_up_machines(connection, server_host):
machines = await send_http_request(
connection, f"{server_host}/v1/meshnet/machines", method="GET"
machines = await send_https_request(
connection,
f"{server_host}/v1/meshnet/machines",
"GET",
CORE_API_CA_CERTIFICATE_PATH,
)

for machine in machines:
await send_http_request(
await send_https_request(
connection,
f"{server_host}/v1/meshnet/machines/{machine['identifier']}",
method="DELETE",
"DELETE",
CORE_API_CA_CERTIFICATE_PATH,
expect_response=False,
)

Expand All @@ -144,14 +125,14 @@ def fixture_machine_data(request):

@pytest.fixture(name="server_host")
def fixture_server_host():
return "http://10.0.80.86:8080"
return CORE_API_URL


@pytest.fixture(name="registered_machines")
async def fixture_register_machine(server_host, machine_data):
async with AsyncExitStack() as exit_stack:
connection = await exit_stack.enter_async_context(
new_connection_by_tag(ConnectionTag.DOCKER_CONE_CLIENT_1)
new_connection_by_tag(ConnectionTag.DOCKER_CONE_CLIENT_3)
)

await clean_up_machines(connection, server_host)
Expand All @@ -161,10 +142,11 @@ async def fixture_register_machine(server_host, machine_data):
for data in machine_data:
payload = json.dumps(data.__dict__)

response_data = await send_http_request(
response_data = await send_https_request(
connection,
f"{server_host}/v1/meshnet/machines",
method="POST",
"POST",
CORE_API_CA_CERTIFICATE_PATH,
data=payload,
)
registered_machines.append(response_data)
Expand Down Expand Up @@ -209,11 +191,14 @@ async def test_register_multiple_machines(registered_machines, machine_data):
async def test_get_all_machines(server_host, registered_machines, machine_data):
async with AsyncExitStack() as exit_stack:
connection = await exit_stack.enter_async_context(
new_connection_by_tag(ConnectionTag.DOCKER_CONE_CLIENT_1)
new_connection_by_tag(ConnectionTag.DOCKER_CONE_CLIENT_3)
)

response_data = await send_http_request(
connection, f"{server_host}/v1/meshnet/machines", "GET"
response_data = await send_https_request(
connection,
f"{server_host}/v1/meshnet/machines",
"GET",
CORE_API_CA_CERTIFICATE_PATH,
)

assert isinstance(response_data, list)
Expand All @@ -237,7 +222,7 @@ async def test_update_registered_machine_data(
):
async with AsyncExitStack() as exit_stack:
connection = await exit_stack.enter_async_context(
new_connection_by_tag(ConnectionTag.DOCKER_CONE_CLIENT_1)
new_connection_by_tag(ConnectionTag.DOCKER_CONE_CLIENT_3)
)

original_data = machine_data[0]
Expand All @@ -251,10 +236,11 @@ async def test_update_registered_machine_data(

for machine in registered_machines:

response_data = await send_http_request(
response_data = await send_https_request(
connection,
f"{server_host}/v1/meshnet/machines/{machine['identifier']}",
"PATCH",
CORE_API_CA_CERTIFICATE_PATH,
data=payload,
)

Expand All @@ -277,20 +263,24 @@ async def test_delete_registered_machine(
):
async with AsyncExitStack() as exit_stack:
connection = await exit_stack.enter_async_context(
new_connection_by_tag(ConnectionTag.DOCKER_CONE_CLIENT_1)
new_connection_by_tag(ConnectionTag.DOCKER_CONE_CLIENT_3)
)

machine = registered_machines[0]

await send_http_request(
await send_https_request(
connection,
f"{server_host}/v1/meshnet/machines/{machine['identifier']}",
"DELETE",
CORE_API_CA_CERTIFICATE_PATH,
expect_response=False,
)

get_response_data = await send_http_request(
connection, f"{server_host}/v1/meshnet/machines", "GET"
get_response_data = await send_https_request(
connection,
f"{server_host}/v1/meshnet/machines",
"GET",
CORE_API_CA_CERTIFICATE_PATH,
)

assert len(get_response_data) == 0
Expand All @@ -309,15 +299,16 @@ async def test_delete_registered_machine(
async def test_get_mesh_map(server_host, registered_machines, machine_data):
async with AsyncExitStack() as exit_stack:
connection = await exit_stack.enter_async_context(
new_connection_by_tag(ConnectionTag.DOCKER_CONE_CLIENT_1)
new_connection_by_tag(ConnectionTag.DOCKER_CONE_CLIENT_3)
)

for machine in registered_machines:

response_data = await send_http_request(
response_data = await send_https_request(
connection,
f"{server_host}/v1/meshnet/machines/{machine['identifier']}/map",
"GET",
CORE_API_CA_CERTIFICATE_PATH,
)

assert isinstance(response_data["peers"], list)
Expand All @@ -333,24 +324,26 @@ async def test_get_mesh_map(server_host, registered_machines, machine_data):
async def not_able_to_register_same_machine_twice(server_host):
async with AsyncExitStack() as exit_stack:
connection = await exit_stack.enter_async_context(
new_connection_by_tag(ConnectionTag.DOCKER_CONE_CLIENT_1)
new_connection_by_tag(ConnectionTag.DOCKER_CONE_CLIENT_3)
)
await clean_up_machines(connection, server_host)

payload = json.dumps(linux_vm.__dict__)

await send_http_request(
await send_https_request(
connection,
f"{server_host}/v1/meshnet/machines",
method="POST",
"POST",
CORE_API_CA_CERTIFICATE_PATH,
data=payload,
expect_response=False,
)

response_data = await send_http_request(
response_data = await send_https_request(
connection,
f"{server_host}/v1/meshnet/machines",
method="POST",
"POST",
CORE_API_CA_CERTIFICATE_PATH,
data=payload,
)

Expand Down
Loading

0 comments on commit 9643480

Please sign in to comment.