From 0af98dad59b1fa886e972333419111106fcaa0d2 Mon Sep 17 00:00:00 2001 From: Mrunal Patel Date: Thu, 22 Oct 2026 00:42:57 +0000 Subject: [PATCH] chore(server): remove unused server macros crate Signed-off-by: Mrunal Patel --- AGENTS.md | 1 - Cargo.lock | 9 - crates/openshell-core/src/lib.rs | 2 +- crates/openshell-server-macros/Cargo.toml | 18 -- crates/openshell-server-macros/src/lib.rs | 326 ---------------------- 5 files changed, 1 insertion(+), 355 deletions(-) delete mode 100644 crates/openshell-server-macros/Cargo.toml delete mode 100644 crates/openshell-server-macros/src/lib.rs diff --git a/AGENTS.md b/AGENTS.md index 434d235b4a..1235fe1183 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -53,7 +53,6 @@ Do not rely on this file for a full inventory. The detailed public and contribut | `crates/openshell-driver-mxc/` | Microsoft MXC compute driver | In-process Windows AppContainer and isolation-session compute backend | | `crates/openshell-prover/` | Policy prover | Policy verification and proof generation | | `crates/openshell-prover-cli/` | Policy prover CLI | Standalone local policy boundary checks | -| `crates/openshell-server-macros/` | Server macros | Compile-time helpers for gateway RPC authorization | | `crates/openshell-supervisor-middleware/` | Middleware runtime | Generic middleware registry, remote service integration, and chain execution | | `crates/openshell-supervisor-middleware-builtins/` | Built-in middleware | First-party in-process middleware implementations | | `crates/openshell-supervisor-network/` | Network supervisor | Proxying, L7 enforcement, policy evaluation, and provider credential injection | diff --git a/Cargo.lock b/Cargo.lock index 0a2fcb8c92..5f713c4e6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5080,15 +5080,6 @@ dependencies = [ "x509-parser 0.16.0", ] -[[package]] -name = "openshell-server-macros" -version = "0.0.0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "openshell-supervisor" version = "0.0.0" diff --git a/crates/openshell-core/src/lib.rs b/crates/openshell-core/src/lib.rs index 9e70b309c2..aa7613554d 100644 --- a/crates/openshell-core/src/lib.rs +++ b/crates/openshell-core/src/lib.rs @@ -100,7 +100,7 @@ mod build_version; /// /// Emitted by `build.rs` via `tonic_build::configure().file_descriptor_set_path(...)`. /// Used by tests in `openshell-server` to enumerate every RPC and verify that -/// each one has an `#[rpc_auth(...)]` declaration on its handler. +/// each one declares the `openshell.options.v1.authorization` proto option. pub const FILE_DESCRIPTOR_SET: &[u8] = include_bytes!(env!("OPENSHELL_DESCRIPTOR_PATH")); #[cfg(test)] diff --git a/crates/openshell-server-macros/Cargo.toml b/crates/openshell-server-macros/Cargo.toml deleted file mode 100644 index f929d43a6f..0000000000 --- a/crates/openshell-server-macros/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -[package] -name = "openshell-server-macros" -version.workspace = true -edition.workspace = true -rust-version.workspace = true -license.workspace = true -repository.workspace = true - -[lib] -proc-macro = true - -[dependencies] -proc-macro2 = "1" -quote = "1" -syn = { version = "2", features = ["full", "extra-traits"] } diff --git a/crates/openshell-server-macros/src/lib.rs b/crates/openshell-server-macros/src/lib.rs deleted file mode 100644 index 167ebb970b..0000000000 --- a/crates/openshell-server-macros/src/lib.rs +++ /dev/null @@ -1,326 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -//! Proc macros for declaring per-handler gRPC auth metadata. -//! -//! `#[rpc_authz(service = "...")]` is applied to a tonic service `impl` -//! block. Each method inside the impl carries an `#[rpc_auth(...)]` -//! attribute describing its auth mode, optional Bearer scope, and -//! required role. The macro emits a const `&[MethodAuth]` adjacent to -//! the impl and re-emits the impl block with the per-method -//! `#[rpc_auth]` attributes stripped so other macros (notably -//! `#[tonic::async_trait]`) see a clean impl. -//! -//! Generated code references `crate::auth::method_authz::{MethodAuth, -//! AuthMode, Role}`, so the macro is only intended for use inside the -//! `openshell-server` crate. - -use proc_macro::TokenStream; -use quote::quote; -use syn::parse::{Parse, ParseStream}; -use syn::{ - Error, Ident, ImplItem, ItemImpl, LitStr, Meta, Result, Token, parse_macro_input, - spanned::Spanned, -}; - -struct AuthzArgs { - service: LitStr, -} - -impl Parse for AuthzArgs { - fn parse(input: ParseStream<'_>) -> Result { - let key: Ident = input.parse()?; - if key != "service" { - return Err(Error::new( - key.span(), - "expected `service = \"\"`", - )); - } - let _eq: Token![=] = input.parse()?; - let service: LitStr = input.parse()?; - Ok(Self { service }) - } -} - -struct RpcAuth { - mode: AuthMode, - scope: Option, - role: Option, -} - -#[derive(Clone, Copy)] -enum AuthMode { - Unauthenticated, - Sandbox, - Bearer, - Dual, -} - -#[derive(Clone, Copy)] -enum RoleLit { - Admin, - User, -} - -impl RpcAuth { - fn parse(meta: &Meta) -> Result { - let span = meta.span(); - let list = match meta { - Meta::List(list) => list, - _ => { - return Err(Error::new( - span, - "expected `#[rpc_auth(auth = \"...\", scope = \"...\", role = \"...\")]`", - )); - } - }; - - let mut mode: Option = None; - let mut scope: Option = None; - let mut role: Option = None; - - list.parse_nested_meta(|m| { - let ident = m - .path - .get_ident() - .ok_or_else(|| m.error("expected `auth`, `scope`, or `role`"))?; - - if ident == "auth" { - if mode.is_some() { - return Err(m.error("`auth` specified more than once")); - } - let value: LitStr = m.value()?.parse()?; - mode = Some(parse_auth_mode(&value)?); - } else if ident == "scope" { - if scope.is_some() { - return Err(m.error("`scope` specified more than once")); - } - let value: LitStr = m.value()?.parse()?; - scope = Some(value); - } else if ident == "role" { - if role.is_some() { - return Err(m.error("`role` specified more than once")); - } - let value: LitStr = m.value()?.parse()?; - role = Some(parse_role(&value)?); - } else { - return Err(m.error("expected `auth`, `scope`, or `role`")); - } - Ok(()) - })?; - - let Some(mode) = mode else { - return Err(Error::new(span, "`#[rpc_auth]` requires `auth = \"...\"`")); - }; - - match mode { - AuthMode::Unauthenticated | AuthMode::Sandbox => { - if let Some(ref s) = scope { - return Err(Error::new( - s.span(), - "`scope` is only valid for `auth = \"bearer\"` or `auth = \"dual\"` (sandbox principals don't carry scopes)", - )); - } - if role.is_some() { - return Err(Error::new( - span, - "`role` is only valid for `auth = \"bearer\"` or `auth = \"dual\"`", - )); - } - } - AuthMode::Bearer | AuthMode::Dual => { - if scope.is_none() { - return Err(Error::new( - span, - "`auth = \"bearer\"` and `auth = \"dual\"` require `scope = \"...\"`", - )); - } - if role.is_none() { - return Err(Error::new( - span, - "`auth = \"bearer\"` and `auth = \"dual\"` require `role = \"...\"`", - )); - } - } - } - - Ok(Self { mode, scope, role }) - } -} - -fn parse_auth_mode(value: &LitStr) -> Result { - match value.value().as_str() { - "unauthenticated" => Ok(AuthMode::Unauthenticated), - "sandbox" => Ok(AuthMode::Sandbox), - "bearer" => Ok(AuthMode::Bearer), - "dual" => Ok(AuthMode::Dual), - other => Err(Error::new( - value.span(), - format!( - "invalid auth mode `{other}`; expected one of `unauthenticated`, `sandbox`, `bearer`, `dual`" - ), - )), - } -} - -fn parse_role(value: &LitStr) -> Result { - match value.value().as_str() { - "admin" => Ok(RoleLit::Admin), - "user" => Ok(RoleLit::User), - other => Err(Error::new( - value.span(), - format!("invalid role `{other}`; expected `admin` or `user`"), - )), - } -} - -/// Convert a Rust snake_case method identifier to the tonic PascalCase -/// gRPC method name (`list_sandboxes` → `ListSandboxes`). -fn snake_to_pascal(ident: &str) -> String { - let mut out = String::with_capacity(ident.len()); - let mut upper_next = true; - for c in ident.chars() { - if c == '_' { - upper_next = true; - continue; - } - if upper_next { - out.extend(c.to_uppercase()); - upper_next = false; - } else { - out.push(c); - } - } - out -} - -/// Name of the per-service const emitted alongside the impl block. The -/// service module is what disambiguates between services — every impl -/// lives in its own module (`crate::grpc::AUTH_METADATA`, -/// another service's `AUTH_METADATA`), so a fixed name reads more -/// naturally than `OPENSHELL_AUTH_METADATA` / `INFERENCE_AUTH_METADATA`. -const AUTH_METADATA_CONST: &str = "AUTH_METADATA"; - -fn trait_ident(item: &ItemImpl) -> Result { - let (_, path, _) = item.trait_.as_ref().ok_or_else(|| { - Error::new( - item.span(), - "`#[rpc_authz]` must be applied to a trait impl (`impl Trait for Type`)", - ) - })?; - path.segments - .last() - .map(|seg| seg.ident.clone()) - .ok_or_else(|| Error::new(path.span(), "could not determine trait identifier")) -} - -#[proc_macro_attribute] -pub fn rpc_authz(args: TokenStream, item: TokenStream) -> TokenStream { - let args = parse_macro_input!(args as AuthzArgs); - let mut item = parse_macro_input!(item as ItemImpl); - - match expand(&args, &mut item) { - Ok(tokens) => tokens.into(), - Err(err) => err.to_compile_error().into(), - } -} - -fn expand(args: &AuthzArgs, item: &mut ItemImpl) -> Result { - // `trait_ident` is still called for its validation side effect: the - // macro must be applied to a trait impl (`impl Trait for Type`). - let trait_ident = trait_ident(item)?; - let const_name = Ident::new(AUTH_METADATA_CONST, trait_ident.span()); - let service = args.service.value(); - - let mut entries: Vec = Vec::new(); - let mut seen_paths: Vec = Vec::new(); - - for impl_item in &mut item.items { - let ImplItem::Fn(method) = impl_item else { - continue; - }; - - let mut found: Option = None; - let mut kept = Vec::with_capacity(method.attrs.len()); - for attr in method.attrs.drain(..) { - if attr.path().is_ident("rpc_auth") { - if found.is_some() { - return Err(Error::new( - attr.span(), - "duplicate `#[rpc_auth]` on the same method", - )); - } - found = Some(attr.meta); - } else { - kept.push(attr); - } - } - method.attrs = kept; - - let Some(meta) = found else { - return Err(Error::new( - method.sig.ident.span(), - "method is missing `#[rpc_auth(...)]`; every RPC method must declare its auth metadata", - )); - }; - - let auth = RpcAuth::parse(&meta)?; - let method_path = format!( - "/{}/{}", - service, - snake_to_pascal(&method.sig.ident.to_string()) - ); - - if seen_paths.contains(&method_path) { - return Err(Error::new( - method.sig.ident.span(), - format!("duplicate gRPC method path `{method_path}`"), - )); - } - seen_paths.push(method_path.clone()); - - let mode_tokens = match auth.mode { - AuthMode::Unauthenticated => { - quote! { crate::auth::method_authz::AuthMode::Unauthenticated } - } - AuthMode::Sandbox => { - quote! { crate::auth::method_authz::AuthMode::Sandbox } - } - AuthMode::Bearer => quote! { crate::auth::method_authz::AuthMode::Bearer }, - AuthMode::Dual => quote! { crate::auth::method_authz::AuthMode::Dual }, - }; - - let scope_tokens = match &auth.scope { - Some(s) => quote! { ::core::option::Option::Some(#s) }, - None => quote! { ::core::option::Option::None }, - }; - - let role_tokens = match auth.role { - Some(RoleLit::Admin) => { - quote! { ::core::option::Option::Some(crate::auth::method_authz::Role::Admin) } - } - Some(RoleLit::User) => { - quote! { ::core::option::Option::Some(crate::auth::method_authz::Role::User) } - } - None => quote! { ::core::option::Option::None }, - }; - - entries.push(quote! { - crate::auth::method_authz::MethodAuth { - path: #method_path, - mode: #mode_tokens, - scope: #scope_tokens, - role: #role_tokens, - } - }); - } - - let entries_count = entries.len(); - let entries_array = quote! { [#(#entries),*] }; - - Ok(quote! { - pub const #const_name: &[crate::auth::method_authz::MethodAuth; #entries_count] = &#entries_array; - - #item - }) -}