2022-03-29 09:53:19 +00:00
|
|
|
package middleware
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
2022-04-21 10:37:39 +00:00
|
|
|
"strings"
|
2022-03-29 09:53:19 +00:00
|
|
|
|
|
|
|
"google.golang.org/grpc"
|
|
|
|
"google.golang.org/grpc/codes"
|
|
|
|
"google.golang.org/grpc/metadata"
|
|
|
|
"google.golang.org/grpc/status"
|
|
|
|
|
|
|
|
"github.com/caos/zitadel/internal/api/authz"
|
|
|
|
)
|
|
|
|
|
|
|
|
type InstanceVerifier interface {
|
|
|
|
GetInstance(ctx context.Context)
|
|
|
|
}
|
|
|
|
|
2022-04-21 10:37:39 +00:00
|
|
|
func InstanceInterceptor(verifier authz.InstanceVerifier, headerName string, ignoredServices ...string) grpc.UnaryServerInterceptor {
|
2022-03-29 09:53:19 +00:00
|
|
|
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
2022-04-21 10:37:39 +00:00
|
|
|
return setInstance(ctx, req, info, handler, verifier, headerName, ignoredServices...)
|
2022-03-29 09:53:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-21 10:37:39 +00:00
|
|
|
func setInstance(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler, verifier authz.InstanceVerifier, headerName string, ignoredServices ...string) (_ interface{}, err error) {
|
|
|
|
for _, service := range ignoredServices {
|
|
|
|
if strings.HasPrefix(info.FullMethod, service) {
|
|
|
|
return handler(ctx, req)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-29 09:53:19 +00:00
|
|
|
host, err := hostNameFromContext(ctx, headerName)
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Error(codes.PermissionDenied, err.Error())
|
|
|
|
}
|
|
|
|
instance, err := verifier.InstanceByHost(ctx, host)
|
|
|
|
if err != nil {
|
|
|
|
return nil, status.Error(codes.PermissionDenied, err.Error())
|
|
|
|
}
|
|
|
|
return handler(authz.WithInstance(ctx, instance), req)
|
|
|
|
}
|
|
|
|
|
|
|
|
func hostNameFromContext(ctx context.Context, headerName string) (string, error) {
|
|
|
|
md, ok := metadata.FromIncomingContext(ctx)
|
|
|
|
if !ok {
|
|
|
|
return "", fmt.Errorf("cannot read metadata")
|
|
|
|
}
|
|
|
|
host, ok := md[headerName]
|
|
|
|
if !ok {
|
|
|
|
return "", fmt.Errorf("cannot find header: %v", headerName)
|
|
|
|
}
|
|
|
|
if len(host) != 1 {
|
|
|
|
return "", fmt.Errorf("invalid host header: %v", host)
|
|
|
|
}
|
|
|
|
return host[0], nil
|
|
|
|
}
|