feat: block instances (#7129)

* docs: fix init description typos

* feat: block instances using limits

* translate

* unit tests

* fix translations

* redirect /ui/login

* fix http interceptor

* cleanup

* fix http interceptor

* fix: delete cookies on gateway 200

* add integration tests

* add command test

* docs

* fix integration tests

* add bulk api and integration test

* optimize bulk set limits

* unit test bulk limits

* fix broken link

* fix assets middleware

* fix broken link

* validate instance id format

* Update internal/eventstore/search_query.go

Co-authored-by: Livio Spring <livio.a@gmail.com>

* remove support for owner bulk limit commands

* project limits to instances

* migrate instances projection

* Revert "migrate instances projection"

This reverts commit 214218732a.

* join limits, remove owner

* remove todo

* use optional bool

* normally validate instance ids

* use 302

* cleanup

* cleanup

* Update internal/api/grpc/system/limits_converter.go

Co-authored-by: Livio Spring <livio.a@gmail.com>

* remove owner

* remove owner from reset

---------

Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
Elio Bischof
2024-01-17 11:16:48 +01:00
committed by GitHub
parent d9d376a275
commit ed0bc39ea4
80 changed files with 1609 additions and 438 deletions

View File

@@ -830,6 +830,9 @@ DefaultInstance:
# A value of "0s" means that all events are available.
# If this value is set, it overwrites the system default unless it is not reset via the admin API.
AuditLogRetention: # ZITADEL_DEFAULTINSTANCE_LIMITS_AUDITLOGRETENTION
# If Block is true, all requests except to /ui/console or the system API are blocked and /ui/login is redirected to /ui/console.
# /ui/console shows a message that the instance is blocked with a link to Console.InstanceManagementURL
Block: # ZITADEL_DEFAULTINSTANCE_LIMITS_BLOCK
Restrictions:
# DisallowPublicOrgRegistration defines if ZITADEL should expose the endpoint /ui/login/register/org
# If it is true, the endpoint returns the HTTP status 404 on GET requests, and 409 on POST requests.
@@ -862,7 +865,8 @@ DefaultInstance:
# ResetInterval: 720h # 30 days
# # Amount defines the number of units for this quota
# Amount: 25000
# # Limit defines whether ZITADEL should block further usage when the configured amount is used
# # Limit defines whether ZITADEL should block further authenticated requests when the configured amount is used.
# # If you not only want to block authenticated requests but also authentication itself, consider using the system APIs SetLimits method.
# Limit: false
# # Notifications are emitted by ZITADEL when certain quota percentages are reached
# Notifications:

View File

@@ -39,7 +39,7 @@ func New() *cobra.Command {
Long: `Sets up the minimum requirements to start ZITADEL.
Prerequisites:
- cockroachdb
- cockroachDB
The user provided by flags needs privileges to
- create the database if it does not exist

View File

@@ -17,10 +17,10 @@ func newDatabase() *cobra.Command {
Short: "initialize only the database",
Long: `Sets up the ZITADEL database.
Prereqesits:
Prerequisites:
- cockroachDB or postgreSQL
The user provided by flags needs priviledge to
The user provided by flags needs privileges to
- create the database if it does not exist
- see other users and create a new one if the user does not exist
- grant all rights of the ZITADEL database to the user created if not yet set

View File

@@ -17,7 +17,7 @@ func newGrant() *cobra.Command {
Short: "set ALL grant to user",
Long: `Sets ALL grant to the database user.
Prereqesits:
Prerequisites:
- cockroachDB or postgreSQL
`,
Run: func(cmd *cobra.Command, args []string) {

View File

@@ -17,10 +17,10 @@ func newUser() *cobra.Command {
Short: "initialize only the database user",
Long: `Sets up the ZITADEL database user.
Prereqesits:
- cockroachDB or postreSQL
Prerequisites:
- cockroachDB or postgreSQL
The user provided by flags needs priviledge to
The user provided by flags needs privileges to
- create the database if it does not exist
- see other users and create a new one if the user does not exist
- grant all rights of the ZITADEL database to the user created if not yet set

View File

@@ -19,7 +19,7 @@ func newZitadel() *cobra.Command {
Short: "initialize ZITADEL internals",
Long: `initialize ZITADEL internals.
Prereqesits:
Prerequisites:
- cockroachDB or postgreSQL with user and database
`,
Run: func(cmd *cobra.Command, args []string) {

26
cmd/setup/21.go Normal file
View File

@@ -0,0 +1,26 @@
package setup
import (
"context"
_ "embed"
"github.com/zitadel/zitadel/internal/database"
)
var (
//go:embed 21.sql
addBlockFieldToLimits string
)
type AddBlockFieldToLimits struct {
dbClient *database.DB
}
func (mig *AddBlockFieldToLimits) Execute(ctx context.Context) error {
_, err := mig.dbClient.ExecContext(ctx, addBlockFieldToLimits)
return err
}
func (mig *AddBlockFieldToLimits) String() string {
return "21_add_block_field_to_limits"
}

1
cmd/setup/21.sql Normal file
View File

@@ -0,0 +1 @@
ALTER TABLE IF EXISTS projections.limits ADD COLUMN IF NOT EXISTS block BOOLEAN;

View File

@@ -78,6 +78,7 @@ type Steps struct {
s18AddLowerFieldsToLoginNames *AddLowerFieldsToLoginNames
s19AddCurrentStatesIndex *AddCurrentSequencesIndex
s20AddByUserSessionIndex *AddByUserIndexToSession
s21AddBlockFieldToLimits *AddBlockFieldToLimits
}
type encryptionKeyConfig struct {

View File

@@ -111,6 +111,7 @@ func Setup(config *Config, steps *Steps, masterKey string) {
steps.s18AddLowerFieldsToLoginNames = &AddLowerFieldsToLoginNames{dbClient: queryDBClient}
steps.s19AddCurrentStatesIndex = &AddCurrentSequencesIndex{dbClient: queryDBClient}
steps.s20AddByUserSessionIndex = &AddByUserIndexToSession{dbClient: queryDBClient}
steps.s21AddBlockFieldToLimits = &AddBlockFieldToLimits{dbClient: queryDBClient}
err = projection.Create(ctx, projectionDBClient, eventstoreClient, config.Projections, nil, nil, nil)
logging.OnError(err).Fatal("unable to start projections")
@@ -165,9 +166,11 @@ func Setup(config *Config, steps *Steps, masterKey string) {
logging.OnError(err).Fatalf("unable to migrate repeatable step: %s", repeatableStep.String())
}
// This step is executed after the repeatable steps because it adds fields to the login_names3 projection
// These steps are executed after the repeatable steps because they add fields projections
err = migration.Migrate(ctx, eventstoreClient, steps.s18AddLowerFieldsToLoginNames)
logging.WithFields("name", steps.s18AddLowerFieldsToLoginNames.String()).OnError(err).Fatal("migration failed")
err = migration.Migrate(ctx, eventstoreClient, steps.s21AddBlockFieldToLimits)
logging.WithFields("name", steps.s21AddBlockFieldToLimits.String()).OnError(err).Fatal("migration failed")
}
func readStmt(fs embed.FS, folder, typ, filename string) (string, error) {

View File

@@ -439,14 +439,14 @@ func startAPIs(
return fmt.Errorf("unable to start console: %w", err)
}
apis.RegisterHandlerOnPrefix(console.HandlerPrefix, c)
consolePath := console.HandlerPrefix + "/"
l, err := login.CreateLogin(
config.Login,
commands,
queries,
authRepo,
store,
console.HandlerPrefix+"/",
consolePath,
oidcServer.AuthCallbackURL(),
provider.AuthCallbackURL(samlProvider),
config.ExternalSecure,
@@ -455,7 +455,7 @@ func startAPIs(
provider.NewIssuerInterceptor(samlProvider.IssuerFromRequest).Handler,
instanceInterceptor.Handler,
assetsCache.Handler,
limitingAccessInterceptor.WithoutLimiting().Handle,
limitingAccessInterceptor.WithRedirect(consolePath).Handle,
keys.User,
keys.IDPConfig,
keys.CSRFCookieKey,