Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 86d516acf6 |
@@ -206,7 +206,10 @@ func TokenInfoFromContext(ctx context.Context) *TokenInfo {
|
||||
}
|
||||
|
||||
// AuthInterceptor returns a gRPC unary server interceptor that validates
|
||||
// bearer tokens and requires the "admin" role.
|
||||
// bearer tokens. Any authenticated user or system account is accepted,
|
||||
// except guests which are explicitly rejected. Admin role is not required
|
||||
// for agent operations — it is reserved for MCIAS account management and
|
||||
// policy changes.
|
||||
func AuthInterceptor(validator TokenValidator) grpc.UnaryServerInterceptor {
|
||||
return func(
|
||||
ctx context.Context,
|
||||
@@ -240,9 +243,9 @@ func AuthInterceptor(validator TokenValidator) grpc.UnaryServerInterceptor {
|
||||
return nil, status.Error(codes.Unauthenticated, "invalid token")
|
||||
}
|
||||
|
||||
if !tokenInfo.HasRole("admin") {
|
||||
slog.Warn("permission denied", "method", info.FullMethod, "user", tokenInfo.Username)
|
||||
return nil, status.Error(codes.PermissionDenied, "admin role required")
|
||||
if tokenInfo.HasRole("guest") {
|
||||
slog.Warn("guest access denied", "method", info.FullMethod, "user", tokenInfo.Username)
|
||||
return nil, status.Error(codes.PermissionDenied, "guest access not permitted")
|
||||
}
|
||||
|
||||
slog.Info("rpc", "method", info.FullMethod, "user", tokenInfo.Username, "account_type", tokenInfo.AccountType)
|
||||
|
||||
@@ -126,7 +126,7 @@ func TestInterceptorRejectsInvalidToken(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestInterceptorRejectsNonAdmin(t *testing.T) {
|
||||
func TestInterceptorAcceptsRegularUser(t *testing.T) {
|
||||
server := mockMCIAS(t, func(authHeader string) (any, int) {
|
||||
return &TokenInfo{
|
||||
Valid: true,
|
||||
@@ -142,6 +142,28 @@ func TestInterceptorRejectsNonAdmin(t *testing.T) {
|
||||
md := metadata.Pairs("authorization", "Bearer user-token")
|
||||
ctx := metadata.NewIncomingContext(context.Background(), md)
|
||||
|
||||
_, err := callInterceptor(ctx, v)
|
||||
if err != nil {
|
||||
t.Fatalf("expected regular user to be accepted, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInterceptorRejectsGuest(t *testing.T) {
|
||||
server := mockMCIAS(t, func(authHeader string) (any, int) {
|
||||
return &TokenInfo{
|
||||
Valid: true,
|
||||
Username: "visitor",
|
||||
Roles: []string{"guest"},
|
||||
AccountType: "human",
|
||||
}, http.StatusOK
|
||||
})
|
||||
defer server.Close()
|
||||
|
||||
v := validatorFromServer(t, server)
|
||||
|
||||
md := metadata.Pairs("authorization", "Bearer guest-token")
|
||||
ctx := metadata.NewIncomingContext(context.Background(), md)
|
||||
|
||||
_, err := callInterceptor(ctx, v)
|
||||
if err == nil {
|
||||
t.Fatal("expected error, got nil")
|
||||
|
||||
Reference in New Issue
Block a user