feat(password_policy_checks): Include password policy checks (#1364)

This commit is contained in:
Nacho Rivera
2022-10-18 10:15:15 +02:00
committed by GitHub
parent 5cc3888022
commit 2b59068e50
30 changed files with 766 additions and 214 deletions

View File

@@ -1,39 +0,0 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2019) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_check110="1.10"
CHECK_TITLE_check110="[check110] Ensure IAM password policy prevents password reuse: 24 or greater"
CHECK_SCORED_check110="SCORED"
CHECK_CIS_LEVEL_check110="LEVEL1"
CHECK_SEVERITY_check110="Medium"
CHECK_ASFF_TYPE_check110="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ALTERNATE_check110="check110"
CHECK_SERVICENAME_check110="iam"
CHECK_RISK_check110='Password policies are used to enforce password complexity requirements. IAM password policies can be used to ensure password are comprised of different character sets. It is recommended that the password policy require at least one uppercase letter.'
CHECK_REMEDIATION_check110='Ensure "Number of passwords to remember" is set to 24.'
CHECK_DOC_check110='https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html'
CHECK_CAF_EPIC_check110='IAM'
check110(){
# "Ensure IAM password policy prevents password reuse: 24 or greater (Scored)"
COMMAND110=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --query 'PasswordPolicy.PasswordReusePrevention' --output text 2> /dev/null)
if [[ $COMMAND110 ]];then
if [[ $COMMAND110 -gt "23" ]];then
textPass "$REGION: Password Policy limits reuse" "$REGION" "password policy"
else
textFail "$REGION: Password Policy has weak reuse requirement (lower than 24)" "$REGION" "password policy"
fi
else
textFail "$REGION: Password Policy missing reuse requirement" "$REGION" "password policy"
fi
}

View File

@@ -1,35 +0,0 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2019) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_check15="1.5"
CHECK_TITLE_check15="[check15] Ensure IAM password policy requires at least one uppercase letter"
CHECK_SCORED_check15="SCORED"
CHECK_CIS_LEVEL_check15="LEVEL1"
CHECK_SEVERITY_check15="Medium"
CHECK_ASFF_TYPE_check15="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ALTERNATE_check105="check15"
CHECK_SERVICENAME_check15="iam"
CHECK_RISK_check15='Password policies are used to enforce password complexity requirements. IAM password policies can be used to ensure password are comprised of different character sets. It is recommended that the password policy require at least one uppercase letter.'
CHECK_REMEDIATION_check15='Ensure "Requires at least one uppercase letter" is checked under "Password Policy".'
CHECK_DOC_check15='https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html'
CHECK_CAF_EPIC_check15='IAM'
check15(){
# "Ensure IAM password policy requires at least one uppercase letter (Scored)"
COMMAND15=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireUppercaseCharacters' 2> /dev/null) # must be true
if [[ "$COMMAND15" == "true" ]];then
textPass "$REGION: Password Policy requires upper case" "$REGION" "password policy"
else
textFail "$REGION: Password Policy missing upper-case requirement" "$REGION" "password policy"
fi
}

View File

@@ -1,35 +0,0 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2019) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_check16="1.6"
CHECK_TITLE_check16="[check16] Ensure IAM password policy require at least one lowercase letter"
CHECK_SCORED_check16="SCORED"
CHECK_CIS_LEVEL_check16="LEVEL1"
CHECK_SEVERITY_check16="Medium"
CHECK_ASFF_TYPE_check16="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ALTERNATE_check106="check16"
CHECK_SERVICENAME_check16="iam"
CHECK_RISK_check16='Password policies are used to enforce password complexity requirements. IAM password policies can be used to ensure password are comprised of different character sets. It is recommended that the password policy require at least one uppercase letter.'
CHECK_REMEDIATION_check16='Ensure "Requires at least one lowercase letter" is checked under "Password Policy".'
CHECK_DOC_check16='https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html'
CHECK_CAF_EPIC_check16='IAM'
check16(){
# "Ensure IAM password policy require at least one lowercase letter (Scored)"
COMMAND16=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireLowercaseCharacters' 2> /dev/null) # must be true
if [[ "$COMMAND16" == "true" ]];then
textPass "$REGION: Password Policy requires lower case" "$REGION" "password policy"
else
textFail "$REGION: Password Policy missing lower-case requirement" "$REGION" "password policy"
fi
}

