* feat(providers): report bounded token-grant failures
Signed-off-by: Shiju <shiju@nvidia.com>
* test(providers): align policy metadata and TLS lockfile
Signed-off-by: Shiju <shiju@nvidia.com>
* test(providers): fix trusted grant recovery fixture
Signed-off-by: Shiju <shiju@nvidia.com>
* test(providers): enable denial API in recovery fixture
Signed-off-by: Shiju <shiju@nvidia.com>
* refactor(providers): simplify token-grant failure reporting
Remove duplication and dead paths from the token-grant failure
reporting without changing classification, the workload-visible
502 response, or the wire format.
- Build the gRPC failure envelope with tonic-types, store the typed
failure in EndpointFailure, and share one request-ID rule and one
endpoint-status authority check.
- Merge the gateway exchange client wrapper, drop forwarding
validators, and name the request field when a reported cause is
rejected.
- Inject fallback credentials only from live provider state and
delete the unread per-connection credential copy. Keep one 502
writer per path and restore the base token-cache handling.
- Check the token endpoint after the cache lookup, still before any
credential acquisition.
- Document 429 and 5xx classification as implemented, and drop tests
that repeat retained assertions through the same code path.
Signed-off-by: Shiju <shiju@nvidia.com>
* refactor(providers): trim token-grant failure tests and supervisor API
Cut the token-grant failure tests to one test per distinct behavior
across core, gateway, supervisor, CLI and Go, and replace the 794-line
closure E2E with status assertions in the existing route-recovery E2E:
the refused grant appears in sandbox status with the response's
request ID, code, stage and upstream status, and the matching grant's
later success clears it.
- Pin the live provider snapshot with one helper used by inspected and
fallback forwarding, and inject selector-matched grants through
inject_for_selectors, which borrows the pinned context. Move the
test-only wrapper into test_support.
- Drop the 35-second wrappers around the gateway grant RPC. The shared
channel bounds the connection attempt and the gateway bounds its
token-service calls.
- Log the token service's OAuth error and error_description, without
control characters and limited to 256 characters each, with the
request ID in the gateway or supervisor log. Status and the workload
response still carry only the bounded cause.
- Keep one check that an untrusted token-service certificate cannot
assert a cause.
Signed-off-by: Shiju <shiju@nvidia.com>
* fix(providers): restore test import and features lockfile
The injection tests named EndpointObservationSender through the parent
module, which no longer imports it. The features suite lockfile kept the
tonic TLS dependency that the removed E2E fixture added.
Signed-off-by: Shiju <shiju@nvidia.com>
* test(providers): fix body-bound fixture width and table type
Pass the response-size width as a named argument; an implicitly captured
constant panics at runtime. Name the mutation type in the validation
table for Clippy.
Signed-off-by: Shiju <shiju@nvidia.com>
* test(providers): pad exact-bound body without a format width
MAX_TOKEN_RESPONSE_BYTES exceeds u16::MAX, the largest format width, so
the padded fixture panicked. Pad with repeat_n as before.
Signed-off-by: Shiju <shiju@nvidia.com>
* test(server): update public RPC schema hash after rebase
Main added the ListProvidersRequest label selector. The merged public
schema hash comes from the Branch Checks storage_proto test output.
Signed-off-by: Shiju <shiju@nvidia.com>
* fix(providers): keep token-service error text out of grant logs
A token service can echo a submitted credential in its OAuth error or
error_description. Log only the classified failure code, HTTP status and
request ID, and cover the canary echo in a dedicated test binary.
Signed-off-by: Shiju <shiju@nvidia.com>
* docs(providers): tighten token grant failure documentation
Signed-off-by: Shiju <shiju@nvidia.com>
* docs(providers): condense token grant failure guidance
Signed-off-by: John Myers <9696606+johntmyers@users.noreply.github.com>
---------
Signed-off-by: Shiju <shiju@nvidia.com>
Signed-off-by: John Myers <9696606+johntmyers@users.noreply.github.com>
Co-authored-by: John Myers <9696606+johntmyers@users.noreply.github.com>
The core, server, and sandbox-backend build scripts always used the vendored protoc binary and ignored PROTOC, so a distro build could not use its system compiler. When PROTOC is set, use it and let prost resolve the includes (PROTOC_INCLUDE still applies); otherwise behave exactly as before. Contributes to #3510.
Signed-off-by: politerealism <burdcat17@gmail.com>
Establish the Phase 1 reference implementation proposed by RFC 0012
while retaining the existing Cargo and Mise workflows during evaluation.
- pin Bazel 9.1.1 and configure Bzlmod, rules_rs, LLVM, protobuf, and
Rust 1.95 toolchains
- import third-party crates from Cargo metadata and propagate the
workspace version into Bazel targets
- add library, binary, proc-macro, unit-test, and integration-test
targets across the supported Rust workspace crates and drivers
- generate protobuf Rust sources and descriptor sets under Bazel while
preserving Cargo-compatible generated-code imports
- annotate aws-lc-sys and zstd-sys native dependencies, build Z3 4.15.2
from source, and generate z3-sys bindings
- make CLI and procfs test fixtures available as explicit Bazel inputs
without relying on fixed host binary paths
- define optimized release targets for Linux x86_64 and aarch64 CLI,
sandbox, and gateway binaries, plus macOS aarch64 artifacts
- add Bazel, buildifier, and lcov to the Nix development environment
RFC: 0012 (rfc12 branch)
Refs: #2491
Signed-off-by: Simon Scatton <sscatton@nvidia.com>
* feat(providers): support SPIFFE-backed token grants
Add provider profile token_grant metadata and expand endpoint-specific
dynamic credentials so sandbox supervisors can request SPIFFE JWT-SVIDs,
exchange them with an OAuth-style token endpoint, cache returned access
tokens, and inject bearer tokens into matching HTTP requests.
Wire Kubernetes and Helm deployments to mount the provider SPIFFE Workload
API socket into sandbox pods for token grant exchange.
Signed-off-by: Taylor Mutch <taylormutch@gmail.com>
Signed-off-by: Gordon Sim <gsim@redhat.com>
* test(examples): add SPIFFE token grant demo
Add a reusable alpha/beta demo that deploys a SPIFFE-verifying token issuer
and protected services, imports a token-grant provider profile, creates a
sandbox, and verifies endpoint-specific bearer tokens.
The script leaves Kubernetes workloads in place, deletes sandboxes through
openshell unless KEEP_SANDBOX=1, and prints protected service logs as proof
of life.
Signed-off-by: Taylor Mutch <taylormutch@gmail.com>
* fix(providers): harden SPIFFE token grants
* fix(providers): harden dynamic token grants
Signed-off-by: Taylor Mutch <taylormutch@gmail.com>
* fix(providers): harden token grant handling
---------
Signed-off-by: Taylor Mutch <taylormutch@gmail.com>
Signed-off-by: Gordon Sim <gsim@redhat.com>
* feat(server): per-handler gRPC auth annotations
Move scope, role, and auth-mode metadata to the handler definition site
via #[rpc_authz] + #[rpc_auth] proc macros. The previously hand-maintained
SCOPED_METHODS, ADMIN_METHODS, UNAUTHENTICATED_METHODS, and
ALLOWED_SANDBOX_METHODS tables are now generated from per-method
annotations on the tonic service impls, with canonical gRPC paths
derived from the service name and method name.
Adds a new openshell-server-macros proc-macro crate, an aggregator in
auth/method_authz.rs, and an exhaustiveness test that decodes the
protobuf FileDescriptorSet (now emitted by openshell-core/build.rs) and
verifies every RPC has an annotation.
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
* refactor(server): rename `sandbox-secret` auth mode to `sandbox`
PR #1404 replaced the shared sandbox secret with per-sandbox
gateway-minted JWTs. A handler marked `sandbox` now authenticates as a
specific `Principal::Sandbox`, not as a holder of a shared credential.
Rename `auth = "sandbox-secret"` to `auth = "sandbox"` and
`AuthMode::SandboxSecret` to `AuthMode::Sandbox` so the name matches
the post-#1404 identity model.
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
* fix(server): enforce per-handler AuthMode at the router
Addresses review feedback on the per-handler auth-annotation work.
- Router-level enforcement of #[rpc_auth] auth mode (HIGH). The previous
router only checked is_sandbox_callable() for Principal::Sandbox; user
principals still flowed into AuthzPolicy::check() and bypassed the
per-handler declaration. A user with `openshell:all` could therefore
reach `sandbox`-only handlers like GetSandboxProviderEnvironment,
ReportPolicyStatus, PushSandboxLogs, and SubmitPolicyAnalysis even
though their annotations said sandbox-only. Adds an
is_user_callable() predicate and rejects User principals at the
router for `sandbox` / `unauthenticated` methods.
- Proc macro now errors on duplicate keys in #[rpc_auth(...)] (LOW). A
second `auth`, `scope`, or `role` previously silently overwrote the
first value; now it fails to compile.
- Regression tests: a unit test for is_user_callable() and a router
test that proves a user with admin role + openshell:all cannot reach
the nine sandbox-only handlers.
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
* docs(server): finish renaming sandbox-secret to sandbox in method_authz doc comments
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
* refactor(server-macros): drop standalone `rpc_auth` stub
The stub was a safety net that fired only when a method had
`#[rpc_auth(...)]` without an enclosing `#[rpc_authz]`. Triggering it
required `rpc_auth` to be imported, which is why both call sites carried
`#[allow(unused_imports)] use openshell_server_macros::{rpc_auth, rpc_authz};`.
Drop the stub and the unused-import workaround. A missing `#[rpc_authz]`
now surfaces as rustc's standard "cannot find attribute `rpc_auth` in
this scope" — clear enough, and one fewer import + lint exception.
Addresses review comment on PR #1596.
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
* refactor(server-macros): emit fixed `AUTH_METADATA` const per service
The previous trait-derived const name turned `OpenShell` into
`OPEN_SHELL_AUTH_METADATA`, splitting the project name across an
underscore. Each impl already lives in its own module
(`crate::grpc::`, `crate::inference::`), so the module path is enough
to disambiguate between services — a fixed `AUTH_METADATA` name reads
more naturally.
Aggregator in `auth/method_authz.rs` now references
`crate::grpc::AUTH_METADATA` and `crate::inference::AUTH_METADATA`
directly.
Addresses review comment on PR #1596.
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
* docs(server-macros): fix typo in AUTH_METADATA_CONST doc comment
OpenShell is one word; reference name in the doc should be
OPENSHELL_AUTH_METADATA, not OPEN_SHELL_AUTH_METADATA.
Addresses review nit on PR #1596.
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
---------
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
Walk ../../proto recursively instead of maintaining a hard-coded list. Sort paths for deterministic codegen and keep cargo:rerun-if-changed scoped to the proto tree.
Signed-off-by: ddurst <267424412+ddurst-nvidia@users.noreply.github.com>
`git describe --tags --long --match "v*"` matches the `vm-dev` tag
alongside release tags. When `vm-dev` sits on or past the latest
release tag in the commit graph (currently the case on main), git
picks it, and the resulting `vm-dev-N-gSHA` string strips the leading
`v` down to `m-dev-N-gSHA`. With `commits == 0` that's returned
verbatim, producing a binary that reports itself as `m-dev`:
$ openshell --version
openshell m-dev
Confirmed on v0.0.28 (#832) and reproduced on v0.0.29 as well.
Restrict the glob to numeric release tags (`v[0-9]*`). All release
tags follow `v\d+\.\d+\.\d+`, so this loses no valid version — it
only filters out `vm-dev`, `vm-prod`, and any similar non-release
tags that share the `v` prefix.
Verified locally on this repo's current HEAD:
# before
$ git describe --tags --long --match 'v*'
vm-dev-0-g355d845
# after
$ git describe --tags --long --match 'v[0-9]*'
v0.0.29-2-g355d845
Closes#832
Signed-off-by: mjamiv <michael.commack@gmail.com>
Compute version strings from git describe in openshell-core's build.rs
using the guess-next-dev scheme (e.g. 0.0.4-dev.6+g2bf9969). All binary
crates and the TUI splash screen now use the shared openshell_core::VERSION
constant instead of CARGO_PKG_VERSION.
In Docker/CI builds where .git is absent, falls back to CARGO_PKG_VERSION
which is already set correctly by the sed-patch pipeline. Also adds
OPENSHELL_CARGO_VERSION support to the cluster image and fast-deploy
supervisor builds for parity with the gateway.