diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-15 16:37:08 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-17 16:30:22 -0600 |
| commit | 45df4d0d9b577fecee798d672695fe24ff57fb1b (patch) | |
| tree | 1b99bf645035b58e0d6db08c7a83521f41f7a75b /vendor/github.com/authzed/grpcutil/middleware.go | |
| parent | f94f79608393d4ab127db63cc41668445ef6b243 (diff) | |
feat: migrate from Cedar to SpiceDB authorization system
This is a major architectural change that replaces the Cedar policy-based
authorization system with SpiceDB's relation-based authorization.
Key changes:
- Migrate from Rust to Go implementation
- Replace Cedar policies with SpiceDB schema and relationships
- Switch from envoy `ext_authz` with Cedar to SpiceDB permission checks
- Update build system and dependencies for Go ecosystem
- Maintain Envoy integration for external authorization
This change enables more flexible permission modeling through SpiceDB's
Google Zanzibar inspired relation-based system, supporting complex
hierarchical permissions that were difficult to express in Cedar.
Breaking change: Existing Cedar policies and Rust-based configuration
will no longer work and need to be migrated to SpiceDB schema.
Diffstat (limited to 'vendor/github.com/authzed/grpcutil/middleware.go')
| -rw-r--r-- | vendor/github.com/authzed/grpcutil/middleware.go | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/vendor/github.com/authzed/grpcutil/middleware.go b/vendor/github.com/authzed/grpcutil/middleware.go new file mode 100644 index 00000000..052367af --- /dev/null +++ b/vendor/github.com/authzed/grpcutil/middleware.go @@ -0,0 +1,118 @@ +package grpcutil + +import ( + "context" + "fmt" + "strings" + + grpcmw "github.com/grpc-ecosystem/go-grpc-middleware" + grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth" + grpcvalidate "github.com/grpc-ecosystem/go-grpc-middleware/validator" + "google.golang.org/grpc" + "google.golang.org/grpc/health" + healthpb "google.golang.org/grpc/health/grpc_health_v1" +) + +// IgnoreAuthMixin is a struct that can be embedded to make a gRPC handler +// ignore any auth requirements set by the gRPC community auth middleware. +type IgnoreAuthMixin struct{} + +var _ grpc_auth.ServiceAuthFuncOverride = (*IgnoreAuthMixin)(nil) + +// AuthFuncOverride implements the grpc_auth.ServiceAuthFuncOverride by +// performing a no-op. +func (m IgnoreAuthMixin) AuthFuncOverride(ctx context.Context, _ string) (context.Context, error) { + return ctx, nil +} + +// AuthlessHealthServer implements a gRPC health endpoint that will ignore any auth +// requirements set by github.com/grpc-ecosystem/go-grpc-middleware/auth. +type AuthlessHealthServer struct { + *health.Server + IgnoreAuthMixin +} + +// NewAuthlessHealthServer returns a new gRPC health server that ignores auth +// middleware. +func NewAuthlessHealthServer() *AuthlessHealthServer { + return &AuthlessHealthServer{Server: health.NewServer()} +} + +// SetServicesHealthy sets the service to SERVING +func (s *AuthlessHealthServer) SetServicesHealthy(svcDesc ...*grpc.ServiceDesc) { + for _, d := range svcDesc { + s.SetServingStatus( + d.ServiceName, + healthpb.HealthCheckResponse_SERVING, + ) + } +} + +// DefaultUnaryMiddleware is a recommended set of middleware that should each gracefully no-op if the middleware is not +// applicable. +var DefaultUnaryMiddleware = []grpc.UnaryServerInterceptor{grpcvalidate.UnaryServerInterceptor()} + +// WrapMethods wraps all non-streaming endpoints with the given list of interceptors. +// It returns a copy of the ServiceDesc with the new wrapped methods. +func WrapMethods(svcDesc grpc.ServiceDesc, interceptors ...grpc.UnaryServerInterceptor) (wrapped *grpc.ServiceDesc) { + chain := grpcmw.ChainUnaryServer(interceptors...) + for i, m := range svcDesc.Methods { + handler := m.Handler + wrapped := grpc.MethodDesc{ + MethodName: m.MethodName, + Handler: func(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + if interceptor == nil { + interceptor = NoopUnaryInterceptor + } + return handler(srv, ctx, dec, grpcmw.ChainUnaryServer(interceptor, chain)) + }, + } + svcDesc.Methods[i] = wrapped + } + return &svcDesc +} + +// WrapStreams wraps all streaming endpoints with the given list of interceptors. +// It returns a copy of the ServiceDesc with the new wrapped methods. +func WrapStreams(svcDesc grpc.ServiceDesc, interceptors ...grpc.StreamServerInterceptor) (wrapped *grpc.ServiceDesc) { + chain := grpcmw.ChainStreamServer(interceptors...) + for i, s := range svcDesc.Streams { + handler := s.Handler + info := &grpc.StreamServerInfo{ + FullMethod: fmt.Sprintf("/%s/%s", svcDesc.ServiceName, s.StreamName), + IsClientStream: s.ClientStreams, + IsServerStream: s.ServerStreams, + } + wrapped := grpc.StreamDesc{ + StreamName: s.StreamName, + ClientStreams: s.ClientStreams, + ServerStreams: s.ServerStreams, + Handler: func(srv interface{}, stream grpc.ServerStream) error { + return chain(srv, stream, info, handler) + }, + } + svcDesc.Streams[i] = wrapped + } + return &svcDesc +} + +// NoopUnaryInterceptor is a gRPC middleware that does not do anything. +func NoopUnaryInterceptor(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { + return handler(ctx, req) +} + +// SplitMethodName is used to split service name and method name from the +// method string passed into Interceptors. +// +// This function is vendored from: +// https://github.com/grpc-ecosystem/go-grpc-prometheus/blob/82c243799c991a7d5859215fba44a81834a52a71/util.go#L31-L37 +// +// Copyright 2016 Michal Witkowski. All Rights Reserved. +// Apache 2.0 Licensed +func SplitMethodName(fullMethodName string) (string, string) { + fullMethodName = strings.TrimPrefix(fullMethodName, "/") // remove leading slash + if i := strings.Index(fullMethodName, "/"); i >= 0 { + return fullMethodName[:i], fullMethodName[i+1:] + } + return "unknown", "unknown" +} |
