feat: system api requires authenticated requests (#3570)

* begin auth

* feat: system api requires authenticated requests

* fix tests
This commit is contained in:
Livio Amstutz 2022-05-30 13:38:30 +02:00 committed by GitHub
parent 41d78ef523
commit 2fc39c0da0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 179 additions and 50 deletions

View File

@ -16,14 +16,6 @@ RUN go mod download
COPY tools ./tools COPY tools ./tools
RUN ./tools/install.sh RUN ./tools/install.sh
ARG COCKROACH_BINARY=cockroach
RUN apt install openssl tzdata tar
# cockroach binary used to backup database
RUN mkdir /usr/local/lib/cockroach
RUN wget -qO- https://binaries.cockroachdb.com/cockroach-v21.2.9.linux-amd64.tgz \
| tar xvz && cp -i cockroach-v21.2.9.linux-amd64/cockroach /usr/local/bin/
RUN rm -r cockroach-v21.2.9.linux-amd64
####################### #######################
## generates static files ## generates static files
@ -92,6 +84,15 @@ COPY --from=go-stub /go/src/github.com/zitadel/zitadel/internal/api/assets/route
####################### #######################
FROM go-base as go-test FROM go-base as go-test
ARG COCKROACH_BINARY=cockroach
RUN apt install openssl tzdata tar
# cockroach binary used to backup database
RUN mkdir /usr/local/lib/cockroach
RUN wget -qO- https://binaries.cockroachdb.com/cockroach-v21.2.9.linux-amd64.tgz \
| tar xvz && cp -i cockroach-v21.2.9.linux-amd64/cockroach /usr/local/bin/
RUN rm -r cockroach-v21.2.9.linux-amd64
# Migrations for cockroach-secure # Migrations for cockroach-secure
RUN go install github.com/rakyll/statik \ RUN go install github.com/rakyll/statik \
&& go test -race -v -coverprofile=profile.cov $(go list ./... | grep -v /operator/) && go test -race -v -coverprofile=profile.cov $(go list ./... | grep -v /operator/)

View File

@ -50,6 +50,7 @@ type Config struct {
EncryptionKeys *encryptionKeyConfig EncryptionKeys *encryptionKeyConfig
DefaultInstance command.InstanceSetup DefaultInstance command.InstanceSetup
AuditLogRetention time.Duration AuditLogRetention time.Duration
SystemAPIUsers map[string]*internal_authz.SystemAPIUser
} }
func MustNewConfig(v *viper.Viper) *Config { func MustNewConfig(v *viper.Viper) *Config {

View File

@ -135,14 +135,14 @@ func startZitadel(config *Config, masterKey string) error {
notification.Start(config.Notification, config.ExternalPort, config.ExternalSecure, commands, queries, dbClient, assets.HandlerPrefix, config.SystemDefaults.Notifications.FileSystemPath, keys.User, keys.SMTP, keys.SMS) notification.Start(config.Notification, config.ExternalPort, config.ExternalSecure, commands, queries, dbClient, assets.HandlerPrefix, config.SystemDefaults.Notifications.FileSystemPath, keys.User, keys.SMTP, keys.SMS)
router := mux.NewRouter() router := mux.NewRouter()
err = startAPIs(ctx, router, commands, queries, eventstoreClient, dbClient, config, storage, authZRepo, keys) err = startAPIs(ctx, router, commands, queries, eventstoreClient, dbClient, config, storage, authZRepo, keys, config.SystemAPIUsers)
if err != nil { if err != nil {
return err return err
} }
return listen(ctx, router, config.Port) return listen(ctx, router, config.Port)
} }
func startAPIs(ctx context.Context, router *mux.Router, commands *command.Commands, queries *query.Queries, eventstore *eventstore.Eventstore, dbClient *sql.DB, config *Config, store static.Storage, authZRepo authz_repo.Repository, keys *encryptionKeys) error { func startAPIs(ctx context.Context, router *mux.Router, commands *command.Commands, queries *query.Queries, eventstore *eventstore.Eventstore, dbClient *sql.DB, config *Config, store static.Storage, authZRepo authz_repo.Repository, keys *encryptionKeys, systemAPIKeys map[string]*internal_authz.SystemAPIUser) error {
repo := struct { repo := struct {
authz_repo.Repository authz_repo.Repository
*query.Queries *query.Queries
@ -150,9 +150,9 @@ func startAPIs(ctx context.Context, router *mux.Router, commands *command.Comman
authZRepo, authZRepo,
queries, queries,
} }
verifier := internal_authz.Start(repo) verifier := internal_authz.Start(repo, config.ExternalDomain, systemAPIKeys)
authenticatedAPIs := api.New(config.Port, router, &repo, config.InternalAuthZ, config.ExternalSecure, config.HTTP2HostHeader) apis := api.New(config.Port, router, queries, verifier, config.InternalAuthZ, config.ExternalSecure, config.HTTP2HostHeader)
authRepo, err := auth_es.Start(config.Auth, config.SystemDefaults, commands, queries, dbClient, keys.OIDC, keys.User) authRepo, err := auth_es.Start(config.Auth, config.SystemDefaults, commands, queries, dbClient, keys.OIDC, keys.User)
if err != nil { if err != nil {
return fmt.Errorf("error starting auth repo: %w", err) return fmt.Errorf("error starting auth repo: %w", err)
@ -161,21 +161,21 @@ func startAPIs(ctx context.Context, router *mux.Router, commands *command.Comman
if err != nil { if err != nil {
return fmt.Errorf("error starting admin repo: %w", err) return fmt.Errorf("error starting admin repo: %w", err)
} }
if err := authenticatedAPIs.RegisterServer(ctx, system.CreateServer(commands, queries, adminRepo, config.Database.Database, config.DefaultInstance)); err != nil { if err := apis.RegisterServer(ctx, system.CreateServer(commands, queries, adminRepo, config.Database.Database, config.DefaultInstance)); err != nil {
return err return err
} }
if err := authenticatedAPIs.RegisterServer(ctx, admin.CreateServer(commands, queries, adminRepo, config.ExternalSecure, keys.User)); err != nil { if err := apis.RegisterServer(ctx, admin.CreateServer(commands, queries, adminRepo, config.ExternalSecure, keys.User)); err != nil {
return err return err
} }
if err := authenticatedAPIs.RegisterServer(ctx, management.CreateServer(commands, queries, config.SystemDefaults, keys.User, config.ExternalSecure, oidc.HandlerPrefix, config.AuditLogRetention)); err != nil { if err := apis.RegisterServer(ctx, management.CreateServer(commands, queries, config.SystemDefaults, keys.User, config.ExternalSecure, oidc.HandlerPrefix, config.AuditLogRetention)); err != nil {
return err return err
} }
if err := authenticatedAPIs.RegisterServer(ctx, auth.CreateServer(commands, queries, authRepo, config.SystemDefaults, keys.User, config.ExternalSecure, config.AuditLogRetention)); err != nil { if err := apis.RegisterServer(ctx, auth.CreateServer(commands, queries, authRepo, config.SystemDefaults, keys.User, config.ExternalSecure, config.AuditLogRetention)); err != nil {
return err return err
} }
instanceInterceptor := middleware.InstanceInterceptor(queries, config.HTTP1HostHeader, login.IgnoreInstanceEndpoints...) instanceInterceptor := middleware.InstanceInterceptor(queries, config.HTTP1HostHeader, login.IgnoreInstanceEndpoints...)
authenticatedAPIs.RegisterHandler(assets.HandlerPrefix, assets.NewHandler(commands, verifier, config.InternalAuthZ, id.SonyFlakeGenerator(), store, queries, instanceInterceptor.Handler)) apis.RegisterHandler(assets.HandlerPrefix, assets.NewHandler(commands, verifier, config.InternalAuthZ, id.SonyFlakeGenerator(), store, queries, instanceInterceptor.Handler))
userAgentInterceptor, err := middleware.NewUserAgentHandler(config.UserAgentCookie, keys.UserAgentCookieKey, id.SonyFlakeGenerator(), config.ExternalSecure, login.EndpointResources) userAgentInterceptor, err := middleware.NewUserAgentHandler(config.UserAgentCookie, keys.UserAgentCookieKey, id.SonyFlakeGenerator(), config.ExternalSecure, login.EndpointResources)
if err != nil { if err != nil {
@ -186,25 +186,25 @@ func startAPIs(ctx context.Context, router *mux.Router, commands *command.Comman
if err != nil { if err != nil {
return fmt.Errorf("unable to start oidc provider: %w", err) return fmt.Errorf("unable to start oidc provider: %w", err)
} }
authenticatedAPIs.RegisterHandler(oidc.HandlerPrefix, oidcProvider.HttpHandler()) apis.RegisterHandler(oidc.HandlerPrefix, oidcProvider.HttpHandler())
openAPIHandler, err := openapi.Start() openAPIHandler, err := openapi.Start()
if err != nil { if err != nil {
return fmt.Errorf("unable to start openapi handler: %w", err) return fmt.Errorf("unable to start openapi handler: %w", err)
} }
authenticatedAPIs.RegisterHandler(openapi.HandlerPrefix, openAPIHandler) apis.RegisterHandler(openapi.HandlerPrefix, openAPIHandler)
c, err := console.Start(config.Console, config.ExternalSecure, oidcProvider.IssuerFromRequest, instanceInterceptor.Handler) c, err := console.Start(config.Console, config.ExternalSecure, oidcProvider.IssuerFromRequest, instanceInterceptor.Handler)
if err != nil { if err != nil {
return fmt.Errorf("unable to start console: %w", err) return fmt.Errorf("unable to start console: %w", err)
} }
authenticatedAPIs.RegisterHandler(console.HandlerPrefix, c) apis.RegisterHandler(console.HandlerPrefix, c)
l, err := login.CreateLogin(config.Login, commands, queries, authRepo, store, console.HandlerPrefix+"/", op.AuthCallbackURL(oidcProvider), config.ExternalSecure, userAgentInterceptor, op.NewIssuerInterceptor(oidcProvider.IssuerFromRequest).Handler, instanceInterceptor.Handler, keys.User, keys.IDPConfig, keys.CSRFCookieKey) l, err := login.CreateLogin(config.Login, commands, queries, authRepo, store, console.HandlerPrefix+"/", op.AuthCallbackURL(oidcProvider), config.ExternalSecure, userAgentInterceptor, op.NewIssuerInterceptor(oidcProvider.IssuerFromRequest).Handler, instanceInterceptor.Handler, keys.User, keys.IDPConfig, keys.CSRFCookieKey)
if err != nil { if err != nil {
return fmt.Errorf("unable to start login: %w", err) return fmt.Errorf("unable to start login: %w", err)
} }
authenticatedAPIs.RegisterHandler(login.HandlerPrefix, l.Handler()) apis.RegisterHandler(login.HandlerPrefix, l.Handler())
return nil return nil
} }

View File

@ -4,6 +4,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/zitadel/logging" "github.com/zitadel/logging"
"github.com/zitadel/zitadel/cmd/admin/initialise" "github.com/zitadel/zitadel/cmd/admin/initialise"
"github.com/zitadel/zitadel/cmd/admin/key" "github.com/zitadel/zitadel/cmd/admin/key"
"github.com/zitadel/zitadel/cmd/admin/setup" "github.com/zitadel/zitadel/cmd/admin/setup"

View File

@ -163,6 +163,13 @@ EncryptionKeys:
CSRFCookieKeyID: "csrfCookieKey" CSRFCookieKeyID: "csrfCookieKey"
UserAgentCookieKeyID: "userAgentCookieKey" UserAgentCookieKeyID: "userAgentCookieKey"
SystemAPIUsers:
# add keys for authentication of the systemAPI here:
# - superuser:
# Path: /path/to/superuser/key.pem
# - superuser2:
# Path: /path/to/superuser2/key.pem
#TODO: remove as soon as possible #TODO: remove as soon as possible
SystemDefaults: SystemDefaults:
SecretGenerators: SecretGenerators:

View File

@ -14,7 +14,6 @@ import (
internal_authz "github.com/zitadel/zitadel/internal/api/authz" internal_authz "github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/grpc/server" "github.com/zitadel/zitadel/internal/api/grpc/server"
http_util "github.com/zitadel/zitadel/internal/api/http" http_util "github.com/zitadel/zitadel/internal/api/http"
"github.com/zitadel/zitadel/internal/authz/repository"
"github.com/zitadel/zitadel/internal/errors" "github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query" "github.com/zitadel/zitadel/internal/query"
"github.com/zitadel/zitadel/internal/telemetry/tracing" "github.com/zitadel/zitadel/internal/telemetry/tracing"
@ -37,23 +36,20 @@ type health interface {
func New( func New(
port uint16, port uint16,
router *mux.Router, router *mux.Router,
repo *struct { queries *query.Queries,
repository.Repository verifier *internal_authz.TokenVerifier,
*query.Queries
},
authZ internal_authz.Config, authZ internal_authz.Config,
externalSecure bool, externalSecure bool,
http2HostName string, http2HostName string,
) *API { ) *API {
verifier := internal_authz.Start(repo)
api := &API{ api := &API{
port: port, port: port,
verifier: verifier, verifier: verifier,
health: repo, health: queries,
router: router, router: router,
externalSecure: externalSecure, externalSecure: externalSecure,
} }
api.grpcServer = server.CreateServer(api.verifier, authZ, repo.Queries, http2HostName) api.grpcServer = server.CreateServer(api.verifier, authZ, queries, http2HostName)
api.routeGRPC() api.routeGRPC()
api.RegisterHandler("/debug", api.healthHandler()) api.RegisterHandler("/debug", api.healthHandler())
@ -68,9 +64,7 @@ func (a *API) RegisterServer(ctx context.Context, grpcServer server.Server) erro
return err return err
} }
a.RegisterHandler(prefix, handler) a.RegisterHandler(prefix, handler)
if a.verifier != nil { a.verifier.RegisterServer(grpcServer.AppName(), grpcServer.MethodPrefix(), grpcServer.AuthMethods())
a.verifier.RegisterServer(grpcServer.AppName(), grpcServer.MethodPrefix(), grpcServer.AuthMethods())
}
return nil return nil
} }

View File

@ -2,6 +2,7 @@ package authz
import ( import (
"context" "context"
"strings"
"github.com/zitadel/zitadel/internal/api/grpc" "github.com/zitadel/zitadel/internal/api/grpc"
http_util "github.com/zitadel/zitadel/internal/api/http" http_util "github.com/zitadel/zitadel/internal/api/http"
@ -67,6 +68,9 @@ func VerifyTokenAndCreateCtxData(ctx context.Context, token, orgID string, t *To
if err != nil { if err != nil {
return CtxData{}, err return CtxData{}, err
} }
if strings.HasPrefix(method, "/zitadel.system.v1.SystemService") {
return CtxData{UserID: userID}, nil
}
var projectID string var projectID string
var origins []string var origins []string
if clientID != "" { if clientID != "" {

View File

@ -68,7 +68,7 @@ func Test_GetUserMethodPermissions(t *testing.T) {
{ {
Roles: []string{"ORG_OWNER"}, Roles: []string{"ORG_OWNER"},
}, },
}}), }}, "", nil),
requiredPerm: "project.read", requiredPerm: "project.read",
authConfig: Config{ authConfig: Config{
RolePermissionMappings: []RoleMapping{ RolePermissionMappings: []RoleMapping{
@ -91,7 +91,7 @@ func Test_GetUserMethodPermissions(t *testing.T) {
name: "No Grants", name: "No Grants",
args: args{ args: args{
ctxData: CtxData{}, ctxData: CtxData{},
verifier: Start(&testVerifier{memberships: []*Membership{}}), verifier: Start(&testVerifier{memberships: []*Membership{}}, "", nil),
requiredPerm: "project.read", requiredPerm: "project.read",
authConfig: Config{ authConfig: Config{
RolePermissionMappings: []RoleMapping{ RolePermissionMappings: []RoleMapping{
@ -119,7 +119,7 @@ func Test_GetUserMethodPermissions(t *testing.T) {
MemberType: MemberTypeIam, MemberType: MemberTypeIam,
Roles: []string{"IAM_OWNER"}, Roles: []string{"IAM_OWNER"},
}, },
}}), }}, "", nil),
requiredPerm: "project.read", requiredPerm: "project.read",
authConfig: Config{ authConfig: Config{
RolePermissionMappings: []RoleMapping{ RolePermissionMappings: []RoleMapping{

View File

@ -2,9 +2,16 @@ package authz
import ( import (
"context" "context"
"crypto/rsa"
"os"
"strings" "strings"
"sync" "sync"
"time"
"github.com/zitadel/oidc/v2/pkg/op"
"gopkg.in/square/go-jose.v2"
"github.com/zitadel/zitadel/internal/crypto"
caos_errs "github.com/zitadel/zitadel/internal/errors" caos_errs "github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/telemetry/tracing" "github.com/zitadel/zitadel/internal/telemetry/tracing"
) )
@ -14,9 +21,10 @@ const (
) )
type TokenVerifier struct { type TokenVerifier struct {
authZRepo authZRepo authZRepo authZRepo
clients sync.Map clients sync.Map
authMethods MethodMapping authMethods MethodMapping
systemJWTProfile op.JWTProfileVerifier
} }
type authZRepo interface { type authZRepo interface {
@ -27,15 +35,74 @@ type authZRepo interface {
ExistsOrg(ctx context.Context, orgID string) error ExistsOrg(ctx context.Context, orgID string) error
} }
func Start(authZRepo authZRepo) (v *TokenVerifier) { func Start(authZRepo authZRepo, systemAPI string, keys map[string]*SystemAPIUser) (v *TokenVerifier) {
return &TokenVerifier{authZRepo: authZRepo} return &TokenVerifier{
authZRepo: authZRepo,
systemJWTProfile: op.NewJWTProfileVerifier(
&systemJWTStorage{
keys: keys,
cachedKeys: make(map[string]*rsa.PublicKey),
},
systemAPI,
1*time.Hour,
time.Second,
),
}
} }
func (v *TokenVerifier) VerifyAccessToken(ctx context.Context, token string, method string) (userID, clientID, agentID, prefLang, resourceOwner string, err error) { func (v *TokenVerifier) VerifyAccessToken(ctx context.Context, token string, method string) (userID, clientID, agentID, prefLang, resourceOwner string, err error) {
if strings.HasPrefix(method, "/zitadel.system.v1.SystemService") {
userID, err := v.verifySystemToken(ctx, token)
if err != nil {
return "", "", "", "", "", err
}
return userID, "", "", "", "", nil
}
userID, agentID, clientID, prefLang, resourceOwner, err = v.authZRepo.VerifyAccessToken(ctx, token, "", GetInstance(ctx).ProjectID()) userID, agentID, clientID, prefLang, resourceOwner, err = v.authZRepo.VerifyAccessToken(ctx, token, "", GetInstance(ctx).ProjectID())
return userID, clientID, agentID, prefLang, resourceOwner, err return userID, clientID, agentID, prefLang, resourceOwner, err
} }
func (v *TokenVerifier) verifySystemToken(ctx context.Context, token string) (string, error) {
jwtReq, err := op.VerifyJWTAssertion(ctx, token, v.systemJWTProfile)
if err != nil {
return "", err
}
return jwtReq.Subject, nil
}
type systemJWTStorage struct {
keys map[string]*SystemAPIUser
mutex sync.Mutex
cachedKeys map[string]*rsa.PublicKey
}
type SystemAPIUser struct {
Path string
}
func (s *systemJWTStorage) GetKeyByIDAndUserID(_ context.Context, _, userID string) (*jose.JSONWebKey, error) {
cachedKey, ok := s.cachedKeys[userID]
if ok {
return &jose.JSONWebKey{KeyID: userID, Key: cachedKey}, nil
}
key, ok := s.keys[userID]
if !ok {
return nil, caos_errs.ThrowNotFound(nil, "AUTHZ-asfd3", "Errors.User.NotFound")
}
defer s.mutex.Unlock()
s.mutex.Lock()
keyData, err := os.ReadFile(key.Path)
if err != nil {
return nil, caos_errs.ThrowInternal(err, "AUTHZ-JK31F", "Errors.NotFound")
}
publicKey, err := crypto.BytesToPublicKey(keyData)
if err != nil {
return nil, err
}
s.cachedKeys[userID] = publicKey
return &jose.JSONWebKey{KeyID: userID, Key: publicKey}, nil
}
type client struct { type client struct {
id string id string
projectID string projectID string

View File

@ -15,10 +15,6 @@ import (
func AuthorizationInterceptor(verifier *authz.TokenVerifier, authConfig authz.Config) grpc.UnaryServerInterceptor { func AuthorizationInterceptor(verifier *authz.TokenVerifier, authConfig authz.Config) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
//TODO: Change as soon as we know how to authenticate system api
if verifier == nil {
return handler(ctx, req)
}
return authorize(ctx, req, info, handler, verifier, authConfig) return authorize(ctx, req, info, handler, verifier, authConfig)
} }
} }

View File

@ -65,7 +65,7 @@ func Test_authorize(t *testing.T) {
info: mockInfo("/no/token/needed"), info: mockInfo("/no/token/needed"),
handler: emptyMockHandler, handler: emptyMockHandler,
verifier: func() *authz.TokenVerifier { verifier: func() *authz.TokenVerifier {
verifier := authz.Start(&verifierMock{}) verifier := authz.Start(&verifierMock{}, "", nil)
verifier.RegisterServer("need", "need", authz.MethodMapping{}) verifier.RegisterServer("need", "need", authz.MethodMapping{})
return verifier return verifier
}(), }(),
@ -84,7 +84,7 @@ func Test_authorize(t *testing.T) {
info: mockInfo("/need/authentication"), info: mockInfo("/need/authentication"),
handler: emptyMockHandler, handler: emptyMockHandler,
verifier: func() *authz.TokenVerifier { verifier: func() *authz.TokenVerifier {
verifier := authz.Start(&verifierMock{}) verifier := authz.Start(&verifierMock{}, "", nil)
verifier.RegisterServer("need", "need", authz.MethodMapping{"/need/authentication": authz.Option{Permission: "authenticated"}}) verifier.RegisterServer("need", "need", authz.MethodMapping{"/need/authentication": authz.Option{Permission: "authenticated"}})
return verifier return verifier
}(), }(),
@ -104,7 +104,7 @@ func Test_authorize(t *testing.T) {
info: mockInfo("/need/authentication"), info: mockInfo("/need/authentication"),
handler: emptyMockHandler, handler: emptyMockHandler,
verifier: func() *authz.TokenVerifier { verifier: func() *authz.TokenVerifier {
verifier := authz.Start(&verifierMock{}) verifier := authz.Start(&verifierMock{}, "", nil)
verifier.RegisterServer("need", "need", authz.MethodMapping{"/need/authentication": authz.Option{Permission: "authenticated"}}) verifier.RegisterServer("need", "need", authz.MethodMapping{"/need/authentication": authz.Option{Permission: "authenticated"}})
return verifier return verifier
}(), }(),
@ -124,7 +124,7 @@ func Test_authorize(t *testing.T) {
info: mockInfo("/need/authentication"), info: mockInfo("/need/authentication"),
handler: emptyMockHandler, handler: emptyMockHandler,
verifier: func() *authz.TokenVerifier { verifier: func() *authz.TokenVerifier {
verifier := authz.Start(&verifierMock{}) verifier := authz.Start(&verifierMock{}, "", nil)
verifier.RegisterServer("need", "need", authz.MethodMapping{"/need/authentication": authz.Option{Permission: "authenticated"}}) verifier.RegisterServer("need", "need", authz.MethodMapping{"/need/authentication": authz.Option{Permission: "authenticated"}})
return verifier return verifier
}(), }(),

View File

@ -28,6 +28,9 @@ func setInstance(ctx context.Context, req interface{}, info *grpc.UnaryServerInf
interceptorCtx, span := tracing.NewServerInterceptorSpan(ctx) interceptorCtx, span := tracing.NewServerInterceptorSpan(ctx)
defer func() { span.EndWithError(err) }() defer func() { span.EndWithError(err) }()
for _, service := range ignoredServices { for _, service := range ignoredServices {
if !strings.HasPrefix(service, "/") {
service = "/" + service
}
if strings.HasPrefix(info.FullMethod, service) { if strings.HasPrefix(info.FullMethod, service) {
return handler(ctx, req) return handler(ctx, req)
} }

View File

@ -9,6 +9,7 @@ import (
"github.com/zitadel/zitadel/internal/api/grpc/server/middleware" "github.com/zitadel/zitadel/internal/api/grpc/server/middleware"
"github.com/zitadel/zitadel/internal/query" "github.com/zitadel/zitadel/internal/query"
"github.com/zitadel/zitadel/internal/telemetry/metrics" "github.com/zitadel/zitadel/internal/telemetry/metrics"
system_pb "github.com/zitadel/zitadel/pkg/grpc/system"
) )
type Server interface { type Server interface {
@ -29,8 +30,7 @@ func CreateServer(verifier *authz.TokenVerifier, authConfig authz.Config, querie
middleware.SentryHandler(), middleware.SentryHandler(),
middleware.NoCacheInterceptor(), middleware.NoCacheInterceptor(),
middleware.ErrorHandler(), middleware.ErrorHandler(),
//TODO: Handle Ignored Services middleware.InstanceInterceptor(queries, hostHeaderName, system_pb.SystemService_MethodPrefix),
middleware.InstanceInterceptor(queries, hostHeaderName, "/zitadel.system.v1.SystemService"),
middleware.AuthorizationInterceptor(verifier, authConfig), middleware.AuthorizationInterceptor(verifier, authConfig),
middleware.TranslationHandler(), middleware.TranslationHandler(),
middleware.ValidationHandler(), middleware.ValidationHandler(),

View File

@ -73,3 +73,7 @@ func StartQueries(ctx context.Context, es *eventstore.Eventstore, sqlClient *sql
return repo, nil return repo, nil
} }
func (q *Queries) Health(ctx context.Context) error {
return q.client.Ping()
}

View File

@ -104,6 +104,10 @@ service SystemService {
post: "/instances/_search" post: "/instances/_search"
body: "*" body: "*"
}; };
option (zitadel.v1.auth_option) = {
permission: "authenticated";
};
} }
// Returns the detail of an instance // Returns the detail of an instance
@ -111,6 +115,10 @@ service SystemService {
option (google.api.http) = { option (google.api.http) = {
get: "/instances/{instance_id}"; get: "/instances/{instance_id}";
}; };
option (zitadel.v1.auth_option) = {
permission: "authenticated";
};
} }
// Creates a new instance with all needed setup data // Creates a new instance with all needed setup data
@ -120,6 +128,10 @@ service SystemService {
post: "/instances" post: "/instances"
body: "*" body: "*"
}; };
option (zitadel.v1.auth_option) = {
permission: "authenticated";
};
} }
// Removes a instances // Removes a instances
@ -128,6 +140,10 @@ service SystemService {
option (google.api.http) = { option (google.api.http) = {
delete: "/instances/{instance_id}" delete: "/instances/{instance_id}"
}; };
option (zitadel.v1.auth_option) = {
permission: "authenticated";
};
} }
// Checks if a domain exists // Checks if a domain exists
@ -136,6 +152,10 @@ service SystemService {
post: "/domains/{domain}/_exists"; post: "/domains/{domain}/_exists";
body: "*" body: "*"
}; };
option (zitadel.v1.auth_option) = {
permission: "authenticated";
};
} }
// Returns the custom domains of an instance // Returns the custom domains of an instance
@ -144,6 +164,10 @@ service SystemService {
post: "/instances/{instance_id}/domains/_search"; post: "/instances/{instance_id}/domains/_search";
body: "*" body: "*"
}; };
option (zitadel.v1.auth_option) = {
permission: "authenticated";
};
} }
// Returns the domain of an instance // Returns the domain of an instance
@ -152,6 +176,10 @@ service SystemService {
post: "/instances/{instance_id}/domains"; post: "/instances/{instance_id}/domains";
body: "*" body: "*"
}; };
option (zitadel.v1.auth_option) = {
permission: "authenticated";
};
} }
// Returns the domain of an instance // Returns the domain of an instance
@ -159,6 +187,10 @@ service SystemService {
option (google.api.http) = { option (google.api.http) = {
delete: "/instances/{instance_id}/domains/{domain}"; delete: "/instances/{instance_id}/domains/{domain}";
}; };
option (zitadel.v1.auth_option) = {
permission: "authenticated";
};
} }
// Returns the domain of an instance // Returns the domain of an instance
@ -167,6 +199,10 @@ service SystemService {
post: "/instances/{instance_id}/domains/_set_primary"; post: "/instances/{instance_id}/domains/_set_primary";
body: "*" body: "*"
}; };
option (zitadel.v1.auth_option) = {
permission: "authenticated";
};
} }
@ -179,6 +215,10 @@ service SystemService {
body: "*" body: "*"
}; };
option (zitadel.v1.auth_option) = {
permission: "authenticated";
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
tags: "views"; tags: "views";
external_docs: { external_docs: {
@ -203,6 +243,9 @@ service SystemService {
post: "/views/{database}/{view_name}"; post: "/views/{database}/{view_name}";
}; };
option (zitadel.v1.auth_option) = {
permission: "authenticated";
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
tags: "views"; tags: "views";
@ -228,6 +271,10 @@ service SystemService {
body: "*" body: "*"
}; };
option (zitadel.v1.auth_option) = {
permission: "authenticated";
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
tags: "failed events"; tags: "failed events";
external_docs: { external_docs: {
@ -253,6 +300,10 @@ service SystemService {
delete: "/failedevents/{database}/{view_name}/{failed_sequence}"; delete: "/failedevents/{database}/{view_name}/{failed_sequence}";
}; };
option (zitadel.v1.auth_option) = {
permission: "authenticated";
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
tags: "failed events"; tags: "failed events";
external_docs: { external_docs: {