Documentation
¶
Overview ¶
Package guard provides security context management and guard registry for the MCP Gateway.
This package is responsible for managing security labels (DIFC - Decentralized Information Flow Control) and storing/retrieving agent identifiers in request contexts.
Relationship with internal/auth:
- internal/auth: Primary authentication logic (header parsing, validation) - internal/guard: Security context management (agent ID tracking, guard registry)
For authentication-related operations, always use the internal/auth package directly.
Example:
// Extract agent ID from auth header and store in context agentID := auth.ExtractAgentID(authHeader) ctx = guard.SetAgentIDInContext(ctx, agentID) // Retrieve agent ID from context agentID := guard.GetAgentIDFromContext(ctx) // Returns "default" if not found
Index ¶
- func GetAgentIDFromContext(ctx context.Context) string
- func GetRegisteredGuardTypes() []string
- func RegisterGuardType(name string, factory GuardFactory)
- func SetAgentIDInContext(ctx context.Context, agentID string) context.Context
- func SetRequestStateInContext(ctx context.Context, state RequestState) context.Context
- type AgentLabelsPayload
- type BackendCaller
- type ContextKey
- type Guard
- type GuardFactory
- type LabelAgentResult
- type NoopGuard
- func (g *NoopGuard) LabelAgent(ctx context.Context, policy interface{}, backend BackendCaller, ...) (*LabelAgentResult, error)
- func (g *NoopGuard) LabelResource(ctx context.Context, toolName string, args interface{}, backend BackendCaller, ...) (*difc.LabeledResource, difc.OperationType, error)
- func (g *NoopGuard) LabelResponse(ctx context.Context, toolName string, result interface{}, ...) (difc.LabeledData, error)
- func (g *NoopGuard) Name() string
- type Registry
- func (r *Registry) Get(serverID string) Guard
- func (r *Registry) GetGuardInfo() map[string]string
- func (r *Registry) Has(serverID string) bool
- func (r *Registry) HasNonNoopGuard() bool
- func (r *Registry) List() []string
- func (r *Registry) Register(serverID string, guard Guard)
- func (r *Registry) Remove(serverID string)
- type RequestState
- type WasmGuard
- func NewWasmGuard(ctx context.Context, name string, wasmPath string, backend BackendCaller) (*WasmGuard, error)
- func NewWasmGuardFromBytes(ctx context.Context, name string, wasmBytes []byte, backend BackendCaller) (*WasmGuard, error)
- func NewWasmGuardWithOptions(ctx context.Context, name string, wasmBytes []byte, backend BackendCaller, ...) (*WasmGuard, error)
- func (g *WasmGuard) Close(ctx context.Context) error
- func (g *WasmGuard) LabelAgent(ctx context.Context, policy interface{}, backend BackendCaller, ...) (*LabelAgentResult, error)
- func (g *WasmGuard) LabelResource(ctx context.Context, toolName string, args interface{}, backend BackendCaller, ...) (*difc.LabeledResource, difc.OperationType, error)
- func (g *WasmGuard) LabelResponse(ctx context.Context, toolName string, result interface{}, ...) (difc.LabeledData, error)
- func (g *WasmGuard) Name() string
- type WasmGuardOptions
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GetAgentIDFromContext ¶
GetAgentIDFromContext extracts the agent ID from the context Returns "default" if not found
func GetRegisteredGuardTypes ¶
func GetRegisteredGuardTypes() []string
GetRegisteredGuardTypes returns all registered guard type names
func RegisterGuardType ¶
func RegisterGuardType(name string, factory GuardFactory)
RegisterGuardType registers a guard type with a factory function This allows dynamic guard creation by name
func SetAgentIDInContext ¶
SetAgentIDInContext sets the agent ID in the context
func SetRequestStateInContext ¶
func SetRequestStateInContext(ctx context.Context, state RequestState) context.Context
SetRequestStateInContext stores guard request state in context
Types ¶
type AgentLabelsPayload ¶ added in v0.1.10
type AgentLabelsPayload struct {
Secrecy []string `json:"secrecy"`
Integrity []string `json:"integrity"`
}
AgentLabelsPayload holds effective secrecy/integrity labels for the session.
type BackendCaller ¶
type BackendCaller interface {
// CallTool makes a read-only call to the backend MCP server
// This is used by guards to gather metadata for labeling
CallTool(ctx context.Context, toolName string, args interface{}) (interface{}, error)
}
BackendCaller provides a way for guards to make read-only calls to the backend to gather information needed for labeling (e.g., fetching issue author)
type ContextKey ¶
type ContextKey string
ContextKey is used for storing values in context
const ( // AgentIDContextKey stores the agent ID in the request context AgentIDContextKey ContextKey = "difc-agent-id" // RequestStateContextKey stores guard-specific request state RequestStateContextKey ContextKey = "difc-request-state" )
type Guard ¶
type Guard interface {
// Name returns the identifier for this guard (e.g., "github", "noop")
Name() string
// LabelAgent initializes guard policy and returns effective agent/session state
// for the current session.
// Returns:
// - result: effective labels, mode, and normalized policy
// - error: any validation/initialization error
LabelAgent(ctx context.Context, policy interface{}, backend BackendCaller, caps *difc.Capabilities) (*LabelAgentResult, error)
// LabelResource determines the resource being accessed and its labels
// This may call the backend (via BackendCaller) to gather metadata needed for labeling
// Returns:
// - resource: The labeled resource (simple or nested structure for fine-grained filtering)
// - operation: The type of operation (Read, Write, or ReadWrite)
// - error: Any error that occurred during labeling
LabelResource(ctx context.Context, toolName string, args interface{}, backend BackendCaller, caps *difc.Capabilities) (*difc.LabeledResource, difc.OperationType, error)
// LabelResponse labels the response data after a successful backend call
// This is used for fine-grained filtering of collections
// Returns:
// - labeledData: The response data with per-item labels (if applicable)
// - error: Any error that occurred during labeling
// If the guard returns nil for labeledData, the reference monitor will use the
// resource labels from LabelResource for the entire response
LabelResponse(ctx context.Context, toolName string, result interface{}, backend BackendCaller, caps *difc.Capabilities) (difc.LabeledData, error)
}
Guard handles DIFC labeling for a specific MCP server Guards ONLY label resources - they do NOT make access control decisions The Reference Monitor (in the server) uses guard-provided labels to enforce DIFC policies
func CreateGuard ¶
CreateGuard creates a guard instance by name using registered factories
type GuardFactory ¶
GuardFactory is a function that creates a guard instance
type LabelAgentResult ¶ added in v0.1.10
type LabelAgentResult struct {
Agent AgentLabelsPayload `json:"agent"`
DIFCMode string `json:"difc_mode"`
NormalizedPolicy map[string]interface{} `json:"normalized_policy,omitempty"`
}
LabelAgentResult describes the effective policy/session state returned by a guard.
type NoopGuard ¶
type NoopGuard struct{}
NoopGuard is the default guard that performs no DIFC labeling It allows all operations by returning empty labels (no restrictions)
func (*NoopGuard) LabelAgent ¶ added in v0.1.10
func (g *NoopGuard) LabelAgent(ctx context.Context, policy interface{}, backend BackendCaller, caps *difc.Capabilities) (*LabelAgentResult, error)
LabelAgent initializes noop guard session state.
func (*NoopGuard) LabelResource ¶
func (g *NoopGuard) LabelResource(ctx context.Context, toolName string, args interface{}, backend BackendCaller, caps *difc.Capabilities) (*difc.LabeledResource, difc.OperationType, error)
LabelResource returns an empty resource with no label requirements Treats all operations as read-write (most conservative assumption)
func (*NoopGuard) LabelResponse ¶
func (g *NoopGuard) LabelResponse(ctx context.Context, toolName string, result interface{}, backend BackendCaller, caps *difc.Capabilities) (difc.LabeledData, error)
LabelResponse returns nil, indicating no fine-grained labeling The reference monitor will use the resource labels for the entire response
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry manages guard instances for different MCP servers
func (*Registry) GetGuardInfo ¶
GetGuardInfo returns information about all registered guards
func (*Registry) HasNonNoopGuard ¶ added in v0.1.12
HasNonNoopGuard returns true if any registered guard is not a noop guard
type RequestState ¶
type RequestState interface{}
RequestState represents any state that the guard needs to pass from request to response This is useful when the guard needs to carry information from LabelResource to LabelResponse
func GetRequestStateFromContext ¶
func GetRequestStateFromContext(ctx context.Context) RequestState
GetRequestStateFromContext retrieves guard request state from context
type WasmGuard ¶ added in v0.1.10
type WasmGuard struct {
// contains filtered or unexported fields
}
WasmGuard implements Guard interface by executing a WASM module in-process The WASM module runs sandboxed within the gateway using wazero runtime Guards cannot make direct network calls - they receive a BackendCaller interface via host functions
Thread Safety: WASM modules are single-threaded, so all calls to a guard instance are serialized using a mutex. Concurrent requests will queue and execute one at a time.
func NewWasmGuard ¶ added in v0.1.10
func NewWasmGuard(ctx context.Context, name string, wasmPath string, backend BackendCaller) (*WasmGuard, error)
NewWasmGuard creates a new WASM guard from a WASM binary file
func NewWasmGuardFromBytes ¶ added in v0.1.10
func NewWasmGuardFromBytes(ctx context.Context, name string, wasmBytes []byte, backend BackendCaller) (*WasmGuard, error)
NewWasmGuardFromBytes creates a new WASM guard from WASM binary bytes This is useful when loading guards from URLs or other sources
func NewWasmGuardWithOptions ¶ added in v0.1.10
func NewWasmGuardWithOptions(ctx context.Context, name string, wasmBytes []byte, backend BackendCaller, opts *WasmGuardOptions) (*WasmGuard, error)
NewWasmGuardWithOptions creates a new WASM guard from WASM binary bytes with custom options Options can be nil to use defaults (stdout/stderr go to os.Stdout/os.Stderr)
func (*WasmGuard) LabelAgent ¶ added in v0.1.10
func (g *WasmGuard) LabelAgent(ctx context.Context, policy interface{}, backend BackendCaller, caps *difc.Capabilities) (*LabelAgentResult, error)
LabelAgent calls the WASM module's label_agent function.
func (*WasmGuard) LabelResource ¶ added in v0.1.10
func (g *WasmGuard) LabelResource(ctx context.Context, toolName string, args interface{}, backend BackendCaller, caps *difc.Capabilities) (*difc.LabeledResource, difc.OperationType, error)
LabelResource calls the WASM module's label_resource function
func (*WasmGuard) LabelResponse ¶ added in v0.1.10
func (g *WasmGuard) LabelResponse(ctx context.Context, toolName string, result interface{}, backend BackendCaller, caps *difc.Capabilities) (difc.LabeledData, error)
LabelResponse calls the WASM module's label_response function
type WasmGuardOptions ¶ added in v0.1.10
type WasmGuardOptions struct {
// Stdout is the writer for WASM stdout output. Defaults to os.Stdout if nil.
Stdout io.Writer
// Stderr is the writer for WASM stderr output. Defaults to os.Stderr if nil.
Stderr io.Writer
}
WasmGuardOptions configures optional settings for WASM guard creation