Skip to content

Commit f8fde7f

Browse files
committed
feat(gateway): add gRPC server reflection
Signed-off-by: Krzysztof Malczuk <kmalczuk@redhat.com>
1 parent 0a0a563 commit f8fde7f

8 files changed

Lines changed: 333 additions & 4 deletions

File tree

‎Cargo.lock‎

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ tokio = { version = "1.43", features = ["full"] }
1919
# gRPC/Protobuf
2020
tonic = "0.14"
2121
tonic-types = "0.14"
22+
tonic-reflection = "0.14"
2223
tonic-prost = "0.14"
2324
tonic-prost-build = "0.14"
2425
prost = "0.14"

‎README.md‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,23 @@ Docker-backed GPU sandboxes auto-select CDI when available and otherwise fall ba
183183

184184
See the [full documentation](https://docs.nvidia.com/openshell/latest) for command guides, tutorials, and reference material.
185185

186+
### Test the gRPC API with grpcurl
187+
188+
The gateway serves the gRPC reflection v1 protocol. After starting a local
189+
plaintext gateway, use `grpcurl` without checking out or supplying the proto
190+
files:
191+
192+
```shell
193+
grpcurl -plaintext localhost:18080 list
194+
grpcurl -plaintext localhost:18080 describe openshell.v1.OpenShell
195+
grpcurl -plaintext -d '{}' localhost:18080 openshell.v1.OpenShell/Health
196+
```
197+
198+
The service list contains the public `openshell.v1.OpenShell` API. Reflection
199+
does not advertise the gateway's internal compute-driver, credential-driver,
200+
interceptor, or middleware services. For a TLS gateway, omit `-plaintext` and
201+
supply the CA and client certificate options required by the deployment.
202+
186203
## Terminal UI
187204

188205
OpenShell includes a real-time terminal dashboard for monitoring gateways, sandboxes, and providers — inspired by [k9s](https://k9scli.io/).

‎architecture/gateway.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ Docker and Podman drivers. Operator-granted listener capabilities for external
106106
drivers are tracked in
107107
[#2539](https://github.com/NVIDIA/OpenShell/issues/2539).
108108

109+
The primary listener serves the gRPC reflection v1 protocol without application
110+
authentication. It advertises only the public `openshell.v1.OpenShell` service.
111+
TLS and client-certificate requirements still apply at the transport layer.
112+
Callback-only listeners reject reflection before authentication.
113+
109114
Operators can configure a gateway-wide gRPC request rate limit. The limit is
110115
applied only to gRPC API traffic after protocol multiplexing; health, metrics,
111116
and local sandbox-service HTTP routes are not rate limited by this control.

‎crates/openshell-server/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ libc = "0.2"
3939

4040
# gRPC
4141
tonic = { workspace = true, features = ["channel", "tls-native-roots"] }
42+
tonic-reflection = { workspace = true }
4243
prost = { workspace = true }
4344
prost-reflect = { workspace = true }
4445
prost-types = { workspace = true }

‎crates/openshell-server/src/auth/oidc.rs‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ use tracing::{debug, error, info, warn};
3232
/// These are structural bypasses for gRPC infrastructure that doesn't map to a
3333
/// single RPC method. Per-method bypasses (e.g. `Health`) are declared at the
3434
/// handler with `auth_mode: "unauthenticated"` in the proto annotation.
35-
const UNAUTHENTICATED_PREFIXES: &[&str] = &["/grpc.reflection.", "/grpc.health."];
35+
const UNAUTHENTICATED_PREFIXES: &[&str] =
36+
&[crate::multiplex::REFLECTION_PATH_PREFIX, "/grpc.health."];
3637

3738
/// Returns `true` if the method needs no authentication at all.
3839
pub fn is_unauthenticated_method(path: &str) -> bool {
@@ -1209,10 +1210,13 @@ mod tests {
12091210
#[test]
12101211
fn reflection_is_unauthenticated() {
12111212
assert!(is_unauthenticated_method(
1213+
"/grpc.reflection.v1.ServerReflection/ServerReflectionInfo"
1214+
));
1215+
assert!(!is_unauthenticated_method(
12121216
"/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo"
12131217
));
1214-
assert!(is_unauthenticated_method(
1215-
"/grpc.reflection.v1.ServerReflection/ServerReflectionInfo"
1218+
assert!(!is_unauthenticated_method(
1219+
"/grpc.reflection.v2.ServerReflection/ServerReflectionInfo"
12161220
));
12171221
}
12181222

0 commit comments

Comments
 (0)