mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 03:47:33 +00:00
feat: add SYSTEM_OWNER role (#6765)
* define roles and permissions * support system user memberships * don't limit system users * cleanup permissions * restrict memberships to aggregates * default to SYSTEM_OWNER * update unit tests * test: system user token test (#6778) * update unit tests * refactor: make authz testable * move session constants * cleanup * comment * comment * decode member type string to enum (#6780) * decode member type string to enum * handle all membership types * decode enums where necessary * decode member type in steps config * update system api docs * add technical advisory * tweak docs a bit * comment in comment * lint * extract token from Bearer header prefix * review changes * fix tests * fix: add fix for activityhandler * add isSystemUser * remove IsSystemUser from activity info * fix: add fix for activityhandler --------- Co-authored-by: Stefan Benz <stefan@caos.ch>
This commit is contained in:
@@ -7,33 +7,6 @@ import (
|
||||
caos_errs "github.com/zitadel/zitadel/internal/errors"
|
||||
)
|
||||
|
||||
func getTestCtx(userID, orgID string) context.Context {
|
||||
return context.WithValue(context.Background(), dataKey, CtxData{UserID: userID, OrgID: orgID})
|
||||
}
|
||||
|
||||
type testVerifier struct {
|
||||
memberships []*Membership
|
||||
}
|
||||
|
||||
func (v *testVerifier) VerifyAccessToken(ctx context.Context, token, clientID, projectID string) (string, string, string, string, string, error) {
|
||||
return "userID", "agentID", "clientID", "de", "orgID", nil
|
||||
}
|
||||
func (v *testVerifier) SearchMyMemberships(ctx context.Context, orgID string, _ bool) ([]*Membership, error) {
|
||||
return v.memberships, nil
|
||||
}
|
||||
|
||||
func (v *testVerifier) ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (string, []string, error) {
|
||||
return "", nil, nil
|
||||
}
|
||||
|
||||
func (v *testVerifier) ExistsOrg(ctx context.Context, orgID, domain string) (string, error) {
|
||||
return orgID, nil
|
||||
}
|
||||
|
||||
func (v *testVerifier) VerifierClientID(ctx context.Context, appName string) (string, string, error) {
|
||||
return "clientID", "projectID", nil
|
||||
}
|
||||
|
||||
func equalStringArray(a, b []string) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
@@ -46,12 +19,18 @@ func equalStringArray(a, b []string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type membershipsResolverFunc func(ctx context.Context, orgID string, shouldTriggerBulk bool) ([]*Membership, error)
|
||||
|
||||
func (m membershipsResolverFunc) SearchMyMemberships(ctx context.Context, orgID string, shouldTriggerBulk bool) ([]*Membership, error) {
|
||||
return m(ctx, orgID, shouldTriggerBulk)
|
||||
}
|
||||
|
||||
func Test_GetUserPermissions(t *testing.T) {
|
||||
type args struct {
|
||||
ctxData CtxData
|
||||
verifier *TokenVerifier
|
||||
requiredPerm string
|
||||
authConfig Config
|
||||
ctxData CtxData
|
||||
membershipsResolver MembershipsResolver
|
||||
requiredPerm string
|
||||
authConfig Config
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -64,11 +43,9 @@ func Test_GetUserPermissions(t *testing.T) {
|
||||
name: "Empty Context",
|
||||
args: args{
|
||||
ctxData: CtxData{},
|
||||
verifier: Start(&testVerifier{memberships: []*Membership{
|
||||
{
|
||||
Roles: []string{"ORG_OWNER"},
|
||||
},
|
||||
}}, "", nil),
|
||||
membershipsResolver: membershipsResolverFunc(func(ctx context.Context, orgID string, shouldTriggerBulk bool) ([]*Membership, error) {
|
||||
return []*Membership{{Roles: []string{"ORG_OWNER"}}}, nil
|
||||
}),
|
||||
requiredPerm: "project.read",
|
||||
authConfig: Config{
|
||||
RolePermissionMappings: []RoleMapping{
|
||||
@@ -90,8 +67,10 @@ func Test_GetUserPermissions(t *testing.T) {
|
||||
{
|
||||
name: "No Grants",
|
||||
args: args{
|
||||
ctxData: CtxData{},
|
||||
verifier: Start(&testVerifier{memberships: []*Membership{}}, "", nil),
|
||||
ctxData: CtxData{},
|
||||
membershipsResolver: membershipsResolverFunc(func(ctx context.Context, orgID string, shouldTriggerBulk bool) ([]*Membership, error) {
|
||||
return []*Membership{}, nil
|
||||
}),
|
||||
requiredPerm: "project.read",
|
||||
authConfig: Config{
|
||||
RolePermissionMappings: []RoleMapping{
|
||||
@@ -112,14 +91,16 @@ func Test_GetUserPermissions(t *testing.T) {
|
||||
name: "Get Permissions",
|
||||
args: args{
|
||||
ctxData: CtxData{UserID: "userID", OrgID: "orgID"},
|
||||
verifier: Start(&testVerifier{memberships: []*Membership{
|
||||
{
|
||||
AggregateID: "IAM",
|
||||
ObjectID: "IAM",
|
||||
MemberType: MemberTypeIam,
|
||||
Roles: []string{"IAM_OWNER"},
|
||||
},
|
||||
}}, "", nil),
|
||||
membershipsResolver: membershipsResolverFunc(func(ctx context.Context, orgID string, shouldTriggerBulk bool) ([]*Membership, error) {
|
||||
return []*Membership{
|
||||
{
|
||||
AggregateID: "IAM",
|
||||
ObjectID: "IAM",
|
||||
MemberType: MemberTypeIAM,
|
||||
Roles: []string{"IAM_OWNER"},
|
||||
},
|
||||
}, nil
|
||||
}),
|
||||
requiredPerm: "project.read",
|
||||
authConfig: Config{
|
||||
RolePermissionMappings: []RoleMapping{
|
||||
@@ -139,7 +120,7 @@ func Test_GetUserPermissions(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, perms, err := getUserPermissions(context.Background(), tt.args.verifier, tt.args.requiredPerm, tt.args.authConfig.RolePermissionMappings, tt.args.ctxData, tt.args.ctxData.OrgID)
|
||||
_, perms, err := getUserPermissions(context.Background(), tt.args.membershipsResolver, tt.args.requiredPerm, tt.args.authConfig.RolePermissionMappings, tt.args.ctxData, tt.args.ctxData.OrgID)
|
||||
|
||||
if tt.wantErr && err == nil {
|
||||
t.Errorf("got wrong result, should get err: actual: %v ", err)
|
||||
@@ -176,7 +157,7 @@ func Test_MapMembershipToPermissions(t *testing.T) {
|
||||
{
|
||||
AggregateID: "1",
|
||||
ObjectID: "1",
|
||||
MemberType: MemberTypeOrganisation,
|
||||
MemberType: MemberTypeOrganization,
|
||||
Roles: []string{"ORG_OWNER"},
|
||||
},
|
||||
},
|
||||
@@ -204,7 +185,7 @@ func Test_MapMembershipToPermissions(t *testing.T) {
|
||||
{
|
||||
AggregateID: "1",
|
||||
ObjectID: "1",
|
||||
MemberType: MemberTypeOrganisation,
|
||||
MemberType: MemberTypeOrganization,
|
||||
Roles: []string{"ORG_OWNER"},
|
||||
},
|
||||
},
|
||||
@@ -232,13 +213,13 @@ func Test_MapMembershipToPermissions(t *testing.T) {
|
||||
{
|
||||
AggregateID: "1",
|
||||
ObjectID: "1",
|
||||
MemberType: MemberTypeOrganisation,
|
||||
MemberType: MemberTypeOrganization,
|
||||
Roles: []string{"ORG_OWNER"},
|
||||
},
|
||||
{
|
||||
AggregateID: "IAM",
|
||||
ObjectID: "IAM",
|
||||
MemberType: MemberTypeIam,
|
||||
MemberType: MemberTypeIAM,
|
||||
Roles: []string{"IAM_OWNER"},
|
||||
},
|
||||
},
|
||||
@@ -266,7 +247,7 @@ func Test_MapMembershipToPermissions(t *testing.T) {
|
||||
{
|
||||
AggregateID: "2",
|
||||
ObjectID: "2",
|
||||
MemberType: MemberTypeOrganisation,
|
||||
MemberType: MemberTypeOrganization,
|
||||
Roles: []string{"ORG_OWNER"},
|
||||
},
|
||||
{
|
||||
@@ -327,7 +308,7 @@ func Test_MapMembershipToPerm(t *testing.T) {
|
||||
membership: &Membership{
|
||||
AggregateID: "Org",
|
||||
ObjectID: "Org",
|
||||
MemberType: MemberTypeOrganisation,
|
||||
MemberType: MemberTypeOrganization,
|
||||
Roles: []string{"ORG_OWNER"},
|
||||
},
|
||||
authConfig: Config{
|
||||
@@ -355,7 +336,7 @@ func Test_MapMembershipToPerm(t *testing.T) {
|
||||
membership: &Membership{
|
||||
AggregateID: "Org",
|
||||
ObjectID: "Org",
|
||||
MemberType: MemberTypeOrganisation,
|
||||
MemberType: MemberTypeOrganization,
|
||||
Roles: []string{"ORG_OWNER"},
|
||||
},
|
||||
authConfig: Config{
|
||||
|
Reference in New Issue
Block a user