def test_gossip_proxy(intercepted_two_node_network):
    nodes = intercepted_two_node_network.docker_nodes
    node = nodes[0]

    tls_certificate_path = node.config.tls_certificate_local_path()
    tls_parameters = {
        "--certificate-file": tls_certificate_path,
        "--node-id": extract_common_name(tls_certificate_path),
    }
    cli = CLI(nodes[0], tls_parameters=tls_parameters)
    account = cli.node.genesis_account
    cli.set_default_deploy_args(
        "--from",
        account.public_key_hex,
        "--private-key",
        cli.private_key_path(account),
        "--public-key",
        cli.public_key_path(account),
        "--payment",
        cli.resource(Contract.STANDARD_PAYMENT),
        "--payment-args",
        cli.payment_json,
    )
    cli("deploy", "--session", cli.resource(Contract.HELLO_NAME_DEFINE))
    block_hash = cli("propose")
    wait_for_block_hash_propagated_to_all_nodes(nodes, block_hash)
Example #2
0
    def address(self) -> str:
        if self.config.behind_proxy:
            if not os.environ.get("TAG_NAME"):
                # Local run
                host_name = "172.17.0.1"  # this works locally
            else:
                # Test suite is in a docker container if in CI
                host_name = f"test-{os.environ.get('TAG_NAME')}"

            certificate_path = self.config.tls_certificate_local_path()
            logging.info(f"certificate_path: {certificate_path}")
            node_id = extract_common_name(certificate_path)
            protocol_port = self.server_proxy_port
            discovery_port = self.kademlia_proxy_port
            addr = f"casperlabs://{node_id}@{host_name}?protocol={protocol_port}&discovery={discovery_port}"
            logging.info(f"Address of the proxy: {addr}")
            return addr

        m = re.search(
            f"Listening for traffic on (casperlabs://.+@{self.container.name}\\?protocol=\\d+&discovery=\\d+)\\.$",
            self.logs(),
            re.MULTILINE | re.DOTALL,
        )
        if m is None:
            raise CasperLabsNodeAddressNotFoundError()
        address = m.group(1)
        return address
Example #3
0
    def invoke_client(self,
                      command: str,
                      decode_stdout: bool = True,
                      add_host: bool = True) -> str:
        volumes = {
            self.node.host_mount_dir: {
                "bind": "/data",
                "mode": "ro"
            },
            "/tmp": {
                "bind": "/tmp",
                "mode": "rw"
            },
        }
        if add_host:
            command = f"--host {self.node.container_name} {command}"
            if self.node.cl_network.grpc_encryption:
                node_id = extract_common_name(
                    self.node.config.tls_certificate_local_path())
                command = f"--node-id {node_id} {command}"
        self.logger.info(f"COMMAND {command}")
        status_code = None
        container = None
        try:
            container = self.docker_client.containers.run(
                image=f"casperlabs/client:{self.node.docker_tag}",
                name=f"client-{self.node.config.number}-{random_string(5)}",
                command=command,
                network=self.node.config.network,
                volumes=volumes,
                detach=True,
                stderr=True,
                stdout=True,
            )
            r = container.wait()
            status_code = r["StatusCode"]
            stdout_raw = container.logs(stdout=True, stderr=False)
            stdout = decode_stdout and stdout_raw.decode("utf-8") or stdout_raw
            stderr = container.logs(stdout=False, stderr=True).decode("utf-8")

            # TODO: I don't understand why but if I just call `self.logger.debug` then
            # it doesn't print anything, even though the level is clearly set.
            if self.log_level == "DEBUG" or status_code != 0:
                self.logger.info(
                    f"EXITED exit_code: {status_code} STDERR: {stderr} STDOUT: {stdout}"
                )
            if status_code:
                raise NonZeroExitCodeError(command=(command, status_code),
                                           exit_code=status_code,
                                           output=stderr)
            return stdout
        finally:
            try:
                if container:
                    container.remove()
            except docker.errors.APIError as e:
                self.logger.warning(
                    f"Exception while removing docker client container: {str(e)}"
                )
