feat: improve instance not found error (#7413)

* feat: improve instance not found error

* unit tests

* check if is templatable

* lint

* assert

* compile tests

* remove error templates

* link to instance not found page

* fmt

* cleanup

* lint
This commit is contained in:
Elio Bischof
2024-02-28 11:49:57 +01:00
committed by GitHub
parent 062d153cfe
commit f4c72cbe14
22 changed files with 55 additions and 38 deletions

View File

@@ -14,6 +14,7 @@ import (
"google.golang.org/grpc/status"
"github.com/zitadel/zitadel/internal/api/authz"
zitadel_http "github.com/zitadel/zitadel/internal/api/http"
"github.com/zitadel/zitadel/internal/i18n"
"github.com/zitadel/zitadel/internal/telemetry/tracing"
"github.com/zitadel/zitadel/internal/zerrors"
@@ -23,15 +24,15 @@ const (
HTTP1Host = "x-zitadel-http1-host"
)
func InstanceInterceptor(verifier authz.InstanceVerifier, headerName string, explicitInstanceIdServices ...string) grpc.UnaryServerInterceptor {
func InstanceInterceptor(verifier authz.InstanceVerifier, headerName, externalDomain string, explicitInstanceIdServices ...string) grpc.UnaryServerInterceptor {
translator, err := i18n.NewZitadelTranslator(language.English)
logging.OnError(err).Panic("unable to get translator")
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
return setInstance(ctx, req, info, handler, verifier, headerName, translator, explicitInstanceIdServices...)
return setInstance(ctx, req, info, handler, verifier, headerName, externalDomain, translator, explicitInstanceIdServices...)
}
}
func setInstance(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler, verifier authz.InstanceVerifier, headerName string, translator *i18n.Translator, idFromRequestsServices ...string) (_ interface{}, err error) {
func setInstance(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler, verifier authz.InstanceVerifier, headerName, externalDomain string, translator *i18n.Translator, idFromRequestsServices ...string) (_ interface{}, err error) {
interceptorCtx, span := tracing.NewServerInterceptorSpan(ctx)
defer func() { span.EndWithError(err) }()
for _, service := range idFromRequestsServices {
@@ -55,16 +56,18 @@ func setInstance(ctx context.Context, req interface{}, info *grpc.UnaryServerInf
return handler(authz.WithInstance(ctx, instance), req)
}
}
host, err := hostFromContext(interceptorCtx, headerName)
if err != nil {
return nil, status.Error(codes.NotFound, err.Error())
}
instance, err := verifier.InstanceByHost(interceptorCtx, host)
if err != nil {
notFoundErr := new(zerrors.NotFoundError)
if errors.As(err, &notFoundErr) {
notFoundErr.Message = translator.LocalizeFromCtx(ctx, notFoundErr.GetMessage(), nil)
err = fmt.Errorf("unable to set instance using origin %s (ExternalDomain is %s): %w", zitadel_http.ComposedOrigin(ctx), externalDomain, err)
zErr := new(zerrors.ZitadelError)
if errors.As(err, &zErr) {
zErr.SetMessage(translator.LocalizeFromCtx(ctx, zErr.GetMessage(), nil))
zErr.Parent = err
err = zErr
}
return nil, status.Error(codes.NotFound, err.Error())
}

View File

@@ -137,7 +137,7 @@ func Test_setInstance(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := setInstance(tt.args.ctx, tt.args.req, tt.args.info, tt.args.handler, tt.args.verifier, tt.args.headerName, nil)
got, err := setInstance(tt.args.ctx, tt.args.req, tt.args.info, tt.args.handler, tt.args.verifier, tt.args.headerName, "", nil)
if (err != nil) != tt.res.err {
t.Errorf("setInstance() error = %v, wantErr %v", err, tt.res.err)
return

View File

@@ -39,6 +39,7 @@ func CreateServer(
authConfig authz.Config,
queries *query.Queries,
hostHeaderName string,
externalDomain string,
tlsConfig *tls.Config,
accessSvc *logstore.Service[*record.AccessLog],
) *grpc.Server {
@@ -50,7 +51,7 @@ func CreateServer(
middleware.DefaultTracingServer(),
middleware.MetricsHandler(metricTypes, grpc_api.Probes...),
middleware.NoCacheInterceptor(),
middleware.InstanceInterceptor(queries, hostHeaderName, system_pb.SystemService_ServiceDesc.ServiceName, healthpb.Health_ServiceDesc.ServiceName),
middleware.InstanceInterceptor(queries, hostHeaderName, externalDomain, system_pb.SystemService_ServiceDesc.ServiceName, healthpb.Health_ServiceDesc.ServiceName),
middleware.AccessStorageInterceptor(accessSvc),
middleware.ErrorHandler(),
middleware.LimitsInterceptor(system_pb.SystemService_ServiceDesc.ServiceName),