diff --git a/internal/management/repository/eventsourcing/eventstore/iam.go b/internal/management/repository/eventsourcing/eventstore/iam.go new file mode 100644 index 0000000000..d5fc14a5e4 --- /dev/null +++ b/internal/management/repository/eventsourcing/eventstore/iam.go @@ -0,0 +1,15 @@ +package eventstore + +import ( + "context" + iam_model "github.com/caos/zitadel/internal/iam/model" + "github.com/caos/zitadel/internal/iam/repository/eventsourcing" +) + +type IamRepository struct { + IamEvents *eventsourcing.IamEventstore +} + +func (repo *IamRepository) IamByID(ctx context.Context, id string) (*iam_model.Iam, error) { + return repo.IamEvents.IamByID(ctx, id) +} diff --git a/internal/management/repository/eventsourcing/repository.go b/internal/management/repository/eventsourcing/repository.go index add525ea8e..91b45f3c03 100644 --- a/internal/management/repository/eventsourcing/repository.go +++ b/internal/management/repository/eventsourcing/repository.go @@ -2,6 +2,7 @@ package eventsourcing import ( "context" + es_iam "github.com/caos/zitadel/internal/iam/repository/eventsourcing" sd "github.com/caos/zitadel/internal/config/systemdefaults" "github.com/caos/zitadel/internal/config/types" @@ -32,6 +33,7 @@ type EsRepository struct { eventstore.UserRepo eventstore.UserGrantRepo eventstore.PolicyRepo + eventstore.IamRepository } func Start(conf Config, systemDefaults sd.SystemDefaults, roles []string) (*EsRepository, error) { @@ -78,6 +80,13 @@ func Start(conf Config, systemDefaults sd.SystemDefaults, roles []string) (*EsRe return nil, err } org := es_org.StartOrg(es_org.OrgConfig{Eventstore: es}) + iam, err := es_iam.StartIam(es_iam.IamConfig{ + Eventstore: es, + Cache: conf.Eventstore.Cache, + }, systemDefaults) + if err != nil { + return nil, err + } eventstoreRepos := handler.EventstoreRepos{ProjectEvents: project, UserEvents: user, OrgEvents: org} spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, eventstoreRepos) @@ -89,6 +98,7 @@ func Start(conf Config, systemDefaults sd.SystemDefaults, roles []string) (*EsRe UserRepo: eventstore.UserRepo{conf.SearchLimit, user, policy, view}, UserGrantRepo: eventstore.UserGrantRepo{conf.SearchLimit, usergrant, view}, PolicyRepo: eventstore.PolicyRepo{policy}, + IamRepository: eventstore.IamRepository{iam}, }, nil } diff --git a/internal/management/repository/iam.go b/internal/management/repository/iam.go new file mode 100644 index 0000000000..2032c7efe5 --- /dev/null +++ b/internal/management/repository/iam.go @@ -0,0 +1,10 @@ +package repository + +import ( + "context" + iam_model "github.com/caos/zitadel/internal/iam/model" +) + +type IamRepository interface { + IamByID(ctx context.Context, id string) (*iam_model.Iam, error) +} diff --git a/internal/management/repository/repository.go b/internal/management/repository/repository.go index ee346cffb1..7351588889 100644 --- a/internal/management/repository/repository.go +++ b/internal/management/repository/repository.go @@ -7,4 +7,5 @@ type Repository interface { OrgRepository UserRepository UserGrantRepository + IamRepository } diff --git a/pkg/management/api/api.go b/pkg/management/api/api.go index 8bb54ccd3d..dc70357ed0 100644 --- a/pkg/management/api/api.go +++ b/pkg/management/api/api.go @@ -4,6 +4,7 @@ import ( "context" "github.com/caos/zitadel/internal/api/auth" authz_repo "github.com/caos/zitadel/internal/authz/repository/eventsourcing" + "github.com/caos/zitadel/internal/config/systemdefaults" "github.com/caos/zitadel/internal/management/repository" grpc_util "github.com/caos/zitadel/internal/api/grpc" @@ -15,8 +16,8 @@ type Config struct { GRPC grpc_util.Config } -func Start(ctx context.Context, conf Config, authZRepo *authz_repo.EsRepository, authZ auth.Config, repo repository.Repository) { - grpcServer := grpc.StartServer(conf.GRPC.ToServerConfig(), authZRepo, authZ, repo) +func Start(ctx context.Context, conf Config, authZRepo *authz_repo.EsRepository, authZ auth.Config, sd systemdefaults.SystemDefaults, repo repository.Repository) { + grpcServer := grpc.StartServer(conf.GRPC.ToServerConfig(), authZRepo, authZ, sd, repo) grpcGateway := grpc.StartGateway(conf.GRPC.ToGatewayConfig()) server.StartServer(ctx, grpcServer) diff --git a/pkg/management/api/grpc/application.go b/pkg/management/api/grpc/application.go index 1c91191d33..444e031f0f 100644 --- a/pkg/management/api/grpc/application.go +++ b/pkg/management/api/grpc/application.go @@ -37,6 +37,9 @@ func (s *Server) UpdateApplication(ctx context.Context, in *ApplicationUpdate) ( return appFromModel(app), nil } func (s *Server) DeactivateApplication(ctx context.Context, in *ApplicationID) (*Application, error) { + if s.IsZitadel(ctx, in.ProjectId) { + return nil, errors.ThrowInvalidArgument(nil, "GRPC-LSped", "Zitadel Project Applications should not be deactivated") + } app, err := s.project.DeactivateApplication(ctx, in.ProjectId, in.Id) if err != nil { return nil, err @@ -52,11 +55,17 @@ func (s *Server) ReactivateApplication(ctx context.Context, in *ApplicationID) ( } func (s *Server) RemoveApplication(ctx context.Context, in *ApplicationID) (*empty.Empty, error) { + if s.IsZitadel(ctx, in.ProjectId) { + return nil, errors.ThrowInvalidArgument(nil, "GRPC-LSpee", "Zitadel Project Applications should not be removed") + } err := s.project.RemoveApplication(ctx, in.ProjectId, in.Id) return &empty.Empty{}, err } func (s *Server) UpdateApplicationOIDCConfig(ctx context.Context, in *OIDCConfigUpdate) (*OIDCConfig, error) { + if s.IsZitadel(ctx, in.ProjectId) { + return nil, errors.ThrowInvalidArgument(nil, "GRPC-LSpee", "Zitadel Project Applications OIdc Config should not be changed") + } config, err := s.project.ChangeOIDCConfig(ctx, oidcConfigUpdateToModel(in)) if err != nil { return nil, err @@ -65,6 +74,9 @@ func (s *Server) UpdateApplicationOIDCConfig(ctx context.Context, in *OIDCConfig } func (s *Server) RegenerateOIDCClientSecret(ctx context.Context, in *ApplicationID) (*ClientSecret, error) { + if s.IsZitadel(ctx, in.ProjectId) { + return nil, errors.ThrowInvalidArgument(nil, "GRPC-Lps4d", "Zitadel Project Applications OIdc Config should not be changed") + } config, err := s.project.ChangeOIDConfigSecret(ctx, in.ProjectId, in.Id) if err != nil { return nil, err diff --git a/pkg/management/api/grpc/project.go b/pkg/management/api/grpc/project.go index 06f06f498c..1c3e0cb7e1 100644 --- a/pkg/management/api/grpc/project.go +++ b/pkg/management/api/grpc/project.go @@ -16,6 +16,9 @@ func (s *Server) CreateProject(ctx context.Context, in *ProjectCreateRequest) (* return projectFromModel(project), nil } func (s *Server) UpdateProject(ctx context.Context, in *ProjectUpdateRequest) (*Project, error) { + if s.IsZitadel(ctx, in.Id) { + return nil, errors.ThrowInvalidArgument(nil, "GRPC-SFH8d", "Zitadel Project should not be updated") + } project, err := s.project.UpdateProject(ctx, projectUpdateToModel(in)) if err != nil { return nil, err @@ -23,6 +26,9 @@ func (s *Server) UpdateProject(ctx context.Context, in *ProjectUpdateRequest) (* return projectFromModel(project), nil } func (s *Server) DeactivateProject(ctx context.Context, in *ProjectID) (*Project, error) { + if s.IsZitadel(ctx, in.Id) { + return nil, errors.ThrowInvalidArgument(nil, "GRPC-PS9cs", "Zitadel Project should not be deactivated") + } project, err := s.project.DeactivateProject(ctx, in.Id) if err != nil { return nil, err @@ -30,6 +36,9 @@ func (s *Server) DeactivateProject(ctx context.Context, in *ProjectID) (*Project return projectFromModel(project), nil } func (s *Server) ReactivateProject(ctx context.Context, in *ProjectID) (*Project, error) { + if s.IsZitadel(ctx, in.Id) { + return nil, errors.ThrowInvalidArgument(nil, "GRPC-LSpe2", "Zitadel Project should not be reactivated") + } project, err := s.project.ReactivateProject(ctx, in.Id) if err != nil { return nil, err @@ -65,6 +74,9 @@ func (s *Server) GetGrantedProjectGrantByID(ctx context.Context, in *ProjectGran } func (s *Server) AddProjectRole(ctx context.Context, in *ProjectRoleAdd) (*ProjectRole, error) { + if s.IsZitadel(ctx, in.Id) { + return nil, errors.ThrowInvalidArgument(nil, "GRPC-PS9cs", "Zitadel Project should not get new role") + } role, err := s.project.AddProjectRole(ctx, projectRoleAddToModel(in)) if err != nil { return nil, err @@ -72,6 +84,9 @@ func (s *Server) AddProjectRole(ctx context.Context, in *ProjectRoleAdd) (*Proje return projectRoleFromModel(role), nil } func (s *Server) ChangeProjectRole(ctx context.Context, in *ProjectRoleChange) (*ProjectRole, error) { + if s.IsZitadel(ctx, in.Id) { + return nil, errors.ThrowInvalidArgument(nil, "GRPC-LASj8", "Zitadel Project should not change roles") + } role, err := s.project.ChangeProjectRole(ctx, projectRoleChangeToModel(in)) if err != nil { return nil, err @@ -80,6 +95,9 @@ func (s *Server) ChangeProjectRole(ctx context.Context, in *ProjectRoleChange) ( } func (s *Server) RemoveProjectRole(ctx context.Context, in *ProjectRoleRemove) (*empty.Empty, error) { + if s.IsZitadel(ctx, in.Id) { + return nil, errors.ThrowInvalidArgument(nil, "GRPC-Psn7s", "do not remove roles from Zitadel Project") + } err := s.project.RemoveProjectRole(ctx, in.Id, in.Key) return &empty.Empty{}, err } @@ -98,3 +116,14 @@ func (s *Server) SearchProjectRoles(ctx context.Context, in *ProjectRoleSearchRe func (s *Server) ProjectChanges(ctx context.Context, changesRequest *ChangeRequest) (*Changes, error) { return nil, errors.ThrowUnimplemented(nil, "GRPC-mci3f", "Not implemented") } + +func (s *Server) IsZitadel(ctx context.Context, projectID string) bool { + iam, err := s.iam.IamByID(ctx, s.systemDefaults.IamID) + if err != nil { + return false + } + if iam.IamProjectID == projectID { + return true + } + return false +} diff --git a/pkg/management/api/grpc/server.go b/pkg/management/api/grpc/server.go index faa7276da8..160379e256 100644 --- a/pkg/management/api/grpc/server.go +++ b/pkg/management/api/grpc/server.go @@ -5,6 +5,7 @@ import ( grpc_util "github.com/caos/zitadel/internal/api/grpc" "github.com/caos/zitadel/internal/api/grpc/server/middleware" authz_repo "github.com/caos/zitadel/internal/authz/repository/eventsourcing" + "github.com/caos/zitadel/internal/config/systemdefaults" mgmt_auth "github.com/caos/zitadel/internal/management/auth" "github.com/caos/zitadel/internal/management/repository" grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" @@ -14,26 +15,30 @@ import ( var _ ManagementServiceServer = (*Server)(nil) type Server struct { - port string - project repository.ProjectRepository - policy repository.PolicyRepository - org repository.OrgRepository - user repository.UserRepository - usergrant repository.UserGrantRepository - verifier *mgmt_auth.TokenVerifier - authZ auth.Config + port string + project repository.ProjectRepository + policy repository.PolicyRepository + org repository.OrgRepository + user repository.UserRepository + usergrant repository.UserGrantRepository + iam repository.IamRepository + verifier *mgmt_auth.TokenVerifier + authZ auth.Config + systemDefaults systemdefaults.SystemDefaults } -func StartServer(conf grpc_util.ServerConfig, authZRepo *authz_repo.EsRepository, authZ auth.Config, repo repository.Repository) *Server { +func StartServer(conf grpc_util.ServerConfig, authZRepo *authz_repo.EsRepository, authZ auth.Config, sd systemdefaults.SystemDefaults, repo repository.Repository) *Server { return &Server{ - port: conf.Port, - project: repo, - policy: repo, - org: repo, - user: repo, - usergrant: repo, - authZ: authZ, - verifier: mgmt_auth.Start(authZRepo), + port: conf.Port, + project: repo, + policy: repo, + org: repo, + user: repo, + usergrant: repo, + iam: repo, + authZ: authZ, + verifier: mgmt_auth.Start(authZRepo), + systemDefaults: sd, } } diff --git a/pkg/management/management.go b/pkg/management/management.go index 355d7d796e..9858ebb94b 100644 --- a/pkg/management/management.go +++ b/pkg/management/management.go @@ -24,5 +24,5 @@ func Start(ctx context.Context, config Config, authZRepo *authz_repo.EsRepositor repo, err := eventsourcing.Start(config.Repository, systemDefaults, roles) logging.Log("MAIN-9uBxp").OnError(err).Panic("unable to start app") - api.Start(ctx, config.API, authZRepo, authZ, repo) + api.Start(ctx, config.API, authZRepo, authZ, systemDefaults, repo) }