@@ -17,10 +17,11 @@ limitations under the License.
1717package secret
1818
1919import (
20- . "github.com/onsi/gomega" // nolint:revive
2120 "regexp"
2221 "slices"
2322 "testing"
23+
24+ . "github.com/onsi/gomega" // nolint:revive
2425)
2526
2627const ErrMsg string = "password does not meet the requirements"
@@ -279,12 +280,15 @@ func TestValidatePassword(t *testing.T) {
279280 alphaNumPattern ,
280281 fernetPattern ,
281282 )
283+
284+ validator := PasswordValidator {}
285+
282286 // Execute ValidatePassword against the generated TestVector
283287 for _ , tt := range tests {
284288 t .Run (tt .name , func (t * testing.T ) {
285289 g := NewWithT (t )
286290
287- err := ValidatePassword (tt .password )
291+ err := validator . Validate (tt .password )
288292
289293 if tt .wantErr {
290294 g .Expect (err ).To (HaveOccurred ())
@@ -295,3 +299,127 @@ func TestValidatePassword(t *testing.T) {
295299 })
296300 }
297301}
302+
303+ func TestValidatePasswordWithCustomRules (t * testing.T ) {
304+ // Define custom requirements (strict rules)
305+ customRequirements := []Rule {
306+ {
307+ description : "Must only contain alphanumerical and safe special characters" ,
308+ pattern : * regexp .MustCompile (`^[a-zA-Z0-9@#%^*-_=+:,.!~]+$` ),
309+ },
310+ }
311+
312+ // Define custom rejects (forbid specific patterns)
313+ customRejects := []Rule {
314+ {
315+ description : "Must not contain carriage return" ,
316+ pattern : * regexp .MustCompile (`[\n]` ),
317+ },
318+ }
319+
320+ tests := []struct {
321+ name string
322+ validator PasswordValidator
323+ password string
324+ wantErr bool
325+ errMsg string
326+ }{
327+ // Test with nil rules (should use defaults)
328+ {
329+ name : "nil rules uses defaults - valid" ,
330+ validator : PasswordValidator {},
331+ password : "ValidPassword123" ,
332+ wantErr : false ,
333+ },
334+ {
335+ name : "nil rules uses defaults - shell expansion rejected" ,
336+ validator : PasswordValidator {},
337+ password : "Password123$HOME" ,
338+ wantErr : true ,
339+ errMsg : ErrMsg ,
340+ },
341+ {
342+ name : "nil rules uses defaults - empty password rejected" ,
343+ validator : PasswordValidator {},
344+ password : "" ,
345+ wantErr : true ,
346+ errMsg : "empty password not allowed" ,
347+ },
348+
349+ // Test with custom requirements only
350+ {
351+ name : "custom requirements - safe special characters" ,
352+ validator : PasswordValidator {
353+ Requirements : & customRequirements ,
354+ },
355+ password : "#S3cure!Pass#" ,
356+ wantErr : false ,
357+ },
358+
359+ // Test with custom rejects only
360+ {
361+ name : "custom rejects - must not contains '\n '" ,
362+ validator : PasswordValidator {
363+ Rejects : & customRejects ,
364+ },
365+ password : "MyPASSWORD123\n " ,
366+ wantErr : true ,
367+ errMsg : ErrMsg ,
368+ },
369+
370+ // Test with both custom requirements and rejects
371+ {
372+ name : "custom both - fully valid password" ,
373+ validator : PasswordValidator {
374+ Requirements : & customRequirements ,
375+ Rejects : & customRejects ,
376+ },
377+ password : "MyS3cure!Pass" ,
378+ wantErr : false ,
379+ },
380+
381+ // Test empty requirements/rejects slices
382+ {
383+ name : "empty requirements slice - allows any non-empty password" ,
384+ validator : PasswordValidator {
385+ Requirements : & []Rule {},
386+ },
387+ password : "a" ,
388+ wantErr : false ,
389+ },
390+ {
391+ name : "empty rejects slice - no rejections" ,
392+ validator : PasswordValidator {
393+ Rejects : & []Rule {},
394+ },
395+ password : "anything$HOME$(cmd)`test`" ,
396+ wantErr : false ,
397+ },
398+ {
399+ name : "both empty - allows any non-empty password" ,
400+ validator : PasswordValidator {
401+ Requirements : & []Rule {},
402+ Rejects : & []Rule {},
403+ },
404+ password : "x" ,
405+ wantErr : false ,
406+ },
407+ }
408+
409+ for _ , tt := range tests {
410+ t .Run (tt .name , func (t * testing.T ) {
411+ g := NewWithT (t )
412+
413+ err := tt .validator .Validate (tt .password )
414+
415+ if tt .wantErr {
416+ g .Expect (err ).To (HaveOccurred ())
417+ if tt .errMsg != "" {
418+ g .Expect (err .Error ()).To (ContainSubstring (tt .errMsg ))
419+ }
420+ } else {
421+ g .Expect (err ).ToNot (HaveOccurred ())
422+ }
423+ })
424+ }
425+ }
0 commit comments