mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-22 13:17:41 +00:00
fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! feat(permissions): Addeding system user support for permission check v2
This commit is contained in:
3
Makefile
3
Makefile
@@ -113,8 +113,7 @@ core_unit_test:
|
|||||||
|
|
||||||
.PHONY: core_integration_db_up
|
.PHONY: core_integration_db_up
|
||||||
core_integration_db_up:
|
core_integration_db_up:
|
||||||
# docker compose -f internal/integration/config/docker-compose.yaml up --pull always --wait $${INTEGRATION_DB_FLAVOR} cache
|
docker compose -f internal/integration/config/docker-compose.yaml up --pull always --wait $${INTEGRATION_DB_FLAVOR} cache
|
||||||
docker compose -f internal/integration/config/docker-compose.yaml up --wait $${INTEGRATION_DB_FLAVOR} cache
|
|
||||||
|
|
||||||
.PHONY: core_integration_db_down
|
.PHONY: core_integration_db_down
|
||||||
core_integration_db_down:
|
core_integration_db_down:
|
||||||
|
@@ -28,10 +28,8 @@ type Migration struct {
|
|||||||
Machine *id.Config
|
Machine *id.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
//go:embed defaults.yaml
|
||||||
//go:embed defaults.yaml
|
var defaultConfig []byte
|
||||||
defaultConfig []byte
|
|
||||||
)
|
|
||||||
|
|
||||||
func mustNewMigrationConfig(v *viper.Viper) *Migration {
|
func mustNewMigrationConfig(v *viper.Viper) *Migration {
|
||||||
config := new(Migration)
|
config := new(Migration)
|
||||||
|
@@ -43,14 +43,14 @@ BEGIN
|
|||||||
END;
|
END;
|
||||||
|
|
||||||
-- Return the organizations where permission were granted thru org-level roles
|
-- Return the organizations where permission were granted thru org-level roles
|
||||||
SELECT array_agg(org_id) INTO org_ids
|
SELECT array_agg(sub.org_id) INTO org_ids
|
||||||
FROM (
|
FROM (
|
||||||
SELECT DISTINCT om.org_id
|
SELECT DISTINCT om.org_id
|
||||||
FROM eventstore.org_members om
|
FROM eventstore.org_members om
|
||||||
WHERE om.role = ANY(matched_roles)
|
WHERE om.role = ANY(matched_roles)
|
||||||
AND om.instance_id = instanceID
|
AND om.instance_id = instanceID
|
||||||
AND om.user_id = userId
|
AND om.user_id = userId
|
||||||
);
|
) AS sub;
|
||||||
RETURN;
|
RETURN;
|
||||||
END;
|
END;
|
||||||
$$;
|
$$;
|
||||||
|
@@ -3,42 +3,67 @@ DROP FUNCTION IF EXISTS eventstore.permitted_orgs;
|
|||||||
CREATE OR REPLACE FUNCTION eventstore.permitted_orgs(
|
CREATE OR REPLACE FUNCTION eventstore.permitted_orgs(
|
||||||
instanceId TEXT
|
instanceId TEXT
|
||||||
, userId TEXT
|
, userId TEXT
|
||||||
|
, system_user_perms JSONB
|
||||||
, perm TEXT
|
, perm TEXT
|
||||||
, system_user_memeber_type INTEGER[]
|
|
||||||
, system_user_instance_id TEXT[]
|
|
||||||
, system_user_aggregate_id TEXT[]
|
|
||||||
, system_user_permissions TEXT[][]
|
|
||||||
, system_user_permissions_length INTEGER[]
|
|
||||||
, filter_orgs TEXT
|
, filter_orgs TEXT
|
||||||
|
|
||||||
, org_ids OUT TEXT[]
|
, org_ids OUT TEXT[]
|
||||||
)
|
)
|
||||||
LANGUAGE 'plpgsql'
|
LANGUAGE 'plpgsql'
|
||||||
STABLE
|
-- STABLE
|
||||||
AS $$
|
AS $$
|
||||||
DECLARE
|
DECLARE
|
||||||
matched_roles TEXT[]; -- roles containing permission
|
matched_roles TEXT[]; -- roles containing permission
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
||||||
IF system_user_memeber_type IS NOT NULL THEN
|
-- if system user
|
||||||
|
IF jsonb_array_length(system_user_perms) = 0 THEN
|
||||||
DECLARE
|
DECLARE
|
||||||
system_user_permission_found bool;
|
has_instance_or_iam_permission bool;
|
||||||
BEGIN
|
BEGIN
|
||||||
SELECT result.perm_found INTO system_user_permission_found
|
|
||||||
FROM (SELECT eventstore.get_org_permission(perm, instanceId,filter_orgs,
|
|
||||||
system_user_memeber_type, system_user_instance_id, system_user_aggregate_id,
|
|
||||||
system_user_permissions, system_user_permissions_length) AS perm_found) AS result;
|
|
||||||
|
|
||||||
IF system_user_permission_found THEN
|
DROP TABLE IF EXISTS matching_system_user_perms;
|
||||||
|
CREATE TEMPORARY TABLE matching_system_user_perms (
|
||||||
|
member_type TEXT,
|
||||||
|
-- instance_id TEXT,
|
||||||
|
aggregate_id TEXT,
|
||||||
|
object_id TEXT,
|
||||||
|
permission TEXT
|
||||||
|
) ON COMMIT DROP;
|
||||||
|
|
||||||
|
|
||||||
|
INSERT INTO matching_system_user_perms
|
||||||
|
(SELECT * FROM eventstore.get_system_permissions(system_user_perms, perm));
|
||||||
|
|
||||||
|
-- check instance or iam level
|
||||||
|
SELECT true INTO has_instance_or_iam_permission
|
||||||
|
FROM matching_system_user_perms msup
|
||||||
|
WHERE (msup.member_type = 'System' AND msup.aggregate_id = '')
|
||||||
|
OR (msup.member_type = 'System' AND msup.aggregate_id = instanceId)
|
||||||
|
OR (msup.member_type = 'IAM' AND msup.aggregate_id = instanceId)
|
||||||
|
LIMIT 1;
|
||||||
|
|
||||||
|
IF has_instance_or_iam_permission THEN
|
||||||
|
-- Return all organizations or only those in filter_orgs
|
||||||
SELECT array_agg(o.org_id) INTO org_ids
|
SELECT array_agg(o.org_id) INTO org_ids
|
||||||
FROM eventstore.instance_orgs o
|
FROM eventstore.instance_orgs o
|
||||||
WHERE o.instance_id = instanceId
|
WHERE o.instance_id = instanceId
|
||||||
AND CASE WHEN filter_orgs != ''
|
AND CASE WHEN filter_orgs != ''
|
||||||
THEN o.org_id IN (filter_orgs)
|
THEN o.org_id IN (filter_orgs)
|
||||||
ELSE TRUE END;
|
ELSE TRUE END;
|
||||||
|
RETURN;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
|
-- SELECT array_agg(msup.aggregate_id) INTO org_ids
|
||||||
|
-- FROM matching_system_user_perms msup
|
||||||
|
-- WHERE msup.instance_id = instanceId
|
||||||
|
-- AND msup.member_type = 'Organization'
|
||||||
|
-- AND CASE WHEN filter_orgs != ''
|
||||||
|
-- THEN msup.aggregate_id IN (filter_orgs)
|
||||||
|
-- ELSE TRUE END;
|
||||||
|
-- RETURN;
|
||||||
|
|
||||||
END;
|
END;
|
||||||
RETURN;
|
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
SELECT array_agg(rp.role) INTO matched_roles
|
SELECT array_agg(rp.role) INTO matched_roles
|
||||||
@@ -48,14 +73,14 @@ BEGIN
|
|||||||
|
|
||||||
-- First try if the permission was granted thru an instance-level role
|
-- First try if the permission was granted thru an instance-level role
|
||||||
DECLARE
|
DECLARE
|
||||||
has_instance_permission bool;
|
has_instance_permission bool;
|
||||||
BEGIN
|
BEGIN
|
||||||
SELECT true INTO has_instance_permission
|
SELECT true INTO has_instance_permission
|
||||||
FROM eventstore.instance_members im
|
FROM eventstore.instance_members im
|
||||||
WHERE im.role = ANY(matched_roles)
|
WHERE im.role = ANY(matched_roles)
|
||||||
AND im.instance_id = instanceId
|
AND im.instance_id = instanceId
|
||||||
AND im.user_id = userId
|
AND im.user_id = userId
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
|
|
||||||
IF has_instance_permission THEN
|
IF has_instance_permission THEN
|
||||||
-- Return all organizations or only those in filter_orgs
|
-- Return all organizations or only those in filter_orgs
|
||||||
@@ -82,84 +107,32 @@ BEGIN
|
|||||||
END;
|
END;
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
DROP FUNCTION IF EXISTS eventstore.get_org_permission;
|
|
||||||
CREATE OR REPLACE FUNCTION eventstore.get_org_permission(
|
|
||||||
perm TEXT
|
|
||||||
, instance_idd TEXT
|
DROP FUNCTION IF EXISTS eventstore.get_system_permissions;
|
||||||
, org_id TEXT
|
CREATE OR REPLACE FUNCTION eventstore.get_system_permissions(
|
||||||
, system_user_memeber_type INTEGER[]
|
permissions_json JSONB
|
||||||
, sustem_user_instance_id TEXT[]
|
, permm TEXT
|
||||||
, system_user_aggregate_id TEXT[]
|
-- , res OUT eventstore.system_perms
|
||||||
, system_user_permissions TEXT[][]
|
|
||||||
, system_user_permissions_length INTEGER[]
|
|
||||||
-- , outt OUT TEXT[]
|
|
||||||
, outt OUT BOOL
|
|
||||||
)
|
)
|
||||||
LANGUAGE 'plpgsql'
|
RETURNS TABLE (
|
||||||
AS $$
|
member_type TEXT,
|
||||||
DECLARE
|
-- instance_id TEXT,
|
||||||
i INTEGER;
|
|
||||||
length INTEGER;
|
|
||||||
permission_length INTEGER;
|
|
||||||
BEGIN
|
|
||||||
-- outt := FALSE;
|
|
||||||
length := array_length(system_user_memeber_type, 1);
|
|
||||||
-- length := 3;
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS permissions;
|
|
||||||
CREATE TEMPORARY TABLE permissions (
|
|
||||||
member_type INTEGER,
|
|
||||||
instance_id TEXT,
|
|
||||||
aggregate_id TEXT,
|
aggregate_id TEXT,
|
||||||
|
object_id TEXT,
|
||||||
permission TEXT
|
permission TEXT
|
||||||
);
|
) AS $$
|
||||||
|
BEGIN
|
||||||
-- <<outer_loop>>
|
RETURN QUERY
|
||||||
FOR i IN 1..length LOOP
|
SELECT * FROM (
|
||||||
-- only interested in organization level and higher
|
SELECT
|
||||||
IF system_user_memeber_type[i] > 3 THEN
|
(perm)->>'member_type' AS member_type,
|
||||||
CONTINUE;
|
(perm)->>'aggregate_id' AS agregate_id,
|
||||||
END IF;
|
(perm)->>'object_id' AS objectId,
|
||||||
permission_length := system_user_permissions_length[i];
|
permis AS permission
|
||||||
|
FROM jsonb_array_elements(permissions_json) AS perm
|
||||||
FOR j IN 1..permission_length LOOP
|
CROSS JOIN jsonb_array_elements_text(perm->'permissions') AS permis) as p
|
||||||
IF system_user_permissions[i][j] != perm THEN
|
WHERE p.permission = permm;
|
||||||
CONTINUE;
|
|
||||||
END IF;
|
|
||||||
INSERT INTO permissions (member_type, instance_id, aggregate_id, permission) VALUES
|
|
||||||
(system_user_memeber_type[i], sustem_user_instance_id[i], system_user_aggregate_id[i], system_user_permissions[i][j] );
|
|
||||||
-- outt := 555;
|
|
||||||
-- RETURN;
|
|
||||||
END LOOP;
|
|
||||||
END LOOP;
|
|
||||||
|
|
||||||
-- outt := (SELECT permission FROM permissions LIMIT 1);
|
|
||||||
SELECT result.res INTO outt
|
|
||||||
FROM (SELECT TRUE AS res FROM permissions p
|
|
||||||
WHERE
|
|
||||||
-- check instance id
|
|
||||||
CASE WHEN p.member_type = 1 OR p.member_type = 2 THEN -- System or IAM
|
|
||||||
p.aggregate_id = instance_idd
|
|
||||||
-- OR p.instance_id IS NULL
|
|
||||||
OR p.instance_id = ''
|
|
||||||
ELSE
|
|
||||||
p.instance_id = instance_idd
|
|
||||||
-- OR p.instance_id IS NULL
|
|
||||||
OR p.instance_id = ''
|
|
||||||
END
|
|
||||||
AND
|
|
||||||
-- check organization
|
|
||||||
CASE WHEN p.member_type = 3 THEN -- organization
|
|
||||||
p.aggregate_id = org_id
|
|
||||||
ELSE
|
|
||||||
TRUE
|
|
||||||
END
|
|
||||||
Limit 1
|
|
||||||
) AS result;
|
|
||||||
|
|
||||||
DROP TABLE permissions;
|
|
||||||
|
|
||||||
END;
|
END;
|
||||||
$$;
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package start
|
package start
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
@@ -131,7 +130,6 @@ func MustNewConfig(v *viper.Viper) *Config {
|
|||||||
|
|
||||||
// Copy the global role permissions mappings to the instance until we allow instance-level configuration over the API.
|
// Copy the global role permissions mappings to the instance until we allow instance-level configuration over the API.
|
||||||
config.DefaultInstance.RolePermissionMappings = config.InternalAuthZ.RolePermissionMappings
|
config.DefaultInstance.RolePermissionMappings = config.InternalAuthZ.RolePermissionMappings
|
||||||
fmt.Printf("@@ >>>>>>>>>>>>>>>>>>>>>>>>>>>> config.SystemAuthZ = %+v\n", config.SystemAuthZ)
|
|
||||||
|
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
@@ -32,7 +32,7 @@ func CheckUserAuthorization(ctx context.Context, req interface{}, token, orgID,
|
|||||||
|
|
||||||
if requiredAuthOption.Permission == authenticated {
|
if requiredAuthOption.Permission == authenticated {
|
||||||
return func(parent context.Context) context.Context {
|
return func(parent context.Context) context.Context {
|
||||||
parent = addGetSystemUserRolesFuncToCtx(parent, SystemAuthConfig.RolePermissionMappings, nil, ctxData)
|
parent = addGetSystemUserRolesFuncToCtx(parent, SystemAuthConfig.RolePermissionMappings, ctxData)
|
||||||
return context.WithValue(parent, dataKey, ctxData)
|
return context.WithValue(parent, dataKey, ctxData)
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ func CheckUserAuthorization(ctx context.Context, req interface{}, token, orgID,
|
|||||||
parent = context.WithValue(parent, dataKey, ctxData)
|
parent = context.WithValue(parent, dataKey, ctxData)
|
||||||
parent = context.WithValue(parent, allPermissionsKey, allPermissions)
|
parent = context.WithValue(parent, allPermissionsKey, allPermissions)
|
||||||
parent = context.WithValue(parent, requestPermissionsKey, requestedPermissions)
|
parent = context.WithValue(parent, requestPermissionsKey, requestedPermissions)
|
||||||
parent = addGetSystemUserRolesFuncToCtx(parent, SystemAuthConfig.RolePermissionMappings, requestedPermissions, ctxData)
|
parent = addGetSystemUserRolesFuncToCtx(parent, SystemAuthConfig.RolePermissionMappings, ctxData)
|
||||||
return parent
|
return parent
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@@ -130,42 +130,34 @@ func GetAllPermissionCtxIDs(perms []string) []string {
|
|||||||
return ctxIDs
|
return ctxIDs
|
||||||
}
|
}
|
||||||
|
|
||||||
type SystemUserAuthParams struct {
|
type SystemUserPermissionsDBQuery struct {
|
||||||
MemberType []int32
|
MemberType string `json:"member_type"`
|
||||||
InstanceID []string
|
AggregateID string `json:"aggregate_id"`
|
||||||
AggregateID []string
|
ObjectID string `json:"object_id"`
|
||||||
Permissions [][]string
|
Permissions []string `json:"permissions"`
|
||||||
PermissionsLength []int32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func addGetSystemUserRolesFuncToCtx(ctx context.Context, systemUserRoleMap []RoleMapping, requestedPermissions []string, ctxData CtxData) context.Context {
|
func addGetSystemUserRolesFuncToCtx(ctx context.Context, systemUserRoleMap []RoleMapping, ctxData CtxData) context.Context {
|
||||||
if len(ctxData.SystemMemberships) == 0 {
|
if len(ctxData.SystemMemberships) == 0 {
|
||||||
return ctx
|
return ctx
|
||||||
// } else if ctxData.SystemMemberships[0].MemberType == MemberTypeSystem {
|
|
||||||
} else {
|
} else {
|
||||||
ctx = context.WithValue(ctx, systemUserRolesFuncKey, func() func(ctx context.Context) *SystemUserAuthParams {
|
ctx = context.WithValue(ctx, systemUserRolesFuncKey, func() func(ctx context.Context) []SystemUserPermissionsDBQuery {
|
||||||
var systemUserAuthParams *SystemUserAuthParams
|
var systemUserPermissionsDbJsonQueryStruct []SystemUserPermissionsDBQuery
|
||||||
chann := make(chan struct{}, 1)
|
chann := make(chan struct{}, 1)
|
||||||
return func(ctx context.Context) *SystemUserAuthParams {
|
return func(ctx context.Context) []SystemUserPermissionsDBQuery {
|
||||||
if systemUserAuthParams != nil {
|
if systemUserPermissionsDbJsonQueryStruct != nil {
|
||||||
return systemUserAuthParams
|
return systemUserPermissionsDbJsonQueryStruct
|
||||||
}
|
}
|
||||||
|
|
||||||
chann <- struct{}{}
|
chann <- struct{}{}
|
||||||
defer func() {
|
defer func() {
|
||||||
<-chann
|
<-chann
|
||||||
}()
|
}()
|
||||||
if systemUserAuthParams != nil {
|
if systemUserPermissionsDbJsonQueryStruct != nil {
|
||||||
return systemUserAuthParams
|
return systemUserPermissionsDbJsonQueryStruct
|
||||||
}
|
}
|
||||||
|
|
||||||
systemUserAuthParams = &SystemUserAuthParams{
|
systemUserPermissionsDbJsonQueryStruct = make([]SystemUserPermissionsDBQuery, len(ctxData.SystemMemberships))
|
||||||
MemberType: make([]int32, len(ctxData.SystemMemberships)),
|
|
||||||
InstanceID: make([]string, len(ctxData.SystemMemberships)),
|
|
||||||
AggregateID: make([]string, len(ctxData.SystemMemberships)),
|
|
||||||
Permissions: make([][]string, len(ctxData.SystemMemberships)),
|
|
||||||
PermissionsLength: make([]int32, len(ctxData.SystemMemberships)),
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, systemPerm := range ctxData.SystemMemberships {
|
for i, systemPerm := range ctxData.SystemMemberships {
|
||||||
permissions := []string{}
|
permissions := []string{}
|
||||||
@@ -175,25 +167,23 @@ func addGetSystemUserRolesFuncToCtx(ctx context.Context, systemUserRoleMap []Rol
|
|||||||
slices.Sort(permissions)
|
slices.Sort(permissions)
|
||||||
permissions = slices.Compact(permissions)
|
permissions = slices.Compact(permissions)
|
||||||
|
|
||||||
systemUserAuthParams.MemberType[i] = MemberTypeServerToMemberTypeDBMap[systemPerm.MemberType]
|
systemUserPermissionsDbJsonQueryStruct[i].MemberType = MemberTypeServerToMemberTypeDBMap[systemPerm.MemberType]
|
||||||
systemUserAuthParams.InstanceID[i] = systemPerm.InstanceID
|
systemUserPermissionsDbJsonQueryStruct[i].AggregateID = systemPerm.AggregateID
|
||||||
systemUserAuthParams.AggregateID[i] = systemPerm.AggregateID
|
systemUserPermissionsDbJsonQueryStruct[i].Permissions = permissions
|
||||||
systemUserAuthParams.Permissions[i] = permissions
|
|
||||||
systemUserAuthParams.PermissionsLength[i] = int32(len(permissions))
|
|
||||||
}
|
}
|
||||||
return systemUserAuthParams
|
return systemUserPermissionsDbJsonQueryStruct
|
||||||
}
|
}
|
||||||
}())
|
}())
|
||||||
}
|
}
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSystemUserAuthParams(ctx context.Context) (*SystemUserAuthParams, error) {
|
func GetSystemUserPermissions(ctx context.Context) ([]SystemUserPermissionsDBQuery, error) {
|
||||||
getSystemUserRolesFuncValue := ctx.Value(systemUserRolesFuncKey)
|
getSystemUserRolesFuncValue := ctx.Value(systemUserRolesFuncKey)
|
||||||
if getSystemUserRolesFuncValue == nil {
|
if getSystemUserRolesFuncValue == nil {
|
||||||
return &SystemUserAuthParams{}, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
getSystemUserRolesFunc, ok := getSystemUserRolesFuncValue.(func(context.Context) *SystemUserAuthParams)
|
getSystemUserRolesFunc, ok := getSystemUserRolesFuncValue.(func(context.Context) []SystemUserPermissionsDBQuery)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("unable to obtain systems role func")
|
return nil, errors.New("unable to obtain systems role func")
|
||||||
}
|
}
|
||||||
|
@@ -72,10 +72,10 @@ const (
|
|||||||
MemberTypeSystem
|
MemberTypeSystem
|
||||||
)
|
)
|
||||||
|
|
||||||
var MemberTypeServerToMemberTypeDBMap map[MemberType]int32 = map[MemberType]int32{
|
var MemberTypeServerToMemberTypeDBMap map[MemberType]string = map[MemberType]string{
|
||||||
MemberTypeSystem: 1,
|
MemberTypeSystem: "System",
|
||||||
MemberTypeIAM: 2,
|
MemberTypeIAM: "IAM",
|
||||||
MemberTypeOrganization: 3,
|
MemberTypeOrganization: "Organization",
|
||||||
}
|
}
|
||||||
|
|
||||||
type TokenVerifier interface {
|
type TokenVerifier interface {
|
||||||
|
@@ -32,8 +32,8 @@ func getUserPermissions(ctx context.Context, resolver MembershipsResolver, requi
|
|||||||
|
|
||||||
if ctxData.SystemMemberships != nil {
|
if ctxData.SystemMemberships != nil {
|
||||||
// for when we get rid of internalAuthz
|
// for when we get rid of internalAuthz
|
||||||
// requestedPermissions, allPermissions = mapMembershipsToPermissions(requiredPerm, ctxData.SystemMemberships, SystemUserRoleMappings)
|
requestedPermissions, allPermissions = mapMembershipsToPermissions(requiredPerm, ctxData.SystemMemberships, SystemUserRoleMappings)
|
||||||
requestedPermissions, allPermissions = mapMembershipsToPermissions(requiredPerm, ctxData.SystemMemberships, roleMappings)
|
// requestedPermissions, allPermissions = mapMembershipsToPermissions(requiredPerm, ctxData.SystemMemberships, roleMappings)
|
||||||
return requestedPermissions, allPermissions, nil
|
return requestedPermissions, allPermissions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,13 +4,11 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-jose/go-jose/v4"
|
"github.com/go-jose/go-jose/v4"
|
||||||
"github.com/zitadel/logging"
|
|
||||||
"github.com/zitadel/oidc/v3/pkg/op"
|
"github.com/zitadel/oidc/v3/pkg/op"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/crypto"
|
"github.com/zitadel/zitadel/internal/crypto"
|
||||||
@@ -33,14 +31,7 @@ func StartSystemTokenVerifierFromConfig(issuer string, keys map[string]*SystemAP
|
|||||||
}
|
}
|
||||||
for _, membership := range key.Memberships {
|
for _, membership := range key.Memberships {
|
||||||
switch membership.MemberType {
|
switch membership.MemberType {
|
||||||
case MemberTypeSystem, MemberTypeIAM:
|
case MemberTypeSystem, MemberTypeIAM, MemberTypeOrganization:
|
||||||
systemUsers[userID] = key.Memberships
|
|
||||||
case MemberTypeOrganization:
|
|
||||||
if membership.AggregateID != "" && membership.InstanceID == "" {
|
|
||||||
errorMsg := fmt.Sprintf("system user %s must include InstancID if AggregateID is set for member type Organization", userID)
|
|
||||||
logging.Error(errorMsg)
|
|
||||||
return nil, errors.New(errorMsg)
|
|
||||||
}
|
|
||||||
systemUsers[userID] = key.Memberships
|
systemUsers[userID] = key.Memberships
|
||||||
case MemberTypeUnspecified, MemberTypeProject, MemberTypeProjectGrant:
|
case MemberTypeUnspecified, MemberTypeProject, MemberTypeProjectGrant:
|
||||||
return nil, errors.New("for system users, only the membership types System, IAM and Organization are supported")
|
return nil, errors.New("for system users, only the membership types System, IAM and Organization are supported")
|
||||||
@@ -76,7 +67,7 @@ func (s *SystemTokenVerifierFromConfig) VerifySystemToken(ctx context.Context, t
|
|||||||
for _, membership := range systemUserMemberships {
|
for _, membership := range systemUserMemberships {
|
||||||
if membership.MemberType == MemberTypeSystem ||
|
if membership.MemberType == MemberTypeSystem ||
|
||||||
membership.MemberType == MemberTypeIAM && GetInstance(ctx).InstanceID() == membership.AggregateID ||
|
membership.MemberType == MemberTypeIAM && GetInstance(ctx).InstanceID() == membership.AggregateID ||
|
||||||
membership.MemberType == MemberTypeOrganization && orgID == membership.AggregateID && GetInstance(ctx).InstanceID() == membership.InstanceID {
|
membership.MemberType == MemberTypeOrganization && orgID == membership.AggregateID {
|
||||||
matchingMemberships = append(matchingMemberships, membership)
|
matchingMemberships = append(matchingMemberships, membership)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -130,13 +130,6 @@ SystemAuthZ:
|
|||||||
- "system.quota.write"
|
- "system.quota.write"
|
||||||
- "system.quota.delete"
|
- "system.quota.delete"
|
||||||
- "system.iam.member.read"
|
- "system.iam.member.read"
|
||||||
- Role: "SYSTEM_OWNER_VIEWER"
|
|
||||||
Permissions:
|
|
||||||
- "system.instance.read"
|
|
||||||
- "system.domain.read"
|
|
||||||
- "system.debug.read"
|
|
||||||
- "system.feature.read"
|
|
||||||
- "system.iam.member.read"
|
|
||||||
- Role: "IAM_OWNER"
|
- Role: "IAM_OWNER"
|
||||||
Permissions:
|
Permissions:
|
||||||
- "iam.read"
|
- "iam.read"
|
||||||
@@ -235,47 +228,10 @@ SystemAuthZ:
|
|||||||
- "userschema.delete"
|
- "userschema.delete"
|
||||||
- "session.read"
|
- "session.read"
|
||||||
- "session.delete"
|
- "session.delete"
|
||||||
- Role: "IAM_OWNER_VIEWER"
|
- Role: "ORG_OWNER"
|
||||||
Permissions:
|
|
||||||
- "iam.read"
|
|
||||||
- "iam.policy.read"
|
|
||||||
- "iam.member.read"
|
|
||||||
- "iam.idp.read"
|
|
||||||
- "iam.action.read"
|
|
||||||
- "iam.flow.read"
|
|
||||||
- "iam.restrictions.read"
|
|
||||||
- "iam.feature.read"
|
|
||||||
- "iam.web_key.read"
|
|
||||||
- "iam.debug.read"
|
|
||||||
- "org.read"
|
|
||||||
- "org.member.read"
|
|
||||||
- "org.idp.read"
|
|
||||||
- "org.action.read"
|
|
||||||
- "org.flow.read"
|
|
||||||
- "org.feature.read"
|
|
||||||
- "user.read"
|
|
||||||
- "user.global.read"
|
|
||||||
- "user.grant.read"
|
|
||||||
- "user.membership.read"
|
|
||||||
- "user.feature.read"
|
|
||||||
- "policy.read"
|
|
||||||
- "project.read"
|
|
||||||
- "project.member.read"
|
|
||||||
- "project.role.read"
|
|
||||||
- "project.app.read"
|
|
||||||
- "project.grant.read"
|
|
||||||
- "project.grant.member.read"
|
|
||||||
- "events.read"
|
|
||||||
- "milestones.read"
|
|
||||||
- "action.target.read"
|
|
||||||
- "action.execution.read"
|
|
||||||
- "userschema.read"
|
|
||||||
- "session.read"
|
|
||||||
- Role: "IAM_ORG_MANAGER"
|
|
||||||
Permissions:
|
Permissions:
|
||||||
- "org.read"
|
- "org.read"
|
||||||
- "org.global.read"
|
- "org.global.read"
|
||||||
- "org.create"
|
|
||||||
- "org.write"
|
- "org.write"
|
||||||
- "org.delete"
|
- "org.delete"
|
||||||
- "org.member.read"
|
- "org.member.read"
|
||||||
@@ -321,7 +277,6 @@ SystemAuthZ:
|
|||||||
- "project.role.delete"
|
- "project.role.delete"
|
||||||
- "project.app.read"
|
- "project.app.read"
|
||||||
- "project.app.write"
|
- "project.app.write"
|
||||||
- "project.app.delete"
|
|
||||||
- "project.grant.read"
|
- "project.grant.read"
|
||||||
- "project.grant.write"
|
- "project.grant.write"
|
||||||
- "project.grant.delete"
|
- "project.grant.delete"
|
||||||
@@ -329,74 +284,3 @@ SystemAuthZ:
|
|||||||
- "project.grant.member.write"
|
- "project.grant.member.write"
|
||||||
- "project.grant.member.delete"
|
- "project.grant.member.delete"
|
||||||
- "session.delete"
|
- "session.delete"
|
||||||
- Role: "IAM_USER_MANAGER"
|
|
||||||
Permissions:
|
|
||||||
- "org.read"
|
|
||||||
- "org.global.read"
|
|
||||||
- "org.member.read"
|
|
||||||
- "org.member.delete"
|
|
||||||
- "user.read"
|
|
||||||
- "user.global.read"
|
|
||||||
- "user.write"
|
|
||||||
- "user.delete"
|
|
||||||
- "user.grant.read"
|
|
||||||
- "user.grant.write"
|
|
||||||
- "user.grant.delete"
|
|
||||||
- "user.membership.read"
|
|
||||||
- "user.passkey.write"
|
|
||||||
- "user.feature.read"
|
|
||||||
- "user.feature.write"
|
|
||||||
- "user.feature.delete"
|
|
||||||
- "project.read"
|
|
||||||
- "project.member.read"
|
|
||||||
- "project.role.read"
|
|
||||||
- "project.app.read"
|
|
||||||
- "project.grant.read"
|
|
||||||
- "project.grant.write"
|
|
||||||
- "project.grant.delete"
|
|
||||||
- "project.grant.member.read"
|
|
||||||
- "session.delete"
|
|
||||||
- Role: "IAM_ADMIN_IMPERSONATOR"
|
|
||||||
Permissions:
|
|
||||||
- "admin.impersonation"
|
|
||||||
- "impersonation"
|
|
||||||
- Role: "IAM_END_USER_IMPERSONATOR"
|
|
||||||
Permissions:
|
|
||||||
- "impersonation"
|
|
||||||
- Role: "IAM_LOGIN_CLIENT"
|
|
||||||
Permissions:
|
|
||||||
- "iam.read"
|
|
||||||
- "iam.policy.read"
|
|
||||||
- "iam.member.read"
|
|
||||||
- "iam.member.write"
|
|
||||||
- "iam.idp.read"
|
|
||||||
- "iam.feature.read"
|
|
||||||
- "iam.restrictions.read"
|
|
||||||
- "org.read"
|
|
||||||
- "org.member.read"
|
|
||||||
- "org.member.write"
|
|
||||||
- "org.idp.read"
|
|
||||||
- "org.feature.read"
|
|
||||||
- "user.read"
|
|
||||||
- "user.write"
|
|
||||||
- "user.grant.read"
|
|
||||||
- "user.grant.write"
|
|
||||||
- "user.membership.read"
|
|
||||||
- "user.credential.write"
|
|
||||||
- "user.passkey.write"
|
|
||||||
- "user.feature.read"
|
|
||||||
- "policy.read"
|
|
||||||
- "project.read"
|
|
||||||
- "project.member.read"
|
|
||||||
- "project.member.write"
|
|
||||||
- "project.role.read"
|
|
||||||
- "project.app.read"
|
|
||||||
- "project.member.read"
|
|
||||||
- "project.member.write"
|
|
||||||
- "project.grant.read"
|
|
||||||
- "project.grant.member.read"
|
|
||||||
- "project.grant.member.write"
|
|
||||||
- "session.read"
|
|
||||||
- "session.link"
|
|
||||||
- "session.delete"
|
|
||||||
- "userschema.read"
|
|
||||||
|
@@ -2,6 +2,7 @@ package query
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
sq "github.com/Masterminds/squirrel"
|
sq "github.com/Masterminds/squirrel"
|
||||||
@@ -11,48 +12,63 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// eventstore.permitted_orgs(instanceid text, userid text, perm text, system_user_perms text[], filter_orgs text)
|
// eventstore.permitted_orgs(instanceid text, userid text, system_user_perms JSONB, perm text filter_orgs text)
|
||||||
wherePermittedOrgsClause = "%s = ANY(eventstore.permitted_orgs(?, ?, ?, ?, ?, ?, ?, ?, ?))"
|
wherePermittedOrgsClause = "%s = ANY(eventstore.permitted_orgs(?, ?, ?, ?, ?))"
|
||||||
wherePermittedOrgsOrCurrentUserClause = "(" + wherePermittedOrgsClause + " OR %s = ?" + ")"
|
wherePermittedOrgsOrCurrentUserClause = "(" + wherePermittedOrgsClause + " OR %s = ?" + ")"
|
||||||
)
|
)
|
||||||
|
|
||||||
// wherePermittedOrgs sets a `WHERE` clause to the query that filters the orgs
|
// wherePermittedOrgs sets a `WHERE` clause to the query that filters the orgs
|
||||||
// for which the authenticated user has the requested permission for.
|
// for which the authenticated user has the requested permission for.
|
||||||
// The user ID is taken from the context.
|
// The user ID is taken from the context.
|
||||||
//
|
|
||||||
// The `orgIDColumn` specifies the table column to which this filter must be applied,
|
// The `orgIDColumn` specifies the table column to which this filter must be applied,
|
||||||
// and is typically the `resource_owner` column in ZITADEL.
|
// and is typically the `resource_owner` column in ZITADEL.
|
||||||
// We use full identifiers in the query builder so this function should be
|
// We use full identifiers in the query builder so this function should be
|
||||||
// called with something like `UserResourceOwnerCol.identifier()` for example.
|
// called with something like `UserResourceOwnerCol.identifier()` for example.
|
||||||
func wherePermittedOrgs(ctx context.Context, query sq.SelectBuilder, systemUserAuthParams *authz.SystemUserAuthParams, filterOrgIds, orgIDColumn, permission string) sq.SelectBuilder {
|
func wherePermittedOrgs(ctx context.Context, query sq.SelectBuilder, systemUserPermission []authz.SystemUserPermissionsDBQuery, filterOrgIds, orgIDColumn, permission string) (sq.SelectBuilder, error) {
|
||||||
userID := authz.GetCtxData(ctx).UserID
|
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")
|
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)
|
||||||
|
if err != nil {
|
||||||
|
return query, err
|
||||||
|
}
|
||||||
|
systemUserPermissionsJson = string(systemUserPermissionsBytes)
|
||||||
|
}
|
||||||
|
|
||||||
return query.Where(
|
return query.Where(
|
||||||
fmt.Sprintf(wherePermittedOrgsClause, orgIDColumn),
|
fmt.Sprintf(wherePermittedOrgsClause, orgIDColumn),
|
||||||
authz.GetInstance(ctx).InstanceID(),
|
authz.GetInstance(ctx).InstanceID(),
|
||||||
userID,
|
userID,
|
||||||
|
systemUserPermissionsJson,
|
||||||
|
systemUserPermission,
|
||||||
permission,
|
permission,
|
||||||
systemUserAuthParams,
|
|
||||||
filterOrgIds,
|
filterOrgIds,
|
||||||
)
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func wherePermittedOrgsOrCurrentUser(ctx context.Context, query sq.SelectBuilder, systemUserAuthParams *authz.SystemUserAuthParams, filterOrgIds, orgIDColumn, userIdColum, permission string) sq.SelectBuilder {
|
func wherePermittedOrgsOrCurrentUser(ctx context.Context, query sq.SelectBuilder, systemUserPermission []authz.SystemUserPermissionsDBQuery, filterOrgIds, orgIDColumn, userIdColum, permission string) (sq.SelectBuilder, error) {
|
||||||
userID := authz.GetCtxData(ctx).UserID
|
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")
|
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)
|
||||||
|
if err != nil {
|
||||||
|
return query, err
|
||||||
|
}
|
||||||
|
systemUserPermissionsJson = string(systemUserPermissionsBytes)
|
||||||
|
}
|
||||||
|
fmt.Printf("@@ >>>>>>>>>>>>>>>>>>>>>>>>>>>> systemUserPermissionsJson = %+v\n", systemUserPermissionsJson)
|
||||||
|
|
||||||
return query.Where(
|
return query.Where(
|
||||||
fmt.Sprintf(wherePermittedOrgsOrCurrentUserClause, orgIDColumn, userIdColum),
|
fmt.Sprintf(wherePermittedOrgsOrCurrentUserClause, orgIDColumn, userIdColum),
|
||||||
authz.GetInstance(ctx).InstanceID(),
|
authz.GetInstance(ctx).InstanceID(),
|
||||||
userID,
|
userID,
|
||||||
|
systemUserPermissionsJson,
|
||||||
permission,
|
permission,
|
||||||
systemUserAuthParams.MemberType,
|
|
||||||
systemUserAuthParams.InstanceID,
|
|
||||||
systemUserAuthParams.AggregateID,
|
|
||||||
systemUserAuthParams.Permissions,
|
|
||||||
systemUserAuthParams.PermissionsLength,
|
|
||||||
filterOrgIds,
|
filterOrgIds,
|
||||||
userID,
|
userID,
|
||||||
)
|
), nil
|
||||||
}
|
}
|
||||||
|
@@ -658,11 +658,14 @@ func (q *Queries) searchUsers(ctx context.Context, queries *UserSearchQueries, f
|
|||||||
})
|
})
|
||||||
if permissionCheckV2 {
|
if permissionCheckV2 {
|
||||||
// extract system user roles
|
// extract system user roles
|
||||||
systemUserPermissions, err := authz.GetSystemUserAuthParams(ctx)
|
systemUserPermissions, err := authz.GetSystemUserPermissions(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, zerrors.ThrowInternal(err, "QUERY-GS9gs", "Errors.Internal")
|
return nil, zerrors.ThrowInternal(err, "QUERY-GS9gs", "Errors.Internal")
|
||||||
}
|
}
|
||||||
query = wherePermittedOrgsOrCurrentUser(ctx, query, systemUserPermissions, filterOrgIds, UserResourceOwnerCol.identifier(), UserIDCol.identifier(), domain.PermissionUserRead)
|
query, err = wherePermittedOrgsOrCurrentUser(ctx, query, systemUserPermissions, filterOrgIds, UserResourceOwnerCol.identifier(), UserIDCol.identifier(), domain.PermissionUserRead)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt, args, err := query.ToSql()
|
stmt, args, err := query.ToSql()
|
||||||
|
Reference in New Issue
Block a user