View File

@@ -1,35 +0,0 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2019) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_check17="1.7"
CHECK_TITLE_check17="[check17] Ensure IAM password policy require at least one symbol"
CHECK_SCORED_check17="SCORED"
CHECK_CIS_LEVEL_check17="LEVEL1"
CHECK_SEVERITY_check17="Medium"
CHECK_ASFF_TYPE_check17="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ALTERNATE_check107="check17"
CHECK_SERVICENAME_check17="iam"
CHECK_RISK_check17='Password policies are used to enforce password complexity requirements. IAM password policies can be used to ensure password are comprised of different character sets. It is recommended that the password policy require at least one uppercase letter.'
CHECK_REMEDIATION_check17='Ensure "Require at least one non-alphanumeric character" is checked under "Password Policy".'
CHECK_DOC_check17='https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html'
CHECK_CAF_EPIC_check17='IAM'
check17(){
# "Ensure IAM password policy require at least one symbol (Scored)"
COMMAND17=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireSymbols' 2> /dev/null) # must be true
if [[ "$COMMAND17" == "true" ]];then
textPass "$REGION: Password Policy requires symbol" "$REGION" "password policy"
else
textFail "$REGION: Password Policy missing symbol requirement" "$REGION" "password policy"
fi
}

View File

@@ -1,35 +0,0 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2019) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_check18="1.8"
CHECK_TITLE_check18="[check18] Ensure IAM password policy require at least one number"
CHECK_SCORED_check18="SCORED"
CHECK_CIS_LEVEL_check18="LEVEL1"
CHECK_SEVERITY_check18="Medium"
CHECK_ASFF_TYPE_check18="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ALTERNATE_check108="check18"
CHECK_SERVICENAME_check18="iam"
CHECK_RISK_check18='Password policies are used to enforce password complexity requirements. IAM password policies can be used to ensure password are comprised of different character sets. It is recommended that the password policy require at least one uppercase letter.'
CHECK_REMEDIATION_check18='Ensure "Require at least one number " is checked under "Password Policy".'
CHECK_DOC_check18='https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html'
CHECK_CAF_EPIC_check18='IAM'
check18(){
# "Ensure IAM password policy require at least one number (Scored)"
COMMAND18=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.RequireNumbers' 2> /dev/null) # must be true
if [[ "$COMMAND18" == "true" ]];then
textPass "$REGION: Password Policy requires number" "$REGION" "password policy"
else
textFail "$REGION: Password Policy missing number requirement" "$REGION" "password policy"
fi
}

View File

@@ -1,35 +0,0 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2019) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_check19="1.9"
CHECK_TITLE_check19="[check19] Ensure IAM password policy requires minimum length of 14 or greater"
CHECK_SCORED_check19="SCORED"
CHECK_CIS_LEVEL_check19="LEVEL1"
CHECK_SEVERITY_check19="Medium"
CHECK_ASFF_TYPE_check19="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ALTERNATE_check109="check19"
CHECK_SERVICENAME_check19="iam"
CHECK_RISK_check19='Password policies are used to enforce password complexity requirements. IAM password policies can be used to ensure password are comprised of different character sets. It is recommended that the password policy require at least one uppercase letter.'
CHECK_REMEDIATION_check19='Ensure "Minimum password length" is set to 14 or greater.'
CHECK_DOC_check19='https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html'
CHECK_CAF_EPIC_check19='IAM'
check19(){
# "Ensure IAM password policy requires minimum length of 14 or greater (Scored)"
COMMAND19=$($AWSCLI iam get-account-password-policy $PROFILE_OPT --region $REGION --output json --query 'PasswordPolicy.MinimumPasswordLength' 2> /dev/null)
if [[ $COMMAND19 -gt "13" ]];then
textPass "$REGION: Password Policy requires more than 13 characters" "$REGION" "password policy"
else
textFail "$REGION: Password Policy missing or weak length requirement" "$REGION" "password policy"
fi
}

