@@ -51,10 +51,6 @@ func (r *ReconcilePerconaServerMongoDB) reconcileCustomUsers(ctx context.Context
5151
5252 handleRoles (ctx , cr , mongoCli )
5353
54- if len (cr .Spec .Users ) == 0 {
55- return nil
56- }
57-
5854 err = handleUsers (ctx , cr , mongoCli , r .client )
5955 if err != nil {
6056 return errors .Wrap (err , "handle users" )
@@ -66,39 +62,24 @@ func (r *ReconcilePerconaServerMongoDB) reconcileCustomUsers(ctx context.Context
6662func handleUsers (ctx context.Context , cr * api.PerconaServerMongoDB , mongoCli mongo.Client , client client.Client ) error {
6763 log := logf .FromContext (ctx )
6864
69- sysUsersSecret := corev1.Secret {}
70- err := client .Get (ctx ,
71- types.NamespacedName {
72- Namespace : cr .Namespace ,
73- Name : api .InternalUserSecretName (cr ),
74- },
75- & sysUsersSecret ,
76- )
77- if err != nil && ! k8serrors .IsNotFound (err ) {
78- return errors .Wrap (err , "get internal sys users secret" )
65+ if len (cr .Spec .Users ) == 0 {
66+ return nil
7967 }
8068
81- sysUserNames := sysUserNames (sysUsersSecret )
69+ systemUserNames , err := fetchSystemUserNames (ctx , cr , client )
70+ if err != nil {
71+ return err
72+ }
8273
83- for _ , user := range cr .Spec .Users {
84- if _ , ok := sysUserNames [user .Name ]; ok {
85- log .Error (nil , "creating user with reserved user name is forbidden" , "user" , user .Name )
86- continue
87- }
74+ uniqueUserNames := make (map [string ]struct {}, len (cr .Spec .Users ))
8875
89- if len (user .Roles ) == 0 {
90- log .Error (nil , "user must have at least one role" , "user" , user .Name )
76+ for _ , user := range cr .Spec .Users {
77+ err := validateUser (& user , systemUserNames , uniqueUserNames )
78+ if err != nil {
79+ log .Error (err , "invalid user" , "user" , user )
9180 continue
9281 }
9382
94- if user .DB == "" {
95- user .DB = "admin"
96- }
97-
98- if user .PasswordSecretRef != nil && user .PasswordSecretRef .Key == "" {
99- user .PasswordSecretRef .Key = "password"
100- }
101-
10283 userInfo , err := mongoCli .GetUserInfo (ctx , user .Name , user .DB )
10384 if err != nil {
10485 log .Error (err , "get user info" )
@@ -150,6 +131,49 @@ func handleUsers(ctx context.Context, cr *api.PerconaServerMongoDB, mongoCli mon
150131 return nil
151132}
152133
134+ func validateUser (user * api.User , sysUserNames , uniqueUserNames map [string ]struct {}) error {
135+ if sysUserNames == nil || uniqueUserNames == nil {
136+ return errors .New ("invalid sys or unique usernames config" )
137+ }
138+
139+ if _ , reserved := sysUserNames [user .Name ]; reserved {
140+ return fmt .Errorf ("creating user with reserved user name %s is forbidden" , user .Name )
141+ }
142+
143+ if _ , exists := uniqueUserNames [user .Name ]; exists {
144+ return fmt .Errorf ("username %s should be unique" , user .Name )
145+ }
146+ uniqueUserNames [user .Name ] = struct {}{}
147+
148+ if len (user .Roles ) == 0 {
149+ return fmt .Errorf ("user %s must have at least one role" , user .Name )
150+ }
151+
152+ if user .DB == "" {
153+ user .DB = "admin"
154+ }
155+
156+ if user .PasswordSecretRef != nil && user .PasswordSecretRef .Key == "" {
157+ user .PasswordSecretRef .Key = "password"
158+ }
159+
160+ return nil
161+ }
162+
163+ func fetchSystemUserNames (ctx context.Context , cr * api.PerconaServerMongoDB , client client.Client ) (map [string ]struct {}, error ) {
164+ sysUsersSecret := corev1.Secret {}
165+ err := client .Get (ctx , types.NamespacedName {
166+ Namespace : cr .Namespace ,
167+ Name : api .InternalUserSecretName (cr ),
168+ }, & sysUsersSecret )
169+
170+ if err != nil && ! k8serrors .IsNotFound (err ) {
171+ return nil , errors .Wrap (err , "get internal sys users secret" )
172+ }
173+
174+ return sysUserNames (sysUsersSecret ), nil
175+ }
176+
153177func handleRoles (ctx context.Context , cr * api.PerconaServerMongoDB , cli mongo.Client ) {
154178 log := logf .FromContext (ctx )
155179 if len (cr .Spec .Roles ) == 0 {
@@ -268,15 +292,15 @@ func toMongoRoleModel(role api.Role) (*mongo.Role, error) {
268292 return mr , nil
269293}
270294
271- // sysUserNames returns a set of system user names from the sysUsersSecret.
295+ // sysUserNames returns a set of system usernames from the sysUsersSecret.
272296func sysUserNames (sysUsersSecret corev1.Secret ) map [string ]struct {} {
273- sysUserNames := make (map [string ]struct {}, len (sysUsersSecret .Data ))
297+ names := make (map [string ]struct {}, len (sysUsersSecret .Data ))
274298 for k , v := range sysUsersSecret .Data {
275299 if strings .Contains (k , "_USER" ) {
276- sysUserNames [string (v )] = struct {}{}
300+ names [string (v )] = struct {}{}
277301 }
278302 }
279- return sysUserNames
303+ return names
280304}
281305
282306func updatePass (
0 commit comments