Example #4
0
 def update_credentials(self, certificate_file, key_file, node_id=None):
     self.node_id = node_id or extract_common_name(certificate_file)
     self.certificate_file = certificate_file
     self.key_file = key_file
     self.credentials = grpc.ssl_channel_credentials(
         root_certificates=read_binary(certificate_file),
         private_key=read_binary(key_file),
         certificate_chain=read_binary(certificate_file),
     )
     self.secure_channel_options = self.node_id and [
         ("grpc.ssl_target_name_override", self.node_id),
         ("grpc.default_authority", self.node_id),
     ]
def test_grpc_encryption_scala_cli(encrypted_two_node_network):
    node = encrypted_two_node_network.docker_nodes[0]
    cli = DockerCLI(
        node,
        tls_parameters={
            "--node-id": extract_common_name(node.config.tls_certificate_local_path())
        },
    )
    logging.info(
        f"EXECUTING {' '.join(cli.expand_args(['show-blocks', '--depth', 1]))}"
    )
    blocks = cli("show-blocks", "--depth", 1)
    logging.debug(f"{blocks}")
def test_grpc_encryption_python_lib(encrypted_two_node_network):
    node = encrypted_two_node_network.docker_nodes[0]
    host = os.environ.get("TAG_NAME", None) and node.container_name or "localhost"
    client = CasperLabsClient(
        host,
        node.grpc_external_docker_port,
        node.grpc_internal_docker_port,
        extract_common_name(node.config.tls_certificate_local_path()),
        node.config.tls_certificate_local_path(),
    )
    blocks = list(client.showBlocks(1))
    assert len(blocks) > 0
    logging.debug(f"{blocks}")
def test_grpc_encryption_python_cli(encrypted_two_node_network):
    nodes = encrypted_two_node_network.docker_nodes

    tls_parameters = {
        "--certificate-file": nodes[0].config.tls_certificate_local_path(),
        "--node-id": extract_common_name(nodes[0].config.tls_certificate_local_path()),
    }
    cli = CLI(nodes[0], tls_parameters=tls_parameters)
    logging.info(
        f"""EXECUTING {' '.join(cli.expand_args(["show-blocks", "--depth", 1]))}"""
    )
    blocks = cli("show-blocks", "--depth", 1)
    assert len(blocks) > 0
    logging.debug(f"{blocks}")
Example #8
0
def test_equivocation(intercepted_two_node_network):
    """
    Generate an equivocating block and check the system can detect it.
    """
    nodes = intercepted_two_node_network.docker_nodes
    for node in nodes:
        node.proxy_server.set_interceptor(
            GenerateEquivocatingBlocksGossipInterceptor)

    node = nodes[0]
    account = node.genesis_account

    tls_certificate_path = node.config.tls_certificate_local_path()
    tls_parameters = {"--node-id": extract_common_name(tls_certificate_path)}

    cli = DockerCLI(nodes[0], tls_parameters=tls_parameters)
    cli.set_default_deploy_args(
        "--from",
        account.public_key_hex,
        "--private-key",
        cli.private_key_path(account),
        "--public-key",
        cli.public_key_path(account),
        "--payment",
        cli.resource(Contract.STANDARD_PAYMENT),
        "--payment-args",
        cli.payment_json,
    )
    cli("deploy", "--session", cli.resource(Contract.HELLO_NAME_DEFINE))
    block_hash = cli("propose")
    logging.info(f"   =============> REAL BLOCK: {block_hash}")

    wait_for_block_hash_propagated_to_all_nodes(nodes, block_hash)

    block_hash = None
    if nodes[0].proxy_server.interceptor.equivocating_block:
        block_hash = nodes[
            0].proxy_server.interceptor.equivocating_block.block_hash
        receiver_node = nodes[1]
        logging.info(
            f"   =============> EQUIVOCATING BLOCK: {block_hash.hex()}")

    wait_for_block_hash_propagated_to_all_nodes([receiver_node],
                                                block_hash.hex())
    assert "Found equivocation:" in receiver_node.logs()