View File

@@ -0,0 +1,46 @@
{
"Provider": "aws",
"CheckID": "iam_password_policy_lowercase",
"CheckTitle": "Ensure IAM password policy require at least one lowercase letter",
"CheckType": ["Software and Configuration Checks", "Industry and Regulatory Standards" ,"CIS AWS Foundations Benchmark"],
"ServiceName": "iam",
"SubServiceName": "",
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
"Severity": "medium",
"ResourceType": "AwsIamPasswordPolicy",
"Description": "Ensure IAM password policy requires at least one uppercase letter",
"Risk": "Password policies are used to enforce password complexity requirements. IAM password policies can be used to ensure password are comprised of different character sets. It is recommended that the password policy require at least one lowercase letter.",
"RelatedUrl": "",
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "",
"Terraform": ""
},
"Recommendation": {
"Text": "Ensure \"Requires at least one lowercase letter\" is checked under \"Password Policy\".",
"Url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html"
}
},
"Categories": [],
"Tags": {
"Tag1Key": "value",
"Tag2Key": "value"
},
"DependsOn": [],
"RelatedTo": [],
"Notes": "",
"Compliance": [
{
"Control": [
"1.6"
],
"Framework": "CIS-AWS",
"Group": [
"level1"
],
"Version": "1.4"
}
]
}

View File

@@ -0,0 +1,26 @@
from lib.check.models import Check, Check_Report
from providers.aws.services.iam.iam_client import iam_client
class iam_password_policy_lowercase(Check):
def execute(self) -> Check_Report:
findings = []
report = Check_Report(self.metadata)
report.region = iam_client.region
report.resource_id = "password_policy"
# Check if password policy exists
if iam_client.password_policy:
# Check if lowercase flag is set
if iam_client.password_policy.lowercase:
report.status = "PASS"
report.status_extended = "IAM password policy does not require at least one lowercase letter."
else:
report.status = "FAIL"
report.status_extended = (
"IAM password policy require at least one lowercase letter."
)
else:
report.status = "FAIL"
report.status_extended = f"Password policy cannot be found"
findings.append(report)
return findings

View File

@@ -0,0 +1,50 @@
from unittest import mock
from boto3 import client
from moto import mock_iam
class Test_iam_password_policy_lowercase:
@mock_iam
def test_iam_password_policy_no_lowercase_flag(self):
iam_client = client("iam")
# update password policy
iam_client.update_account_password_policy(RequireLowercaseCharacters=False)
from providers.aws.lib.audit_info.audit_info import current_audit_info
from providers.aws.services.iam.iam_service import IAM
with mock.patch(
"providers.aws.services.iam.iam_password_policy_lowercase.iam_password_policy_lowercase.iam_client",
new=IAM(current_audit_info),
):
# Test Check
from providers.aws.services.iam.iam_password_policy_lowercase.iam_password_policy_lowercase import (
iam_password_policy_lowercase,
)
check = iam_password_policy_lowercase()
result = check.execute()
assert result[0].status == "FAIL"
@mock_iam
def test_iam_password_policy_lowercase_flag(self):
iam_client = client("iam")
# update password policy
iam_client.update_account_password_policy(RequireLowercaseCharacters=True)
from providers.aws.lib.audit_info.audit_info import current_audit_info
from providers.aws.services.iam.iam_service import IAM
with mock.patch(
"providers.aws.services.iam.iam_password_policy_lowercase.iam_password_policy_lowercase.iam_client",
new=IAM(current_audit_info),
):
# Test Check
from providers.aws.services.iam.iam_password_policy_lowercase.iam_password_policy_lowercase import (
iam_password_policy_lowercase,
)
check = iam_password_policy_lowercase()
result = check.execute()
assert result[0].status == "PASS"

