-
Notifications
You must be signed in to change notification settings - Fork 8
/
credentials.go
113 lines (94 loc) · 2.7 KB
/
credentials.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package zebra
import (
"errors"
"strings"
"unicode"
)
var (
ErrPassLen = errors.New("password is less than 12 characters long")
ErrPassCase = errors.New("password does not contain both upper and lowercase")
ErrPassNum = errors.New("password does not contain a number")
ErrPassSpecial = errors.New("password does not contain a special character")
ErrUnknownCredential = errors.New("unknown credential type")
ErrNoKeys = errors.New("keys is nil")
)
// Credentials represents a named resource that has a set of keys (where each key is
// an authentication method) with corresponding values (where each value is the
// information to store for the authentication method).
type Credentials struct {
LoginID string `json:"loginId"`
Keys map[string]string `json:"keys,omitempty"`
}
func NewCredentials(loginID string) Credentials {
return Credentials{
LoginID: loginID,
Keys: map[string]string{},
}
}
func (c Credentials) Add(key string, value string) error {
validKeys := map[string]string{"password": "", "ssh-key": ""}
if _, ok := validKeys[key]; !ok {
return ErrUnknownCredential
}
c.Keys[key] = value
return nil
}
// Validate returns an error if the given Credentials object has incorrect values.
// Else, it returns nil.
func (c Credentials) Validate() error {
if c.LoginID == "" {
return ErrIDEmpty
}
if len(c.Keys) == 0 {
return ErrNoKeys
}
keyValidators := map[string]func(string) error{
"password": ValidatePassword,
"ssh-key": ValidateSSHKey,
}
for keyType, key := range c.Keys {
v := keyValidators[keyType]
if err := v(key); err != nil {
return err
}
}
return nil
}
// Check to make sure password follows rules.
// 1. At least 12 characters long.
// 2. Contains upper and lowercase letters.
// 3. Contains at least 1 number.
// 4. Contains at least 1 special character.
func ValidatePassword(password string) error { //nolint:cyclop
minLength := 12
var okLen, okLower, okUpper, okNum, okSpec bool
for _, char := range password {
switch {
case unicode.IsLower(char) && unicode.IsLetter(char):
okLower = true
case unicode.IsUpper(char) && unicode.IsLetter(char):
okUpper = true
case unicode.IsDigit(char):
okNum = true
case strings.Contains("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", string(char)): //nolint:gocritic
okSpec = true
}
}
okLen = len(password) >= minLength
switch {
case !okLen:
return ErrPassLen
case (!okLower || !okUpper):
return ErrPassCase
case !okNum:
return ErrPassNum
case !okSpec:
return ErrPassSpecial
}
return nil
}
// TO BE IMPLEMENTED AT A LATER TIME.
// Check to make sure SSH key follows specified rules.
func ValidateSSHKey(key string) error {
return nil
}