Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ tokio = { version = "1.43", features = ["full"] }

# gRPC/Protobuf
tonic = "0.14"
tonic-reflection = "0.14"
tonic-prost = "0.14"
tonic-prost-build = "0.14"
prost = "0.14"
Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,24 @@ Docker-backed GPU sandboxes auto-select CDI when available and otherwise fall ba

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

### Test the gRPC API with grpcurl

The gateway serves the gRPC reflection v1 protocol. After starting a local
plaintext gateway, use `grpcurl` without checking out or supplying the proto
files:

```shell
grpcurl -plaintext localhost:18080 list
grpcurl -plaintext localhost:18080 describe openshell.v1.OpenShell
grpcurl -plaintext -d '{}' localhost:18080 openshell.v1.OpenShell/Health
```

The service list contains the public `openshell.v1.OpenShell` and
`openshell.inference.v1.Inference` APIs. Reflection does not advertise the
gateway's internal compute-driver, credential-driver, interceptor, or
middleware services. For a TLS gateway, omit `-plaintext` and supply the CA and
client certificate options required by the deployment.

## Terminal UI

OpenShell includes a real-time terminal dashboard for monitoring gateways, sandboxes, and providers — inspired by [k9s](https://k9scli.io/).
Expand Down
6 changes: 6 additions & 0 deletions architecture/gateway.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ Docker and Podman drivers. Operator-granted listener capabilities for external
drivers are tracked in
[#2539](https://github.com/NVIDIA/OpenShell/issues/2539).

The primary listener serves the gRPC reflection v1 protocol without application
authentication. It advertises only the public `openshell.v1.OpenShell` and
`openshell.inference.v1.Inference` services. TLS and client-certificate
requirements still apply at the transport layer. Callback-only listeners reject
reflection before authentication.

Operators can configure a gateway-wide gRPC request rate limit. The limit is
applied only to gRPC API traffic after protocol multiplexing; health, metrics,
and local sandbox-service HTTP routes are not rate limited by this control.
Expand Down
1 change: 1 addition & 0 deletions crates/openshell-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ nix = { workspace = true }

# gRPC
tonic = { workspace = true, features = ["channel", "tls-native-roots"] }
tonic-reflection = { workspace = true }
prost = { workspace = true }
prost-reflect = { workspace = true }
prost-types = { workspace = true }
Expand Down
10 changes: 7 additions & 3 deletions crates/openshell-server/src/auth/oidc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ use tracing::{debug, info, warn};
/// These are structural bypasses for gRPC infrastructure that doesn't map to a
/// single RPC method. Per-method bypasses (e.g. `Health`) are declared at the
/// handler with `auth_mode: "unauthenticated"` in the proto annotation.
const UNAUTHENTICATED_PREFIXES: &[&str] = &["/grpc.reflection.", "/grpc.health."];
const UNAUTHENTICATED_PREFIXES: &[&str] =
&[crate::multiplex::REFLECTION_PATH_PREFIX, "/grpc.health."];

/// Returns `true` if the method needs no authentication at all.
pub fn is_unauthenticated_method(path: &str) -> bool {
Expand Down Expand Up @@ -407,10 +408,13 @@ mod tests {
#[test]
fn reflection_is_unauthenticated() {
assert!(is_unauthenticated_method(
"/grpc.reflection.v1.ServerReflection/ServerReflectionInfo"
));
assert!(!is_unauthenticated_method(
"/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo"
));
assert!(is_unauthenticated_method(
"/grpc.reflection.v1.ServerReflection/ServerReflectionInfo"
assert!(!is_unauthenticated_method(
"/grpc.reflection.v2.ServerReflection/ServerReflectionInfo"
));
}

Expand Down
Loading
Loading