mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-15 18:25:13 +00:00
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 <[email protected]> * remove support for owner bulk limit commands * project limits to instances * migrate instances projection * Revert "migrate instances projection" This reverts commit 214218732a56e6df823beac1972adfcf8beeded5. * 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 <[email protected]> * remove owner * remove owner from reset --------- Co-authored-by: Livio Spring <[email protected]>
This commit is contained in:
co-authored by
Livio Spring
parent
d9d376a275
commit
ed0bc39ea4
@@ -4,15 +4,12 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||
objectpb "github.com/zitadel/zitadel/pkg/grpc/object"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/system"
|
||||
)
|
||||
|
||||
func (s *Server) SetLimits(ctx context.Context, req *system.SetLimitsRequest) (*system.SetLimitsResponse, error) {
|
||||
details, err := s.command.SetLimits(
|
||||
ctx,
|
||||
req.GetInstanceId(),
|
||||
instanceLimitsPbToCommand(req),
|
||||
)
|
||||
details, err := s.command.SetLimits(ctx, setInstanceLimitsPbToCommand(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -21,8 +18,23 @@ func (s *Server) SetLimits(ctx context.Context, req *system.SetLimitsRequest) (*
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) ResetLimits(ctx context.Context, req *system.ResetLimitsRequest) (*system.ResetLimitsResponse, error) {
|
||||
details, err := s.command.ResetLimits(ctx, req.GetInstanceId())
|
||||
func (s *Server) BulkSetLimits(ctx context.Context, req *system.BulkSetLimitsRequest) (*system.BulkSetLimitsResponse, error) {
|
||||
details, targetDetails, err := s.command.SetInstanceLimitsBulk(ctx, bulkSetInstanceLimitsPbToCommand(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp := &system.BulkSetLimitsResponse{
|
||||
Details: object.AddToDetailsPb(details.Sequence, details.EventDate, details.ResourceOwner),
|
||||
TargetDetails: make([]*objectpb.ObjectDetails, len(targetDetails)),
|
||||
}
|
||||
for i := range targetDetails {
|
||||
resp.TargetDetails[i] = object.AddToDetailsPb(targetDetails[i].Sequence, targetDetails[i].EventDate, targetDetails[i].ResourceOwner)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (s *Server) ResetLimits(ctx context.Context, _ *system.ResetLimitsRequest) (*system.ResetLimitsResponse, error) {
|
||||
details, err := s.command.ResetLimits(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -7,10 +7,23 @@ import (
|
||||
"github.com/zitadel/zitadel/pkg/grpc/system"
|
||||
)
|
||||
|
||||
func instanceLimitsPbToCommand(req *system.SetLimitsRequest) *command.SetLimits {
|
||||
func setInstanceLimitsPbToCommand(req *system.SetLimitsRequest) *command.SetLimits {
|
||||
var setLimits = new(command.SetLimits)
|
||||
if req.AuditLogRetention != nil {
|
||||
setLimits.AuditLogRetention = gu.Ptr(req.AuditLogRetention.AsDuration())
|
||||
}
|
||||
setLimits.Block = req.Block
|
||||
return setLimits
|
||||
}
|
||||
|
||||
func bulkSetInstanceLimitsPbToCommand(req *system.BulkSetLimitsRequest) []*command.SetInstanceLimitsBulk {
|
||||
cmds := make([]*command.SetInstanceLimitsBulk, len(req.Limits))
|
||||
for i := range req.Limits {
|
||||
setLimitsReq := req.Limits[i]
|
||||
cmds[i] = &command.SetInstanceLimitsBulk{
|
||||
InstanceID: setLimitsReq.GetInstanceId(),
|
||||
SetLimits: *setInstanceLimitsPbToCommand(req.Limits[i]),
|
||||
}
|
||||
}
|
||||
return cmds
|
||||
}
|
||||
|
||||
@@ -0,0 +1,287 @@
|
||||
//go:build integration
|
||||
|
||||
package system_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/muhlemmer/gu"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/admin"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/system"
|
||||
)
|
||||
|
||||
func TestServer_Limits_Block(t *testing.T) {
|
||||
domain, instanceID, iamOwnerCtx := Tester.UseIsolatedInstance(t, CTX, SystemCTX)
|
||||
tests := []*test{
|
||||
publicAPIBlockingTest(domain),
|
||||
{
|
||||
name: "mutating API",
|
||||
testGrpc: func(tt assert.TestingT, expectBlocked bool) {
|
||||
randomGrpcIdpName := randomString("idp-grpc", 5)
|
||||
_, err := Tester.Client.Admin.AddGitHubProvider(iamOwnerCtx, &admin.AddGitHubProviderRequest{
|
||||
Name: randomGrpcIdpName,
|
||||
ClientId: "client-id",
|
||||
ClientSecret: "client-secret",
|
||||
})
|
||||
assertGrpcError(tt, err, expectBlocked)
|
||||
//nolint:contextcheck
|
||||
idpExists := idpExistsCondition(tt, instanceID, randomGrpcIdpName)
|
||||
if expectBlocked {
|
||||
// We ensure that the idp really is not created
|
||||
assert.Neverf(tt, idpExists, 5*time.Second, 1*time.Second, "idp should never be created")
|
||||
} else {
|
||||
assert.Eventuallyf(tt, idpExists, 5*time.Second, 1*time.Second, "idp should be created")
|
||||
}
|
||||
},
|
||||
testHttp: func(tt assert.TestingT) (*http.Request, error, func(assert.TestingT, *http.Response, bool)) {
|
||||
randomHttpIdpName := randomString("idp-http", 5)
|
||||
req, err := http.NewRequestWithContext(
|
||||
CTX,
|
||||
"POST",
|
||||
fmt.Sprintf("http://%s/admin/v1/idps/github", net.JoinHostPort(domain, "8080")),
|
||||
strings.NewReader(`{
|
||||
"name": "`+randomHttpIdpName+`",
|
||||
"clientId": "client-id",
|
||||
"clientSecret": "client-secret"
|
||||
}`),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err, nil
|
||||
}
|
||||
req.Header.Set("Authorization", Tester.BearerToken(iamOwnerCtx))
|
||||
return req, nil, func(ttt assert.TestingT, response *http.Response, expectBlocked bool) {
|
||||
assertLimitResponse(ttt, response, expectBlocked)
|
||||
assertSetLimitingCookie(ttt, response, expectBlocked)
|
||||
}
|
||||
},
|
||||
}, {
|
||||
name: "discovery",
|
||||
testHttp: func(tt assert.TestingT) (*http.Request, error, func(assert.TestingT, *http.Response, bool)) {
|
||||
req, err := http.NewRequestWithContext(
|
||||
CTX,
|
||||
"GET",
|
||||
fmt.Sprintf("http://%s/.well-known/openid-configuration", net.JoinHostPort(domain, "8080")),
|
||||
nil,
|
||||
)
|
||||
return req, err, func(ttt assert.TestingT, response *http.Response, expectBlocked bool) {
|
||||
assertLimitResponse(ttt, response, expectBlocked)
|
||||
assertSetLimitingCookie(ttt, response, expectBlocked)
|
||||
}
|
||||
},
|
||||
}, {
|
||||
name: "login",
|
||||
testHttp: func(tt assert.TestingT) (*http.Request, error, func(assert.TestingT, *http.Response, bool)) {
|
||||
req, err := http.NewRequestWithContext(
|
||||
CTX,
|
||||
"GET",
|
||||
fmt.Sprintf("http://%s/ui/login/login/externalidp/callback", net.JoinHostPort(domain, "8080")),
|
||||
nil,
|
||||
)
|
||||
return req, err, func(ttt assert.TestingT, response *http.Response, expectBlocked bool) {
|
||||
// the login paths should return a redirect if the instance is blocked
|
||||
if expectBlocked {
|
||||
assert.Equal(ttt, http.StatusFound, response.StatusCode)
|
||||
} else {
|
||||
assertLimitResponse(ttt, response, false)
|
||||
}
|
||||
assertSetLimitingCookie(ttt, response, expectBlocked)
|
||||
}
|
||||
},
|
||||
}, {
|
||||
name: "console",
|
||||
testHttp: func(tt assert.TestingT) (*http.Request, error, func(assert.TestingT, *http.Response, bool)) {
|
||||
req, err := http.NewRequestWithContext(
|
||||
CTX,
|
||||
"GET",
|
||||
fmt.Sprintf("http://%s/ui/console/", net.JoinHostPort(domain, "8080")),
|
||||
nil,
|
||||
)
|
||||
return req, err, func(ttt assert.TestingT, response *http.Response, expectBlocked bool) {
|
||||
// the console is not blocked so we can render a link to an instance management portal.
|
||||
// A CDN can cache these assets easily
|
||||
// We also don't care about a cookie because the environment.json already takes care of that.
|
||||
assertLimitResponse(ttt, response, false)
|
||||
}
|
||||
},
|
||||
}, {
|
||||
name: "environment.json",
|
||||
testHttp: func(tt assert.TestingT) (*http.Request, error, func(assert.TestingT, *http.Response, bool)) {
|
||||
req, err := http.NewRequestWithContext(
|
||||
CTX,
|
||||
"GET",
|
||||
fmt.Sprintf("http://%s/ui/console/assets/environment.json", net.JoinHostPort(domain, "8080")),
|
||||
nil,
|
||||
)
|
||||
return req, err, func(ttt assert.TestingT, response *http.Response, expectBlocked bool) {
|
||||
// the environment.json should always return successfully
|
||||
assertLimitResponse(ttt, response, false)
|
||||
assertSetLimitingCookie(ttt, response, expectBlocked)
|
||||
body, err := io.ReadAll(response.Body)
|
||||
assert.NoError(ttt, err)
|
||||
var compFunc assert.ComparisonAssertionFunc = assert.NotContains
|
||||
if expectBlocked {
|
||||
compFunc = assert.Contains
|
||||
}
|
||||
compFunc(ttt, string(body), `"exhausted":true`)
|
||||
}
|
||||
},
|
||||
}}
|
||||
_, err := Tester.Client.System.SetLimits(SystemCTX, &system.SetLimitsRequest{
|
||||
InstanceId: instanceID,
|
||||
Block: gu.Ptr(true),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
// The following call ensures that an undefined bool is not deserialized to false
|
||||
_, err = Tester.Client.System.SetLimits(SystemCTX, &system.SetLimitsRequest{
|
||||
InstanceId: instanceID,
|
||||
AuditLogRetention: durationpb.New(time.Hour),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
for _, tt := range tests {
|
||||
var isFirst bool
|
||||
t.Run(tt.name+" with blocking", func(t *testing.T) {
|
||||
isFirst = isFirst || !t.Skipped()
|
||||
testBlockingAPI(t, tt, true, isFirst)
|
||||
})
|
||||
}
|
||||
_, err = Tester.Client.System.SetLimits(SystemCTX, &system.SetLimitsRequest{
|
||||
InstanceId: instanceID,
|
||||
Block: gu.Ptr(false),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
for _, tt := range tests {
|
||||
var isFirst bool
|
||||
t.Run(tt.name+" without blocking", func(t *testing.T) {
|
||||
isFirst = isFirst || !t.Skipped()
|
||||
testBlockingAPI(t, tt, false, isFirst)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type test struct {
|
||||
name string
|
||||
testHttp func(t assert.TestingT) (req *http.Request, err error, assertResponse func(t assert.TestingT, response *http.Response, expectBlocked bool))
|
||||
testGrpc func(t assert.TestingT, expectBlocked bool)
|
||||
}
|
||||
|
||||
func testBlockingAPI(t *testing.T, tt *test, expectBlocked bool, isFirst bool) {
|
||||
req, err, assertResponse := tt.testHttp(t)
|
||||
require.NoError(t, err)
|
||||
testHTTP := func(tt assert.TestingT) {
|
||||
resp, err := (&http.Client{
|
||||
// Don't follow redirects
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}).Do(req)
|
||||
defer func() {
|
||||
require.NoError(t, resp.Body.Close())
|
||||
}()
|
||||
require.NoError(t, err)
|
||||
assertResponse(t, resp, expectBlocked)
|
||||
}
|
||||
if isFirst {
|
||||
// limits are eventually consistent, so we need to wait for the blocking to be set on the first test
|
||||
assert.EventuallyWithT(t, func(c *assert.CollectT) {
|
||||
testHTTP(c)
|
||||
}, 15*time.Second, time.Second, "wait for blocking to be set")
|
||||
} else {
|
||||
testHTTP(t)
|
||||
}
|
||||
if tt.testGrpc != nil {
|
||||
tt.testGrpc(t, expectBlocked)
|
||||
}
|
||||
}
|
||||
|
||||
func publicAPIBlockingTest(domain string) *test {
|
||||
return &test{
|
||||
name: "public API",
|
||||
testGrpc: func(tt assert.TestingT, expectBlocked bool) {
|
||||
conn, err := grpc.DialContext(CTX, net.JoinHostPort(domain, "8080"),
|
||||
grpc.WithBlock(),
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
)
|
||||
assert.NoError(tt, err)
|
||||
_, err = admin.NewAdminServiceClient(conn).Healthz(CTX, &admin.HealthzRequest{})
|
||||
assertGrpcError(tt, err, expectBlocked)
|
||||
},
|
||||
testHttp: func(tt assert.TestingT) (*http.Request, error, func(assert.TestingT, *http.Response, bool)) {
|
||||
req, err := http.NewRequestWithContext(
|
||||
CTX,
|
||||
"GET",
|
||||
fmt.Sprintf("http://%s/admin/v1/healthz", net.JoinHostPort(domain, "8080")),
|
||||
nil,
|
||||
)
|
||||
return req, err, func(ttt assert.TestingT, response *http.Response, expectBlocked bool) {
|
||||
assertLimitResponse(ttt, response, expectBlocked)
|
||||
assertSetLimitingCookie(ttt, response, expectBlocked)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// If expectSet is true, we expect the cookie to be set
|
||||
// If expectSet is false, we expect the cookie to be deleted
|
||||
func assertSetLimitingCookie(t assert.TestingT, response *http.Response, expectSet bool) {
|
||||
for _, cookie := range response.Cookies() {
|
||||
if cookie.Name == "zitadel.quota.exhausted" {
|
||||
if expectSet {
|
||||
assert.Greater(t, cookie.MaxAge, 0)
|
||||
} else {
|
||||
assert.LessOrEqual(t, cookie.MaxAge, 0)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
assert.FailNow(t, "cookie not found")
|
||||
}
|
||||
|
||||
func assertGrpcError(t assert.TestingT, err error, expectBlocked bool) {
|
||||
if expectBlocked {
|
||||
assert.Equal(t, codes.ResourceExhausted, status.Convert(err).Code())
|
||||
return
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func assertLimitResponse(t assert.TestingT, response *http.Response, expectBlocked bool) {
|
||||
if expectBlocked {
|
||||
assert.Equal(t, http.StatusTooManyRequests, response.StatusCode)
|
||||
return
|
||||
}
|
||||
assert.GreaterOrEqual(t, response.StatusCode, 200)
|
||||
assert.Less(t, response.StatusCode, 300)
|
||||
}
|
||||
|
||||
func idpExistsCondition(t assert.TestingT, instanceID, idpName string) func() bool {
|
||||
return func() bool {
|
||||
nameQuery, err := query.NewIDPTemplateNameSearchQuery(query.TextEquals, idpName)
|
||||
assert.NoError(t, err)
|
||||
instanceQuery, err := query.NewIDPTemplateResourceOwnerSearchQuery(instanceID)
|
||||
assert.NoError(t, err)
|
||||
idps, err := Tester.Queries.IDPTemplates(authz.WithInstanceID(CTX, instanceID), &query.IDPTemplateSearchQueries{
|
||||
Queries: []query.SearchQuery{
|
||||
instanceQuery,
|
||||
nameQuery,
|
||||
},
|
||||
}, false)
|
||||
assert.NoError(t, err)
|
||||
return len(idps.Templates) > 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
//go:build integration
|
||||
|
||||
package system_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/muhlemmer/gu"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/integration"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/system"
|
||||
)
|
||||
|
||||
func TestServer_Limits_Bulk(t *testing.T) {
|
||||
const len = 5
|
||||
type instance struct{ domain, id string }
|
||||
instances := make([]*instance, len)
|
||||
for i := 0; i < len; i++ {
|
||||
domain := integration.RandString(5) + ".integration.localhost"
|
||||
resp, err := Tester.Client.System.CreateInstance(SystemCTX, &system.CreateInstanceRequest{
|
||||
InstanceName: "testinstance",
|
||||
CustomDomain: domain,
|
||||
Owner: &system.CreateInstanceRequest_Machine_{
|
||||
Machine: &system.CreateInstanceRequest_Machine{
|
||||
UserName: "owner",
|
||||
Name: "owner",
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
instances[i] = &instance{domain, resp.GetInstanceId()}
|
||||
}
|
||||
resp, err := Tester.Client.System.BulkSetLimits(SystemCTX, &system.BulkSetLimitsRequest{
|
||||
Limits: []*system.SetLimitsRequest{{
|
||||
InstanceId: instances[0].id,
|
||||
Block: gu.Ptr(true),
|
||||
}, {
|
||||
InstanceId: instances[1].id,
|
||||
Block: gu.Ptr(false),
|
||||
}, {
|
||||
InstanceId: instances[2].id,
|
||||
Block: gu.Ptr(true),
|
||||
}, {
|
||||
InstanceId: instances[3].id,
|
||||
Block: gu.Ptr(false),
|
||||
}, {
|
||||
InstanceId: instances[4].id,
|
||||
Block: gu.Ptr(true),
|
||||
}},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
details := resp.GetTargetDetails()
|
||||
require.Len(t, details, len)
|
||||
t.Run("the first instance is blocked", func(t *testing.T) {
|
||||
require.Equal(t, instances[0].id, details[0].GetResourceOwner(), "resource owner must be instance id")
|
||||
testBlockingAPI(t, publicAPIBlockingTest(instances[0].domain), true, true)
|
||||
})
|
||||
t.Run("the second instance isn't blocked", func(t *testing.T) {
|
||||
require.Equal(t, instances[1].id, details[1].GetResourceOwner(), "resource owner must be instance id")
|
||||
testBlockingAPI(t, publicAPIBlockingTest(instances[1].domain), false, true)
|
||||
})
|
||||
t.Run("the third instance is blocked", func(t *testing.T) {
|
||||
require.Equal(t, instances[2].id, details[2].GetResourceOwner(), "resource owner must be instance id")
|
||||
testBlockingAPI(t, publicAPIBlockingTest(instances[2].domain), true, true)
|
||||
})
|
||||
t.Run("the fourth instance isn't blocked", func(t *testing.T) {
|
||||
require.Equal(t, instances[3].id, details[3].GetResourceOwner(), "resource owner must be instance id")
|
||||
testBlockingAPI(t, publicAPIBlockingTest(instances[3].domain), false, true)
|
||||
})
|
||||
t.Run("the fifth instance is blocked", func(t *testing.T) {
|
||||
require.Equal(t, instances[4].id, details[4].GetResourceOwner(), "resource owner must be instance id")
|
||||
testBlockingAPI(t, publicAPIBlockingTest(instances[4].domain), true, true)
|
||||
})
|
||||
}
|
||||
+10
-11
@@ -1,6 +1,6 @@
|
||||
//go:build integration
|
||||
|
||||
package system_test
|
||||
package quotas_enabled_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -23,13 +23,12 @@ import (
|
||||
var callURL = "http://localhost:" + integration.PortQuotaServer
|
||||
|
||||
func TestServer_QuotaNotification_Limit(t *testing.T) {
|
||||
_, instanceID, iamOwnerCtx := Tester.UseIsolatedInstance(t, CTX, SystemCTX)
|
||||
amount := 10
|
||||
percent := 50
|
||||
percentAmount := amount * percent / 100
|
||||
|
||||
_, err := Tester.Client.System.SetQuota(SystemCTX, &system.SetQuotaRequest{
|
||||
InstanceId: instanceID,
|
||||
InstanceId: Tester.Instance.InstanceID(),
|
||||
Unit: quota_pb.Unit_UNIT_REQUESTS_ALL_AUTHENTICATED,
|
||||
From: timestamppb.Now(),
|
||||
ResetInterval: durationpb.New(time.Minute * 5),
|
||||
@@ -51,23 +50,23 @@ func TestServer_QuotaNotification_Limit(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
for i := 0; i < percentAmount; i++ {
|
||||
_, err := Tester.Client.Admin.GetDefaultOrg(iamOwnerCtx, &admin.GetDefaultOrgRequest{})
|
||||
_, err := Tester.Client.Admin.GetDefaultOrg(IAMOwnerCTX, &admin.GetDefaultOrgRequest{})
|
||||
require.NoErrorf(t, err, "error in %d call of %d", i, percentAmount)
|
||||
}
|
||||
awaitNotification(t, Tester.QuotaNotificationChan, quota.RequestsAllAuthenticated, percent)
|
||||
|
||||
for i := 0; i < (amount - percentAmount); i++ {
|
||||
_, err := Tester.Client.Admin.GetDefaultOrg(iamOwnerCtx, &admin.GetDefaultOrgRequest{})
|
||||
_, err := Tester.Client.Admin.GetDefaultOrg(IAMOwnerCTX, &admin.GetDefaultOrgRequest{})
|
||||
require.NoErrorf(t, err, "error in %d call of %d", i, percentAmount)
|
||||
}
|
||||
awaitNotification(t, Tester.QuotaNotificationChan, quota.RequestsAllAuthenticated, 100)
|
||||
|
||||
_, limitErr := Tester.Client.Admin.GetDefaultOrg(iamOwnerCtx, &admin.GetDefaultOrgRequest{})
|
||||
_, limitErr := Tester.Client.Admin.GetDefaultOrg(IAMOwnerCTX, &admin.GetDefaultOrgRequest{})
|
||||
require.Error(t, limitErr)
|
||||
}
|
||||
|
||||
func TestServer_QuotaNotification_NoLimit(t *testing.T) {
|
||||
_, instanceID, iamOwnerCtx := Tester.UseIsolatedInstance(t, CTX, SystemCTX)
|
||||
_, instanceID, IAMOwnerCTX := Tester.UseIsolatedInstance(t, CTX, SystemCTX)
|
||||
amount := 10
|
||||
percent := 50
|
||||
percentAmount := amount * percent / 100
|
||||
@@ -95,24 +94,24 @@ func TestServer_QuotaNotification_NoLimit(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
for i := 0; i < percentAmount; i++ {
|
||||
_, err := Tester.Client.Admin.GetDefaultOrg(iamOwnerCtx, &admin.GetDefaultOrgRequest{})
|
||||
_, err := Tester.Client.Admin.GetDefaultOrg(IAMOwnerCTX, &admin.GetDefaultOrgRequest{})
|
||||
require.NoErrorf(t, err, "error in %d call of %d", i, percentAmount)
|
||||
}
|
||||
awaitNotification(t, Tester.QuotaNotificationChan, quota.RequestsAllAuthenticated, percent)
|
||||
|
||||
for i := 0; i < (amount - percentAmount); i++ {
|
||||
_, err := Tester.Client.Admin.GetDefaultOrg(iamOwnerCtx, &admin.GetDefaultOrgRequest{})
|
||||
_, err := Tester.Client.Admin.GetDefaultOrg(IAMOwnerCTX, &admin.GetDefaultOrgRequest{})
|
||||
require.NoErrorf(t, err, "error in %d call of %d", i, percentAmount)
|
||||
}
|
||||
awaitNotification(t, Tester.QuotaNotificationChan, quota.RequestsAllAuthenticated, 100)
|
||||
|
||||
for i := 0; i < amount; i++ {
|
||||
_, err := Tester.Client.Admin.GetDefaultOrg(iamOwnerCtx, &admin.GetDefaultOrgRequest{})
|
||||
_, err := Tester.Client.Admin.GetDefaultOrg(IAMOwnerCTX, &admin.GetDefaultOrgRequest{})
|
||||
require.NoErrorf(t, err, "error in %d call of %d", i, percentAmount)
|
||||
}
|
||||
awaitNotification(t, Tester.QuotaNotificationChan, quota.RequestsAllAuthenticated, 200)
|
||||
|
||||
_, limitErr := Tester.Client.Admin.GetDefaultOrg(iamOwnerCtx, &admin.GetDefaultOrgRequest{})
|
||||
_, limitErr := Tester.Client.Admin.GetDefaultOrg(IAMOwnerCTX, &admin.GetDefaultOrgRequest{})
|
||||
require.NoError(t, limitErr)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
//go:build integration
|
||||
|
||||
package quotas_enabled_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/integration"
|
||||
)
|
||||
|
||||
var (
|
||||
CTX context.Context
|
||||
SystemCTX context.Context
|
||||
IAMOwnerCTX context.Context
|
||||
Tester *integration.Tester
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
os.Exit(func() int {
|
||||
ctx, _, cancel := integration.Contexts(5 * time.Minute)
|
||||
defer cancel()
|
||||
CTX = ctx
|
||||
|
||||
Tester = integration.NewTester(ctx, `
|
||||
Quotas:
|
||||
Access:
|
||||
Enabled: true
|
||||
`)
|
||||
defer Tester.Done()
|
||||
SystemCTX = Tester.WithAuthorization(ctx, integration.SystemUser)
|
||||
IAMOwnerCTX = Tester.WithAuthorization(ctx, integration.IAMOwner)
|
||||
return m.Run()
|
||||
}())
|
||||
}
|
||||
Reference in New Issue
Block a user