def test_check_deploy_signatures(intercepted_two_node_network):
    """
    This test uses an interceptor that modifies block retrieved
    by node-1 from node-0 with GetBlockChunked method of the gossip service
    and removes approvals from deploys in the block.
    node-1 should not accept this block.
    """
    nodes = intercepted_two_node_network.docker_nodes
    for node in nodes:
        node.proxy_server.set_interceptor(RemoveSignatureGossipInterceptor)
    node = nodes[0]
    account = node.genesis_account

    tls_certificate_path = node.config.tls_certificate_local_path()
    tls_parameters = {
        # Currently only Python client requires --certificate-file
        # It may not need it in the future.
        # "--certificate-file": tls_certificate_path,
        "--node-id": extract_common_name(tls_certificate_path)
    }

    cli = DockerCLI(nodes[0], tls_parameters=tls_parameters)
    cli.set_default_deploy_args(
        "--from",
        account.public_key_hex,
        "--private-key",
        cli.private_key_path(account),
        "--public-key",
        cli.public_key_path(account),
        "--payment",
        cli.resource(Contract.STANDARD_PAYMENT),
        "--payment-args",
        cli.payment_json,
    )
    cli("deploy", "--session", cli.resource(Contract.HELLO_NAME_DEFINE))
    block_hash = cli("propose")

    with raises(Exception):
        wait_for_block_hash_propagated_to_all_nodes(nodes, block_hash)

    assert "InvalidDeploySignature" in nodes[1].logs()
def test_grpc_encryption_python_cli_and_proxy(encrypted_two_node_network):
    node = encrypted_two_node_network.docker_nodes[0]

    tls_certificate_path = node.config.tls_certificate_local_path()
    tls_key_path = local_path(node.config.tls_key_path())
    tls_parameters = {
        "--certificate-file": tls_certificate_path,
        "--node-id": extract_common_name(tls_certificate_path),
    }

    cli = CLI(node, tls_parameters=tls_parameters)
    cli.port = 50401  # We will be talking to proxy on 50401, node is on 40401

    proxy_client = grpc_proxy.proxy_client(
        node,
        node_port=40401,
        node_host=cli.host,
        proxy_port=50401,
        client_certificate_file=tls_certificate_path,
        client_key_file=tls_key_path,
        server_certificate_file=tls_certificate_path,
        server_key_file=tls_key_path,
    )

    cli.host = "localhost"

    logging.info(
        f"""EXECUTING {' '.join(cli.expand_args(["show-blocks", "--depth", 1]))}"""
    )
    block_infos = cli("show-blocks", "--depth", 1)
    logging.info(f"{block_infos[0]}")
    assert len(block_infos) > 0
    block_info = cli("show-block", block_infos[0].summary.block_hash)
    logging.info(f"{block_info}")

    proxy_client.stop()

    with raises(CLIErrorExit) as excinfo:
        block_info = cli("show-block", block_infos[0].summary.block_hash)
    # Expected grpc error: UNAVAILABLE
    assert '"grpc_status":14' in str(excinfo.value)
Example #11
0
    def __init__(self, node: "DockerNode"):  # NOQA
        super(PythonClient, self).__init__()
        self.node = node
        self.abi = ABI
        host = node.node_host

        certificate_file = None
        node_id = None
        if self.node.config.grpc_encryption:
            certificate_file = self.node.config.tls_certificate_local_path()
            node_id = extract_common_name(certificate_file)

        self.client = CasperLabsClient(
            host=host,
            port_internal=self.node.grpc_internal_docker_port,
            port=self.node.grpc_external_docker_port,
            node_id=node_id,
            certificate_file=certificate_file,
        )
        logging.info(f"PythonClient(host={self.client.host}, "
                     f"port={self.node.grpc_external_docker_port}, "
                     f"port_internal={self.node.grpc_internal_docker_port})")