View File

@@ -0,0 +1,46 @@
{
"Provider": "aws",
"CheckID": "iam_password_policy_minimum_length_14",
"CheckTitle": "Ensure IAM password policy requires minimum length of 14 or greater",
"CheckType": ["Software and Configuration Checks", "Industry and Regulatory Standards" ,"CIS AWS Foundations Benchmark"],
"ServiceName": "iam",
"SubServiceName": "",
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
"Severity": "medium",
"ResourceType": "AwsIamPasswordPolicy",
"Description": "Ensure IAM password policy requires minimum length of 14 or greater",
"Risk": "Password policies are used to enforce password complexity requirements. IAM password policies can be used to ensure password are comprised of different character sets. It is recommended that the password policy require minimum length of 14 or greater.",
"RelatedUrl": "",
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "",
"Terraform": ""
},
"Recommendation": {
"Text": "Ensure \"Minimum password length\" is checked under \"Password Policy\".",
"Url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html"
}
},
"Categories": [],
"Tags": {
"Tag1Key": "value",
"Tag2Key": "value"
},
"DependsOn": [],
"RelatedTo": [],
"Notes": "",
"Compliance": [
{
"Control": [
"1.9"
],
"Framework": "CIS-AWS",
"Group": [
"level1"
],
"Version": "1.4"
}
]
}

View File

@@ -0,0 +1,29 @@
from lib.check.models import Check, Check_Report
from providers.aws.services.iam.iam_client import iam_client
class iam_password_policy_minimum_length_14(Check):
def execute(self) -> Check_Report:
findings = []
report = Check_Report(self.metadata)
report.region = iam_client.region
report.resource_id = "password_policy"
# Check if password policy exists
if iam_client.password_policy:
# Check password policy length
if (
iam_client.password_policy.length
and iam_client.password_policy.length >= 14
):
report.status = "PASS"
report.status_extended = "IAM password policy does not requires minimum length of 14 characters."
else:
report.status = "FAIL"
report.status_extended = (
"IAM password policy requires minimum length of 14 characters."
)
else:
report.status = "FAIL"
report.status_extended = "Password policy cannot be found"
findings.append(report)
return findings

View File

@@ -0,0 +1,72 @@
from unittest import mock
from boto3 import client
from moto import mock_iam
class Test_iam_password_policy_minimum_length_14:
@mock_iam
def test_iam_password_policy_minimum_length_equal_14(self):
iam_client = client("iam")
# update password policy
iam_client.update_account_password_policy(MinimumPasswordLength=14)
from providers.aws.lib.audit_info.audit_info import current_audit_info
from providers.aws.services.iam.iam_service import IAM
with mock.patch(
"providers.aws.services.iam.iam_password_policy_minimum_length_14.iam_password_policy_minimum_length_14.iam_client",
new=IAM(current_audit_info),
):
# Test Check
from providers.aws.services.iam.iam_password_policy_minimum_length_14.iam_password_policy_minimum_length_14 import (
iam_password_policy_minimum_length_14,
)
check = iam_password_policy_minimum_length_14()
result = check.execute()
assert result[0].status == "PASS"
@mock_iam
def test_iam_password_policy_minimum_length_greater_14(self):
iam_client = client("iam")
# update password policy
iam_client.update_account_password_policy(MinimumPasswordLength=20)
from providers.aws.lib.audit_info.audit_info import current_audit_info
from providers.aws.services.iam.iam_service import IAM
with mock.patch(
"providers.aws.services.iam.iam_password_policy_minimum_length_14.iam_password_policy_minimum_length_14.iam_client",
new=IAM(current_audit_info),
):
# Test Check
from providers.aws.services.iam.iam_password_policy_minimum_length_14.iam_password_policy_minimum_length_14 import (
iam_password_policy_minimum_length_14,
)
check = iam_password_policy_minimum_length_14()
result = check.execute()
assert result[0].status == "PASS"
@mock_iam
def test_iam_password_policy_minimum_length_less_14(self):
iam_client = client("iam")
# update password policy
iam_client.update_account_password_policy(MinimumPasswordLength=10)
from providers.aws.lib.audit_info.audit_info import current_audit_info
from providers.aws.services.iam.iam_service import IAM
with mock.patch(
"providers.aws.services.iam.iam_password_policy_minimum_length_14.iam_password_policy_minimum_length_14.iam_client",
new=IAM(current_audit_info),
):
# Test Check
from providers.aws.services.iam.iam_password_policy_minimum_length_14.iam_password_policy_minimum_length_14 import (
iam_password_policy_minimum_length_14,
)
check = iam_password_policy_minimum_length_14()
result = check.execute()
assert result[0].status == "FAIL"

