Files
ionscale/internal/server/rpc.go
T
2022-06-03 14:25:31 +02:00

59 lines
1.6 KiB
Go

package server
import (
"context"
"fmt"
"github.com/bufbuild/connect-go"
"github.com/jsiebens/ionscale/internal/key"
"github.com/jsiebens/ionscale/internal/token"
apiconnect "github.com/jsiebens/ionscale/pkg/gen/ionscale/v1/ionscalev1connect"
"net/http"
"strings"
)
var (
errInvalidToken = connect.NewError(connect.CodeUnauthenticated, fmt.Errorf("invalid token"))
)
func NewRpcHandler(systemAdminKey key.ServerPrivate, handler apiconnect.IonscaleServiceHandler) (string, http.Handler) {
interceptors := connect.WithInterceptors(authenticationInterceptor(systemAdminKey))
return apiconnect.NewIonscaleServiceHandler(handler, interceptors)
}
func authenticationInterceptor(systemAdminKey key.ServerPrivate) connect.UnaryInterceptorFunc {
return func(next connect.UnaryFunc) connect.UnaryFunc {
return func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) {
name := req.Spec().Procedure
if strings.HasSuffix(name, "/GetVersion") {
return next(ctx, req)
}
authorizationHeader := req.Header().Get("Authorization")
valid := validateAuthorizationToken(systemAdminKey, authorizationHeader)
if valid {
return next(ctx, req)
}
return nil, errInvalidToken
}
}
}
func validateAuthorizationToken(systemAdminKey key.ServerPrivate, authorization string) bool {
if len(authorization) == 0 {
return false
}
bearerToken := strings.TrimPrefix(authorization, "Bearer ")
if token.IsSystemAdminToken(bearerToken) {
_, err := token.ParseSystemAdminToken(systemAdminKey, bearerToken)
return err == nil
}
return false
}