mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-22 22:07:47 +00:00
fixup! fixup! fixup! fixup! fixup! fixup! fixup! Merge branch 'main' into syste-users-permissions
Tims requested changes
This commit is contained in:
@@ -28,8 +28,10 @@ type Migration struct {
|
||||
Machine *id.Config
|
||||
}
|
||||
|
||||
//go:embed defaults.yaml
|
||||
var defaultConfig []byte
|
||||
var (
|
||||
//go:embed defaults.yaml
|
||||
defaultConfig []byte
|
||||
)
|
||||
|
||||
func mustNewMigrationConfig(v *viper.Viper) *Migration {
|
||||
config := new(Migration)
|
||||
|
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
type InitPermittedOrgsFunction52 struct {
|
||||
eventstoreClient *database.DB
|
||||
dbClient *database.DB
|
||||
}
|
||||
|
||||
//go:embed 52/*.sql
|
||||
@@ -25,7 +25,7 @@ func (mig *InitPermittedOrgsFunction52) Execute(ctx context.Context, _ eventstor
|
||||
}
|
||||
for _, stmt := range statements {
|
||||
logging.WithFields("file", stmt.file, "migration", mig.String()).Info("execute statement")
|
||||
if _, err := mig.eventstoreClient.ExecContext(ctx, stmt.query); err != nil {
|
||||
if _, err := mig.dbClient.ExecContext(ctx, stmt.query); err != nil {
|
||||
return fmt.Errorf("%s %s: %w", mig.String(), stmt.file, err)
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,22 @@ DROP FUNCTION IF EXISTS eventstore.get_system_permissions;
|
||||
|
||||
CREATE OR REPLACE FUNCTION eventstore.get_system_permissions(
|
||||
permissions_json JSONB
|
||||
/*
|
||||
[
|
||||
{
|
||||
"member_type": "System",
|
||||
"aggregate_id": "",
|
||||
"object_id": "",
|
||||
"permissions": ["iam.read", "iam.write", "iam.polic.read"]
|
||||
},
|
||||
{
|
||||
"member_type": "IAM",
|
||||
"aggregate_id": "310716990375453665",
|
||||
"object_id": "",
|
||||
"permissions": ["iam.read", "iam.write", "iam.polic.read"]
|
||||
}
|
||||
]
|
||||
*/
|
||||
, permm TEXT
|
||||
)
|
||||
RETURNS TABLE (
|
||||
|
@@ -1,3 +1,111 @@
|
||||
DROP FUNCTION IF EXISTS eventstore.check_system_user_perms;
|
||||
|
||||
CREATE OR REPLACE FUNCTION eventstore.check_system_user_perms(
|
||||
system_user_perms JSONB
|
||||
, perm TEXT
|
||||
, filter_orgs TEXT
|
||||
|
||||
, org_ids OUT TEXT[]
|
||||
)
|
||||
LANGUAGE 'plpgsql'
|
||||
AS $$
|
||||
DECLARE
|
||||
has_instance_or_iam_permission bool;
|
||||
member_type_found bool;
|
||||
aggregate_ids TEXT;
|
||||
check_aggregates bool;
|
||||
BEGIN
|
||||
|
||||
DROP TABLE IF EXISTS matching_system_user_perms;
|
||||
CREATE TEMPORARY TABLE matching_system_user_perms (
|
||||
member_type TEXT,
|
||||
aggregate_id TEXT,
|
||||
object_id TEXT
|
||||
) ON COMMIT DROP;
|
||||
|
||||
INSERT INTO matching_system_user_perms
|
||||
(SELECT * FROM eventstore.get_system_permissions(system_user_perms, perm));
|
||||
|
||||
-- System member type
|
||||
SELECT TRUE INTO member_type_found
|
||||
FROM matching_system_user_perms msup
|
||||
WHERE msup.member_type = 'System'
|
||||
LIMIT 1;
|
||||
|
||||
IF member_type_found THEN
|
||||
-- Return all organizations or only those in filter_orgs
|
||||
SELECT array_agg(o.org_id) INTO org_ids
|
||||
FROM eventstore.instance_orgs o
|
||||
WHERE
|
||||
CASE WHEN filter_orgs != ''
|
||||
THEN o.org_id IN (filter_orgs)
|
||||
ELSE TRUE END;
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
-- IAM member type
|
||||
SELECT TRUE, array_agg(msup.aggregate_id) INTO member_type_found, aggregate_ids
|
||||
FROM matching_system_user_perms msup
|
||||
WHERE msup.member_type = 'IAM'
|
||||
GROUP BY msup.member_type
|
||||
LIMIT 1;
|
||||
|
||||
IF member_type_found THEN
|
||||
IF (SELECT FALSE WHERE '' = ANY (aggregate_ids::TEXT[])) = FALSE THEN
|
||||
check_aggregates := FALSE;
|
||||
ELSE
|
||||
check_aggregates := TRUE;
|
||||
END IF;
|
||||
|
||||
-- Return all organizations or only those in filter_orgs
|
||||
SELECT array_agg(o.org_id) INTO org_ids
|
||||
FROM eventstore.instance_orgs o
|
||||
WHERE CASE
|
||||
WHEN check_aggregates THEN
|
||||
o.instance_id = ANY (aggregate_ids::TEXT[])
|
||||
ELSE
|
||||
TRUE
|
||||
END
|
||||
AND CASE WHEN filter_orgs != ''
|
||||
THEN o.org_id IN (filter_orgs)
|
||||
ELSE TRUE END;
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
-- Organization member type
|
||||
SELECT TRUE, array_agg(msup.aggregate_id) INTO member_type_found, aggregate_ids
|
||||
FROM matching_system_user_perms msup
|
||||
WHERE msup.member_type = 'Organization'
|
||||
GROUP BY msup.member_type
|
||||
LIMIT 1;
|
||||
|
||||
IF member_type_found THEN
|
||||
member_type_found := FALSE;
|
||||
-- if any of the aggregate_ids = '', then we search on all organization
|
||||
IF (SELECT FALSE WHERE '' = ANY (aggregate_ids::TEXT[])) = FALSE THEN
|
||||
check_aggregates := FALSE;
|
||||
ELSE
|
||||
check_aggregates := TRUE;
|
||||
END IF;
|
||||
|
||||
-- Return all organizations or only those in filter_orgs
|
||||
SELECT array_agg(o.org_id) INTO org_ids
|
||||
FROM eventstore.instance_orgs o
|
||||
WHERE
|
||||
CASE
|
||||
WHEN check_aggregates THEN
|
||||
o.org_id = ANY (aggregate_ids::TEXT[])
|
||||
ELSE
|
||||
TRUE
|
||||
END
|
||||
AND CASE WHEN filter_orgs != ''
|
||||
THEN o.org_id IN (filter_orgs)
|
||||
ELSE TRUE END;
|
||||
RETURN;
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
|
||||
DROP FUNCTION IF EXISTS eventstore.permitted_orgs;
|
||||
|
||||
CREATE OR REPLACE FUNCTION eventstore.permitted_orgs(
|
||||
@@ -14,104 +122,9 @@ AS $$
|
||||
BEGIN
|
||||
|
||||
-- if system user
|
||||
IF jsonb_array_length(system_user_perms) != 0 THEN
|
||||
DECLARE
|
||||
has_instance_or_iam_permission bool;
|
||||
member_type_found bool;
|
||||
aggregate_ids TEXT;
|
||||
check_aggregates bool;
|
||||
BEGIN
|
||||
|
||||
DROP TABLE IF EXISTS matching_system_user_perms;
|
||||
CREATE TEMPORARY TABLE matching_system_user_perms (
|
||||
member_type TEXT,
|
||||
aggregate_id TEXT,
|
||||
object_id TEXT
|
||||
) ON COMMIT DROP;
|
||||
|
||||
|
||||
INSERT INTO matching_system_user_perms
|
||||
(SELECT * FROM eventstore.get_system_permissions(system_user_perms, perm));
|
||||
|
||||
-- System member type
|
||||
SELECT TRUE INTO member_type_found
|
||||
FROM matching_system_user_perms msup
|
||||
WHERE msup.member_type = 'System'
|
||||
LIMIT 1;
|
||||
|
||||
IF member_type_found THEN
|
||||
-- Return all organizations or only those in filter_orgs
|
||||
SELECT array_agg(o.org_id) INTO org_ids
|
||||
FROM eventstore.instance_orgs o
|
||||
WHERE
|
||||
CASE WHEN filter_orgs != ''
|
||||
THEN o.org_id IN (filter_orgs)
|
||||
ELSE TRUE END;
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
-- IAM member type
|
||||
SELECT TRUE, array_agg(msup.aggregate_id) INTO member_type_found, aggregate_ids
|
||||
FROM matching_system_user_perms msup
|
||||
WHERE msup.member_type = 'IAM'
|
||||
GROUP BY msup.member_type
|
||||
LIMIT 1;
|
||||
|
||||
IF member_type_found THEN
|
||||
IF (SELECT FALSE WHERE '' = ANY (aggregate_ids::TEXT[])) = FALSE THEN
|
||||
check_aggregates := FALSE;
|
||||
ELSE
|
||||
check_aggregates := TRUE;
|
||||
END IF;
|
||||
|
||||
-- Return all organizations or only those in filter_orgs
|
||||
SELECT array_agg(o.org_id) INTO org_ids
|
||||
FROM eventstore.instance_orgs o
|
||||
WHERE CASE
|
||||
WHEN check_aggregates THEN
|
||||
o.instance_id = ANY (aggregate_ids::TEXT[])
|
||||
ELSE
|
||||
TRUE
|
||||
END
|
||||
AND CASE WHEN filter_orgs != ''
|
||||
THEN o.org_id IN (filter_orgs)
|
||||
ELSE TRUE END;
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
-- Organization member type
|
||||
SELECT TRUE, array_agg(msup.aggregate_id) INTO member_type_found, aggregate_ids
|
||||
FROM matching_system_user_perms msup
|
||||
WHERE msup.member_type = 'Organization'
|
||||
GROUP BY msup.member_type
|
||||
LIMIT 1;
|
||||
|
||||
IF member_type_found THEN
|
||||
member_type_found := FALSE;
|
||||
-- if any of the aggregate_ids = '', then we search on all organization
|
||||
IF (SELECT FALSE WHERE '' = ANY (aggregate_ids::TEXT[])) = FALSE THEN
|
||||
check_aggregates := FALSE;
|
||||
ELSE
|
||||
check_aggregates := TRUE;
|
||||
END IF;
|
||||
|
||||
-- Return all organizations or only those in filter_orgs
|
||||
SELECT array_agg(o.org_id) INTO org_ids
|
||||
FROM eventstore.instance_orgs o
|
||||
WHERE
|
||||
CASE
|
||||
WHEN check_aggregates THEN
|
||||
o.org_id = ANY (aggregate_ids::TEXT[])
|
||||
ELSE
|
||||
TRUE
|
||||
END
|
||||
AND CASE WHEN filter_orgs != ''
|
||||
THEN o.org_id IN (filter_orgs)
|
||||
ELSE TRUE END;
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
END;
|
||||
IF system_user_perms IS NOT NULL THEN
|
||||
org_ids := eventstore.check_system_user_perms(system_user_perms, perm, filter_orgs)
|
||||
RETURN;
|
||||
ELSE
|
||||
DECLARE
|
||||
matched_roles TEXT[]; -- roles containing permission
|
||||
@@ -154,7 +167,6 @@ BEGIN
|
||||
AND om.instance_id = instanceID
|
||||
AND om.user_id = userId
|
||||
) AS sub;
|
||||
RETURN;
|
||||
END;
|
||||
END IF;
|
||||
END;
|
||||
|
@@ -12,7 +12,7 @@ import (
|
||||
"github.com/zitadel/zitadel/cmd/encryption"
|
||||
"github.com/zitadel/zitadel/cmd/hooks"
|
||||
"github.com/zitadel/zitadel/internal/actions"
|
||||
internal_authz "github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/api/oidc"
|
||||
"github.com/zitadel/zitadel/internal/api/ui/login"
|
||||
"github.com/zitadel/zitadel/internal/cache/connector"
|
||||
@@ -33,7 +33,8 @@ type Config struct {
|
||||
Database database.Config
|
||||
Caches *connector.CachesConfig
|
||||
SystemDefaults systemdefaults.SystemDefaults
|
||||
InternalAuthZ internal_authz.Config
|
||||
InternalAuthZ authz.Config
|
||||
SystemAuthZ authz.Config
|
||||
ExternalDomain string
|
||||
ExternalPort uint16
|
||||
ExternalSecure bool
|
||||
@@ -51,7 +52,7 @@ type Config struct {
|
||||
Login login.Config
|
||||
WebAuthNName string
|
||||
Telemetry *handlers.TelemetryPusherConfig
|
||||
SystemAPIUsers map[string]*internal_authz.SystemAPIUser
|
||||
SystemAPIUsers map[string]*authz.SystemAPIUser
|
||||
}
|
||||
|
||||
type InitProjections struct {
|
||||
@@ -66,12 +67,12 @@ func MustNewConfig(v *viper.Viper) *Config {
|
||||
err := v.Unmarshal(config,
|
||||
viper.DecodeHook(mapstructure.ComposeDecodeHookFunc(
|
||||
hooks.SliceTypeStringDecode[*domain.CustomMessageText],
|
||||
hooks.SliceTypeStringDecode[internal_authz.RoleMapping],
|
||||
hooks.MapTypeStringDecode[string, *internal_authz.SystemAPIUser],
|
||||
hooks.SliceTypeStringDecode[authz.RoleMapping],
|
||||
hooks.MapTypeStringDecode[string, *authz.SystemAPIUser],
|
||||
hooks.MapHTTPHeaderStringDecode,
|
||||
database.DecodeHook,
|
||||
actions.HTTPConfigDecodeHook,
|
||||
hook.EnumHookFunc(internal_authz.MemberTypeString),
|
||||
hook.EnumHookFunc(authz.MemberTypeString),
|
||||
hook.Base64ToBytesHookFunc(),
|
||||
hook.TagToLanguageHookFunc(),
|
||||
mapstructure.StringToTimeDurationHookFunc(),
|
||||
|
@@ -178,7 +178,7 @@ func Setup(ctx context.Context, config *Config, steps *Steps, masterKey string)
|
||||
steps.s49InitPermittedOrgsFunction = &InitPermittedOrgsFunction{eventstoreClient: dbClient}
|
||||
steps.s50IDPTemplate6UsePKCE = &IDPTemplate6UsePKCE{dbClient: dbClient}
|
||||
steps.s51IDPTemplate6RootCA = &IDPTemplate6RootCA{dbClient: dbClient}
|
||||
steps.s52InitPermittedOrgsFunction = &InitPermittedOrgsFunction52{eventstoreClient: dbClient}
|
||||
steps.s52InitPermittedOrgsFunction = &InitPermittedOrgsFunction52{dbClient: dbClient}
|
||||
|
||||
err = projection.Create(ctx, dbClient, eventstoreClient, config.Projections, nil, nil, nil)
|
||||
logging.OnError(err).Fatal("unable to start projections")
|
||||
@@ -412,7 +412,7 @@ func startCommandsQueries(
|
||||
sessionTokenVerifier,
|
||||
func(q *query.Queries) domain.PermissionCheck {
|
||||
return func(ctx context.Context, permission, orgID, resourceID string) (err error) {
|
||||
return internal_authz.CheckPermission(ctx, &authz_es.UserMembershipRepo{Queries: q}, nil, config.InternalAuthZ.RolePermissionMappings, permission, orgID, resourceID)
|
||||
return internal_authz.CheckPermission(ctx, &authz_es.UserMembershipRepo{Queries: q}, config.SystemAuthZ.RolePermissionMappings, config.InternalAuthZ.RolePermissionMappings, permission, orgID, resourceID)
|
||||
}
|
||||
},
|
||||
0, // not needed for projections
|
||||
@@ -437,7 +437,7 @@ func startCommandsQueries(
|
||||
authZRepo, err := authz.Start(queries, eventstoreClient, dbClient, keys.OIDC, config.ExternalSecure)
|
||||
logging.OnError(err).Fatal("unable to start authz repo")
|
||||
permissionCheck := func(ctx context.Context, permission, orgID, resourceID string) (err error) {
|
||||
return internal_authz.CheckPermission(ctx, authZRepo, nil, config.InternalAuthZ.RolePermissionMappings, permission, orgID, resourceID)
|
||||
return internal_authz.CheckPermission(ctx, authZRepo, config.SystemAuthZ.RolePermissionMappings, config.InternalAuthZ.RolePermissionMappings, permission, orgID, resourceID)
|
||||
}
|
||||
|
||||
commands, err := command.StartCommands(ctx,
|
||||
|
@@ -495,7 +495,7 @@ func startAPIs(
|
||||
}
|
||||
instanceInterceptor := middleware.InstanceInterceptor(queries, config.ExternalDomain, login.IgnoreInstanceEndpoints...)
|
||||
assetsCache := middleware.AssetsCacheInterceptor(config.AssetStorage.Cache.MaxAge, config.AssetStorage.Cache.SharedMaxAge)
|
||||
apis.RegisterHandlerOnPrefix(assets.HandlerPrefix, assets.NewHandler(commands, verifier, config.InternalAuthZ, id.SonyFlakeGenerator(), store, queries, middleware.CallDurationHandler, instanceInterceptor.Handler, assetsCache.Handler, limitingAccessInterceptor.Handle))
|
||||
apis.RegisterHandlerOnPrefix(assets.HandlerPrefix, assets.NewHandler(commands, verifier, config.SystemAuthZ, config.InternalAuthZ, id.SonyFlakeGenerator(), store, queries, middleware.CallDurationHandler, instanceInterceptor.Handler, assetsCache.Handler, limitingAccessInterceptor.Handle))
|
||||
|
||||
apis.RegisterHandlerOnPrefix(idp.HandlerPrefix, idp.NewHandler(commands, queries, keys.IDPConfig, instanceInterceptor.Handler))
|
||||
|
||||
@@ -539,7 +539,7 @@ func startAPIs(
|
||||
keys.User,
|
||||
&config.SCIM,
|
||||
instanceInterceptor.HandlerFuncWithError,
|
||||
middleware.AuthorizationInterceptor(verifier, config.InternalAuthZ).HandlerFuncWithError))
|
||||
middleware.AuthorizationInterceptor(verifier, config.SystemAuthZ, config.InternalAuthZ).HandlerFuncWithError))
|
||||
|
||||
c, err := console.Start(config.Console, config.ExternalSecure, oidcServer.IssuerFromRequest, middleware.CallDurationHandler, instanceInterceptor.Handler, limitingAccessInterceptor, config.CustomerPortal)
|
||||
if err != nil {
|
||||
|
@@ -94,13 +94,13 @@ func DefaultErrorHandler(translator *i18n.Translator) func(w http.ResponseWriter
|
||||
}
|
||||
}
|
||||
|
||||
func NewHandler(commands *command.Commands, verifier authz.APITokenVerifier, authConfig authz.Config, idGenerator id.Generator, storage static.Storage, queries *query.Queries, callDurationInterceptor, instanceInterceptor, assetCacheInterceptor, accessInterceptor func(handler http.Handler) http.Handler) http.Handler {
|
||||
func NewHandler(commands *command.Commands, verifier authz.APITokenVerifier, systemAuthCOnfig authz.Config, authConfig authz.Config, idGenerator id.Generator, storage static.Storage, queries *query.Queries, callDurationInterceptor, instanceInterceptor, assetCacheInterceptor, accessInterceptor func(handler http.Handler) http.Handler) http.Handler {
|
||||
translator, err := i18n.NewZitadelTranslator(language.English)
|
||||
logging.OnError(err).Panic("unable to get translator")
|
||||
h := &Handler{
|
||||
commands: commands,
|
||||
errorHandler: DefaultErrorHandler(translator),
|
||||
authInterceptor: http_mw.AuthorizationInterceptor(verifier, authConfig),
|
||||
authInterceptor: http_mw.AuthorizationInterceptor(verifier, systemAuthCOnfig, authConfig),
|
||||
idGenerator: idGenerator,
|
||||
storage: storage,
|
||||
query: queries,
|
||||
@@ -129,8 +129,10 @@ func (l *publicFileDownloader) ResourceOwner(_ context.Context, ownerPath string
|
||||
return ownerPath
|
||||
}
|
||||
|
||||
const maxMemory = 2 << 20
|
||||
const paramFile = "file"
|
||||
const (
|
||||
maxMemory = 2 << 20
|
||||
paramFile = "file"
|
||||
)
|
||||
|
||||
func UploadHandleFunc(s AssetsService, uploader Uploader) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@@ -2,12 +2,12 @@ package authz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
@@ -167,7 +167,7 @@ func addGetSystemUserRolesFuncToCtx(ctx context.Context, systemUserRoleMap []Rol
|
||||
slices.Sort(permissions)
|
||||
permissions = slices.Compact(permissions)
|
||||
|
||||
systemUserPermissionsDbJsonQueryStruct[i].MemberType = MemberTypeServerToMemberTypeDBMap[systemPerm.MemberType]
|
||||
systemUserPermissionsDbJsonQueryStruct[i].MemberType = systemPerm.MemberType.String()
|
||||
systemUserPermissionsDbJsonQueryStruct[i].AggregateID = systemPerm.AggregateID
|
||||
systemUserPermissionsDbJsonQueryStruct[i].Permissions = permissions
|
||||
}
|
||||
@@ -178,14 +178,15 @@ func addGetSystemUserRolesFuncToCtx(ctx context.Context, systemUserRoleMap []Rol
|
||||
return ctx
|
||||
}
|
||||
|
||||
func GetSystemUserPermissions(ctx context.Context) ([]SystemUserPermissionsDBQuery, error) {
|
||||
func GetSystemUserPermissions(ctx context.Context) []SystemUserPermissionsDBQuery {
|
||||
getSystemUserRolesFuncValue := ctx.Value(systemUserRolesFuncKey)
|
||||
if getSystemUserRolesFuncValue == nil {
|
||||
return nil, nil
|
||||
return nil
|
||||
}
|
||||
getSystemUserRolesFunc, ok := getSystemUserRolesFuncValue.(func(context.Context) []SystemUserPermissionsDBQuery)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to obtain systems role func")
|
||||
logging.WithFields("Authz").Error("unable to cast []SystemUserPermissionsDBQuery")
|
||||
return nil
|
||||
}
|
||||
return getSystemUserRolesFunc(ctx), nil
|
||||
return getSystemUserRolesFunc(ctx)
|
||||
}
|
||||
|
@@ -56,9 +56,6 @@ type Membership struct {
|
||||
ObjectID string
|
||||
|
||||
Roles []string
|
||||
|
||||
// aggregate all the permissions for each role
|
||||
Permissions []string
|
||||
}
|
||||
|
||||
type MemberType int32
|
||||
@@ -72,12 +69,6 @@ const (
|
||||
MemberTypeSystem
|
||||
)
|
||||
|
||||
var MemberTypeServerToMemberTypeDBMap map[MemberType]string = map[MemberType]string{
|
||||
MemberTypeSystem: "System",
|
||||
MemberTypeIAM: "IAM",
|
||||
MemberTypeOrganization: "Organization",
|
||||
}
|
||||
|
||||
type TokenVerifier interface {
|
||||
ExistsOrg(ctx context.Context, id, domain string) (string, error)
|
||||
ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (projectID string, origins []string, err error)
|
||||
|
@@ -14,14 +14,16 @@ import (
|
||||
)
|
||||
|
||||
type AuthInterceptor struct {
|
||||
verifier authz.APITokenVerifier
|
||||
authConfig authz.Config
|
||||
verifier authz.APITokenVerifier
|
||||
authConfig authz.Config
|
||||
systemAuthConfig authz.Config
|
||||
}
|
||||
|
||||
func AuthorizationInterceptor(verifier authz.APITokenVerifier, authConfig authz.Config) *AuthInterceptor {
|
||||
func AuthorizationInterceptor(verifier authz.APITokenVerifier, systemAuthConfig authz.Config, authConfig authz.Config) *AuthInterceptor {
|
||||
return &AuthInterceptor{
|
||||
verifier: verifier,
|
||||
authConfig: authConfig,
|
||||
verifier: verifier,
|
||||
authConfig: authConfig,
|
||||
systemAuthConfig: systemAuthConfig,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +33,7 @@ func (a *AuthInterceptor) Handler(next http.Handler) http.Handler {
|
||||
|
||||
func (a *AuthInterceptor) HandlerFunc(next http.Handler) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, err := authorize(r, a.verifier, a.authConfig)
|
||||
ctx, err := authorize(r, a.verifier, a.systemAuthConfig, a.authConfig)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
@@ -44,7 +46,7 @@ func (a *AuthInterceptor) HandlerFunc(next http.Handler) http.HandlerFunc {
|
||||
|
||||
func (a *AuthInterceptor) HandlerFuncWithError(next HandlerFuncWithError) HandlerFuncWithError {
|
||||
return func(w http.ResponseWriter, r *http.Request) error {
|
||||
ctx, err := authorize(r, a.verifier, a.authConfig)
|
||||
ctx, err := authorize(r, a.verifier, a.systemAuthConfig, a.authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -56,7 +58,7 @@ func (a *AuthInterceptor) HandlerFuncWithError(next HandlerFuncWithError) Handle
|
||||
|
||||
type httpReq struct{}
|
||||
|
||||
func authorize(r *http.Request, verifier authz.APITokenVerifier, authConfig authz.Config) (_ context.Context, err error) {
|
||||
func authorize(r *http.Request, verifier authz.APITokenVerifier, systemAuthConfig authz.Config, authConfig authz.Config) (_ context.Context, err error) {
|
||||
ctx := r.Context()
|
||||
|
||||
authOpt, needsToken := checkAuthMethod(r, verifier)
|
||||
@@ -71,8 +73,7 @@ func authorize(r *http.Request, verifier authz.APITokenVerifier, authConfig auth
|
||||
return nil, zerrors.ThrowUnauthenticated(nil, "AUT-1179", "auth header missing")
|
||||
}
|
||||
|
||||
// TODO look into this
|
||||
ctxSetter, err := authz.CheckUserAuthorization(authCtx, &httpReq{}, authToken, http_util.GetOrgID(r), "", verifier, nil, authConfig.RolePermissionMappings, authOpt, r.RequestURI)
|
||||
ctxSetter, err := authz.CheckUserAuthorization(authCtx, &httpReq{}, authToken, http_util.GetOrgID(r), "", verifier, systemAuthConfig.RolePermissionMappings, authConfig.RolePermissionMappings, authOpt, r.RequestURI)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/drone/envsubst"
|
||||
@@ -138,7 +139,7 @@ func machineID() (uint16, error) {
|
||||
errors = append(errors, "No machine identification method enabled.")
|
||||
}
|
||||
|
||||
// logging.WithFields("errors", strings.Join(errors, ", ")).Panic("none of the enabled methods for identifying the machine succeeded")
|
||||
logging.WithFields("errors", strings.Join(errors, ", ")).Panic("none of the enabled methods for identifying the machine succeeded")
|
||||
// this return will never happen because of panic one line before
|
||||
return 0, nil
|
||||
}
|
||||
|
@@ -108,179 +108,3 @@ SystemDefaults:
|
||||
KeyConfig:
|
||||
PrivateKeyLifetime: 7200h
|
||||
PublicKeyLifetime: 14400h
|
||||
|
||||
SystemAuthZ:
|
||||
RolePermissionMappings:
|
||||
- Role: "SYSTEM_OWNER"
|
||||
Permissions:
|
||||
- "system.instance.read"
|
||||
- "system.instance.write"
|
||||
- "system.instance.delete"
|
||||
- "system.domain.read"
|
||||
- "system.domain.write"
|
||||
- "system.domain.delete"
|
||||
- "system.debug.read"
|
||||
- "system.debug.write"
|
||||
- "system.debug.delete"
|
||||
- "system.feature.read"
|
||||
- "system.feature.write"
|
||||
- "system.feature.delete"
|
||||
- "system.limits.write"
|
||||
- "system.limits.delete"
|
||||
- "system.quota.write"
|
||||
- "system.quota.delete"
|
||||
- "system.iam.member.read"
|
||||
- Role: "IAM_OWNER"
|
||||
Permissions:
|
||||
- "iam.read"
|
||||
- "iam.write"
|
||||
- "iam.policy.read"
|
||||
- "iam.policy.write"
|
||||
- "iam.policy.delete"
|
||||
- "iam.member.read"
|
||||
- "iam.member.write"
|
||||
- "iam.member.delete"
|
||||
- "iam.idp.read"
|
||||
- "iam.idp.write"
|
||||
- "iam.idp.delete"
|
||||
- "iam.action.read"
|
||||
- "iam.action.write"
|
||||
- "iam.action.delete"
|
||||
- "iam.flow.read"
|
||||
- "iam.flow.write"
|
||||
- "iam.flow.delete"
|
||||
- "iam.feature.read"
|
||||
- "iam.feature.write"
|
||||
- "iam.feature.delete"
|
||||
- "iam.restrictions.read"
|
||||
- "iam.restrictions.write"
|
||||
- "iam.web_key.write"
|
||||
- "iam.web_key.delete"
|
||||
- "iam.web_key.read"
|
||||
- "iam.debug.write"
|
||||
- "iam.debug.read"
|
||||
- "org.read"
|
||||
- "org.global.read"
|
||||
- "org.create"
|
||||
- "org.write"
|
||||
- "org.delete"
|
||||
- "org.member.read"
|
||||
- "org.member.write"
|
||||
- "org.member.delete"
|
||||
- "org.idp.read"
|
||||
- "org.idp.write"
|
||||
- "org.idp.delete"
|
||||
- "org.action.read"
|
||||
- "org.action.write"
|
||||
- "org.action.delete"
|
||||
- "org.flow.read"
|
||||
- "org.flow.write"
|
||||
- "org.flow.delete"
|
||||
- "org.feature.read"
|
||||
- "org.feature.write"
|
||||
- "org.feature.delete"
|
||||
- "user.read"
|
||||
- "user.global.read"
|
||||
- "user.write"
|
||||
- "user.delete"
|
||||
- "user.grant.read"
|
||||
- "user.grant.write"
|
||||
- "user.grant.delete"
|
||||
- "user.membership.read"
|
||||
- "user.credential.write"
|
||||
- "user.passkey.write"
|
||||
- "user.feature.read"
|
||||
- "user.feature.write"
|
||||
- "user.feature.delete"
|
||||
- "policy.read"
|
||||
- "policy.write"
|
||||
- "policy.delete"
|
||||
- "project.read"
|
||||
- "project.create"
|
||||
- "project.write"
|
||||
- "project.delete"
|
||||
- "project.member.read"
|
||||
- "project.member.write"
|
||||
- "project.member.delete"
|
||||
- "project.role.read"
|
||||
- "project.role.write"
|
||||
- "project.role.delete"
|
||||
- "project.app.read"
|
||||
- "project.app.write"
|
||||
- "project.app.delete"
|
||||
- "project.grant.read"
|
||||
- "project.grant.write"
|
||||
- "project.grant.delete"
|
||||
- "project.grant.member.read"
|
||||
- "project.grant.member.write"
|
||||
- "project.grant.member.delete"
|
||||
- "events.read"
|
||||
- "milestones.read"
|
||||
- "session.read"
|
||||
- "session.delete"
|
||||
- "action.target.read"
|
||||
- "action.target.write"
|
||||
- "action.target.delete"
|
||||
- "action.execution.read"
|
||||
- "action.execution.write"
|
||||
- "userschema.read"
|
||||
- "userschema.write"
|
||||
- "userschema.delete"
|
||||
- "session.read"
|
||||
- "session.delete"
|
||||
- Role: "ORG_OWNER"
|
||||
Permissions:
|
||||
- "org.read"
|
||||
- "org.global.read"
|
||||
- "org.write"
|
||||
- "org.delete"
|
||||
- "org.member.read"
|
||||
- "org.member.write"
|
||||
- "org.member.delete"
|
||||
- "org.idp.read"
|
||||
- "org.idp.write"
|
||||
- "org.idp.delete"
|
||||
- "org.action.read"
|
||||
- "org.action.write"
|
||||
- "org.action.delete"
|
||||
- "org.flow.read"
|
||||
- "org.flow.write"
|
||||
- "org.flow.delete"
|
||||
- "org.feature.read"
|
||||
- "org.feature.write"
|
||||
- "org.feature.delete"
|
||||
- "user.read"
|
||||
- "user.global.read"
|
||||
- "user.write"
|
||||
- "user.delete"
|
||||
- "user.grant.read"
|
||||
- "user.grant.write"
|
||||
- "user.grant.delete"
|
||||
- "user.membership.read"
|
||||
- "user.credential.write"
|
||||
- "user.passkey.write"
|
||||
- "user.feature.read"
|
||||
- "user.feature.write"
|
||||
- "user.feature.delete"
|
||||
- "policy.read"
|
||||
- "policy.write"
|
||||
- "policy.delete"
|
||||
- "project.read"
|
||||
- "project.create"
|
||||
- "project.write"
|
||||
- "project.delete"
|
||||
- "project.member.read"
|
||||
- "project.member.write"
|
||||
- "project.member.delete"
|
||||
- "project.role.read"
|
||||
- "project.role.write"
|
||||
- "project.role.delete"
|
||||
- "project.app.read"
|
||||
- "project.app.write"
|
||||
- "project.grant.read"
|
||||
- "project.grant.write"
|
||||
- "project.grant.delete"
|
||||
- "project.grant.member.read"
|
||||
- "project.grant.member.write"
|
||||
- "project.grant.member.delete"
|
||||
- "session.delete"
|
||||
|
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -24,17 +25,18 @@ const (
|
||||
// and is typically the `resource_owner` column in ZITADEL.
|
||||
// We use full identifiers in the query builder so this function should be
|
||||
// called with something like `UserResourceOwnerCol.identifier()` for example.
|
||||
func wherePermittedOrgs(ctx context.Context, query sq.SelectBuilder, systemUserPermission []authz.SystemUserPermissionsDBQuery, filterOrgIds, orgIDColumn, permission string) (sq.SelectBuilder, error) {
|
||||
func wherePermittedOrgs(ctx context.Context, query sq.SelectBuilder, filterOrgIds, orgIDColumn, permission string) (sq.SelectBuilder, error) {
|
||||
userID := authz.GetCtxData(ctx).UserID
|
||||
logging.WithFields("permission_check_v2_flag", authz.GetFeatures(ctx).PermissionCheckV2, "org_id_column", orgIDColumn, "permission", permission, "user_id", userID).Debug("permitted orgs check used")
|
||||
|
||||
systemUserPermissionsJson := "[]"
|
||||
if systemUserPermission != nil {
|
||||
systemUserPermissionsBytes, err := json.Marshal(systemUserPermission)
|
||||
systemUserPermissions := authz.GetSystemUserPermissions(ctx)
|
||||
var systemUserPermissionsJson []byte
|
||||
if systemUserPermissions != nil {
|
||||
var err error
|
||||
systemUserPermissionsJson, err = json.Marshal(systemUserPermissions)
|
||||
if err != nil {
|
||||
return query, err
|
||||
return query, zerrors.ThrowInternal(err, "AUTHZ-HS4us", "Errors.Internal")
|
||||
}
|
||||
systemUserPermissionsJson = string(systemUserPermissionsBytes)
|
||||
}
|
||||
|
||||
return query.Where(
|
||||
@@ -42,23 +44,23 @@ func wherePermittedOrgs(ctx context.Context, query sq.SelectBuilder, systemUserP
|
||||
authz.GetInstance(ctx).InstanceID(),
|
||||
userID,
|
||||
systemUserPermissionsJson,
|
||||
systemUserPermission,
|
||||
permission,
|
||||
filterOrgIds,
|
||||
), nil
|
||||
}
|
||||
|
||||
func wherePermittedOrgsOrCurrentUser(ctx context.Context, query sq.SelectBuilder, systemUserPermission []authz.SystemUserPermissionsDBQuery, filterOrgIds, orgIDColumn, userIdColum, permission string) (sq.SelectBuilder, error) {
|
||||
func wherePermittedOrgsOrCurrentUser(ctx context.Context, query sq.SelectBuilder, filterOrgIds, orgIDColumn, userIdColum, permission string) (sq.SelectBuilder, error) {
|
||||
userID := authz.GetCtxData(ctx).UserID
|
||||
logging.WithFields("permission_check_v2_flag", authz.GetFeatures(ctx).PermissionCheckV2, "org_id_column", orgIDColumn, "user_id_colum", userIdColum, "permission", permission, "user_id", userID).Debug("permitted orgs check used")
|
||||
|
||||
systemUserPermissionsJson := "[]"
|
||||
if systemUserPermission != nil {
|
||||
systemUserPermissionsBytes, err := json.Marshal(systemUserPermission)
|
||||
systemUserPermissions := authz.GetSystemUserPermissions(ctx)
|
||||
var systemUserPermissionsJson []byte
|
||||
if systemUserPermissions != nil {
|
||||
var err error
|
||||
systemUserPermissionsJson, err = json.Marshal(systemUserPermissions)
|
||||
if err != nil {
|
||||
return query, err
|
||||
return query, zerrors.ThrowInternal(err, "AUTHZ-HS4us", "Errors.Internal")
|
||||
}
|
||||
systemUserPermissionsJson = string(systemUserPermissionsBytes)
|
||||
}
|
||||
|
||||
return query.Where(
|
||||
|
@@ -655,12 +655,7 @@ func (q *Queries) searchUsers(ctx context.Context, queries *UserSearchQueries, f
|
||||
UserInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||
})
|
||||
if permissionCheckV2 {
|
||||
// extract system user roles
|
||||
systemUserPermissions, err := authz.GetSystemUserPermissions(ctx)
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "QUERY-GS9gs", "Errors.Internal")
|
||||
}
|
||||
query, err = wherePermittedOrgsOrCurrentUser(ctx, query, systemUserPermissions, filterOrgIds, UserResourceOwnerCol.identifier(), UserIDCol.identifier(), domain.PermissionUserRead)
|
||||
query, err = wherePermittedOrgsOrCurrentUser(ctx, query, filterOrgIds, UserResourceOwnerCol.identifier(), UserIDCol.identifier(), domain.PermissionUserRead)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
Reference in New Issue
Block a user