feat: permit all features to every instance and organisation (#3566)

This commit is contained in:
Livio Amstutz
2022-05-02 11:18:17 +02:00
committed by GitHub
parent a9f71ba08e
commit 861cf07700
71 changed files with 90 additions and 6589 deletions

View File

@@ -54,7 +54,6 @@ Services:
Methods:
OrgLabelPolicyLogo:
Path: "/policy/label/logo"
Feature: "label_policy.private_label"
HasDarkMode: true
Handlers:
- Name: Upload
@@ -71,7 +70,6 @@ Services:
Permission: policy.read
OrgLabelPolicyIcon:
Path: "/policy/label/icon"
Feature: "label_policy.private_label"
HasDarkMode: true
Handlers:
- Name: Upload
@@ -88,7 +86,6 @@ Services:
Permission: policy.read
OrgLabelPolicyFont:
Path: "/policy/label/font"
Feature: "label_policy.private_label"
Handlers:
- Name: Upload
Comment:
@@ -107,7 +104,6 @@ Services:
Methods:
MyUserAvatar:
Path: "/me/avatar"
Features: "label_policy.private_label"
Handlers:
- Name: Upload
Comment:

View File

@@ -31,7 +31,6 @@ func main() {
type Method struct {
Path string
Feature string
HasDarkMode bool
Handlers []Handler
}
@@ -144,15 +143,13 @@ var {{.Name}}_AuthMethods = authz.MethodMapping {
{{ range $service := .Services}}
{{ range $method := .Methods}}
{{ range $handler := .Handlers}}
{{ if (or $method.Feature $handler.Permission) }}
{{ if $handler.Permission }}
"{{$handler.Method}}:{{$prefix}}{{$service.Prefix}}{{$method.Path}}{{$handler.PathSuffix}}": authz.Option{
Permission: "{{$handler.Permission}}",
Feature: "{{$method.Feature}}",
},
{{ if $method.HasDarkMode }}
"{{$handler.Method}}:{{$prefix}}{{$service.Prefix}}{{$method.Path}}/dark{{$handler.PathSuffix}}": authz.Option{
Permission: "{{$handler.Permission}}",
Feature: "{{$method.Feature}}",
},
{{end}}
{{end}}

View File

@@ -23,13 +23,6 @@ func CheckUserAuthorization(ctx context.Context, req interface{}, token, orgID s
return nil, err
}
if requiredAuthOption.Feature != "" {
err = CheckOrgFeatures(ctx, verifier, ctxData.OrgID, requiredAuthOption.Feature)
if err != nil {
return nil, err
}
}
if requiredAuthOption.Permission == authenticated {
return func(parent context.Context) context.Context {
return context.WithValue(parent, dataKey, ctxData)
@@ -56,10 +49,6 @@ func CheckUserAuthorization(ctx context.Context, req interface{}, token, orgID s
}, nil
}
func CheckOrgFeatures(ctx context.Context, t *TokenVerifier, orgID string, requiredFeatures ...string) error {
return t.authZRepo.CheckOrgFeatures(ctx, orgID, requiredFeatures...)
}
func checkUserPermissions(req interface{}, userPerms []string, authOpt Option) error {
if len(userPerms) == 0 {
return errors.ThrowPermissionDenied(nil, "AUTH-5mWD2", "No matching permissions found")

View File

@@ -34,10 +34,6 @@ func (v *testVerifier) VerifierClientID(ctx context.Context, appName string) (st
return "clientID", "projectID", nil
}
func (v *testVerifier) CheckOrgFeatures(context.Context, string, ...string) error {
return nil
}
func equalStringArray(a, b []string) bool {
if len(a) != len(b) {
return false

View File

@@ -25,7 +25,6 @@ type authZRepo interface {
SearchMyMemberships(ctx context.Context) ([]*Membership, error)
ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (projectID string, origins []string, err error)
ExistsOrg(ctx context.Context, orgID string) error
CheckOrgFeatures(ctx context.Context, orgID string, requiredFeatures ...string) error
}
func Start(authZRepo authZRepo) (v *TokenVerifier) {

View File

@@ -1,120 +0,0 @@
package admin
import (
"context"
features_grpc "github.com/zitadel/zitadel/internal/api/grpc/features"
object_grpc "github.com/zitadel/zitadel/internal/api/grpc/object"
"github.com/zitadel/zitadel/internal/domain"
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
)
func (s *Server) GetDefaultFeatures(ctx context.Context, _ *admin_pb.GetDefaultFeaturesRequest) (*admin_pb.GetDefaultFeaturesResponse, error) {
features, err := s.query.DefaultFeatures(ctx)
if err != nil {
return nil, err
}
return &admin_pb.GetDefaultFeaturesResponse{
Features: features_grpc.ModelFeaturesToPb(features),
}, nil
}
func (s *Server) SetDefaultFeatures(ctx context.Context, req *admin_pb.SetDefaultFeaturesRequest) (*admin_pb.SetDefaultFeaturesResponse, error) {
details, err := s.command.SetDefaultFeatures(ctx, setDefaultFeaturesRequestToDomain(req))
if err != nil {
return nil, err
}
return &admin_pb.SetDefaultFeaturesResponse{
Details: object_grpc.DomainToChangeDetailsPb(details),
}, nil
}
func (s *Server) GetOrgFeatures(ctx context.Context, req *admin_pb.GetOrgFeaturesRequest) (*admin_pb.GetOrgFeaturesResponse, error) {
features, err := s.query.FeaturesByOrgID(ctx, req.OrgId)
if err != nil {
return nil, err
}
return &admin_pb.GetOrgFeaturesResponse{
Features: features_grpc.ModelFeaturesToPb(features),
}, nil
}
func (s *Server) SetOrgFeatures(ctx context.Context, req *admin_pb.SetOrgFeaturesRequest) (*admin_pb.SetOrgFeaturesResponse, error) {
details, err := s.command.SetOrgFeatures(ctx, req.OrgId, setOrgFeaturesRequestToDomain(req))
if err != nil {
return nil, err
}
return &admin_pb.SetOrgFeaturesResponse{
Details: object_grpc.DomainToChangeDetailsPb(details),
}, nil
}
func (s *Server) ResetOrgFeatures(ctx context.Context, req *admin_pb.ResetOrgFeaturesRequest) (*admin_pb.ResetOrgFeaturesResponse, error) {
details, err := s.command.RemoveOrgFeatures(ctx, req.OrgId)
if err != nil {
return nil, err
}
return &admin_pb.ResetOrgFeaturesResponse{
Details: object_grpc.DomainToChangeDetailsPb(details),
}, nil
}
func setDefaultFeaturesRequestToDomain(req *admin_pb.SetDefaultFeaturesRequest) *domain.Features {
actionsAllowed := features_grpc.ActionsAllowedToDomain(req.ActionsAllowed)
if req.Actions {
actionsAllowed = domain.ActionsAllowedUnlimited
}
return &domain.Features{
TierName: req.TierName,
TierDescription: req.Description,
AuditLogRetention: req.AuditLogRetention.AsDuration(),
LoginPolicyFactors: req.LoginPolicyFactors,
LoginPolicyIDP: req.LoginPolicyIdp,
LoginPolicyPasswordless: req.LoginPolicyPasswordless,
LoginPolicyRegistration: req.LoginPolicyRegistration,
LoginPolicyUsernameLogin: req.LoginPolicyUsernameLogin,
LoginPolicyPasswordReset: req.LoginPolicyPasswordReset,
PasswordComplexityPolicy: req.PasswordComplexityPolicy,
LabelPolicyPrivateLabel: req.LabelPolicy || req.LabelPolicyPrivateLabel,
LabelPolicyWatermark: req.LabelPolicyWatermark,
CustomDomain: req.CustomDomain,
PrivacyPolicy: req.PrivacyPolicy,
MetadataUser: req.MetadataUser,
CustomTextLogin: req.CustomTextLogin || req.CustomText,
CustomTextMessage: req.CustomTextMessage,
LockoutPolicy: req.LockoutPolicy,
ActionsAllowed: actionsAllowed,
MaxActions: int(req.MaxActions),
}
}
func setOrgFeaturesRequestToDomain(req *admin_pb.SetOrgFeaturesRequest) *domain.Features {
actionsAllowed := features_grpc.ActionsAllowedToDomain(req.ActionsAllowed)
if req.Actions {
actionsAllowed = domain.ActionsAllowedUnlimited
}
return &domain.Features{
TierName: req.TierName,
TierDescription: req.Description,
State: features_grpc.FeaturesStateToDomain(req.State),
StateDescription: req.StateDescription,
AuditLogRetention: req.AuditLogRetention.AsDuration(),
LoginPolicyFactors: req.LoginPolicyFactors,
LoginPolicyIDP: req.LoginPolicyIdp,
LoginPolicyPasswordless: req.LoginPolicyPasswordless,
LoginPolicyRegistration: req.LoginPolicyRegistration,
LoginPolicyUsernameLogin: req.LoginPolicyUsernameLogin,
LoginPolicyPasswordReset: req.LoginPolicyPasswordReset,
PasswordComplexityPolicy: req.PasswordComplexityPolicy,
LabelPolicyPrivateLabel: req.LabelPolicy || req.LabelPolicyPrivateLabel,
LabelPolicyWatermark: req.LabelPolicyWatermark,
CustomDomain: req.CustomDomain,
PrivacyPolicy: req.PrivacyPolicy,
MetadataUser: req.MetadataUser,
CustomTextLogin: req.CustomTextLogin || req.CustomText,
CustomTextMessage: req.CustomTextMessage,
LockoutPolicy: req.LockoutPolicy,
ActionsAllowed: actionsAllowed,
MaxActions: int(req.MaxActions),
}
}

View File

@@ -1,18 +0,0 @@
package auth
import (
"context"
"github.com/zitadel/zitadel/internal/api/authz"
auth_pb "github.com/zitadel/zitadel/pkg/grpc/auth"
)
func (s *Server) ListMyZitadelFeatures(ctx context.Context, _ *auth_pb.ListMyZitadelFeaturesRequest) (*auth_pb.ListMyZitadelFeaturesResponse, error) {
features, err := s.query.FeaturesByOrgID(ctx, authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}
return &auth_pb.ListMyZitadelFeaturesResponse{
Result: features.EnabledFeatureTypes(),
}, nil
}

View File

@@ -1,6 +1,8 @@
package auth
import (
"time"
"google.golang.org/grpc"
"github.com/zitadel/zitadel/internal/api/authz"
@@ -22,13 +24,14 @@ const (
type Server struct {
auth.UnimplementedAuthServiceServer
command *command.Commands
query *query.Queries
repo repository.Repository
defaults systemdefaults.SystemDefaults
assetsAPIDomain string
userCodeAlg crypto.EncryptionAlgorithm
externalSecure bool
command *command.Commands
query *query.Queries
repo repository.Repository
defaults systemdefaults.SystemDefaults
assetsAPIDomain string
userCodeAlg crypto.EncryptionAlgorithm
externalSecure bool
auditLogRetention time.Duration
}
type Config struct {
@@ -42,15 +45,17 @@ func CreateServer(command *command.Commands,
assetsAPIDomain string,
userCodeAlg crypto.EncryptionAlgorithm,
externalSecure bool,
auditLogRetention time.Duration,
) *Server {
return &Server{
command: command,
query: query,
repo: authRepo,
defaults: defaults,
assetsAPIDomain: assetsAPIDomain,
userCodeAlg: userCodeAlg,
externalSecure: externalSecure,
command: command,
query: query,
repo: authRepo,
defaults: defaults,
assetsAPIDomain: assetsAPIDomain,
userCodeAlg: userCodeAlg,
externalSecure: externalSecure,
auditLogRetention: auditLogRetention,
}
}

View File

@@ -56,11 +56,7 @@ func (s *Server) RemoveMyUser(ctx context.Context, _ *auth_pb.RemoveMyUserReques
func (s *Server) ListMyUserChanges(ctx context.Context, req *auth_pb.ListMyUserChangesRequest) (*auth_pb.ListMyUserChangesResponse, error) {
sequence, limit, asc := change.ChangeQueryToQuery(req.Query)
features, err := s.query.FeaturesByOrgID(ctx, authz.GetCtxData(ctx).ResourceOwner)
if err != nil {
return nil, err
}
changes, err := s.query.UserChanges(ctx, authz.GetCtxData(ctx).UserID, sequence, limit, asc, features.AuditLogRetention)
changes, err := s.query.UserChanges(ctx, authz.GetCtxData(ctx).UserID, sequence, limit, asc, s.auditLogRetention)
if err != nil {
return nil, err
}

View File

@@ -1,108 +0,0 @@
package features
import (
"google.golang.org/protobuf/types/known/durationpb"
object_grpc "github.com/zitadel/zitadel/internal/api/grpc/object"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/query"
features_pb "github.com/zitadel/zitadel/pkg/grpc/features"
)
func ModelFeaturesToPb(features *query.Features) *features_pb.Features {
return &features_pb.Features{
IsDefault: features.IsDefault,
Tier: FeatureTierToPb(features.TierName, features.TierDescription, features.State, features.StateDescription),
AuditLogRetention: durationpb.New(features.AuditLogRetention),
LoginPolicyFactors: features.LoginPolicyFactors,
LoginPolicyIdp: features.LoginPolicyIDP,
LoginPolicyPasswordless: features.LoginPolicyPasswordless,
LoginPolicyRegistration: features.LoginPolicyRegistration,
LoginPolicyUsernameLogin: features.LoginPolicyUsernameLogin,
LoginPolicyPasswordReset: features.LoginPolicyPasswordReset,
PasswordComplexityPolicy: features.PasswordComplexityPolicy,
LabelPolicy: features.LabelPolicyPrivateLabel,
CustomDomain: features.CustomDomain,
LabelPolicyPrivateLabel: features.LabelPolicyPrivateLabel,
LabelPolicyWatermark: features.LabelPolicyWatermark,
PrivacyPolicy: features.PrivacyPolicy,
CustomText: features.CustomTextMessage,
CustomTextMessage: features.CustomTextMessage,
CustomTextLogin: features.CustomTextLogin,
MetadataUser: features.MetadataUser,
LockoutPolicy: features.LockoutPolicy,
Actions: features.ActionsAllowed != domain.ActionsNotAllowed,
ActionsAllowed: ActionsAllowedToPb(features.ActionsAllowed),
MaxActions: features.MaxActions,
Details: object_grpc.ChangeToDetailsPb(
features.Sequence,
features.ChangeDate,
features.AggregateID,
),
}
}
func FeatureTierToPb(name, description string, status domain.FeaturesState, statusDescription string) *features_pb.FeatureTier {
return &features_pb.FeatureTier{
Name: name,
Description: description,
State: FeaturesStateToPb(status),
StatusInfo: statusDescription,
}
}
func FeaturesStateToPb(status domain.FeaturesState) features_pb.FeaturesState {
switch status {
case domain.FeaturesStateActive:
return features_pb.FeaturesState_FEATURES_STATE_ACTIVE
case domain.FeaturesStateActionRequired:
return features_pb.FeaturesState_FEATURES_STATE_ACTION_REQUIRED
case domain.FeaturesStateCanceled:
return features_pb.FeaturesState_FEATURES_STATE_CANCELED
case domain.FeaturesStateGrandfathered:
return features_pb.FeaturesState_FEATURES_STATE_GRANDFATHERED
default:
return features_pb.FeaturesState_FEATURES_STATE_ACTIVE
}
}
func FeaturesStateToDomain(status features_pb.FeaturesState) domain.FeaturesState {
switch status {
case features_pb.FeaturesState_FEATURES_STATE_ACTIVE:
return domain.FeaturesStateActive
case features_pb.FeaturesState_FEATURES_STATE_ACTION_REQUIRED:
return domain.FeaturesStateActionRequired
case features_pb.FeaturesState_FEATURES_STATE_CANCELED:
return domain.FeaturesStateCanceled
case features_pb.FeaturesState_FEATURES_STATE_GRANDFATHERED:
return domain.FeaturesStateGrandfathered
default:
return -1
}
}
func ActionsAllowedToDomain(allowed features_pb.ActionsAllowed) domain.ActionsAllowed {
switch allowed {
case features_pb.ActionsAllowed_ACTIONS_ALLOWED_NOT_ALLOWED:
return domain.ActionsNotAllowed
case features_pb.ActionsAllowed_ACTIONS_ALLOWED_MAX:
return domain.ActionsMaxAllowed
case features_pb.ActionsAllowed_ACTIONS_ALLOWED_UNLIMITED:
return domain.ActionsAllowedUnlimited
default:
return domain.ActionsNotAllowed
}
}
func ActionsAllowedToPb(allowed domain.ActionsAllowed) features_pb.ActionsAllowed {
switch allowed {
case domain.ActionsNotAllowed:
return features_pb.ActionsAllowed_ACTIONS_ALLOWED_NOT_ALLOWED
case domain.ActionsMaxAllowed:
return features_pb.ActionsAllowed_ACTIONS_ALLOWED_MAX
case domain.ActionsAllowedUnlimited:
return features_pb.ActionsAllowed_ACTIONS_ALLOWED_UNLIMITED
default:
return features_pb.ActionsAllowed_ACTIONS_ALLOWED_NOT_ALLOWED
}
}

View File

@@ -1,19 +0,0 @@
package management
import (
"context"
"github.com/zitadel/zitadel/internal/api/authz"
features_grpc "github.com/zitadel/zitadel/internal/api/grpc/features"
mgmt_pb "github.com/zitadel/zitadel/pkg/grpc/management"
)
func (s *Server) GetFeatures(ctx context.Context, req *mgmt_pb.GetFeaturesRequest) (*mgmt_pb.GetFeaturesResponse, error) {
features, err := s.query.FeaturesByOrgID(ctx, authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}
return &mgmt_pb.GetFeaturesResponse{
Features: features_grpc.ModelFeaturesToPb(features),
}, nil
}

View File

@@ -34,11 +34,7 @@ func (s *Server) GetOrgByDomainGlobal(ctx context.Context, req *mgmt_pb.GetOrgBy
func (s *Server) ListOrgChanges(ctx context.Context, req *mgmt_pb.ListOrgChangesRequest) (*mgmt_pb.ListOrgChangesResponse, error) {
sequence, limit, asc := change_grpc.ChangeQueryToQuery(req.Query)
features, err := s.query.FeaturesByOrgID(ctx, authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}
response, err := s.query.OrgChanges(ctx, authz.GetCtxData(ctx).OrgID, sequence, limit, asc, features.AuditLogRetention)
response, err := s.query.OrgChanges(ctx, authz.GetCtxData(ctx).OrgID, sequence, limit, asc, s.auditLogRetention)
if err != nil {
return nil, err
}

View File

@@ -111,11 +111,7 @@ func (s *Server) ListGrantedProjectRoles(ctx context.Context, req *mgmt_pb.ListG
func (s *Server) ListProjectChanges(ctx context.Context, req *mgmt_pb.ListProjectChangesRequest) (*mgmt_pb.ListProjectChangesResponse, error) {
sequence, limit, asc := change_grpc.ChangeQueryToQuery(req.Query)
features, err := s.query.FeaturesByOrgID(ctx, authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}
res, err := s.query.ProjectChanges(ctx, req.ProjectId, sequence, limit, asc, features.AuditLogRetention)
res, err := s.query.ProjectChanges(ctx, req.ProjectId, sequence, limit, asc, s.auditLogRetention)
if err != nil {
return nil, err
}

View File

@@ -44,11 +44,7 @@ func (s *Server) ListApps(ctx context.Context, req *mgmt_pb.ListAppsRequest) (*m
func (s *Server) ListAppChanges(ctx context.Context, req *mgmt_pb.ListAppChangesRequest) (*mgmt_pb.ListAppChangesResponse, error) {
sequence, limit, asc := change_grpc.ChangeQueryToQuery(req.Query)
features, err := s.query.FeaturesByOrgID(ctx, authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}
res, err := s.query.ApplicationChanges(ctx, req.ProjectId, req.AppId, sequence, limit, asc, features.AuditLogRetention)
res, err := s.query.ApplicationChanges(ctx, req.ProjectId, req.AppId, sequence, limit, asc, s.auditLogRetention)
if err != nil {
return nil, err
}

View File

@@ -1,6 +1,8 @@
package management
import (
"time"
"google.golang.org/grpc"
"github.com/zitadel/zitadel/internal/api/authz"
@@ -20,14 +22,15 @@ var _ management.ManagementServiceServer = (*Server)(nil)
type Server struct {
management.UnimplementedManagementServiceServer
command *command.Commands
query *query.Queries
systemDefaults systemdefaults.SystemDefaults
assetAPIPrefix string
passwordHashAlg crypto.HashAlgorithm
userCodeAlg crypto.EncryptionAlgorithm
externalSecure bool
issuerPath string
command *command.Commands
query *query.Queries
systemDefaults systemdefaults.SystemDefaults
assetAPIPrefix string
passwordHashAlg crypto.HashAlgorithm
userCodeAlg crypto.EncryptionAlgorithm
externalSecure bool
issuerPath string
auditLogRetention time.Duration
}
func CreateServer(
@@ -38,16 +41,18 @@ func CreateServer(
userCodeAlg crypto.EncryptionAlgorithm,
externalSecure bool,
issuerPath string,
auditLogRetention time.Duration,
) *Server {
return &Server{
command: command,
query: query,
systemDefaults: sd,
assetAPIPrefix: assetAPIPrefix,
passwordHashAlg: crypto.NewBCrypt(sd.SecretGenerators.PasswordSaltCost),
userCodeAlg: userCodeAlg,
externalSecure: externalSecure,
issuerPath: issuerPath,
command: command,
query: query,
systemDefaults: sd,
assetAPIPrefix: assetAPIPrefix,
passwordHashAlg: crypto.NewBCrypt(sd.SecretGenerators.PasswordSaltCost),
userCodeAlg: userCodeAlg,
externalSecure: externalSecure,
issuerPath: issuerPath,
auditLogRetention: auditLogRetention,
}
}

View File

@@ -79,11 +79,7 @@ func (s *Server) ListUsers(ctx context.Context, req *mgmt_pb.ListUsersRequest) (
func (s *Server) ListUserChanges(ctx context.Context, req *mgmt_pb.ListUserChangesRequest) (*mgmt_pb.ListUserChangesResponse, error) {
sequence, limit, asc := change_grpc.ChangeQueryToQuery(req.Query)
features, err := s.query.FeaturesByOrgID(ctx, authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}
res, err := s.query.UserChanges(ctx, req.UserId, sequence, limit, asc, features.AuditLogRetention)
res, err := s.query.UserChanges(ctx, req.UserId, sequence, limit, asc, s.auditLogRetention)
if err != nil {
return nil, err
}

View File

@@ -37,9 +37,6 @@ func (v *verifierMock) ExistsOrg(ctx context.Context, orgID string) error {
func (v *verifierMock) VerifierClientID(ctx context.Context, appName string) (string, string, error) {
return "", "", nil
}
func (v *verifierMock) CheckOrgFeatures(context.Context, string, ...string) error {
return nil
}
func Test_authorize(t *testing.T) {
type args struct {