Select Git revision
protobuf_endpoint_converters.microgen.go
grpc.go 3.39 KiB
package auth
import (
"context"
kitgrpc "github.com/go-kit/kit/transport/grpc"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)
const (
OAuth2IdentityMetadata = "x-perxis-identity"
TLSIdentityMetadata = "x-forwarded-client-cert"
AccessMetadata = "x-perxis-access"
AuthorizationMetadata = "authorization"
)
func GRPCToContext(factory *PrincipalFactory) kitgrpc.ServerRequestFunc {
return func(ctx context.Context, md metadata.MD) context.Context {
if identity := md.Get(TLSIdentityMetadata); len(identity) > 0 {
return WithPrincipal(ctx, factory.Principal(identity[0]))
}
if identity := md.Get(OAuth2IdentityMetadata); len(identity) > 0 {
return WithPrincipal(ctx, factory.Principal(identity[0]))
}
if identity := md.Get(AuthorizationMetadata); len(identity) > 0 {
return WithPrincipal(ctx, factory.Principal(identity[0]))
}
if access := md.Get(AccessMetadata); len(access) > 0 {
return WithPrincipal(ctx, factory.System())
}
return WithPrincipal(ctx, factory.Anonymous())
}
}
func ContextToGRPC() kitgrpc.ClientRequestFunc {
return func(ctx context.Context, md *metadata.MD) context.Context {
p := GetPrincipal(ctx)
switch p := p.(type) {
case *UserPrincipal:
if p.GetIdentity(ctx) != "" {
(*md)[OAuth2IdentityMetadata] = []string{p.GetIdentity(ctx)}
}
case *ClientPrincipal:
if ident := p.GetIdentity(ctx); ident != nil {
switch {
case ident.OAuthClientID != "":
(*md)[OAuth2IdentityMetadata] = []string{ident.OAuthClientID + "@clients"}
case ident.TLSSubject != "":
(*md)[TLSIdentityMetadata] = []string{ident.TLSSubject}
case ident.APIKey != "":
(*md)[AuthorizationMetadata] = []string{"API-Key " + ident.APIKey}
}
}
case *SystemPrincipal:
(*md)[AccessMetadata] = []string{p.GetID(ctx)}
}
return ctx
}
}
// PrincipalServerInterceptor - grpc-интерсептор, который используется для получения данных принципала из grpc-метаданы и добавления в контекст ''. В случае, если
// сервис не использует проверку прав 'Principal' к системе, в параметрах передается пустой объект '&PrincipalFactory{}'
func PrincipalServerInterceptor(factory *PrincipalFactory) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
if md, ok := metadata.FromIncomingContext(ctx); ok {
ctx = GRPCToContext(factory)(ctx, md)
}
return handler(ctx, req)
}
}
// PrincipalClientInterceptor - grpc-интерсептор, который используется для получения данных принципала. В случае, если
// сервис не использует проверку прав 'Principal' к системе, в параметрах передается пустой объект '&PrincipalFactory{}'
func PrincipalClientInterceptor() grpc.UnaryClientInterceptor {
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
md, ok := metadata.FromOutgoingContext(ctx)
if !ok {
md = metadata.MD{}
}
ctx = metadata.NewOutgoingContext(ContextToGRPC()(ctx, &md), md)
return invoker(ctx, method, req, reply, cc, opts...)
}
}