From a45c3b62be05cda6899be31cef2881f918bcbed9 Mon Sep 17 00:00:00 2001 From: Jonathan Zernik Date: Sun, 19 Jul 2020 20:20:34 -0700 Subject: [PATCH] Add envoy proxy (#95) * Add envoy proxy * Add frontend, still not working * Open port to frontend * Fix static html page * Fix url in client js code, but CORS is still blocked * Successfully make request from browser to sqkserver through proxy * Expose ports for sqkserver in docker * Remove unused frontend files * Remove duplicate envoy config file --- docker/docker-compose.yml | 2 + docker/envoy/Dockerfile | 20 +++++++ docker/frontend/Dockerfile | 47 ++++++++++++++++ docker/sqkserver/Dockerfile | 3 ++ frontend/client.js | 33 ++++++++++++ frontend/envoy.yaml | 54 +++++++++++++++++++ frontend/index.html | 11 ++++ frontend/package.json | 16 ++++++ itests/docker-compose.yml | 25 +++++++++ proto/squeak_admin.proto | 9 ++++ .../admin/squeak_admin_server_servicer.py | 3 ++ 11 files changed, 223 insertions(+) create mode 100644 docker/envoy/Dockerfile create mode 100644 docker/frontend/Dockerfile create mode 100644 frontend/client.js create mode 100644 frontend/envoy.yaml create mode 100644 frontend/index.html create mode 100644 frontend/package.json diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index f031a559..0e727909 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -41,7 +41,9 @@ services: - ./config.ini:/app/config.ini ports: - 8774:8774 + - 8994:8994 - 18774:18774 + - 18994:18994 links: - "lnd:lnd" depends_on: diff --git a/docker/envoy/Dockerfile b/docker/envoy/Dockerfile new file mode 100644 index 00000000..e9365b2a --- /dev/null +++ b/docker/envoy/Dockerfile @@ -0,0 +1,20 @@ +# Copyright 2018 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM envoyproxy/envoy:v1.15.0 + +# COPY "docker/envoy/envoy.yaml" /etc/envoy/envoy.yaml +COPY "frontend/envoy.yaml" /etc/envoy/envoy.yaml + +CMD /usr/local/bin/envoy -c /etc/envoy/envoy.yaml -l trace --log-path /tmp/envoy_info.log diff --git a/docker/frontend/Dockerfile b/docker/frontend/Dockerfile new file mode 100644 index 00000000..3d5f344c --- /dev/null +++ b/docker/frontend/Dockerfile @@ -0,0 +1,47 @@ +# Copyright 2018 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM node:10-stretch + +RUN apt-get -qq update && apt-get -qq install -y \ + unzip + +WORKDIR /tmp + +RUN curl -sSL https://github.com/protocolbuffers/protobuf/releases/download/v3.12.2/\ +protoc-3.12.2-linux-x86_64.zip -o protoc.zip && \ + unzip -qq protoc.zip && \ + cp ./bin/protoc /usr/local/bin/protoc + +RUN curl -sSL https://github.com/grpc/grpc-web/releases/download/1.2.0/\ +protoc-gen-grpc-web-1.2.0-linux-x86_64 -o /usr/local/bin/protoc-gen-grpc-web && \ + chmod +x /usr/local/bin/protoc-gen-grpc-web + +COPY frontend . + +RUN mkdir proto +COPY proto/squeak_admin.proto proto/ +RUN curl -o rpc.proto -s https://raw.githubusercontent.com/lightningnetwork/lnd/master/lnrpc/rpc.proto +RUN cp rpc.proto proto/lnd.proto + +RUN protoc -I=. proto/squeak_admin.proto proto/lnd.proto \ + --js_out=import_style=commonjs:. \ + --grpc-web_out=import_style=commonjs,mode=grpcwebtext:. + +RUN npm install && \ + npm link grpc-web && \ + npx webpack client.js + +EXPOSE 8081 +CMD ["python", "-m", "SimpleHTTPServer", "8081"] diff --git a/docker/sqkserver/Dockerfile b/docker/sqkserver/Dockerfile index cabf7977..24473fd8 100644 --- a/docker/sqkserver/Dockerfile +++ b/docker/sqkserver/Dockerfile @@ -33,6 +33,9 @@ RUN ./install-rpc.sh RUN python3 setup.py install EXPOSE 8774 +EXPOSE 8994 +EXPOSE 18774 +EXPOSE 18994 # Copy the entrypoint script. COPY "docker/sqkserver/start-sqkserver.sh" . diff --git a/frontend/client.js b/frontend/client.js new file mode 100644 index 00000000..a2a4d0e7 --- /dev/null +++ b/frontend/client.js @@ -0,0 +1,33 @@ +/** + * + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +const {HelloRequest, + HelloReply} = require('./proto/squeak_admin_pb.js'); +const {SqueakAdminClient} = require('./proto/squeak_admin_grpc_web_pb.js'); + +var client = new SqueakAdminClient('http://' + window.location.hostname + ':8080', + null, null); + +var request = new HelloRequest(); +request.setName('World'); + +console.log('Testing...'); + +client.sayHello(request, {}, (err, response) => { + console.log(response.getMessage()); +}); diff --git a/frontend/envoy.yaml b/frontend/envoy.yaml new file mode 100644 index 00000000..3f6dee65 --- /dev/null +++ b/frontend/envoy.yaml @@ -0,0 +1,54 @@ +admin: + access_log_path: /tmp/admin_access.log + address: + socket_address: { address: 0.0.0.0, port_value: 9901 } + +static_resources: + listeners: + - name: listener_0 + address: + socket_address: { address: 0.0.0.0, port_value: 8080 } + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager + codec_type: auto + stat_prefix: ingress_http + route_config: + name: local_route + virtual_hosts: + - name: local_service + domains: ["*"] + routes: + - match: { prefix: "/" } + route: + cluster: squeak_admin_service + max_grpc_timeout: 0s + cors: + allow_origin_string_match: + - prefix: "*" + allow_methods: GET, PUT, DELETE, POST, OPTIONS + allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout + max_age: "1728000" + expose_headers: custom-header-1,grpc-status,grpc-message + http_filters: + - name: envoy.filters.http.grpc_web + - name: envoy.filters.http.cors + - name: envoy.filters.http.router + clusters: + - name: squeak_admin_service + connect_timeout: 0.25s + type: logical_dns + http2_protocol_options: {} + lb_policy: round_robin + # win/mac hosts: Use address: host.docker.internal instead of address: localhost in the line below + load_assignment: + cluster_name: cluster_0 + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: sqkserver + port_value: 8994 diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 00000000..9872cd58 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,11 @@ + + + + +gRPC-Web Example + + + +

Open up the developer console and see the logs for the output.

+ + diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 00000000..6e4ffe32 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,16 @@ +{ + "name": "grpc-web-simple-example", + "version": "0.1.0", + "description": "gRPC-Web simple example", + "main": "server.js", + "devDependencies": { + "@grpc/grpc-js": "~1.0.5", + "@grpc/proto-loader": "~0.5.4", + "async": "~1.5.2", + "google-protobuf": "~3.12.0", + "grpc-web": "~1.2.0", + "lodash": "~4.17.0", + "webpack": "~4.43.0", + "webpack-cli": "~3.3.11" + } +} diff --git a/itests/docker-compose.yml b/itests/docker-compose.yml index 2b85a29c..5373e516 100644 --- a/itests/docker-compose.yml +++ b/itests/docker-compose.yml @@ -100,6 +100,11 @@ services: - test_shared:/rpc - test_lnd_server_dir:/root/.lnd - ./config.ini:/app/config.ini + ports: + - 8774:8774 + - 8994:8994 + - 18774:18774 + - 18994:18994 links: - "btcd:btcd" - "lnd_server:lnd" @@ -122,6 +127,26 @@ services: - "lnd_client:lnd" command: tail -f /dev/null + envoy: + image: envoy + container_name: test_envoy + build: + context: ../ + dockerfile: docker/envoy/Dockerfile + ports: + - 8080:8080 + links: + - "sqkserver:sqkserver" + + frontend: + image: frontend + container_name: test_frontend + build: + context: ../ + dockerfile: docker/frontend/Dockerfile + ports: + - 8081:8081 + volumes: # btcctl and lnd containers. test_shared: diff --git a/proto/squeak_admin.proto b/proto/squeak_admin.proto index c44294cb..2648e52f 100644 --- a/proto/squeak_admin.proto +++ b/proto/squeak_admin.proto @@ -12,6 +12,8 @@ import "proto/lnd.proto"; // Interface exported by the server. service SqueakAdmin { + rpc SayHello (HelloRequest) returns (HelloReply); + /** sqkadmin: `getsqueak` */ rpc GetBalance (GetBalanceRequest) returns (GetBalanceReply) {} @@ -38,6 +40,13 @@ service SqueakAdmin { } +message HelloRequest { + string name = 1; +} + +message HelloReply { + string message = 1; +} message GetBalanceRequest { } diff --git a/squeakserver/admin/squeak_admin_server_servicer.py b/squeakserver/admin/squeak_admin_server_servicer.py index ca76eeab..0fcafad3 100644 --- a/squeakserver/admin/squeak_admin_server_servicer.py +++ b/squeakserver/admin/squeak_admin_server_servicer.py @@ -18,6 +18,9 @@ class SqueakAdminServerServicer(squeak_admin_pb2_grpc.SqueakAdminServicer): self.port = port self.handler = handler + def SayHello(self, request, context): + return squeak_admin_pb2.HelloReply(message='Hello, %s!' % request.name) + def GetBalance(self, request, context): wallet_balance_response = self.handler.handle_get_balance() return squeak_admin_pb2.GetBalanceReply(