diff --git a/not_my_board/_http.py b/not_my_board/_http.py index e5c7e17..879ecda 100644 --- a/not_my_board/_http.py +++ b/not_my_board/_http.py @@ -345,3 +345,27 @@ class _ParsedURL: username: Optional[str] password: Optional[str] ssl: Union[bool, ssl.SSLContext] + + +# pylint: disable=import-outside-toplevel +async def _main(): + import argparse + import pathlib + + parser = argparse.ArgumentParser(description="Request JSON from an HTTP server") + parser.add_argument( + "--cacert", + type=pathlib.Path, + action="append", + help="path to CA certificates, which should be trusted", + ) + parser.add_argument("url", help="HTTP(S) URL of the JSON document") + args = parser.parse_args() + + client = Client(args.cacert) + result = await client.get_json(args.url) + print(result) + + +if __name__ == "__main__": + util.run(_main()) diff --git a/scripts/_vmctl/alpine-chroot-install.sh b/scripts/_vmctl/alpine-chroot-install.sh index 3d1c470..c99455e 100644 --- a/scripts/_vmctl/alpine-chroot-install.sh +++ b/scripts/_vmctl/alpine-chroot-install.sh @@ -62,6 +62,38 @@ wait EOF chmod +x /usr/local/bin/while-stdin +# create self-signed certificates +install -d /etc/not-my-board/ +openssl req \ + -x509 \ + -newkey ec \ + -pkeyopt ec_paramgen_curve:secp384r1 \ + -days 365000 \ + -nodes \ + -keyout "/etc/not-my-board/not-my-board-root-ca.key" \ + -out "/etc/not-my-board/not-my-board-root-ca.crt" \ + -subj "/CN=not-my-board-root-ca" + +hostname="hub.local" +openssl req \ + -x509 \ + -CA "/etc/not-my-board/not-my-board-root-ca.crt" \ + -CAkey "/etc/not-my-board/not-my-board-root-ca.key" \ + -newkey ec \ + -pkeyopt ec_paramgen_curve:prime256v1 \ + -days 365000 \ + -nodes \ + -keyout "/etc/not-my-board/not-my-board.key" \ + -out "/etc/not-my-board/not-my-board.crt" \ + -subj "/CN=$hostname" \ + -addext "subjectAltName=DNS:$hostname,DNS:*.$hostname" \ + -addext "basicConstraints=CA:FALSE" \ + -addext "keyUsage=digitalSignature,keyEncipherment" \ + -addext "extendedKeyUsage=serverAuth" + +rm "/etc/not-my-board/not-my-board-root-ca.key" +chown admin:admin /etc/not-my-board/not-my-board.key + enable_services() { runlevel="$1" shift diff --git a/scripts/vmctl b/scripts/vmctl index dfe5523..56d2c29 100755 --- a/scripts/vmctl +++ b/scripts/vmctl @@ -122,9 +122,11 @@ EOF "linux-$kernel_variant" \ linux-firmware-none \ openssh \ + openssl \ py3-meson-python \ py3-pip \ python3 \ + tinyproxy \ tzdata \ ; diff --git a/tests/test_http.py b/tests/test_http.py new file mode 100644 index 0000000..31af019 --- /dev/null +++ b/tests/test_http.py @@ -0,0 +1,46 @@ +async def test_proxy_connect(vms): + async with vms.hub.ssh_task("not-my-board hub", "hub"): + async with vms.hub.ssh_task( + "tinyproxy -d -c ./src/tests/tinyproxy.conf", "tinyproxy" + ): + # wait for listening sockets + await vms.hub.ssh_poll("nc -z 127.0.0.1 2092") + await vms.hub.ssh_poll("nc -z 127.0.0.1 8888") + + result = await vms.hub.ssh( + ( + "http_proxy=http://127.0.0.1:8888 " + "python3 -m not_my_board._http http://hub.local:2092/api/v1/places" + ), + prefix="http GET", + ) + assert result.stdout == "{'places': []}" + + +async def test_proxy_connect_https(vms): + async with vms.hub.ssh_task( + ( + "uvicorn --host 0.0.0.0 --port 2092 " + "--ssl-keyfile /etc/not-my-board/not-my-board.key " + "--ssl-certfile /etc/not-my-board/not-my-board.crt " + "not_my_board:asgi_app" + ), + "hub", + ): + async with vms.hub.ssh_task( + "tinyproxy -d -c ./src/tests/tinyproxy.conf", "tinyproxy" + ): + # wait for listening sockets + await vms.hub.ssh_poll("nc -z 127.0.0.1 2092") + await vms.hub.ssh_poll("nc -z 127.0.0.1 8888") + + result = await vms.hub.ssh( + ( + "https_proxy=http://127.0.0.1:8888 " + "python3 -m not_my_board._http " + "--cacert /etc/not-my-board/not-my-board-root-ca.crt " + "https://hub.local:2092/api/v1/places" + ), + prefix="http GET", + ) + assert result.stdout == "{'places': []}" diff --git a/tests/tinyproxy.conf b/tests/tinyproxy.conf new file mode 100644 index 0000000..b4e7d66 --- /dev/null +++ b/tests/tinyproxy.conf @@ -0,0 +1,4 @@ +Port 8888 +Listen 127.0.0.1 +Timeout 600 +Allow 127.0.0.1