From 0219fa777087cd87f1db26e9867d0f0a24e430f6 Mon Sep 17 00:00:00 2001 From: Arvid Jakobsson Date: Fri, 2 Dec 2022 15:58:12 +0100 Subject: [PATCH 1/2] Tezt/Node: add [--cors-origin] --- tezt/lib_tezos/node.ml | 5 ++++- tezt/lib_tezos/node.mli | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tezt/lib_tezos/node.ml b/tezt/lib_tezos/node.ml index 7e10d0c23552..fa25366a91b7 100644 --- a/tezt/lib_tezos/node.ml +++ b/tezt/lib_tezos/node.ml @@ -50,6 +50,7 @@ type argument = | Media_type of media_type | Metadata_size_limit of int option | Metrics_addr of string + | Cors_origin of string let make_argument = function | Network x -> ["--network"; x] @@ -75,6 +76,7 @@ let make_argument = function | Metadata_size_limit None -> ["--metadata-size-limit"; "unlimited"] | Metadata_size_limit (Some i) -> ["--metadata-size-limit"; string_of_int i] | Metrics_addr metrics_addr -> ["--metrics-addr"; metrics_addr] + | Cors_origin cors_origin -> ["--cors-origin"; cors_origin] let make_arguments arguments = List.flatten (List.map make_argument arguments) @@ -112,7 +114,8 @@ let is_redundant = function | Media_type _, _ | Metadata_size_limit _, _ | Peer _, _ - | Metrics_addr _, _ -> + | Metrics_addr _, _ + | Cors_origin _, _ -> false type 'a known = Unknown | Known of 'a diff --git a/tezt/lib_tezos/node.mli b/tezt/lib_tezos/node.mli index 6592141da1da..714e1fece5c2 100644 --- a/tezt/lib_tezos/node.mli +++ b/tezt/lib_tezos/node.mli @@ -80,6 +80,7 @@ type argument = | Media_type of media_type (** [--media-type] *) | Metadata_size_limit of int option (** --metadata-size-limit *) | Metrics_addr of string (** [--metrics-addr] *) + | Cors_origin of string (** [--cors-origin] *) (** Tezos node states. *) type t -- GitLab From 1ec2544b5f5998c5d9741552e390a6fc67f42cfd Mon Sep 17 00:00:00 2001 From: Arvid Jakobsson Date: Fri, 2 Dec 2022 15:58:24 +0100 Subject: [PATCH 2/2] Tezt: migrate [test_cors.py] --- tests_python/tests_014/test_cors.py | 47 ----------- tests_python/tests_015/test_cors.py | 47 ----------- tests_python/tests_alpha/test_cors.py | 47 ----------- tezt/tests/main.ml | 1 + tezt/tests/node_cors.ml | 111 ++++++++++++++++++++++++++ 5 files changed, 112 insertions(+), 141 deletions(-) delete mode 100644 tests_python/tests_014/test_cors.py delete mode 100644 tests_python/tests_015/test_cors.py delete mode 100644 tests_python/tests_alpha/test_cors.py create mode 100644 tezt/tests/node_cors.ml diff --git a/tests_python/tests_014/test_cors.py b/tests_python/tests_014/test_cors.py deleted file mode 100644 index 80b064285d86..000000000000 --- a/tests_python/tests_014/test_cors.py +++ /dev/null @@ -1,47 +0,0 @@ -import pytest -from daemons.node import Node -from launchers.sandbox import Sandbox -from tools import utils - - -@pytest.fixture(scope="class") -def node(sandbox: Sandbox): - """Launches one node in sandbox mode (genesis)""" - sandbox.add_node(0, params=['--cors-origin', '*']) - yield sandbox.node(0) - - -class TestCors: - def test_preflight(self, node: Node): - origin = 'localhost' - port = node.rpc_port - headers = { - 'Origin': origin, - 'Access-Control-Request-Method': 'GET', - 'Access-Control-Request-Headers': 'Content-Type', - } - res = utils.rpc( - origin, - port, - 'options', - '/chains/main/blocks/head/header/shell', - headers=headers, - ) - print(res.headers) - assert res.headers["access-control-allow-origin"] == '*' - assert res.headers["access-control-allow-methods"] == 'GET' - assert res.headers["access-control-allow-headers"] == 'Content-Type' - - def test_request(self, node: Node): - origin = 'localhost' - port = node.rpc_port - headers = {'Origin': origin, 'Content-Type': 'application/json'} - res = utils.rpc( - origin, - port, - 'get', - '/chains/main/blocks/head/header/shell', - headers=headers, - ) - print(res.headers) - assert res.headers["access-control-allow-origin"] == '*' diff --git a/tests_python/tests_015/test_cors.py b/tests_python/tests_015/test_cors.py deleted file mode 100644 index 80b064285d86..000000000000 --- a/tests_python/tests_015/test_cors.py +++ /dev/null @@ -1,47 +0,0 @@ -import pytest -from daemons.node import Node -from launchers.sandbox import Sandbox -from tools import utils - - -@pytest.fixture(scope="class") -def node(sandbox: Sandbox): - """Launches one node in sandbox mode (genesis)""" - sandbox.add_node(0, params=['--cors-origin', '*']) - yield sandbox.node(0) - - -class TestCors: - def test_preflight(self, node: Node): - origin = 'localhost' - port = node.rpc_port - headers = { - 'Origin': origin, - 'Access-Control-Request-Method': 'GET', - 'Access-Control-Request-Headers': 'Content-Type', - } - res = utils.rpc( - origin, - port, - 'options', - '/chains/main/blocks/head/header/shell', - headers=headers, - ) - print(res.headers) - assert res.headers["access-control-allow-origin"] == '*' - assert res.headers["access-control-allow-methods"] == 'GET' - assert res.headers["access-control-allow-headers"] == 'Content-Type' - - def test_request(self, node: Node): - origin = 'localhost' - port = node.rpc_port - headers = {'Origin': origin, 'Content-Type': 'application/json'} - res = utils.rpc( - origin, - port, - 'get', - '/chains/main/blocks/head/header/shell', - headers=headers, - ) - print(res.headers) - assert res.headers["access-control-allow-origin"] == '*' diff --git a/tests_python/tests_alpha/test_cors.py b/tests_python/tests_alpha/test_cors.py deleted file mode 100644 index 80b064285d86..000000000000 --- a/tests_python/tests_alpha/test_cors.py +++ /dev/null @@ -1,47 +0,0 @@ -import pytest -from daemons.node import Node -from launchers.sandbox import Sandbox -from tools import utils - - -@pytest.fixture(scope="class") -def node(sandbox: Sandbox): - """Launches one node in sandbox mode (genesis)""" - sandbox.add_node(0, params=['--cors-origin', '*']) - yield sandbox.node(0) - - -class TestCors: - def test_preflight(self, node: Node): - origin = 'localhost' - port = node.rpc_port - headers = { - 'Origin': origin, - 'Access-Control-Request-Method': 'GET', - 'Access-Control-Request-Headers': 'Content-Type', - } - res = utils.rpc( - origin, - port, - 'options', - '/chains/main/blocks/head/header/shell', - headers=headers, - ) - print(res.headers) - assert res.headers["access-control-allow-origin"] == '*' - assert res.headers["access-control-allow-methods"] == 'GET' - assert res.headers["access-control-allow-headers"] == 'Content-Type' - - def test_request(self, node: Node): - origin = 'localhost' - port = node.rpc_port - headers = {'Origin': origin, 'Content-Type': 'application/json'} - res = utils.rpc( - origin, - port, - 'get', - '/chains/main/blocks/head/header/shell', - headers=headers, - ) - print(res.headers) - assert res.headers["access-control-allow-origin"] == '*' diff --git a/tezt/tests/main.ml b/tezt/tests/main.ml index b0988712c24a..56b8f04c0176 100644 --- a/tezt/tests/main.ml +++ b/tezt/tests/main.ml @@ -134,6 +134,7 @@ let register_protocol_tests_that_use_supports_correctly () = Mockup.register_global_constants ~protocols ; Monitor_operations.register ~protocols ; Multinode_snapshot.register ~protocols ; + Node_cors.register ~protocols ; Node_event_level.register ~protocols ; Normalize.register ~protocols ; Operation_validation.register ~protocols ; diff --git a/tezt/tests/node_cors.ml b/tezt/tests/node_cors.ml new file mode 100644 index 000000000000..2a2f9372d87c --- /dev/null +++ b/tezt/tests/node_cors.ml @@ -0,0 +1,111 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Testing + ------- + Component: Tests CORS + Invocation: dune exec tezt/tests/main.exe -- --file node_cors.ml + Subject: Tests the node's [--cors-origin] flag +*) + +let rpc ~verb ~headers uri = + let* response, response_body = + Cohttp_lwt_unix.Client.call + ~headers:(Cohttp.Header.of_list headers) + verb + uri + in + Log.debug + ~prefix:"RPC" + "RPC response: %s" + (Cohttp.Code.string_of_status response.status) ; + return (response, response_body) + +let check_header ~__LOC__ (response : Cohttp.Response.t) header expected_value = + Check.( + (Cohttp.Header.get response.headers header = expected_value) + (option string) + ~__LOC__ + ~error_msg:("Expected header " ^ header ^ " to have value %R, got %L")) + +let nodes_args = Node.[Cors_origin "*"] + +let test_preflight = + Protocol.register_test ~__FILE__ ~title:"CORS preflight" ~tags:["cors"] + @@ fun protocol -> + let* node, _client = + Client.init_with_protocol ~nodes_args `Client ~protocol () + in + let origin = "localhost" in + let port = Node.rpc_port node in + let headers = + [ + ("Origin", origin); + ("Access-Control-Request-Method", "GET"); + ("Access-Control-Request-Headers", "Content-Type"); + ] + in + let uri = + Uri.make + ~scheme:"http" + ~host:origin + ~port + ~path:"/chains/main/blocks/head/header/shell" + () + in + let* response, _response_body = rpc ~verb:`OPTIONS ~headers uri in + check_header ~__LOC__ response "access-control-allow-origin" (Some "*") ; + check_header ~__LOC__ response "access-control-allow-methods" (Some "GET") ; + check_header + ~__LOC__ + response + "access-control-allow-headers" + (Some "Content-Type") ; + unit + +let test_request = + Protocol.register_test ~__FILE__ ~title:"CORS request" ~tags:["cors"] + @@ fun protocol -> + let* node, _client = + Client.init_with_protocol ~nodes_args `Client ~protocol () + in + let origin = "localhost" in + let port = Node.rpc_port node in + let headers = [("Origin", origin); ("Content-Type", "application/json")] in + let uri = + Uri.make + ~scheme:"http" + ~host:origin + ~port + ~path:"/chains/main/blocks/head/header/shell" + () + in + let* response, _response_body = rpc ~verb:`OPTIONS ~headers uri in + check_header ~__LOC__ response "access-control-allow-origin" (Some "*") ; + unit + +let register ~protocols = + test_preflight protocols ; + test_request protocols -- GitLab