Documentation ¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var CheckAccessKeysRotated = rules.Register( scan.Rule{ AVDID: "AVD-AWS-0146", Provider: providers.AWSProvider, Frameworks: map[framework.Framework][]string{ framework.CIS_AWS_1_2: {"1.4"}, framework.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: severity.Low, }, func(s *state.State) (results scan.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( scan.Rule{ AVDID: "AVD-AWS-0123", Aliases: []string{ "aws-iam-enforce-mfa", }, Provider: providers.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: &scan.EngineMetadata{ GoodExamples: terraformEnforceMfaGoodExamples, BadExamples: terraformEnforceMfaBadExamples, Links: terraformEnforceMfaLinks, RemediationMarkdown: terraformEnforceMfaRemediationMarkdown, }, Severity: severity.Medium, }, func(s *state.State) (results scan.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( scan.Rule{ AVDID: "AVD-AWS-0145", Provider: providers.AWSProvider, Service: "iam", ShortCode: "enforce-user-mfa", Frameworks: map[framework.Framework][]string{ framework.CIS_AWS_1_2: {"1.2"}, framework.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: severity.Medium, }, func(s *state.State) (results scan.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 CheckLimitUserAccessKeys = rules.Register( scan.Rule{ AVDID: "AVD-AWS-0167", Provider: providers.AWSProvider, Frameworks: map[framework.Framework][]string{ framework.CIS_AWS_1_4: {"1.13"}, }, Service: "iam", ShortCode: "limit-user-access-keys", Summary: "No user should have more than one active access key.", Impact: "Widened scope for compromise.", Resolution: "Limit the number of active access keys to one key per user.", Explanation: ` Multiple active access keys widens the scope for compromise. `, Links: []string{ "https://console.aws.amazon.com/iam/", }, Severity: severity.Low, }, func(s *state.State) (results scan.Results) { for _, user := range s.AWS.IAM.Users { var countActive int for _, key := range user.AccessKeys { if key.Active.IsTrue() { countActive++ } } if countActive > 1 { results.Add("User has more than one active access key", &user) } else { results.AddPassed(&user) } } return }, )
View Source
var CheckNoPasswordReuse = rules.Register( scan.Rule{ AVDID: "AVD-AWS-0056", Provider: providers.AWSProvider, Service: "iam", ShortCode: "no-password-reuse", Frameworks: map[framework.Framework][]string{ framework.Default: nil, framework.CIS_AWS_1_2: {"1.10"}, framework.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: &scan.EngineMetadata{ GoodExamples: terraformNoPasswordReuseGoodExamples, BadExamples: terraformNoPasswordReuseBadExamples, Links: terraformNoPasswordReuseLinks, RemediationMarkdown: terraformNoPasswordReuseRemediationMarkdown, }, Severity: severity.Medium, }, func(s *state.State) (results scan.Results) { policy := s.AWS.IAM.PasswordPolicy if policy.Metadata.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( scan.Rule{ AVDID: "AVD-AWS-0057", Provider: providers.AWSProvider, Service: "iam", ShortCode: "no-policy-wildcards", Frameworks: map[framework.Framework][]string{ framework.Default: nil, framework.CIS_AWS_1_4: {"1.16"}, }, 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: &scan.EngineMetadata{ GoodExamples: terraformNoPolicyWildcardsGoodExamples, BadExamples: terraformNoPolicyWildcardsBadExamples, Links: terraformNoPolicyWildcardsLinks, RemediationMarkdown: terraformNoPolicyWildcardsRemediationMarkdown, }, CloudFormation: &scan.EngineMetadata{ GoodExamples: cloudFormationNoPolicyWildcardsGoodExamples, BadExamples: cloudFormationNoPolicyWildcardsBadExamples, Links: cloudFormationNoPolicyWildcardsLinks, RemediationMarkdown: cloudFormationNoPolicyWildcardsRemediationMarkdown, }, Severity: severity.High, }, func(s *state.State) (results scan.Results) { for _, policy := range s.AWS.IAM.Policies { if policy.Builtin.IsTrue() { continue } results = checkPolicy(policy.Document, results) } for _, group := range s.AWS.IAM.Groups { for _, policy := range group.Policies { if policy.Builtin.IsTrue() { continue } results = checkPolicy(policy.Document, results) } } for _, user := range s.AWS.IAM.Users { for _, policy := range user.Policies { if policy.Builtin.IsTrue() { continue } results = checkPolicy(policy.Document, results) } } for _, role := range s.AWS.IAM.Roles { for _, policy := range role.Policies { if policy.Builtin.IsTrue() { continue } results = checkPolicy(policy.Document, results) } } return results }, )
View Source
var CheckRemoveExpiredCertificates = rules.Register( scan.Rule{ AVDID: "AVD-AWS-0168", Provider: providers.AWSProvider, Frameworks: map[framework.Framework][]string{ framework.CIS_AWS_1_4: {"1.19"}, }, Service: "iam", ShortCode: "remove-expired-certificates", Summary: "Delete expired TLS certificates", Impact: "Risk of misconfiguration and damage to credibility", Resolution: "Remove expired certificates", Explanation: ` Removing expired SSL/TLS certificates eliminates the risk that an invalid certificate will be deployed accidentally to a resource such as AWS Elastic Load Balancer (ELB), which can damage the credibility of the application/website behind the ELB. As a best practice, it is recommended to delete expired certificates. `, Links: []string{ "https://console.aws.amazon.com/iam/", }, Severity: severity.Low, }, func(s *state.State) (results scan.Results) { for _, certificate := range s.AWS.IAM.ServerCertificates { if certificate.Expiration.Before(time.Now()) { results.Add("Certificate has expired.", &certificate) } else { results.AddPassed(&certificate) } } return }, )
View Source
var CheckRequireLowercaseInPasswords = rules.Register( scan.Rule{ AVDID: "AVD-AWS-0058", Provider: providers.AWSProvider, Service: "iam", ShortCode: "require-lowercase-in-passwords", Frameworks: map[framework.Framework][]string{ framework.Default: nil, framework.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: &scan.EngineMetadata{ GoodExamples: terraformRequireLowercaseInPasswordsGoodExamples, BadExamples: terraformRequireLowercaseInPasswordsBadExamples, Links: terraformRequireLowercaseInPasswordsLinks, RemediationMarkdown: terraformRequireLowercaseInPasswordsRemediationMarkdown, }, Severity: severity.Medium, }, func(s *state.State) (results scan.Results) { policy := s.AWS.IAM.PasswordPolicy if policy.Metadata.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( scan.Rule{ AVDID: "AVD-AWS-0059", Provider: providers.AWSProvider, Service: "iam", ShortCode: "require-numbers-in-passwords", Frameworks: map[framework.Framework][]string{ framework.Default: nil, framework.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: &scan.EngineMetadata{ GoodExamples: terraformRequireNumbersInPasswordsGoodExamples, BadExamples: terraformRequireNumbersInPasswordsBadExamples, Links: terraformRequireNumbersInPasswordsLinks, RemediationMarkdown: terraformRequireNumbersInPasswordsRemediationMarkdown, }, Severity: severity.Medium, }, func(s *state.State) (results scan.Results) { policy := s.AWS.IAM.PasswordPolicy if policy.Metadata.IsUnmanaged() { return } if policy.RequireNumbers.IsFalse() { results.Add( "Password policy does not require numbers.", policy.RequireNumbers, ) } else { results.AddPassed(&policy) } return }, )
View Source
var CheckRequireSupportRole = rules.Register( scan.Rule{ AVDID: "AVD-AWS-0169", Provider: providers.AWSProvider, Frameworks: map[framework.Framework][]string{ framework.CIS_AWS_1_4: {"1.17"}, }, Service: "iam", ShortCode: "require-support-role", Summary: "Missing IAM Role to allow authorized users to manage incidents with AWS Support.", Impact: "Incident management is not possible without a support role.", Resolution: "Create an IAM role with the necessary permissions to manage incidents with AWS Support.", Explanation: ` By implementing least privilege for access control, an IAM Role will require an appropriate IAM Policy to allow Support Center Access in order to manage Incidents with AWS Support. `, Links: []string{ "https://console.aws.amazon.com/iam/", }, Severity: severity.Low, }, func(s *state.State) (results scan.Results) { for _, role := range s.AWS.IAM.Roles { for _, policy := range role.Policies { if policy.Builtin.IsTrue() && policy.Name.EqualTo("AWSSupportAccess") { results.AddPassed(&role) return } } } results.Add("Missing IAM support role.", defsecTypes.NewUnmanagedMetadata()) return results }, )
View Source
var CheckRequireSymbolsInPasswords = rules.Register( scan.Rule{ AVDID: "AVD-AWS-0060", Provider: providers.AWSProvider, Service: "iam", ShortCode: "require-symbols-in-passwords", Frameworks: map[framework.Framework][]string{ framework.Default: nil, framework.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: &scan.EngineMetadata{ GoodExamples: terraformRequireSymbolsInPasswordsGoodExamples, BadExamples: terraformRequireSymbolsInPasswordsBadExamples, Links: terraformRequireSymbolsInPasswordsLinks, RemediationMarkdown: terraformRequireSymbolsInPasswordsRemediationMarkdown, }, Severity: severity.Medium, }, func(s *state.State) (results scan.Results) { policy := s.AWS.IAM.PasswordPolicy if policy.Metadata.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( scan.Rule{ AVDID: "AVD-AWS-0061", Provider: providers.AWSProvider, Service: "iam", ShortCode: "require-uppercase-in-passwords", Frameworks: map[framework.Framework][]string{ framework.Default: nil, framework.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: &scan.EngineMetadata{ GoodExamples: terraformRequireUppercaseInPasswordsGoodExamples, BadExamples: terraformRequireUppercaseInPasswordsBadExamples, Links: terraformRequireUppercaseInPasswordsLinks, RemediationMarkdown: terraformRequireUppercaseInPasswordsRemediationMarkdown, }, Severity: severity.Medium, }, func(s *state.State) (results scan.Results) { policy := s.AWS.IAM.PasswordPolicy if policy.Metadata.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( scan.Rule{ AVDID: "AVD-AWS-0062", Provider: providers.AWSProvider, Service: "iam", ShortCode: "set-max-password-age", Frameworks: map[framework.Framework][]string{ framework.Default: nil, framework.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: &scan.EngineMetadata{ GoodExamples: terraformSetMaxPasswordAgeGoodExamples, BadExamples: terraformSetMaxPasswordAgeBadExamples, Links: terraformSetMaxPasswordAgeLinks, RemediationMarkdown: terraformSetMaxPasswordAgeRemediationMarkdown, }, Severity: severity.Medium, }, func(s *state.State) (results scan.Results) { policy := s.AWS.IAM.PasswordPolicy if policy.Metadata.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( scan.Rule{ AVDID: "AVD-AWS-0063", Provider: providers.AWSProvider, Service: "iam", ShortCode: "set-minimum-password-length", Frameworks: map[framework.Framework][]string{ framework.Default: nil, framework.CIS_AWS_1_2: {"1.9"}, framework.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: &scan.EngineMetadata{ GoodExamples: terraformSetMinimumPasswordLengthGoodExamples, BadExamples: terraformSetMinimumPasswordLengthBadExamples, Links: terraformSetMinimumPasswordLengthLinks, RemediationMarkdown: terraformSetMinimumPasswordLengthRemediationMarkdown, }, Severity: severity.Medium, }, func(s *state.State) (results scan.Results) { policy := s.AWS.IAM.PasswordPolicy if policy.Metadata.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( scan.Rule{ AVDID: "AVD-AWS-0144", Provider: providers.AWSProvider, Frameworks: map[framework.Framework][]string{ framework.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: severity.Medium, }, func(s *state.State) (results scan.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 }, )
View Source
var CheckUnusedCredentialsDisabled45Days = rules.Register( scan.Rule{ AVDID: "AVD-AWS-0166", Provider: providers.AWSProvider, Frameworks: map[framework.Framework][]string{ framework.CIS_AWS_1_4: {"1.12"}, }, Service: "iam", ShortCode: "disable-unused-credentials-45-days", Summary: "AWS IAM users can access AWS resources using different types of credentials, such as\npasswords or access keys. It is recommended that all credentials that have been unused in\n45 or greater days be deactivated or removed.", Impact: "Leaving unused credentials active widens the scope for compromise.", Resolution: "Disable credentials which are no longer used.", Explanation: ` Disabling or removing unnecessary credentials will reduce 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: severity.Low, }, func(s *state.State) (results scan.Results) { for _, user := range s.AWS.IAM.Users { if user.HasLoggedIn() && user.LastAccess.Before(time.Now().Add(-45*24*time.Hour)) { results.Add("User has not logged in for >45 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(-45*24*time.Hour)) { continue } results.Add(fmt.Sprintf("User access key '%s' has not been used in >45 days", key.AccessKeyId.Value()), &user) hasKey = true } if !hasKey { results.AddPassed(&user) } } return }, )
Functions ¶
This section is empty.
Types ¶
This section is empty.
Source Files ¶
- disable_unused_credentials.go
- disable_unused_credentials_45.go
- enforce_group_mfa.go
- enforce_group_mfa.tf.go
- enforce_root_hardware_mfa.go
- enforce_root_mfa.go
- enforce_user_mfa.go
- limit_root_account_usage.go
- limit_user_access_keys.go
- no_password_reuse.go
- no_password_reuse.tf.go
- no_policy_wildcards.cf.go
- no_policy_wildcards.go
- no_policy_wildcards.tf.go
- no_root_access_keys.go
- no_root_access_keys.tf.go
- no_user_attached_policies.go
- no_user_attached_policies.tf.go
- remove_expired_certificates.go
- require_lowercase_in_passwords.go
- require_lowercase_in_passwords.tf.go
- require_numbers_in_passwords.go
- require_numbers_in_passwords.tf.go
- require_support_role.go
- require_symbols_in_passwords.go
- require_symbols_in_passwords.tf.go
- require_uppercase_in_passwords.go
- require_uppercase_in_passwords.tf.go
- rotate_access_keys.go
- set_max_password_age.go
- set_max_password_age.tf.go
- set_minimum_password_length.go
- set_minimum_password_length.tf.go
Click to show internal directories.
Click to hide internal directories.