iam

package
v1.0.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 31, 2022 License: MIT Imports: 11 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var CheckAccessKeysRotated = rules.Register(
	scan2.Rule{
		AVDID:    "AVD-AWS-0146",
		Provider: providers2.AWSProvider,
		Frameworks: map[framework2.Framework][]string{
			framework2.CIS_AWS_1_2: {"1.4"},
			framework2.CIS_AWS_1_4: {"1.14"},
		},
		Service:    "iam",
		ShortCode:  "rotate-access-keys",
		Summary:    "Access keys should be rotated at least every 90 days",
		Impact:     "Compromised keys are more likely to be used to compromise the account",
		Resolution: "Rotate keys every 90 days or less",
		Explanation: `
Regularly rotating your IAM credentials helps prevent a compromised set of IAM access keys from accessing components in your AWS account.
			`,
		Links: []string{
			"https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/automatically-rotate-iam-user-access-keys-at-scale-with-aws-organizations-and-aws-secrets-manager.html",
		},
		Severity: severity2.Low,
	},
	func(s *state2.State) (results scan2.Results) {

		for _, user := range s.AWS.IAM.Users {
			var hasKey bool
			for _, key := range user.AccessKeys {
				if key.Active.IsFalse() {
					continue
				}
				if key.CreationDate.Before(time.Now().Add(-time.Hour * 24 * 90)) {
					days := int(time.Since(key.CreationDate.Value().Add(-time.Hour*24*90)).Hours() / 24)
					if days == 0 {
						days = 1
					}
					results.Add(fmt.Sprintf("User access key '%s' should have been rotated %d day(s) ago", key.AccessKeyId.Value(), days), &user)
					hasKey = true
				}
			}
			if !hasKey {
				results.AddPassed(&user)
			}
		}

		return
	},
)
View Source
var CheckEnforceGroupMFA = rules.Register(
	scan2.Rule{
		AVDID: "AVD-AWS-0123",
		Aliases: []string{
			"aws-iam-enforce-mfa",
		},
		Provider:   providers2.AWSProvider,
		Service:    "iam",
		ShortCode:  "enforce-group-mfa",
		Summary:    "IAM groups should have MFA enforcement activated.",
		Impact:     "IAM groups are more vulnerable to compromise without multi factor authentication activated",
		Resolution: "Use terraform-module/enforce-mfa/aws to ensure that MFA is enforced",
		Explanation: `
IAM groups should be protected with multi factor authentication to add safe guards to password compromise.
			`,
		Links: []string{
			"https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html#password-policy-details",
		},
		Terraform: &scan2.EngineMetadata{
			GoodExamples:        terraformEnforceMfaGoodExamples,
			BadExamples:         terraformEnforceMfaBadExamples,
			Links:               terraformEnforceMfaLinks,
			RemediationMarkdown: terraformEnforceMfaRemediationMarkdown,
		},
		Severity: severity2.Medium,
	},
	func(s *state2.State) (results scan2.Results) {

		for _, group := range s.AWS.IAM.Groups {
			var mfaEnforced bool
			for _, policy := range group.Policies {
				document := policy.Document.Parsed
				statements, _ := document.Statements()
				for _, statement := range statements {
					conditions, _ := statement.Conditions()
					for _, condition := range conditions {
						key, _ := condition.Key()
						if strings.EqualFold(key, "aws:MultiFactorAuthPresent") {
							mfaEnforced = true
							break
						}
					}
				}
			}
			if !mfaEnforced {
				results.Add("Multi-Factor authentication is not enforced for group", &group)
			}
		}

		return
	},
)
View Source
var CheckEnforceUserMFA = rules.Register(
	scan2.Rule{
		AVDID:     "AVD-AWS-0145",
		Provider:  providers2.AWSProvider,
		Service:   "iam",
		ShortCode: "enforce-user-mfa",
		Frameworks: map[framework2.Framework][]string{
			framework2.CIS_AWS_1_2: {"1.2"},
			framework2.CIS_AWS_1_4: {"1.4"},
		},
		Summary:    "IAM Users should have MFA enforcement activated.",
		Impact:     "User accounts are more vulnerable to compromise without multi factor authentication activated",
		Resolution: "Enable MFA for the user account",
		Explanation: `
IAM user accounts should be protected with multi factor authentication to add safe guards to password compromise.
			`,
		Links: []string{
			"https://console.aws.amazon.com/iam/",
		},
		Severity: severity2.Medium,
	},
	func(s *state2.State) (results scan2.Results) {

		for _, user := range s.AWS.IAM.Users {
			if user.HasLoggedIn() && len(user.MFADevices) == 0 {
				results.Add("User account does not have MFA", &user)
			} else {
				results.AddPassed(&user)
			}
		}

		return
	},
)
View Source
var CheckNoPasswordReuse = rules.Register(
	scan2.Rule{
		AVDID:     "AVD-AWS-0056",
		Provider:  providers2.AWSProvider,
		Service:   "iam",
		ShortCode: "no-password-reuse",
		Frameworks: map[framework2.Framework][]string{
			framework2.Default:     nil,
			framework2.CIS_AWS_1_2: {"1.10"},
			framework2.CIS_AWS_1_4: {"1.9"},
		},
		Summary:    "IAM Password policy should prevent password reuse.",
		Impact:     "Password reuse increase the risk of compromised passwords being abused",
		Resolution: "Prevent password reuse in the policy",
		Explanation: `IAM account password policies should prevent the reuse of passwords. 

The account password policy should be set to prevent using any of the last five used passwords.`,
		Links: []string{
			"https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html#password-policy-details",
		},
		Terraform: &scan2.EngineMetadata{
			GoodExamples:        terraformNoPasswordReuseGoodExamples,
			BadExamples:         terraformNoPasswordReuseBadExamples,
			Links:               terraformNoPasswordReuseLinks,
			RemediationMarkdown: terraformNoPasswordReuseRemediationMarkdown,
		},
		Severity: severity2.Medium,
	},
	func(s *state2.State) (results scan2.Results) {

		policy := s.AWS.IAM.PasswordPolicy
		if policy.IsUnmanaged() {
			return
		}

		if policy.ReusePreventionCount.LessThan(5) {
			results.Add(
				"Password policy allows reuse of recent passwords.",
				policy.ReusePreventionCount,
			)
		} else {
			results.AddPassed(&policy)
		}
		return
	},
)
View Source
var CheckNoPolicyWildcards = rules.Register(
	scan2.Rule{
		AVDID:       "AVD-AWS-0057",
		Provider:    providers2.AWSProvider,
		Service:     "iam",
		ShortCode:   "no-policy-wildcards",
		Summary:     "IAM policy should avoid use of wildcards and instead apply the principle of least privilege",
		Impact:      "Overly permissive policies may grant access to sensitive resources",
		Resolution:  "Specify the exact permissions required, and to which resources they should apply instead of using wildcards.",
		Explanation: `You should use the principle of least privilege when defining your IAM policies. This means you should specify each exact permission required without using wildcards, as this could cause the granting of access to certain undesired actions, resources and principals.`,
		Links: []string{
			"https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html",
		},
		Terraform: &scan2.EngineMetadata{
			GoodExamples:        terraformNoPolicyWildcardsGoodExamples,
			BadExamples:         terraformNoPolicyWildcardsBadExamples,
			Links:               terraformNoPolicyWildcardsLinks,
			RemediationMarkdown: terraformNoPolicyWildcardsRemediationMarkdown,
		},
		CloudFormation: &scan2.EngineMetadata{
			GoodExamples:        cloudFormationNoPolicyWildcardsGoodExamples,
			BadExamples:         cloudFormationNoPolicyWildcardsBadExamples,
			Links:               cloudFormationNoPolicyWildcardsLinks,
			RemediationMarkdown: cloudFormationNoPolicyWildcardsRemediationMarkdown,
		},
		Severity: severity2.High,
	},
	func(s *state2.State) (results scan2.Results) {
		for _, policy := range s.AWS.IAM.Policies {
			results = checkPolicy(policy.Document, results)
		}
		for _, group := range s.AWS.IAM.Groups {
			for _, policy := range group.Policies {
				results = checkPolicy(policy.Document, results)
			}
		}
		for _, user := range s.AWS.IAM.Users {
			for _, policy := range user.Policies {
				results = checkPolicy(policy.Document, results)
			}
		}
		for _, role := range s.AWS.IAM.Roles {
			for _, policy := range role.Policies {
				results = checkPolicy(policy.Document, results)
			}
		}
		return results
	},
)
View Source
var CheckRequireLowercaseInPasswords = rules.Register(
	scan2.Rule{
		AVDID:     "AVD-AWS-0058",
		Provider:  providers2.AWSProvider,
		Service:   "iam",
		ShortCode: "require-lowercase-in-passwords",
		Frameworks: map[framework2.Framework][]string{
			framework2.Default:     nil,
			framework2.CIS_AWS_1_2: {"1.6"},
		},
		Summary:     "IAM Password policy should have requirement for at least one lowercase character.",
		Impact:      "Short, simple passwords are easier to compromise",
		Resolution:  "Enforce longer, more complex passwords in the policy",
		Explanation: `IAM account password policies should ensure that passwords content including at least one lowercase character.`,
		Links: []string{
			"https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html#password-policy-details",
		},
		Terraform: &scan2.EngineMetadata{
			GoodExamples:        terraformRequireLowercaseInPasswordsGoodExamples,
			BadExamples:         terraformRequireLowercaseInPasswordsBadExamples,
			Links:               terraformRequireLowercaseInPasswordsLinks,
			RemediationMarkdown: terraformRequireLowercaseInPasswordsRemediationMarkdown,
		},
		Severity: severity2.Medium,
	},
	func(s *state2.State) (results scan2.Results) {
		policy := s.AWS.IAM.PasswordPolicy
		if policy.IsUnmanaged() {
			return
		}

		if policy.RequireLowercase.IsFalse() {
			results.Add(
				"Password policy does not require lowercase characters.",
				policy.RequireLowercase,
			)
		} else {
			results.AddPassed(&policy)
		}
		return
	},
)
View Source
var CheckRequireNumbersInPasswords = rules.Register(
	scan2.Rule{
		AVDID:     "AVD-AWS-0059",
		Provider:  providers2.AWSProvider,
		Service:   "iam",
		ShortCode: "require-numbers-in-passwords",
		Frameworks: map[framework2.Framework][]string{
			framework2.Default:     nil,
			framework2.CIS_AWS_1_2: {"1.8"},
		},
		Summary:     "IAM Password policy should have requirement for at least one number in the password.",
		Impact:      "Short, simple passwords are easier to compromise",
		Resolution:  "Enforce longer, more complex passwords in the policy",
		Explanation: `IAM account password policies should ensure that passwords content including at least one number.`,
		Links: []string{
			"https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html#password-policy-details",
		},
		Terraform: &scan2.EngineMetadata{
			GoodExamples:        terraformRequireNumbersInPasswordsGoodExamples,
			BadExamples:         terraformRequireNumbersInPasswordsBadExamples,
			Links:               terraformRequireNumbersInPasswordsLinks,
			RemediationMarkdown: terraformRequireNumbersInPasswordsRemediationMarkdown,
		},
		Severity: severity2.Medium,
	},
	func(s *state2.State) (results scan2.Results) {
		policy := s.AWS.IAM.PasswordPolicy
		if policy.IsUnmanaged() {
			return
		}

		if policy.RequireNumbers.IsFalse() {
			results.Add(
				"Password policy does not require numbers.",
				policy.RequireNumbers,
			)
		} else {
			results.AddPassed(&policy)
		}
		return
	},
)
View Source
var CheckRequireSymbolsInPasswords = rules.Register(
	scan2.Rule{
		AVDID:     "AVD-AWS-0060",
		Provider:  providers2.AWSProvider,
		Service:   "iam",
		ShortCode: "require-symbols-in-passwords",
		Frameworks: map[framework2.Framework][]string{
			framework2.Default:     nil,
			framework2.CIS_AWS_1_2: {"1.7"},
		},
		Summary:     "IAM Password policy should have requirement for at least one symbol in the password.",
		Impact:      "Short, simple passwords are easier to compromise",
		Resolution:  "Enforce longer, more complex passwords in the policy",
		Explanation: `IAM account password policies should ensure that passwords content including a symbol.`,
		Links: []string{
			"https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html#password-policy-details",
		},
		Terraform: &scan2.EngineMetadata{
			GoodExamples:        terraformRequireSymbolsInPasswordsGoodExamples,
			BadExamples:         terraformRequireSymbolsInPasswordsBadExamples,
			Links:               terraformRequireSymbolsInPasswordsLinks,
			RemediationMarkdown: terraformRequireSymbolsInPasswordsRemediationMarkdown,
		},
		Severity: severity2.Medium,
	},
	func(s *state2.State) (results scan2.Results) {
		policy := s.AWS.IAM.PasswordPolicy
		if policy.IsUnmanaged() {
			return
		}

		if policy.RequireSymbols.IsFalse() {
			results.Add(
				"Password policy does not require symbols.",
				policy.RequireSymbols,
			)
		} else {
			results.AddPassed(&policy)
		}
		return
	},
)
View Source
var CheckRequireUppercaseInPasswords = rules.Register(
	scan2.Rule{
		AVDID:     "AVD-AWS-0061",
		Provider:  providers2.AWSProvider,
		Service:   "iam",
		ShortCode: "require-uppercase-in-passwords",
		Frameworks: map[framework2.Framework][]string{
			framework2.Default:     nil,
			framework2.CIS_AWS_1_2: {"1.5"},
		},
		Summary:    "IAM Password policy should have requirement for at least one uppercase character.",
		Impact:     "Short, simple passwords are easier to compromise",
		Resolution: "Enforce longer, more complex passwords in the policy",
		Explanation: `,
IAM account password policies should ensure that passwords content including at least one uppercase character.`,
		Links: []string{
			"https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html#password-policy-details",
		},
		Terraform: &scan2.EngineMetadata{
			GoodExamples:        terraformRequireUppercaseInPasswordsGoodExamples,
			BadExamples:         terraformRequireUppercaseInPasswordsBadExamples,
			Links:               terraformRequireUppercaseInPasswordsLinks,
			RemediationMarkdown: terraformRequireUppercaseInPasswordsRemediationMarkdown,
		},
		Severity: severity2.Medium,
	},
	func(s *state2.State) (results scan2.Results) {
		policy := s.AWS.IAM.PasswordPolicy
		if policy.IsUnmanaged() {
			return
		}

		if policy.RequireUppercase.IsFalse() {
			results.Add(
				"Password policy does not require uppercase characters.",
				policy.RequireUppercase,
			)
		} else {
			results.AddPassed(&policy)
		}
		return
	},
)
View Source
var CheckSetMaxPasswordAge = rules.Register(
	scan2.Rule{
		AVDID:     "AVD-AWS-0062",
		Provider:  providers2.AWSProvider,
		Service:   "iam",
		ShortCode: "set-max-password-age",
		Frameworks: map[framework2.Framework][]string{
			framework2.Default:     nil,
			framework2.CIS_AWS_1_2: {"1.11"},
		},
		Summary:    "IAM Password policy should have expiry less than or equal to 90 days.",
		Impact:     "Long life password increase the likelihood of a password eventually being compromised",
		Resolution: "Limit the password duration with an expiry in the policy",
		Explanation: `IAM account password policies should have a maximum age specified. 
		
The account password policy should be set to expire passwords after 90 days or less.`,
		Links: []string{
			"https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html#password-policy-details",
		},
		Terraform: &scan2.EngineMetadata{
			GoodExamples:        terraformSetMaxPasswordAgeGoodExamples,
			BadExamples:         terraformSetMaxPasswordAgeBadExamples,
			Links:               terraformSetMaxPasswordAgeLinks,
			RemediationMarkdown: terraformSetMaxPasswordAgeRemediationMarkdown,
		},
		Severity: severity2.Medium,
	},
	func(s *state2.State) (results scan2.Results) {
		policy := s.AWS.IAM.PasswordPolicy
		if policy.IsUnmanaged() {
			return
		}

		if policy.MaxAgeDays.GreaterThan(90) {
			results.Add(
				"Password policy allows a maximum password age of greater than 90 days.",
				policy.MaxAgeDays,
			)
		} else {
			results.AddPassed(&policy)
		}
		return
	},
)
View Source
var CheckSetMinimumPasswordLength = rules.Register(
	scan2.Rule{
		AVDID:     "AVD-AWS-0063",
		Provider:  providers2.AWSProvider,
		Service:   "iam",
		ShortCode: "set-minimum-password-length",
		Frameworks: map[framework2.Framework][]string{
			framework2.Default:     nil,
			framework2.CIS_AWS_1_2: {"1.9"},
			framework2.CIS_AWS_1_4: {"1.8"},
		},
		Summary:    "IAM Password policy should have minimum password length of 14 or more characters.",
		Impact:     "Short, simple passwords are easier to compromise",
		Resolution: "Enforce longer, more complex passwords in the policy",
		Explanation: `IAM account password policies should ensure that passwords have a minimum length. 

The account password policy should be set to enforce minimum password length of at least 14 characters.`,
		Links: []string{
			"https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html#password-policy-details",
		},
		Terraform: &scan2.EngineMetadata{
			GoodExamples:        terraformSetMinimumPasswordLengthGoodExamples,
			BadExamples:         terraformSetMinimumPasswordLengthBadExamples,
			Links:               terraformSetMinimumPasswordLengthLinks,
			RemediationMarkdown: terraformSetMinimumPasswordLengthRemediationMarkdown,
		},
		Severity: severity2.Medium,
	},
	func(s *state2.State) (results scan2.Results) {
		policy := s.AWS.IAM.PasswordPolicy
		if policy.IsUnmanaged() {
			return
		}

		if policy.MinimumLength.LessThan(14) {
			results.Add(
				"Password policy has a minimum password length of less than 14 characters.",
				policy.MinimumLength,
			)
		} else {
			results.AddPassed(&policy)
		}
		return
	},
)
View Source
var CheckUnusedCredentialsDisabled = rules.Register(
	scan2.Rule{
		AVDID:    "AVD-AWS-0144",
		Provider: providers2.AWSProvider,
		Frameworks: map[framework2.Framework][]string{
			framework2.CIS_AWS_1_2: {"1.3"},
		},
		Service:    "iam",
		ShortCode:  "disable-unused-credentials",
		Summary:    "Credentials which are no longer used should be disabled.",
		Impact:     "Leaving unused credentials active widens the scope for compromise.",
		Resolution: "Disable credentials which are no longer used.",
		Explanation: `
CIS recommends that you remove or deactivate all credentials that have been unused in 90 days or more. Disabling or removing unnecessary credentials reduces the window of opportunity for credentials associated with a compromised or abandoned account to be used.
			`,
		Links: []string{
			"https://console.aws.amazon.com/iam/",
		},
		Severity: severity2.Medium,
	},
	func(s *state2.State) (results scan2.Results) {

		for _, user := range s.AWS.IAM.Users {
			if user.HasLoggedIn() && user.LastAccess.Before(time.Now().Add(-90*24*time.Hour)) {
				results.Add("User has not logged in for >90 days", &user)
				continue
			}
			var hasKey bool
			for _, key := range user.AccessKeys {
				if key.Active.IsFalse() || !key.LastAccess.GetMetadata().IsResolvable() ||
					key.LastAccess.After(time.Now().Add(-90*24*time.Hour)) {
					continue
				}
				results.Add(fmt.Sprintf("User access key '%s' has not been used in >90 days", key.AccessKeyId.Value()), &user)
				hasKey = true
			}
			if !hasKey {
				results.AddPassed(&user)
			}
		}

		return
	},
)

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL