Skip to content
This repository has been archived by the owner on Jan 11, 2023. It is now read-only.

Enforce windows password complexity requirements in acs-engine client… #3854

Merged
merged 3 commits into from
Sep 20, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions pkg/api/vlabs/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -894,9 +894,38 @@ func (w *WindowsProfile) Validate(orchestratorType string) error {
if e := validate.Var(w.AdminPassword, "required"); e != nil {
return errors.New("WindowsProfile.AdminPassword is required, when agent pool specifies windows")
}
if validatePasswordComplexity(w.AdminUsername, w.AdminPassword) == false {
return errors.New("WindowsProfile.AdminPassword complexity not met. Windows password should contain 3 of the following categories - uppercase letters(A-Z), lowercase(a-z) letters, digits(0-9), special characters (~!@#$%^&*_-+=`|\\(){}[]:;<>,.?/')")
}
return validateKeyVaultSecrets(w.Secrets, true)
}

func validatePasswordComplexity(name string, password string) (out bool) {

if strings.EqualFold(name, password) {
return false
}

if len(password) == 0 {
return false
}

hits := 0
if regexp.MustCompile(`[0-9]+`).MatchString(password) {
hits++
}
if regexp.MustCompile(`[A-Z]+`).MatchString(password) {
hits++
}
if regexp.MustCompile(`[a-z]`).MatchString(password) {
hits++
}
if regexp.MustCompile(`[~!@#\$%\^&\*_\-\+=\x60\|\(\){}\[\]:;"'<>,\.\?/]+`).MatchString(password) {
hits++
}
return hits > 2
}

// Validate validates the KubernetesConfig
func (k *KubernetesConfig) Validate(k8sVersion string, hasWindows bool) error {
// number of minimum retries allowed for kubelet to post node status
Expand Down
16 changes: 15 additions & 1 deletion pkg/api/vlabs/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1077,7 +1077,7 @@ func getK8sDefaultProperties(hasWindows bool) *Properties {
}
p.WindowsProfile = &WindowsProfile{
AdminUsername: "azureuser",
AdminPassword: "password",
AdminPassword: "replacepassword1234$",
}
}

Expand Down Expand Up @@ -1265,6 +1265,20 @@ func TestWindowsVersions(t *testing.T) {
"should not error on valid Windows version: %v", err,
)
}
p = getK8sDefaultProperties(true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's add a unit test case for a valid password

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I see that's already covered with the general valid Windows profile. However the length = 0 and name == password cases are both missing.

p.WindowsProfile.AdminPassword = "Password"
if err := p.Validate(false); err == nil {
t.Errorf(
"should error on windows password complexity not match because no digits and special characters found in the password ",
)
}
p = getK8sDefaultProperties(true)
p.WindowsProfile.AdminPassword = "123!@#"
if err := p.Validate(false); err == nil {
t.Errorf(
"should error on windows password complexity not match because uppercase and lowercase letters found in the password",
)
}
sv, _ := semver.Make(version)
p = getK8sDefaultProperties(true)
p.OrchestratorProfile.OrchestratorRelease = fmt.Sprintf("%d.%d", sv.Major, sv.Minor)
Expand Down