View File

@@ -0,0 +1,46 @@
{
"Provider": "aws",
"CheckID": "iam_password_policy_number",
"CheckTitle": "Ensure IAM password policy require at least one number",
"CheckType": ["Software and Configuration Checks", "Industry and Regulatory Standards" ,"CIS AWS Foundations Benchmark"],
"ServiceName": "iam",
"SubServiceName": "",
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
"Severity": "medium",
"ResourceType": "AwsIamPasswordPolicy",
"Description": "Ensure IAM password policy require at least one number",
"Risk": "Password policies are used to enforce password complexity requirements. IAM password policies can be used to ensure password are comprised of different character sets. It is recommended that the password policy require at least one number.",
"RelatedUrl": "",
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "",
"Terraform": ""
},
"Recommendation": {
"Text": "Ensure \"Require at least one number\" is checked under \"Password Policy\".",
"Url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html"
}
},
"Categories": [],
"Tags": {
"Tag1Key": "value",
"Tag2Key": "value"
},
"DependsOn": [],
"RelatedTo": [],
"Notes": "",
"Compliance": [
{
"Control": [
"1.8"
],
"Framework": "CIS-AWS",
"Group": [
"level1"
],
"Version": "1.4"
}
]
}

View File

@@ -0,0 +1,28 @@
from lib.check.models import Check, Check_Report
from providers.aws.services.iam.iam_client import iam_client
class iam_password_policy_number(Check):
def execute(self) -> Check_Report:
findings = []
report = Check_Report(self.metadata)
report.region = iam_client.region
report.resource_id = "password_policy"
# Check if password policy exists
if iam_client.password_policy:
# Check if number flag is set
if iam_client.password_policy.numbers:
report.status = "PASS"
report.status_extended = (
"IAM password policy does not require at least one number"
)
else:
report.status = "FAIL"
report.status_extended = (
"IAM password policy require at least one number."
)
else:
report.status = "FAIL"
report.status_extended = "There is no password policy."
findings.append(report)
return findings

View File

@@ -0,0 +1,50 @@
from unittest import mock
from boto3 import client
from moto import mock_iam
class Test_iam_password_policy_number:
@mock_iam
def test_iam_password_policy_no_number_flag(self):
iam_client = client("iam")
# update password policy
iam_client.update_account_password_policy(RequireNumbers=False)
from providers.aws.lib.audit_info.audit_info import current_audit_info
from providers.aws.services.iam.iam_service import IAM
with mock.patch(
"providers.aws.services.iam.iam_password_policy_number.iam_password_policy_number.iam_client",
new=IAM(current_audit_info),
):
# Test Check
from providers.aws.services.iam.iam_password_policy_number.iam_password_policy_number import (
iam_password_policy_number,
)
check = iam_password_policy_number()
result = check.execute()
assert result[0].status == "FAIL"
@mock_iam
def test_iam_password_policy_number_flag(self):
iam_client = client("iam")
# update password policy
iam_client.update_account_password_policy(RequireNumbers=True)
from providers.aws.lib.audit_info.audit_info import current_audit_info
from providers.aws.services.iam.iam_service import IAM
with mock.patch(
"providers.aws.services.iam.iam_password_policy_number.iam_password_policy_number.iam_client",
new=IAM(current_audit_info),
):
# Test Check
from providers.aws.services.iam.iam_password_policy_number.iam_password_policy_number import (
iam_password_policy_number,
)
check = iam_password_policy_number()
result = check.execute()
assert result[0].status == "PASS"

