From 25806df2caa317a99c276572609c91bb8ff4b588 Mon Sep 17 00:00:00 2001 From: Ryan Northey Date: Fri, 4 Jul 2025 16:09:42 +0100 Subject: [PATCH] repo: Add READMEs Signed-off-by: Ryan Northey --- README.md | 36 ++++++++ dynamic/README.md | 81 ++++++++++++++++++ go/README.md | 145 +++++++++++++++++++++++++++++++ wasm/README.md | 214 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 476 insertions(+) create mode 100644 README.md create mode 100644 dynamic/README.md create mode 100644 go/README.md create mode 100644 wasm/README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..e244d70 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +# Envoy Modules + +This repository hosts buildable out-of-tree extensions for [Envoy Proxy](https://www.envoyproxy.io/). These modules extend Envoy's functionality without requiring modifications to the core Envoy codebase. + +## Module Types + +Envoy supports three primary approaches for building extensions: + +### [Dynamic Modules](./dynamic/) +Native extensions written in C++, Rust, or Go that are compiled as shared libraries and loaded dynamically at runtime. + +### [Go Extensions](./go/) +Extensions written using the Envoy Go SDK, providing additional features and a Go-native development experience. + +### [WebAssembly (Wasm) Modules](./wasm/) +Cross-platform extensions compiled from C++, Rust, or other languages to WebAssembly bytecode. + +## Getting Started + +Each module type has its own development workflow and requirements. Please refer to the README in each directory for specific instructions: + +- [Dynamic Modules Documentation](./dynamic/README.md) +- [Go Extensions Documentation](./go/README.md) +- [Wasm Modules Documentation](./wasm/README.md) + +## Contributing + +Contributions are welcome! Please ensure your modules: +- Follow Envoy's extension best practices +- Include comprehensive documentation +- Provide example configurations +- Include tests where applicable + +## License + +This repository is licensed under the same terms as Envoy Proxy. See [LICENSE](./LICENSE) for details. diff --git a/dynamic/README.md b/dynamic/README.md new file mode 100644 index 0000000..3b68973 --- /dev/null +++ b/dynamic/README.md @@ -0,0 +1,81 @@ +# Dynamic Modules + +Dynamic modules are native extensions for Envoy that are compiled as shared libraries and loaded at runtime. These modules can be written in C++, Rust, or Go. + +## Overview + +Dynamic modules provide the highest performance and most direct integration with Envoy's core APIs. They are loaded as `.so` (Linux), `.dylib` (macOS), or `.dll` (Windows) files. + +## Supported Languages + +### C++ +- Direct access to Envoy's C++ APIs +- Best performance characteristics +- Requires matching Envoy ABI version + +### Rust +- Safe systems programming +- Can use FFI to interact with Envoy's C++ APIs +- Growing ecosystem of Envoy Rust bindings + +### Go +- Uses cgo for C++ interop +- Note: For pure Go extensions, consider using the [Go SDK](../go/) + +## Building Dynamic Modules + +### Prerequisites +- Matching Envoy version and build environment +- Bazel or CMake build system +- C++ toolchain (for C++ modules) +- Rust toolchain (for Rust modules) +- Go toolchain with cgo support (for Go modules) + +### Build Process +1. Match your build environment to the target Envoy version +2. Implement the required extension interfaces +3. Build as a shared library +4. Configure Envoy to load the module at runtime + +## Module Structure + +``` +dynamic/ +├── filters/ # HTTP/Network filters +├── access_loggers/ # Access logging extensions +├── tracers/ # Distributed tracing implementations +└── stats_sinks/ # Statistics output extensions +``` + +## Configuration + +Dynamic modules are configured in Envoy using the `envoy.extensions.common.dynamic_modules` extension: + +```yaml +static_resources: + listeners: + - filter_chains: + - filters: + - name: envoy.filters.http.dynamic_module + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.dynamic_module.v3.DynamicModule + library_path: "/path/to/module.so" + library_id: "my_module" +``` + +## Best Practices + +1. **Version Compatibility**: Ensure your module is built against the same Envoy version it will run with +2. **Error Handling**: Implement robust error handling as crashes will take down the entire Envoy process +3. **Resource Management**: Properly manage memory and other resources +4. **Thread Safety**: Ensure your code is thread-safe as Envoy uses multiple worker threads + +## Examples + +See the `examples/` subdirectory for sample implementations in each language. + +## Debugging + +- Use `ldd` (Linux) or `otool -L` (macOS) to verify library dependencies +- Enable debug logging in Envoy to see module loading information +- Consider using AddressSanitizer or other debugging tools during development diff --git a/go/README.md b/go/README.md new file mode 100644 index 0000000..2f2be11 --- /dev/null +++ b/go/README.md @@ -0,0 +1,145 @@ +# Go Extensions + +Go extensions for Envoy are built using the official Envoy Go SDK, providing a Go-native development experience with additional features beyond what's available in other extension mechanisms. + +## Overview + +The Envoy Go SDK enables writing Envoy extensions in pure Go, offering: +- Familiar Go development patterns +- Access to Go's standard library and ecosystem +- Simplified memory management with garbage collection +- Built-in concurrency primitives + +## Features + +### Unique Capabilities +- Direct manipulation of headers and body +- Async processing with goroutines +- Access to external services during request processing +- Dynamic configuration updates +- Native Go testing frameworks + +### Supported Extension Points +- HTTP filters +- Network filters +- Access loggers +- Custom protocols + +## Getting Started + +### Prerequisites +- Go 1.19 or later +- Envoy built with Go support enabled +- Basic understanding of Envoy's filter chain + +### Installation + +```bash +go get github.com/envoyproxy/go-control-plane +``` + +## Project Structure + +``` +go/ +├── http/ # HTTP filter implementations +│ ├── auth/ # Authentication filters +│ ├── ratelimit/ # Rate limiting filters +│ └── transform/ # Request/response transformation +├── network/ # Network filter implementations +└── common/ # Shared utilities and helpers +``` + +## Example HTTP Filter + +```go +package main + +import ( + "github.com/envoyproxy/envoy/contrib/golang/common/go/api" +) + +type myFilter struct { + api.PassThroughStreamFilter + config *filterConfig +} + +func (f *myFilter) DecodeHeaders(headers api.RequestHeaderMap, endStream bool) api.StatusType { + // Process request headers + headers.Set("x-custom-header", "processed-by-go") + return api.Continue +} + +func (f *myFilter) EncodeHeaders(headers api.ResponseHeaderMap, endStream bool) api.StatusType { + // Process response headers + return api.Continue +} +``` + +## Configuration + +Go extensions are configured using the `envoy.filters.http.golang` filter: + +```yaml +http_filters: +- name: envoy.filters.http.golang + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config + library_id: "my-go-filter" + library_path: "/path/to/filter.so" + plugin_config: + "@type": type.googleapis.com/xds.type.v3.TypedStruct + value: + key: "value" +``` + +## Building + +### Build Command +```bash +go build -buildmode=c-shared -o filter.so . +``` + +### Build Flags +- `-buildmode=c-shared`: Required for Envoy integration +- `-trimpath`: Recommended for production builds +- `-ldflags="-s -w"`: Reduce binary size + +## Performance Considerations + +1. **Garbage Collection**: Be mindful of GC pauses in latency-sensitive paths +2. **Goroutine Usage**: Avoid spawning excessive goroutines per request +3. **Memory Allocation**: Reuse objects where possible +4. **Blocking Operations**: Use async patterns for I/O operations + +## Testing + +```go +func TestFilter(t *testing.T) { + // Use the test harness provided by the SDK + harness := test.NewFilterTestHarness() + // Configure and run tests +} +``` + +## Best Practices + +1. **Error Handling**: Always handle errors gracefully +2. **Logging**: Use structured logging for debugging +3. **Configuration**: Validate configuration during initialization +4. **Resource Cleanup**: Implement proper cleanup in filter destructors +5. **Panics**: Avoid panics - they will crash the Envoy process + +## Examples + +See the `examples/` directory for complete working examples including: +- JWT authentication filter +- Request routing based on custom logic +- Response caching +- Custom metrics collection + +## Resources + +- [Envoy Go SDK Documentation](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/golang_filter) +- [Go Control Plane](https://github.com/envoyproxy/go-control-plane) +- [Example Filters](https://github.com/envoyproxy/envoy/tree/main/examples/golang) diff --git a/wasm/README.md b/wasm/README.md new file mode 100644 index 0000000..d3507e8 --- /dev/null +++ b/wasm/README.md @@ -0,0 +1,214 @@ +# WebAssembly (Wasm) Modules + +WebAssembly modules provide a cross-platform, sandboxed environment for extending Envoy. Write your extensions in C++, Rust, AssemblyScript, or other languages that compile to Wasm. + +## Overview + +Wasm modules offer several advantages: +- **Portability**: Run the same binary across different platforms and Envoy builds +- **Isolation**: Sandboxed execution prevents crashes from affecting Envoy +- **Language Flexibility**: Use any language that compiles to Wasm +- **Dynamic Loading**: Load and update modules without restarting Envoy + +## Supported Languages + +### Rust +- Most mature ecosystem for Envoy Wasm development +- Uses `proxy-wasm-rust-sdk` +- Excellent memory safety guarantees + +### C++ +- Uses `proxy-wasm-cpp-sdk` +- Familiar for developers with Envoy experience +- Direct mapping to proxy-wasm ABI + +### AssemblyScript +- TypeScript-like syntax +- Quick development cycle +- Good for simpler filters + +### TinyGo +- Go syntax with Wasm compilation +- Limited standard library support +- Smaller binary size than regular Go + +## Architecture + +Wasm modules interact with Envoy through the proxy-wasm ABI: + +``` +┌─────────────────┐ +│ Envoy Host │ +├─────────────────┤ +│ Proxy-Wasm ABI │ +├─────────────────┤ +│ Wasm Module │ +│ (Your Filter) │ +└─────────────────┘ +``` + +## Getting Started + +### Prerequisites +- Language-specific toolchain (Rust, C++, etc.) +- `wasm-opt` for optimization (optional but recommended) +- Envoy with Wasm support enabled + +### Quick Start (Rust) + +1. Install Rust and wasm32 target: +```bash +rustup target add wasm32-wasi +``` + +2. Create a new project: +```bash +cargo new --lib my-filter +cd my-filter +``` + +3. Add dependencies to `Cargo.toml`: +```toml +[dependencies] +proxy-wasm = "0.2" +log = "0.4" + +[lib] +crate-type = ["cdylib"] +``` + +4. Implement your filter: +```rust +use proxy_wasm::traits::*; +use proxy_wasm::types::*; + +#[no_mangle] +pub fn _start() { + proxy_wasm::set_log_level(LogLevel::Info); + proxy_wasm::set_root_context(|_| -> Box { + Box::new(MyRootContext) + }); +} +``` + +## Module Structure + +``` +wasm/ +├── filters/ # HTTP/Network filters +│ ├── auth/ # Authentication modules +│ ├── ratelimit/ # Rate limiting modules +│ └── transform/ # Transform modules +├── examples/ # Example implementations +└── tools/ # Build and test utilities +``` + +## Building + +### Rust +```bash +cargo build --target wasm32-wasi --release +wasm-opt -Oz target/wasm32-wasi/release/my_filter.wasm -o my_filter.optimized.wasm +``` + +### C++ +```bash +em++ -O3 -s WASM=1 -s EXPORTED_FUNCTIONS=['_start'] \ + --no-entry -o my_filter.wasm my_filter.cpp +``` + +## Configuration + +Wasm modules are configured using the `envoy.filters.http.wasm` filter: + +```yaml +http_filters: +- name: envoy.filters.http.wasm + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm + config: + root_id: "my_filter" + vm_config: + vm_id: "my_filter_vm" + runtime: "envoy.wasm.runtime.v8" + code: + local: + filename: "/path/to/my_filter.wasm" + configuration: + "@type": type.googleapis.com/google.protobuf.StringValue + value: | + { + "key": "value" + } +``` + +## Performance Optimization + +1. **Binary Size**: Use `wasm-opt` with `-Oz` flag +2. **Memory Usage**: Implement efficient data structures +3. **Host Calls**: Minimize calls across the Wasm boundary +4. **Compilation**: Use release builds with optimizations + +## Debugging + +### Logging +```rust +log::info!("Processing request: {:?}", path); +``` + +### Local Testing +Use `proxy-wasm-test-framework` for unit testing: +```rust +#[test] +fn test_request_headers() { + let mut filter = MyHttpContext::new(); + filter.on_http_request_headers(1, false); + // Assert expected behavior +} +``` + +## Best Practices + +1. **Error Handling**: Always handle potential failures gracefully +2. **Configuration Validation**: Validate JSON/config during initialization +3. **Resource Management**: Clean up resources in `on_done()` callbacks +4. **State Management**: Use context effectively for per-request state +5. **Versioning**: Include version info in your module for debugging + +## Common Patterns + +### Authentication Check +```rust +fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action { + match self.get_http_request_header("authorization") { + Some(token) => { + if self.validate_token(&token) { + Action::Continue + } else { + self.send_http_response(401, vec![], Some(b"Unauthorized")); + Action::Pause + } + } + None => { + self.send_http_response(401, vec![], Some(b"Missing Authorization")); + Action::Pause + } + } +} +``` + +## Examples + +Complete examples available in `examples/`: +- Basic HTTP header manipulation +- JWT validation +- Rate limiting with shared state +- Request/response transformation +- External service callouts + +## Resources + +- [Proxy-Wasm Specification](https://github.com/proxy-wasm/spec) +- [Rust SDK](https://github.com/proxy-wasm/proxy-wasm-rust-sdk) +- [C++ SDK](https://github.com/proxy-wasm/proxy-wasm-cpp-sdk) +- [WebAssembly Hub](https://webassemblyhub.io/)