Checkpoint: auth, engine, seal, server, grpc updates
Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
@@ -2,6 +2,7 @@ package grpcserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
@@ -25,7 +26,7 @@ func tokenInfoFromContext(ctx context.Context) *auth.TokenInfo {
|
||||
// authInterceptor validates the Bearer token from gRPC metadata and injects
|
||||
// *auth.TokenInfo into the context. The set of method full names that require
|
||||
// auth is passed in; all others pass through without validation.
|
||||
func authInterceptor(authenticator *auth.Authenticator, methods map[string]bool) grpc.UnaryServerInterceptor {
|
||||
func authInterceptor(authenticator *auth.Authenticator, logger *slog.Logger, methods map[string]bool) grpc.UnaryServerInterceptor {
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
if !methods[info.FullMethod] {
|
||||
return handler(ctx, req)
|
||||
@@ -33,14 +34,17 @@ func authInterceptor(authenticator *auth.Authenticator, methods map[string]bool)
|
||||
|
||||
token := extractToken(ctx)
|
||||
if token == "" {
|
||||
logger.Debug("grpc request rejected: missing token", "method", info.FullMethod)
|
||||
return nil, status.Error(codes.Unauthenticated, "missing authorization token")
|
||||
}
|
||||
|
||||
tokenInfo, err := authenticator.ValidateToken(token)
|
||||
if err != nil {
|
||||
logger.Debug("grpc request rejected: invalid token", "method", info.FullMethod, "error", err)
|
||||
return nil, status.Error(codes.Unauthenticated, "invalid token")
|
||||
}
|
||||
|
||||
logger.Debug("grpc request authenticated", "method", info.FullMethod, "username", tokenInfo.Username)
|
||||
ctx = context.WithValue(ctx, tokenInfoKey, tokenInfo)
|
||||
return handler(ctx, req)
|
||||
}
|
||||
@@ -48,27 +52,30 @@ func authInterceptor(authenticator *auth.Authenticator, methods map[string]bool)
|
||||
|
||||
// adminInterceptor requires IsAdmin on the token info for the listed methods.
|
||||
// Must run after authInterceptor.
|
||||
func adminInterceptor(methods map[string]bool) grpc.UnaryServerInterceptor {
|
||||
func adminInterceptor(logger *slog.Logger, methods map[string]bool) grpc.UnaryServerInterceptor {
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
if !methods[info.FullMethod] {
|
||||
return handler(ctx, req)
|
||||
}
|
||||
ti := tokenInfoFromContext(ctx)
|
||||
if ti == nil || !ti.IsAdmin {
|
||||
logger.Debug("grpc request rejected: admin required", "method", info.FullMethod)
|
||||
return nil, status.Error(codes.PermissionDenied, "admin required")
|
||||
}
|
||||
logger.Debug("grpc admin request authorized", "method", info.FullMethod, "username", ti.Username)
|
||||
return handler(ctx, req)
|
||||
}
|
||||
}
|
||||
|
||||
// sealInterceptor rejects calls with FailedPrecondition when the vault is
|
||||
// sealed, for the listed methods.
|
||||
func sealInterceptor(sealMgr *seal.Manager, methods map[string]bool) grpc.UnaryServerInterceptor {
|
||||
func sealInterceptor(sealMgr *seal.Manager, logger *slog.Logger, methods map[string]bool) grpc.UnaryServerInterceptor {
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
if !methods[info.FullMethod] {
|
||||
return handler(ctx, req)
|
||||
}
|
||||
if sealMgr.State() != seal.StateUnsealed {
|
||||
logger.Debug("grpc request rejected: vault sealed", "method", info.FullMethod)
|
||||
return nil, status.Error(codes.FailedPrecondition, "vault is sealed")
|
||||
}
|
||||
return handler(ctx, req)
|
||||
|
||||
@@ -66,9 +66,9 @@ func (s *GRPCServer) Start() error {
|
||||
creds := credentials.NewTLS(tlsCfg)
|
||||
|
||||
interceptor := chainInterceptors(
|
||||
sealInterceptor(s.sealMgr, sealRequiredMethods()),
|
||||
authInterceptor(s.auth, authRequiredMethods()),
|
||||
adminInterceptor(adminRequiredMethods()),
|
||||
sealInterceptor(s.sealMgr, s.logger, sealRequiredMethods()),
|
||||
authInterceptor(s.auth, s.logger, authRequiredMethods()),
|
||||
adminInterceptor(s.logger, adminRequiredMethods()),
|
||||
)
|
||||
|
||||
s.srv = grpc.NewServer(
|
||||
|
||||
Reference in New Issue
Block a user