View File

@@ -0,0 +1,46 @@
{
"Provider": "aws",
"CheckID": "iam_password_policy_reuse_24",
"CheckTitle": "Ensure IAM password policy prevents password reuse: 24 or greater",
"CheckType": ["Software and Configuration Checks", "Industry and Regulatory Standards" ,"CIS AWS Foundations Benchmark"],
"ServiceName": "iam",
"SubServiceName": "",
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
"Severity": "medium",
"ResourceType": "AwsIamPasswordPolicy",
"Description": "Ensure IAM password policy prevents password reuse: 24 or greater",
"Risk": "Password policies are used to enforce password complexity requirements. IAM password policies can be used to ensure password are comprised of different character sets. It is recommended that the password policy prevents at least password reuse of 24 or greater.",
"RelatedUrl": "",
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "",
"Terraform": ""
},
"Recommendation": {
"Text": "Ensure \"Number of passwords to remember\" is set to 24.",
"Url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html"
}
},
"Categories": [],
"Tags": {
"Tag1Key": "value",
"Tag2Key": "value"
},
"DependsOn": [],
"RelatedTo": [],
"Notes": "",
"Compliance": [
{
"Control": [
"1.10"
],
"Framework": "CIS-AWS",
"Group": [
"level1"
],
"Version": "1.4"
}
]
}

View File

@@ -0,0 +1,31 @@
from lib.check.models import Check, Check_Report
from providers.aws.services.iam.iam_client import iam_client
class iam_password_policy_reuse_24(Check):
def execute(self) -> Check_Report:
findings = []
report = Check_Report(self.metadata)
report.region = iam_client.region
report.resource_id = "password_policy"
# Check if password policy exists
if iam_client.password_policy:
# Check if reuse prevention flag is set
if (
iam_client.password_policy.reuse_prevention
and iam_client.password_policy.reuse_prevention == 24
):
report.status = "PASS"
report.status_extended = (
"IAM password policy reuse prevention is equal to 24."
)
else:
report.status = "FAIL"
report.status_extended = (
"IAM password policy reuse prevention is less than 24 or not set."
)
else:
report.status = "FAIL"
report.status_extended = "Password policy cannot be found"
findings.append(report)
return findings

View File

@@ -0,0 +1,50 @@
from unittest import mock
from boto3 import client
from moto import mock_iam
class Test_iam_password_policy_reuse_24:
@mock_iam
def test_iam_password_policy_reuse_prevention_equal_24(self):
iam_client = client("iam")
# update password policy
iam_client.update_account_password_policy(PasswordReusePrevention=24)
from providers.aws.lib.audit_info.audit_info import current_audit_info
from providers.aws.services.iam.iam_service import IAM
with mock.patch(
"providers.aws.services.iam.iam_password_policy_reuse_24.iam_password_policy_reuse_24.iam_client",
new=IAM(current_audit_info),
):
# Test Check
from providers.aws.services.iam.iam_password_policy_reuse_24.iam_password_policy_reuse_24 import (
iam_password_policy_reuse_24,
)
check = iam_password_policy_reuse_24()
result = check.execute()
assert result[0].status == "PASS"
@mock_iam
def test_iam_password_policy_reuse_prevention_less_24(self):
iam_client = client("iam")
# update password policy
iam_client.update_account_password_policy(PasswordReusePrevention=20)
from providers.aws.lib.audit_info.audit_info import current_audit_info
from providers.aws.services.iam.iam_service import IAM
with mock.patch(
"providers.aws.services.iam.iam_password_policy_reuse_24.iam_password_policy_reuse_24.iam_client",
new=IAM(current_audit_info),
):
# Test Check
from providers.aws.services.iam.iam_password_policy_reuse_24.iam_password_policy_reuse_24 import (
iam_password_policy_reuse_24,
)
check = iam_password_policy_reuse_24()
result = check.execute()
assert result[0].status == "FAIL"

View File

@@ -0,0 +1,46 @@
{
"Provider": "aws",
"CheckID": "iam_password_policy_symbol",
"CheckTitle": "Ensure IAM password policy require at least one symbol",
"CheckType": ["Software and Configuration Checks", "Industry and Regulatory Standards" ,"CIS AWS Foundations Benchmark"],
"ServiceName": "iam",
"SubServiceName": "",
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
"Severity": "medium",
"ResourceType": "AwsIamPasswordPolicy",
"Description": "Ensure IAM password policy require at least one symbol",
"Risk": "Password policies are used to enforce password complexity requirements. IAM password policies can be used to ensure password are comprised of different character sets. It is recommended that the password policy require at least one non-alphanumeric character.",
"RelatedUrl": "",
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "",
"Terraform": ""
},
"Recommendation": {
"Text": "Ensure \"Require at least one non-alphanumeric character\" is checked under \"Password Policy\".",
"Url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html"
}
},
"Categories": [],
"Tags": {
"Tag1Key": "value",
"Tag2Key": "value"
},
"DependsOn": [],
"RelatedTo": [],
"Notes": "",
"Compliance": [
{
"Control": [
"1.7"
],
"Framework": "CIS-AWS",
"Group": [
"level1"
],
"Version": "1.4"
}
]
}

View File

@@ -0,0 +1,28 @@
from lib.check.models import Check, Check_Report
from providers.aws.services.iam.iam_client import iam_client
class iam_password_policy_symbol(Check):
def execute(self) -> Check_Report:
findings = []
report = Check_Report(self.metadata)
report.region = iam_client.region
report.resource_id = "password_policy"
# Check if password policy exists
if iam_client.password_policy:
# Check if symbol flag is set
if iam_client.password_policy.symbols:
report.status = "PASS"
report.status_extended = (
"IAM password policy does not require at least one symbol."
)
else:
report.status = "FAIL"
report.status_extended = (
"IAM password policy requires at least one symbol."
)
else:
report.status = "FAIL"
report.status_extended = "There is no password policy."
findings.append(report)
return findings

View File

@@ -0,0 +1,50 @@
from unittest import mock
from boto3 import client
from moto import mock_iam
class Test_iam_password_policy_symbol:
@mock_iam
def test_iam_password_policy_no_symbol_flag(self):
iam_client = client("iam")
# update password policy
iam_client.update_account_password_policy(RequireSymbols=False)
from providers.aws.lib.audit_info.audit_info import current_audit_info
from providers.aws.services.iam.iam_service import IAM
with mock.patch(
"providers.aws.services.iam.iam_password_policy_symbol.iam_password_policy_symbol.iam_client",
new=IAM(current_audit_info),
):
# Test Check
from providers.aws.services.iam.iam_password_policy_symbol.iam_password_policy_symbol import (
iam_password_policy_symbol,
)
check = iam_password_policy_symbol()
result = check.execute()
assert result[0].status == "FAIL"
@mock_iam
def test_iam_password_policy_symbol_flag(self):
iam_client = client("iam")
# update password policy
iam_client.update_account_password_policy(RequireSymbols=True)
from providers.aws.lib.audit_info.audit_info import current_audit_info
from providers.aws.services.iam.iam_service import IAM
with mock.patch(
"providers.aws.services.iam.iam_password_policy_symbol.iam_password_policy_symbol.iam_client",
new=IAM(current_audit_info),
):
# Test Check
from providers.aws.services.iam.iam_password_policy_symbol.iam_password_policy_symbol import (
iam_password_policy_symbol,
)
check = iam_password_policy_symbol()
result = check.execute()
assert result[0].status == "PASS"

View File

@@ -0,0 +1,46 @@
{
"Provider": "aws",
"CheckID": "iam_password_policy_uppercase",
"CheckTitle": "Ensure IAM password policy requires at least one uppercase letter",
"CheckType": ["Software and Configuration Checks", "Industry and Regulatory Standards" ,"CIS AWS Foundations Benchmark"],
"ServiceName": "iam",
"SubServiceName": "",
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
"Severity": "medium",
"ResourceType": "AwsIamPasswordPolicy",
"Description": "Ensure IAM password policy requires at least one uppercase letter",
"Risk": "Password policies are used to enforce password complexity requirements. IAM password policies can be used to ensure password are comprised of different character sets. It is recommended that the password policy require at least one uppercase letter.",
"RelatedUrl": "",
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "",
"Terraform": ""
},
"Recommendation": {
"Text": "Ensure \"Requires at least one uppercase letter\" is checked under \"Password Policy\".",
"Url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html"
}
},
"Categories": [],
"Tags": {
"Tag1Key": "value",
"Tag2Key": "value"
},
"DependsOn": [],
"RelatedTo": [],
"Notes": "",
"Compliance": [
{
"Control": [
"1.5"
],
"Framework": "CIS-AWS",
"Group": [
"level1"
],
"Version": "1.4"
}
]
}

View File

@@ -0,0 +1,26 @@
from lib.check.models import Check, Check_Report
from providers.aws.services.iam.iam_client import iam_client
class iam_password_policy_uppercase(Check):
def execute(self) -> Check_Report:
findings = []
report = Check_Report(self.metadata)
report.region = iam_client.region
report.resource_id = "password_policy"
# Check if password policy exists
if iam_client.password_policy:
# Check if uppercase flag is set
if iam_client.password_policy.uppercase:
report.status = "PASS"
report.status_extended = (
"IAM password policy requires at least one uppercase letter."
)
else:
report.status = "FAIL"
report.status_extended = "IAM password policy does not require at least one uppercase letter."
else:
report.status = "FAIL"
report.status_extended = "There is no password policy."
findings.append(report)
return findings

View File

@@ -0,0 +1,50 @@
from unittest import mock
from boto3 import client
from moto import mock_iam
class Test_iam_password_policy_uppercase:
@mock_iam
def test_iam_password_policy_no_uppercase_flag(self):
iam_client = client("iam")
# update password policy
iam_client.update_account_password_policy(RequireUppercaseCharacters=False)
from providers.aws.lib.audit_info.audit_info import current_audit_info
from providers.aws.services.iam.iam_service import IAM
with mock.patch(
"providers.aws.services.iam.iam_password_policy_uppercase.iam_password_policy_uppercase.iam_client",
new=IAM(current_audit_info),
):
# Test Check
from providers.aws.services.iam.iam_password_policy_uppercase.iam_password_policy_uppercase import (
iam_password_policy_uppercase,
)
check = iam_password_policy_uppercase()
result = check.execute()
assert result[0].status == "FAIL"
@mock_iam
def test_iam_password_policy_uppercase_flag(self):
iam_client = client("iam")
# update password policy
iam_client.update_account_password_policy(RequireUppercaseCharacters=True)
from providers.aws.lib.audit_info.audit_info import current_audit_info
from providers.aws.services.iam.iam_service import IAM
with mock.patch(
"providers.aws.services.iam.iam_password_policy_uppercase.iam_password_policy_uppercase.iam_client",
new=IAM(current_audit_info),
):
# Test Check
from providers.aws.services.iam.iam_password_policy_uppercase.iam_password_policy_uppercase import (
iam_password_policy_uppercase,
)
check = iam_password_policy_uppercase()
result = check.execute()
assert result[0].status == "PASS"