Example #12
0
 def __init__(
     self,
     service_stub,
     add_servicer_to_server,
     node_host: str,
     node_port: int,
     proxy_port: int,
     encrypted_connection: bool = True,
     server_certificate_file: str = None,
     server_key_file: str = None,
     client_certificate_file: str = None,
     client_key_file: str = None,
     interceptor=None,
 ):
     super().__init__()
     self.service_stub = service_stub
     self.add_servicer_to_server = add_servicer_to_server
     self.node_host = node_host
     self.node_port = node_port
     self.proxy_port = proxy_port
     self.server_certificate_file = server_certificate_file
     self.server_key_file = server_key_file
     self.client_certificate_file = client_certificate_file
     self.client_key_file = client_key_file
     self.encrypted_connection = encrypted_connection
     self.node_id = None
     if self.encrypted_connection:
         self.node_id = extract_common_name(self.client_certificate_file)
     self.servicer = ProxyServicer(
         node_host=self.node_host,
         node_port=self.node_port,
         proxy_port=self.proxy_port,
         encrypted_connection=self.encrypted_connection,
         certificate_file=self.client_certificate_file,
         key_file=self.client_key_file,
         node_id=self.node_id,
         service_stub=self.service_stub,
         interceptor=interceptor,
     )
Example #13
0
def test_grpc_encryption_python_cli(encrypted_two_node_network):
    nodes = encrypted_two_node_network.docker_nodes

    # The idea of the test was to check if it is possible to provide the client
    # with a certificate other than the node's certificate, and overwrite it with
    # node_id (CN in node's certificate). Unfortunately, it doesn't work, i.e.
    # we can do it but connection will fail with:
    # "Handshake failed with fatal error SSL_ERROR_SSL: error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED."
    # If not for the above the "--certificate-file" option would point to certficate of the nodes[1]
    # in this test.
    tls_parameters = {
        "--certificate-file":
        nodes[0].config.tls_certificate_local_path(),
        "--node-id":
        extract_common_name(nodes[0].config.tls_certificate_local_path()),
    }
    cli = CLI(nodes[0], tls_parameters=tls_parameters)
    logging.info(
        f"""EXECUTING {' '.join(cli.expand_args(["show-blocks", "--depth", 1]))}"""
    )
    blocks = cli("show-blocks", "--depth", 1)
    assert len(blocks)
    logging.debug(f"{blocks}")
Example #14
0
    def __init__(self, node: "DockerNode"):  # NOQA
        super(PythonClient, self).__init__()
        self.node = node
        self.abi = ABI
        # If $TAG_NAME is set it means we are running in docker, see docker_run_test.sh
        host = (os.environ.get("TAG_NAME", None) and self.node.container_name
                or "localhost")

        certificate_file = None
        node_id = None
        if self.node.config.grpc_encryption:
            certificate_file = self.node.config.tls_certificate_local_path()
            node_id = extract_common_name(certificate_file)

        self.client = CasperLabsClient(
            host=host,
            internal_port=self.node.grpc_internal_docker_port,
            port=self.node.grpc_external_docker_port,
            node_id=node_id,
            certificate_file=certificate_file,
        )
        logging.info(f"PythonClient(host={self.client.host}, "
                     f"port={self.node.grpc_external_docker_port}, "
                     f"internal_port={self.node.grpc_internal_docker_port})")
Example #15
0
 def _node_address(self, config):
     node_id = extract_common_name(config.tls_certificate_local_path())
     return f"casperlabs://{node_id}@node-{config.number}-{config.rand_str}-{self._docker_tag(config)}-{config.unique_run_num}?protocol=40400&discovery=40404"
Example #16
0
 def node_id(self) -> str:
     return extract_common_name(self.config.tls_certificate_local_path())