-
Notifications
You must be signed in to change notification settings - Fork 101
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for sending error responses with gRPC status codes.
Note that some hosts (e.g. Envoy v1.31+) already map HTTP status codes from send_http_response() to gRPC status codes, when talking with gRPC clients, so this API is needed only when more control is needed. Fixes #148. Signed-off-by: Piotr Sikora <[email protected]>
- Loading branch information
1 parent
442edc3
commit 2500068
Showing
10 changed files
with
334 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
[package] | ||
publish = false | ||
name = "proxy-wasm-example-grpc-auth-random" | ||
version = "0.0.1" | ||
authors = ["Piotr Sikora <[email protected]>"] | ||
description = "Proxy-Wasm plugin example: gRPC auth (random)" | ||
license = "Apache-2.0" | ||
edition = "2018" | ||
|
||
[lib] | ||
crate-type = ["cdylib"] | ||
|
||
[dependencies] | ||
log = "0.4" | ||
proxy-wasm = { path = "../../" } | ||
|
||
[profile.release] | ||
lto = true | ||
opt-level = 3 | ||
codegen-units = 1 | ||
panic = "abort" | ||
strip = "debuginfo" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
## Proxy-Wasm plugin example: gRPC auth (random) | ||
|
||
Proxy-Wasm plugin that grants access based on a result of gRPC callout. | ||
|
||
### Building | ||
|
||
```sh | ||
$ cargo build --target wasm32-wasi --release | ||
``` | ||
|
||
### Using in Envoy | ||
|
||
This example can be run with [`docker compose`](https://docs.docker.com/compose/install/) | ||
and has a matching Envoy configuration. | ||
|
||
```sh | ||
$ docker compose up | ||
``` | ||
|
||
#### Access granted. | ||
|
||
Send gRPC request to `localhost:10000` service `hello.HelloService`: | ||
|
||
```sh | ||
$ grpcurl -d '{"greeting": "Rust"}' -plaintext localhost:10000 hello.HelloService/SayHello | ||
{ | ||
"reply": "hello Rust" | ||
} | ||
``` | ||
|
||
Expected Envoy logs: | ||
|
||
```console | ||
[...] wasm log grpc_auth_random: Access granted. | ||
``` | ||
|
||
#### Access forbidden. | ||
|
||
Send gRPC request to `localhost:10000` service `hello.HelloService`: | ||
|
||
```sh | ||
$ grpcurl -d '{"greeting": "Rust"}' -plaintext localhost:10000 hello.HelloService/SayHello | ||
ERROR: | ||
Code: Aborted | ||
Message: Aborted by Proxy-Wasm! | ||
``` | ||
|
||
Expected Envoy logs: | ||
|
||
```console | ||
[...] wasm log grpc_auth_random: Access forbidden. | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Copyright 2022 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 | ||
# | ||
# http://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. | ||
|
||
services: | ||
envoy: | ||
image: envoyproxy/envoy:v1.24-latest | ||
hostname: envoy | ||
ports: | ||
- "10000:10000" | ||
volumes: | ||
- ./envoy.yaml:/etc/envoy/envoy.yaml | ||
- ./target/wasm32-wasi/release:/etc/envoy/proxy-wasm-plugins | ||
networks: | ||
- envoymesh | ||
depends_on: | ||
- grpcbin | ||
grpcbin: | ||
image: kong/grpcbin | ||
hostname: grpcbin | ||
ports: | ||
- "9000:9000" | ||
- "9001:9001" | ||
networks: | ||
- envoymesh | ||
networks: | ||
envoymesh: {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# Copyright 2022 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 | ||
# | ||
# http://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. | ||
|
||
static_resources: | ||
listeners: | ||
address: | ||
socket_address: | ||
address: 0.0.0.0 | ||
port_value: 10000 | ||
filter_chains: | ||
- filters: | ||
- name: envoy.filters.network.http_connection_manager | ||
typed_config: | ||
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager | ||
stat_prefix: ingress_http | ||
codec_type: AUTO | ||
route_config: | ||
name: local_routes | ||
virtual_hosts: | ||
- name: local_service | ||
domains: | ||
- "*" | ||
routes: | ||
- match: | ||
prefix: "/" | ||
route: | ||
cluster: grpcbin | ||
http_filters: | ||
- name: envoy.filters.http.wasm | ||
typed_config: | ||
"@type": type.googleapis.com/udpa.type.v1.TypedStruct | ||
type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm | ||
value: | ||
config: | ||
name: "grpc_auth_random" | ||
vm_config: | ||
runtime: "envoy.wasm.runtime.v8" | ||
code: | ||
local: | ||
filename: "/etc/envoy/proxy-wasm-plugins/proxy_wasm_example_grpc_auth_random.wasm" | ||
- name: envoy.filters.http.router | ||
typed_config: | ||
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router | ||
clusters: | ||
- name: httpbin | ||
connect_timeout: 5s | ||
type: STRICT_DNS | ||
lb_policy: ROUND_ROBIN | ||
load_assignment: | ||
cluster_name: httpbin | ||
endpoints: | ||
- lb_endpoints: | ||
- endpoint: | ||
address: | ||
socket_address: | ||
address: httpbin | ||
port_value: 8080 | ||
- name: grpcbin | ||
connect_timeout: 5s | ||
type: STRICT_DNS | ||
lb_policy: ROUND_ROBIN | ||
http2_protocol_options: {} | ||
load_assignment: | ||
cluster_name: grpcbin | ||
endpoints: | ||
- lb_endpoints: | ||
- endpoint: | ||
address: | ||
socket_address: | ||
address: grpcbin | ||
port_value: 9000 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// Copyright 2020 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 | ||
// | ||
// http://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. | ||
|
||
use log::info; | ||
use proxy_wasm::traits::*; | ||
use proxy_wasm::types::*; | ||
use std::time::Duration; | ||
|
||
proxy_wasm::main! {{ | ||
proxy_wasm::set_log_level(LogLevel::Trace); | ||
proxy_wasm::set_http_context(|_, _| -> Box<dyn HttpContext> { Box::new(GrpcAuthRandom) }); | ||
}} | ||
|
||
struct GrpcAuthRandom; | ||
|
||
impl HttpContext for GrpcAuthRandom { | ||
fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action { | ||
match self.get_http_request_header("content-type") { | ||
Some(value) if value.starts_with("application/grpc") => {} | ||
_ => { | ||
// Reject non-gRPC clients. | ||
self.send_http_response( | ||
503, | ||
vec![("Powered-By", "proxy-wasm")], | ||
Some(b"Service accessible only to gRPC clients.\n"), | ||
); | ||
return Action::Pause; | ||
} | ||
} | ||
|
||
match self.get_http_request_header(":path") { | ||
Some(value) if value.starts_with("/grpc.reflection") => { | ||
// Always allow gRPC calls to the reflection API. | ||
Action::Continue | ||
} | ||
_ => { | ||
// Allow other gRPC calls based on the result of grpcbin.GRPCBin/RandomError. | ||
self.dispatch_grpc_call( | ||
"grpcbin", | ||
"grpcbin.GRPCBin", | ||
"RandomError", | ||
vec![], | ||
None, | ||
Duration::from_secs(1), | ||
) | ||
.unwrap(); | ||
Action::Pause | ||
} | ||
} | ||
} | ||
|
||
fn on_http_response_headers(&mut self, _: usize, _: bool) -> Action { | ||
self.set_http_response_header("Powered-By", Some("proxy-wasm")); | ||
Action::Continue | ||
} | ||
} | ||
|
||
impl Context for GrpcAuthRandom { | ||
fn on_grpc_call_response(&mut self, _: u32, status_code: u32, _: usize) { | ||
if status_code % 2 == 0 { | ||
info!("Access granted."); | ||
self.resume_http_request(); | ||
} else { | ||
info!("Access forbidden."); | ||
self.send_grpc_response( | ||
GrpcStatusCode::Aborted, | ||
Some("Aborted by Proxy-Wasm!"), | ||
vec![("Powered-By", b"proxy-wasm")], | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters