envoy-control-plane for Rust

This package exposes the Envoy xDS protos and gRPC services via prost. It also enables reading JSON and YAML bootstrap files into prost-generated structs, e.g. if you have a bootstrap.yaml containing:

```yaml

admin: address: socketAddress: address: "127.0.0.1" portValue: 9901 node: id: envoy-test-1 cluster: envoy-test-cluster-1 staticResources: listeners: - name: server-1 address: socketAddress: address: 127.0.0.1 portValue: 9000 filterChains: - filters: - name: envoy.filters.network.httpconnectionmanager typedConfig: "@type": type.googleapis.com/envoy.extensions.filters.network.httpconnectionmanager.v3.HttpConnectionManager statPrefix: ingresshttp httpFilters: - name: envoy.filters.http.router routeConfig: name: localroute virtualHosts: - name: localservice domains: ["*"] routes: - match: prefix: "/" route: cluster: local-srv transportSocket: name: envoy.transportsockets.tls typedConfig: '@type': type.googleapis.com/envoy.extensions.transportsockets.tls.v3.DownstreamTlsContext requireClientCertificate: value: true commonTlsContext: tlsParams: tlsMinimumProtocolVersion: TLSv13 tlsMaximumProtocolVersion: TLSv13 validationContext: trustedCa: filename: ./certs/ca.crt matchTypedSubjectAltNames: - sanType: DNS matcher: exact: client.test tlsCertificates: - certificateChain: filename: ./certs/server.test.ecdsa-p256.crt privateKey: filename: ./certs/server.test.ecdsa-p256.key clusters: - name: local-srv type: STATIC lbPolicy: ROUNDROBIN loadAssignment: clusterName: local-srv endpoints: - lbEndpoints: - endpoint: address: socketAddress: address: "127.0.0.1" portValue: 9110 ```

You can read that Bootstrap config in with:

```rust use envoycontrolplane::envoy::config::bootstrap::v3::Bootstrap;

let configcontents = readall(&args.configpath).await?; let configext = args.configpath.extension().unwrapordefault(); let bootstrap: Bootstrap = if configext == "yaml" || configext == "yml" { eprintln!("WARNING: YAML support is incomplete (e.g. durations don't work)"); serdeyaml::fromstr(&configcontents)? } else { serdejson::fromstr(&config_contents)? }; ```

Envoy uses a lot of protobuf Any values for polymorphism. As you can see above we read them off disk just fine, but there is an additional hoop to jump through in order to actually access a typed instance:

```rust let downstreamtlscontexttypeurl = DownstreamTlsContext::default().type_url();

// this works for the bootstrap config above, but real code wouldn't hardcode pulling // the value out in such a fragile way. let bootstraptlsconfig = bootstrap .staticresources .asref() .unwrap() .listeners[0] .filterchains[0] .transportsocket .asref() .unwrap() .configtype .asref() .unwrap(); // there are not other ConfigType enum variants, so this let works fine. let ConfigType::TypedConfig(tlsany) = bootstraptlsconfig; // because the TypedConfig is Any, we need to check the typeurl if &tlsany.typeurl == downstreamtlscontexttypeurl { let ctx = DownstreamTlsContext::decode(&*tlsany.value).unwrap(); // store or do something with the DownstreamTlsContext instance } else { panic!("unsupported typed config: {}", &tlsany.typeurl); } ```

Caveats

License

The code in this package is available under the Apache 2.0 license, as found in the LICENSE file. Envoy itself (and its API protos) are also licensed under Apache 2.0.