grpc-experiments/gdebug/docker/envoy/zprox.sh

122 lines
4.0 KiB
Bash
Executable File

#!/bin/bash
set -exu -o pipefail
if [ "$#" -ne 5 ]; then
echo "Usage: ./zprox localport grpcaddr grpcport assetsaddr assetsport"
echo "localport: the port envoy proxy should listen"
echo "grpcaddr, grpcport: the addr+port of the gRPC service"
echo "assetsaddr, assetsport: the ip+port of the web server serving zpages assets (html, js, etc)"
exit 1
fi
TEMP=$(mktemp --suffix=.yaml)
function finish {
rm "$TEMP"
}
trap finish EXIT
readonly LOCAL_PORT=$1
readonly GRPC_ADDR=$2
readonly GRPC_PORT=$3
readonly ASSETS_ADDR=$4
readonly ASSETS_PORT=$5
readonly GDEBUG_TOKEN_NAME="gdebug-xsrf-token"
cat > "$TEMP" <<TERMINATOR
static_resources:
listeners:
- name: my_listener
address:
socket_address:
address: 0.0.0.0
port_value: $LOCAL_PORT
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
codec_type: auto
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains:
- "*"
routes:
- match:
prefix: "/"
headers:
- name: "Content-Type"
prefix_match: "application/grpc-web"
route:
cluster: local_service_grpc
- match:
prefix: "/"
route:
cluster: local_service_web
http_filters:
- name: envoy.lua
config:
inline_code: |
function envoy_on_request(request_handle)
-- hyphens are special characters in lua search patterns and must be escaped with a %
function esc_hyphens(s)
result, _ = string.gsub(s, "%-", "%%%-")
return result
end
headers = request_handle:headers()
content_type = headers:get("content-type")
if content_type and string.find(content_type, esc_hyphens("application/grpc-web")) then
xsrf_header = headers:get("$GDEBUG_TOKEN_NAME")
-- There can be only one cookie header: https://tools.ietf.org/html/rfc6265#section-5.4
cookies = headers:get("cookie") or ""
-- The token value is a base64 encoded binary and may have trailing = characters for padding
-- This is written as two statements because of lua's str matching limitations
xsrf_cookie = string.match(cookies, esc_hyphens("^$GDEBUG_TOKEN_NAME=(%w+=*)")) or string.match(cookies, esc_hyphens("; $GDEBUG_TOKEN_NAME=(%w+=*)"))
-- ~= means "not equals" in lua
if xsrf_header == nil or xsrf_header == "" or xsrf_cookie == nil or xsrf_cookie == "" or xsrf_header ~= xsrf_cookie then
request_handle:logInfo("rejecting request: xsrf token not set")
request_handle:respond({[":status"] = "401"}, "$GDEBUG_TOKEN_NAME must be set")
end
end
end
- name: envoy.grpc_web
config: {}
- name: envoy.router
access_log:
name: envoy.file_access_log
config:
path: "/dev/stdout"
clusters:
- name: local_service_grpc
connect_timeout: 0.250s
type: strict_dns
lb_policy: round_robin
http2_protocol_options: {}
hosts:
- socket_address:
address: $GRPC_ADDR
port_value: $GRPC_PORT
- name: local_service_web
connect_timeout: 0.250s
type: strict_dns
lb_policy: round_robin
hosts:
- socket_address:
address: $ASSETS_ADDR
port_value: $ASSETS_PORT
admin:
access_log_path: "/tmp/envoy/admin_access.log"
address:
socket_address:
address: 0.0.0.0
port_value: 9901
TERMINATOR
/usr/local/bin/envoy --v2-config-only -c "$TEMP"