diff --git a/scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols16_test.rego b/scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols16_test.rego
index f251cf5c..9279c075 100644
--- a/scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols16_test.rego
+++ b/scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols16_test.rego
@@ -1,5 +1,11 @@
package commoncontrols
+
import future.keywords
+import data.utils.FailTestBothNonCompliant
+import data.utils.FailTestGroupNonCompliant
+import data.utils.FailTestNoEvent
+import data.utils.FailTestOUNonCompliant
+import data.utils.PassTestResult
#
# GWS.COMMONCONTROLS.16.1
@@ -27,11 +33,7 @@ test_Unlisted_Correct_V1 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
+ PassTestResult(PolicyId, Output)
}
test_Unlisted_Correct_V2 if {
@@ -67,11 +69,7 @@ test_Unlisted_Correct_V2 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
+ PassTestResult(PolicyId, Output)
}
test_Unlisted_Incorrect_V1 if {
@@ -95,15 +93,9 @@ test_Unlisted_Incorrect_V1 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", [
- "The following OUs are non-compliant:
",
- "- Test Top-Level OU: Access to additional services without individual control is turned on
",
- "
"
- ])
+ failedOU := [{"Name": "Test Top-Level OU",
+ "Value": NonComplianceMessage16_1}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Unlisted_Incorrect_V2 if {
@@ -118,15 +110,7 @@ test_Unlisted_Incorrect_V2 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", [
- "No relevant event in the current logs for the top-level OU, Test Top-Level OU. While we are unable ",
- "to determine the state from the logs, the default setting ",
- "is non-compliant; manual check recommended."
- ])
+ FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
#--
@@ -156,11 +140,7 @@ test_EarlyAccessApps_OUs_Correct_V1 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
+ PassTestResult(PolicyId, Output)
}
test_EarlyAccessApps_OUs_Correct_V2 if {
@@ -196,11 +176,7 @@ test_EarlyAccessApps_OUs_Correct_V2 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
+ PassTestResult(PolicyId, Output)
}
test_EarlyAccessApps_OUs_Incorrect_V1 if {
@@ -225,15 +201,9 @@ test_EarlyAccessApps_OUs_Incorrect_V1 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", [
- "The following OUs are non-compliant:",
- "- Test Top-Level OU: Service status is ON
",
- "
"
- ])
+ failedOU := [{"Name": "Test Top-Level OU",
+ "Value": NonComplianceMessage16_2}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_EarlyAccessApps_OUs_Incorrect_V2 if {
@@ -269,15 +239,9 @@ test_EarlyAccessApps_OUs_Incorrect_V2 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", [
- "The following OUs are non-compliant:",
- "- Test Second-Level OU: Service status is ON
",
- "
"
- ])
+ failedOU := [{"Name": "Test Second-Level OU",
+ "Value": NonComplianceMessage16_2}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_EarlyAccessApps_OUs_Correct_Groups_Incorrect_V1 if {
@@ -313,15 +277,9 @@ test_EarlyAccessApps_OUs_Correct_Groups_Incorrect_V1 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", [
- "The following groups are non-compliant:",
- "- Test Group 1: Service status is ON
",
- "
"
- ])
+ failedGroup := [{"Name": "Test Group 1",
+ "Value": NonComplianceMessage16_2}]
+ FailTestGroupNonCompliant(PolicyId, Output, failedGroup)
}
test_EarlyAccessApps_OUs_Correct_Groups_Incorrect_V2 if {
@@ -368,16 +326,11 @@ test_EarlyAccessApps_OUs_Correct_Groups_Incorrect_V2 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", [
- "The following groups are non-compliant:",
- "- Test Group 1: Service status is ON
",
- "- Test Group 2: Service status is ON
",
- "
"
- ])
+ failedGroup := [{"Name": "Test Group 1",
+ "Value": NonComplianceMessage16_2},
+ {"Name": "Test Group 2",
+ "Value": NonComplianceMessage16_2}]
+ FailTestGroupNonCompliant(PolicyId, Output, failedGroup)
}
test_EarlyAccessApps_OUs_Groups_Incorrect_V1 if {
@@ -424,18 +377,13 @@ test_EarlyAccessApps_OUs_Groups_Incorrect_V1 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", [
- "The following OUs are non-compliant:",
- "- Test Top-Level OU: Service status is ON
",
- "
",
- "The following groups are non-compliant:",
- "- Test Group 1: Service status is ON
",
- "- Test Group 2: Service status is ON
",
- "
"
- ])
+
+ failedGroup := [{"Name": "Test Group 1",
+ "Value": NonComplianceMessage16_2},
+ {"Name": "Test Group 2",
+ "Value": NonComplianceMessage16_2}]
+ failedOU := [{"Name": "Test Top-Level OU",
+ "Value": NonComplianceMessage16_2}]
+ FailTestBothNonCompliant(PolicyId, Output, failedOU, failedGroup)
}
#--
diff --git a/scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols_api01_test.rego b/scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols_api01_test.rego
new file mode 100644
index 00000000..245c0be5
--- /dev/null
+++ b/scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols_api01_test.rego
@@ -0,0 +1,151 @@
+package commoncontrols
+
+import future.keywords
+import data.utils
+import data.utils.FailTestOUNonCompliant
+import data.utils.PassTestResult
+
+GoodCaseInputApi01 := {
+ "policies": {
+ "topOU": {
+ "security_two_step_verification_device_trust": {
+ "allowTrustingDevice": false
+ },
+ "security_two_step_verification_enforcement": {
+ "enforcedFrom": "2024-02-16T23:22:21.732Z"
+ },
+ "security_two_step_verification_enforcement_factor": {
+ "allowedSignInFactorSet": "PASSKEY_ONLY"
+ },
+ "security_two_step_verification_enrollment": {
+ "allowEnrollment": true
+ },
+ "security_two_step_verification_grace_period": {
+ "enrollmentGracePeriod": "168h"}
+ },
+ "nextOU": {
+ "security_two_step_verification_grace_period": {
+ "enrollmentGracePeriod": "604800s"}
+ }
+ },
+ "tenant_info": {
+ "topLevelOU": "topOU"
+ }
+}
+
+BadCaseInputApi01 := {
+ "policies": {
+ "topOU": {
+ "security_two_step_verification_device_trust": {
+ "allowTrustingDevice": true
+ },
+ "security_two_step_verification_enforcement": {
+ "enforcedFrom": "2025-02-16T23:22:21.732Z"
+ },
+ "security_two_step_verification_enforcement_factor": {
+ "allowedSignInFactorSet": "ALL"
+ },
+ "security_two_step_verification_enrollment": {
+ "allowEnrollment": false
+ },
+ "security_two_step_verification_grace_period": {
+ "enrollmentGracePeriod": "0s"}
+ },
+ "nextOU": {
+ "security_two_step_verification_enforcement": {
+ "enforcedFrom": "2028-02-16T23:22:21.732Z"
+ },
+ "security_two_step_verification_enforcement_factor": {
+ "allowedSignInFactorSet": "ALL"
+ },
+ "security_two_step_verification_enrollment": {
+ "allowEnrollment": true
+ }
+ },
+ "thirdOU": {
+ "security_two_step_verification_enforcement": {
+ "enforcedFrom": "2035-02-16T23:22:21.732Z"
+ },
+ "security_two_step_verification_enforcement_factor": {
+ "allowedSignInFactorSet": "PASSKEY_ONLY"
+ },
+ "security_two_step_verification_enrollment": {
+ "allowEnrollment": true
+ }
+ }
+ },
+ "tenant_info": {
+ "topLevelOU": "topOU"
+ }
+}
+
+BadCaseInputApi01a := {
+ "policies": {
+ "topOU": {
+ "security_login_challenges": {
+ "enableEmployeeIdChallenge": true
+ }
+ },
+ "nextOU": {
+ "security_login_challenges": {
+ "enableEmployeeIdChallenge": false
+ }
+ }
+ },
+ "tenant_info": {
+ "topLevelOU": "topOU"
+ }
+}
+
+test_2SV_Correct_1 if {
+ PolicyId := CommonControlsId1_1
+ Output := tests with input as GoodCaseInputApi01
+
+ PassTestResult(PolicyId, Output)
+}
+
+test_2SV_Incorrect_1 if {
+ PolicyId := CommonControlsId1_1
+ Output := tests with input as BadCaseInputApi01
+
+ failedOU := [{"Name": "nextOU",
+ "Value": NonComplianceMessage1_1b(GetFriendlyMethods("ALL"))},
+ {"Name": "thirdOU",
+ "Value": NonComplianceMessage1_1c},
+ {"Name": "topOU",
+ "Value": NonComplianceMessage1_1a}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
+}
+
+test_EnrollPeriod_Correct_1 if {
+ PolicyId := CommonControlsId1_2
+ Output := tests with input as GoodCaseInputApi01
+
+ PassTestResult(PolicyId, Output)
+}
+
+test_EnrollPeriod_Incorrect_1 if {
+ PolicyId := CommonControlsId1_2
+ Output := tests with input as BadCaseInputApi01
+
+ failedOU := [{"Name": "topOU",
+ "Value": NonComplianceMessage1_2(0,
+ utils.DurationToSeconds("7d"))}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
+}
+
+test_DeviceTrust_Correct_1 if {
+ PolicyId := CommonControlsId1_3
+ Output := tests with input as GoodCaseInputApi01
+
+ PassTestResult(PolicyId, Output)
+}
+
+test_DeviceTrust_Incorrect_1 if {
+ PolicyId := CommonControlsId1_3
+ Output := tests with input as BadCaseInputApi01
+
+ failedOU := [{"Name": "topOU",
+ "Value": NonComplianceMessage1_3}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
+}
diff --git a/scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols_api04_test.rego b/scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols_api04_test.rego
index 39c7d038..6aa43b55 100644
--- a/scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols_api04_test.rego
+++ b/scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols_api04_test.rego
@@ -29,7 +29,7 @@ GoodCaseInputApi04 := {
}
}
-BaseCaseInputApi04 := {
+BadCaseInputApi04 := {
"policies": {
"topOU": {
"security_session_controls": {
@@ -56,7 +56,7 @@ test_CCAPI_ReAuth_Comply_1 if {
test_CCAPI_ReAuth_NonComply_1 if {
PolicyId := CommonControlsId4_1
- Output := tests with input as BaseCaseInputApi04
+ Output := tests with input as BadCaseInputApi04
failedOU := [{"Name": "nextOU",
"Value": NonComplianceMessage4_1(GetFriendlyValue4_1(800 * 60))}]
diff --git a/scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols_api16_test.rego b/scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols_api16_test.rego
new file mode 100644
index 00000000..c81248a7
--- /dev/null
+++ b/scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols_api16_test.rego
@@ -0,0 +1,66 @@
+package commoncontrols
+
+import future.keywords
+import data.utils.FailTestOUNonCompliant
+import data.utils.PassTestResult
+
+GoodCaseInputApi16 := {
+ "policies": {
+ "topOU": {
+ "early_access_apps_service_status": {"serviceState": "DISABLED"}
+ }
+ },
+ "tenant_info": {
+ "topLevelOU": "topOU"
+ }
+}
+
+BadCaseInputApi16 := {
+ "policies": {
+ "topOU": {
+ "early_access_apps_service_status": {"serviceState": "ENABLED"}
+ }
+ },
+ "tenant_info": {
+ "topLevelOU": "topOU"
+ }
+}
+
+BadCaseInputApi16a := {
+ "policies": {
+ "topOU": {
+ "early_access_apps_service_status": {"serviceState": "DISABLED"}
+ },
+ "nextOU": {
+ "early_access_apps_service_status": {"serviceState": "ENABLED"}
+ },
+ },
+ "tenant_info": {
+ "topLevelOU": "topOU"
+ }
+}
+
+test_EarlyAccess_Correct_1 if {
+ PolicyId := CommonControlsId16_2
+ Output := tests with input as GoodCaseInputApi16
+
+ PassTestResult(PolicyId, Output)
+}
+
+test_EarlyAccess_Incorrect_1 if {
+ PolicyId := CommonControlsId16_2
+ Output := tests with input as BadCaseInputApi16
+
+ failedOU := [{"Name": "topOU",
+ "Value": NonComplianceMessage16_2}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
+}
+
+test_EarlyAccess_Incorrect_2 if {
+ PolicyId := CommonControlsId16_2
+ Output := tests with input as BadCaseInputApi16a
+
+ failedOU := [{"Name": "nextOU",
+ "Value": NonComplianceMessage16_2}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
+}
diff --git a/scubagoggles/Testing/RegoTests/gmail/gmail01_test.rego b/scubagoggles/Testing/RegoTests/gmail/gmail01_test.rego
index cfb15db5..5821a148 100644
--- a/scubagoggles/Testing/RegoTests/gmail/gmail01_test.rego
+++ b/scubagoggles/Testing/RegoTests/gmail/gmail01_test.rego
@@ -1,5 +1,9 @@
package gmail
+
import future.keywords
+import data.utils.FailTestNoEvent
+import data.utils.FailTestOUNonCompliant
+import data.utils.PassTestResult
#
# GWS.GMAIL.1.1
@@ -25,11 +29,7 @@ test_MailDelegation_Correct_V1 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
+ PassTestResult(PolicyId, Output)
}
test_MailDelegation_Correct_V2 if {
@@ -63,11 +63,7 @@ test_MailDelegation_Correct_V2 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
+ PassTestResult(PolicyId, Output)
}
test_MailDelegation_Correct_V3 if {
@@ -101,11 +97,7 @@ test_MailDelegation_Correct_V3 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
+ PassTestResult(PolicyId, Output)
}
test_MailDelegation_Incorrect_V1 if {
@@ -129,15 +121,7 @@ test_MailDelegation_Incorrect_V1 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", [
- "No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
- "While we are unable to determine the state from the logs, the default setting ",
- "is compliant; manual check recommended."
- ])
+ FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
test_MailDelegation_Incorrect_V2 if {
@@ -161,12 +145,9 @@ test_MailDelegation_Incorrect_V2 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Test Top-Level OU: ",
- "Mail delegation is set to enabled
"])
+ failedOU := [{"Name": "Test Top-Level OU",
+ "Value": NonComplianceMessage1_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_MailDelegation_Incorrect_V3 if {
@@ -200,12 +181,9 @@ test_MailDelegation_Incorrect_V3 if {
},
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Test Top-Level OU: ",
- "Mail delegation is set to enabled
"])
+ failedOU := [{"Name": "Test Top-Level OU",
+ "Value": NonComplianceMessage1_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_MailDelegation_Incorrect_V4 if {
@@ -229,12 +207,9 @@ test_MailDelegation_Incorrect_V4 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Secondary OU: ",
- "Mail delegation is set to enabled
"])
+ failedOU := [{"Name": "Secondary OU",
+ "Value": NonComplianceMessage1_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_MailDelegation_Incorrect_V5 if {
@@ -268,11 +243,8 @@ test_MailDelegation_Incorrect_V5 if {
},
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Secondary OU: ",
- "Mail delegation is set to enabled
"])
+ failedOU := [{"Name": "Secondary OU",
+ "Value": NonComplianceMessage1_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
diff --git a/scubagoggles/Testing/RegoTests/gmail/gmail08_test.rego b/scubagoggles/Testing/RegoTests/gmail/gmail08_test.rego
index 52bab032..dc5059a2 100644
--- a/scubagoggles/Testing/RegoTests/gmail/gmail08_test.rego
+++ b/scubagoggles/Testing/RegoTests/gmail/gmail08_test.rego
@@ -1,5 +1,9 @@
package gmail
+
import future.keywords
+import data.utils.FailTestNoEvent
+import data.utils.FailTestOUNonCompliant
+import data.utils.PassTestResult
#
# GWS.GMAIL.8.1
@@ -25,11 +29,7 @@ test_UserEmailUploads_Correct_V1 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
+ PassTestResult(PolicyId, Output)
}
test_UserEmailUploads_Correct_V2 if {
@@ -63,11 +63,7 @@ test_UserEmailUploads_Correct_V2 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
+ PassTestResult(PolicyId, Output)
}
test_UserEmailUploads_Correct_V3 if {
@@ -101,11 +97,7 @@ test_UserEmailUploads_Correct_V3 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
+ PassTestResult(PolicyId, Output)
}
test_UserEmailUploads_Incorrect_V1 if {
@@ -129,15 +121,7 @@ test_UserEmailUploads_Incorrect_V1 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", [
- "No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
- "While we are unable to determine the state from the logs, the default setting ",
- "is compliant; manual check recommended."
- ])
+ FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
test_UserEmailUploads_Incorrect_V2 if {
@@ -161,12 +145,9 @@ test_UserEmailUploads_Incorrect_V2 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Test Top-Level OU: ",
- "User email uploads is set to enabled
"])
+ failedOU := [{"Name": "Test Top-Level OU",
+ "Value": NonComplianceMessage8_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_UserEmailUploads_Incorrect_V3 if {
@@ -200,12 +181,9 @@ test_UserEmailUploads_Incorrect_V3 if {
},
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Test Top-Level OU: ",
- "User email uploads is set to enabled
"])
+ failedOU := [{"Name": "Test Top-Level OU",
+ "Value": NonComplianceMessage8_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_UserEmailUploads_Incorrect_V4 if {
@@ -229,12 +207,9 @@ test_UserEmailUploads_Incorrect_V4 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Secondary OU: ",
- "User email uploads is set to enabled
"])
+ failedOU := [{"Name": "Secondary OU",
+ "Value": NonComplianceMessage8_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_UserEmailUploads_Incorrect_V5 if {
@@ -268,11 +243,8 @@ test_UserEmailUploads_Incorrect_V5 if {
},
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Secondary OU: ",
- "User email uploads is set to enabled
"])
+ failedOU := [{"Name": "Secondary OU",
+ "Value": NonComplianceMessage8_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
diff --git a/scubagoggles/Testing/RegoTests/gmail/gmail09_test.rego b/scubagoggles/Testing/RegoTests/gmail/gmail09_test.rego
index 50a6638b..199b8621 100644
--- a/scubagoggles/Testing/RegoTests/gmail/gmail09_test.rego
+++ b/scubagoggles/Testing/RegoTests/gmail/gmail09_test.rego
@@ -1,5 +1,8 @@
package gmail
+
import future.keywords
+import data.utils.FailTestOUNonCompliant
+import data.utils.PassTestResult
#
# GWS.GMAIL.9.1
@@ -36,11 +39,7 @@ test_ImapAccess_Correct_V1 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
+ PassTestResult(PolicyId, Output)
}
test_ImapAccess_Incorrect_V1 if {
@@ -74,12 +73,9 @@ test_ImapAccess_Incorrect_V1 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Test Top-Level OU: ",
- "POP and IMAP access are enabled
"])
+ failedOU := [{"Name": "Test Top-Level OU",
+ "Value": GetFriendlyValue9_1(true, true)}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_ImapAccess_Incorrect_V2 if {
@@ -113,12 +109,9 @@ test_ImapAccess_Incorrect_V2 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Secondary OU: ",
- "POP and IMAP access are enabled
"])
+ failedOU := [{"Name": "Secondary OU",
+ "Value": GetFriendlyValue9_1(true, true)}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_ImapAccess_Incorrect_V3 if {
@@ -172,11 +165,8 @@ test_ImapAccess_Incorrect_V3 if {
},
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Secondary OU: ",
- "IMAP access is enabled
"])
+ failedOU := [{"Name": "Secondary OU",
+ "Value": GetFriendlyValue9_1(true, false)}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
diff --git a/scubagoggles/Testing/RegoTests/gmail/gmail10_test.rego b/scubagoggles/Testing/RegoTests/gmail/gmail10_test.rego
index 6c5f3e76..f0d41cb9 100644
--- a/scubagoggles/Testing/RegoTests/gmail/gmail10_test.rego
+++ b/scubagoggles/Testing/RegoTests/gmail/gmail10_test.rego
@@ -1,5 +1,9 @@
package gmail
+
import future.keywords
+import data.utils.FailTestNoEvent
+import data.utils.FailTestOUNonCompliant
+import data.utils.PassTestResult
#
# GWS.GMAIL.10.1
@@ -25,11 +29,7 @@ test_GoogleWorkspaceSync_Correct_V1 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
+ PassTestResult(PolicyId, Output)
}
test_GoogleWorkspaceSync_Correct_V2 if {
@@ -63,11 +63,7 @@ test_GoogleWorkspaceSync_Correct_V2 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
+ PassTestResult(PolicyId, Output)
}
test_GoogleWorkspaceSync_Correct_V3 if {
@@ -101,11 +97,7 @@ test_GoogleWorkspaceSync_Correct_V3 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
+ PassTestResult(PolicyId, Output)
}
test_GoogleWorkspaceSync_Correct_V4 if {
@@ -139,11 +131,7 @@ test_GoogleWorkspaceSync_Correct_V4 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
+ PassTestResult(PolicyId, Output)
}
test_GoogleWorkspaceSync_Incorrect_V1 if {
@@ -167,15 +155,7 @@ test_GoogleWorkspaceSync_Incorrect_V1 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", [
- "No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
- "While we are unable to determine the state from the logs, the default setting ",
- "is non-compliant; manual check recommended."
- ])
+ FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
test_GoogleWorkspaceSync_Incorrect_V2 if {
@@ -199,12 +179,9 @@ test_GoogleWorkspaceSync_Incorrect_V2 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Test Top-Level OU: ",
- "Automatically enable outlook sync is set to enabled
"])
+ failedOU := [{"Name": "Test Top-Level OU",
+ "Value": NonComplianceMessage10_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_GoogleWorkspaceSync_Incorrect_V3 if {
@@ -238,12 +215,9 @@ test_GoogleWorkspaceSync_Incorrect_V3 if {
},
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Test Top-Level OU: ",
- "Automatically enable outlook sync is set to enabled
"])
+ failedOU := [{"Name": "Test Top-Level OU",
+ "Value": NonComplianceMessage10_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_GoogleWorkspaceSync_Incorrect_V4 if {
@@ -267,12 +241,9 @@ test_GoogleWorkspaceSync_Incorrect_V4 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Secondary OU: ",
- "Automatically enable outlook sync is set to enabled
"])
+ failedOU := [{"Name": "Secondary OU",
+ "Value": NonComplianceMessage10_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_GoogleWorkspaceSync_Incorrect_V5 if {
@@ -306,12 +277,9 @@ test_GoogleWorkspaceSync_Incorrect_V5 if {
},
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Secondary OU: ",
- "Automatically enable outlook sync is set to enabled
"])
+ failedOU := [{"Name": "Secondary OU",
+ "Value": NonComplianceMessage10_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
diff --git a/scubagoggles/Testing/RegoTests/gmail/gmail12_test.rego b/scubagoggles/Testing/RegoTests/gmail/gmail12_test.rego
index ffdf175c..d277566c 100644
--- a/scubagoggles/Testing/RegoTests/gmail/gmail12_test.rego
+++ b/scubagoggles/Testing/RegoTests/gmail/gmail12_test.rego
@@ -1,5 +1,9 @@
package gmail
+
import future.keywords
+import data.utils.FailTestNoEvent
+import data.utils.FailTestOUNonCompliant
+import data.utils.PassTestResult
#
# GWS.GMAIL.12.1
@@ -25,11 +29,7 @@ test_PerUserOutboundGateway_Correct_V1 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
+ PassTestResult(PolicyId, Output)
}
test_PerUserOutboundGateway_Correct_V2 if {
@@ -63,11 +63,7 @@ test_PerUserOutboundGateway_Correct_V2 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
+ PassTestResult(PolicyId, Output)
}
test_PerUserOutboundGateway_Correct_V3 if {
@@ -101,11 +97,7 @@ test_PerUserOutboundGateway_Correct_V3 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
+ PassTestResult(PolicyId, Output)
}
test_PerUserOutboundGateway_Incorrect_V1 if {
@@ -129,15 +121,7 @@ test_PerUserOutboundGateway_Incorrect_V1 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- RuleOutput[0].RequirementMet
- RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", [
- "No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
- "While we are unable to determine the state from the logs, the default setting ",
- "is compliant; manual check recommended."
- ])
+ FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
test_PerUserOutboundGateway_Incorrect_V2 if {
@@ -161,12 +145,9 @@ test_PerUserOutboundGateway_Incorrect_V2 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Test Top-Level OU: ",
- "Allow per-user outbound gateways is set to enabled
"])
+ failedOU := [{"Name": "Test Top-Level OU",
+ "Value": NonComplianceMessage12_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_PerUserOutboundGateway_Incorrect_V3 if {
@@ -200,12 +181,9 @@ test_PerUserOutboundGateway_Incorrect_V3 if {
},
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Test Top-Level OU: ",
- "Allow per-user outbound gateways is set to enabled
"])
+ failedOU := [{"Name": "Test Top-Level OU",
+ "Value": NonComplianceMessage12_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_PerUserOutboundGateway_Incorrect_V4 if {
@@ -229,12 +207,9 @@ test_PerUserOutboundGateway_Incorrect_V4 if {
}
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Secondary OU: ",
- "Allow per-user outbound gateways is set to enabled
"])
+ failedOU := [{"Name": "Secondary OU",
+ "Value": NonComplianceMessage12_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_PerUserOutboundGateway_Incorrect_V5 if {
@@ -268,11 +243,8 @@ test_PerUserOutboundGateway_Incorrect_V5 if {
},
}
- RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
- count(RuleOutput) == 1
- not RuleOutput[0].RequirementMet
- not RuleOutput[0].NoSuchEvent
- RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:- Secondary OU: ",
- "Allow per-user outbound gateways is set to enabled
"])
+ failedOU := [{"Name": "Secondary OU",
+ "Value": NonComplianceMessage12_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
diff --git a/scubagoggles/Testing/RegoTests/gmail/gmail_api01_test.rego b/scubagoggles/Testing/RegoTests/gmail/gmail_api01_test.rego
new file mode 100644
index 00000000..42b0c82a
--- /dev/null
+++ b/scubagoggles/Testing/RegoTests/gmail/gmail_api01_test.rego
@@ -0,0 +1,73 @@
+package gmail
+
+import future.keywords
+import data.utils.FailTestOUNonCompliant
+import data.utils.PassTestResult
+
+GoodGmailApi01 := {
+ "policies": {
+ "topOU": {
+ "gmail_mail_delegation": {"enableMailDelegation": false},
+ "gmail_service_status": {"serviceState": "ENABLED"}
+ },
+ "nextOU": {
+ "gmail_mail_delegation": {"enableMailDelegation": true},
+ "gmail_service_status": {"serviceState": "DISABLED"}
+ }
+ },
+ "tenant_info": {
+ "topLevelOU": "topOU"
+ }
+}
+
+BadGmailApi01 := {
+ "policies": {
+ "topOU": {
+ "gmail_mail_delegation": {"enableMailDelegation": true},
+ "gmail_service_status": {"serviceState": "ENABLED"}
+ }
+ },
+ "tenant_info": {
+ "topLevelOU": "topOU"
+ }
+}
+
+BadGmailApi01a := {
+ "policies": {
+ "topOU": {
+ "gmail_mail_delegation": {"enableMailDelegation": false},
+ "gmail_service_status": {"serviceState": "ENABLED"}
+ },
+ "nextOU": {
+ "gmail_mail_delegation": {"enableMailDelegation": true}
+ }
+ },
+ "tenant_info": {
+ "topLevelOU": "topOU"
+ }
+}
+
+test_MailDelegation_Correct_1 if {
+ PolicyId := GmailId1_1
+ Output := tests with input as GoodGmailApi01
+
+ PassTestResult(PolicyId, Output)
+}
+
+test_MailDelegation_Incorrect_1 if {
+ PolicyId := GmailId1_1
+ Output := tests with input as BadGmailApi01
+
+ failedOU := [{"Name": "topOU",
+ "Value": NonComplianceMessage1_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
+}
+
+test_MailDelegation_Incorrect_2 if {
+ PolicyId := GmailId1_1
+ Output := tests with input as BadGmailApi01a
+
+ failedOU := [{"Name": "nextOU",
+ "Value": NonComplianceMessage1_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
+}
diff --git a/scubagoggles/Testing/RegoTests/gmail/gmail_api08_test.rego b/scubagoggles/Testing/RegoTests/gmail/gmail_api08_test.rego
new file mode 100644
index 00000000..cd69deba
--- /dev/null
+++ b/scubagoggles/Testing/RegoTests/gmail/gmail_api08_test.rego
@@ -0,0 +1,46 @@
+package gmail
+
+import future.keywords
+import data.utils.FailTestOUNonCompliant
+import data.utils.PassTestResult
+
+GoodGmailApi08 := {
+ "policies": {
+ "topOU": {
+ "gmail_user_email_uploads": {"enableMailAndContactsImport": false},
+ "gmail_service_status": {"serviceState": "ENABLED"},
+ }
+ },
+ "tenant_info": {
+ "topLevelOU": "topOU"
+ }
+}
+
+BadGmailApi08 := {
+ "policies": {
+ "topOU": {
+ "gmail_user_email_uploads": {"enableMailAndContactsImport": true},
+ "gmail_service_status": {"serviceState": "ENABLED"
+ }
+ }
+ },
+ "tenant_info": {
+ "topLevelOU": "topOU"
+ }
+}
+
+test_EmailUploads_Correct_1 if {
+ PolicyId := GmailId8_1
+ Output := tests with input as GoodGmailApi08
+
+ PassTestResult(PolicyId, Output)
+}
+
+test_EmailUploads_Incorrect_1 if {
+ PolicyId := GmailId8_1
+ Output := tests with input as BadGmailApi08
+
+ failedOU := [{"Name": "topOU",
+ "Value": NonComplianceMessage8_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
+}
diff --git a/scubagoggles/Testing/RegoTests/gmail/gmail_api09_test.rego b/scubagoggles/Testing/RegoTests/gmail/gmail_api09_test.rego
new file mode 100644
index 00000000..97c996d4
--- /dev/null
+++ b/scubagoggles/Testing/RegoTests/gmail/gmail_api09_test.rego
@@ -0,0 +1,61 @@
+package gmail
+
+import future.keywords
+import data.utils.FailTestOUNonCompliant
+import data.utils.PassTestResult
+
+GoodGmailApi09 := {
+ "policies": {
+ "topOU": {
+ "gmail_pop_access": {"enablePopAccess": false},
+ "gmail_imap_access": {"enableImapAccess": false},
+ "gmail_service_status": {"serviceState": "ENABLED"},
+ }
+ },
+ "tenant_info": {
+ "topLevelOU": "topOU"
+ }
+}
+
+BadGmailApi09 := {
+ "policies": {
+ "topOU": {
+ "gmail_pop_access": {"enablePopAccess": true},
+ "gmail_imap_access": {"enableImapAccess": true},
+ "gmail_service_status": {"serviceState": "ENABLED"}
+ },
+ "nextOU": {
+ "gmail_imap_access": {"enableImapAccess": false}
+ },
+ "thirdOU": {
+ "gmail_pop_access": {"enablePopAccess": false}
+ },
+ "fourthOU": {
+ "gmail_imap_access": {"enableImapAccess": false},
+ "gmail_pop_access": {"enablePopAccess": false}
+ }
+ },
+ "tenant_info": {
+ "topLevelOU": "topOU"
+ }
+}
+
+test_ImapPopEnable_Correct_1 if {
+ PolicyId := GmailId9_1
+ Output := tests with input as GoodGmailApi09
+
+ PassTestResult(PolicyId, Output)
+}
+
+test_ImapPopEnable_Incorrect_1 if {
+ PolicyId := GmailId9_1
+ Output := tests with input as BadGmailApi09
+
+ failedOU := [{"Name": "nextOU",
+ "Value": GetFriendlyValue9_1(false, true)},
+ {"Name": "thirdOU",
+ "Value": GetFriendlyValue9_1(true, false)},
+ {"Name": "topOU",
+ "Value": GetFriendlyValue9_1(true, true)}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
+}
diff --git a/scubagoggles/Testing/RegoTests/gmail/gmail_api10_test.rego b/scubagoggles/Testing/RegoTests/gmail/gmail_api10_test.rego
new file mode 100644
index 00000000..77049d03
--- /dev/null
+++ b/scubagoggles/Testing/RegoTests/gmail/gmail_api10_test.rego
@@ -0,0 +1,48 @@
+package gmail
+
+import future.keywords
+import data.utils.FailTestOUNonCompliant
+import data.utils.PassTestResult
+
+GoodGmailApi10 := {
+ "policies": {
+ "topOU": {
+ "gmail_workspace_sync_for_outlook": {
+ "enableGoogleWorkspaceSyncForMicrosoftOutlook": false},
+ "gmail_service_status": {"serviceState": "ENABLED"},
+ }
+ },
+ "tenant_info": {
+ "topLevelOU": "topOU"
+ }
+}
+
+BadGmailApi10 := {
+ "policies": {
+ "topOU": {
+ "gmail_workspace_sync_for_outlook": {
+ "enableGoogleWorkspaceSyncForMicrosoftOutlook": true},
+ "gmail_service_status": {"serviceState": "ENABLED"
+ }
+ }
+ },
+ "tenant_info": {
+ "topLevelOU": "topOU"
+ }
+}
+
+test_SyncEnable_Correct_1 if {
+ PolicyId := GmailId10_1
+ Output := tests with input as GoodGmailApi10
+
+ PassTestResult(PolicyId, Output)
+}
+
+test_SyncEnable_Incorrect_1 if {
+ PolicyId := GmailId10_1
+ Output := tests with input as BadGmailApi10
+
+ failedOU := [{"Name": "topOU",
+ "Value": NonComplianceMessage10_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
+}
diff --git a/scubagoggles/Testing/RegoTests/gmail/gmail_api12_test.rego b/scubagoggles/Testing/RegoTests/gmail/gmail_api12_test.rego
new file mode 100644
index 00000000..307e2036
--- /dev/null
+++ b/scubagoggles/Testing/RegoTests/gmail/gmail_api12_test.rego
@@ -0,0 +1,48 @@
+package gmail
+
+import future.keywords
+import data.utils.FailTestOUNonCompliant
+import data.utils.PassTestResult
+
+GoodGmailApi12 := {
+ "policies": {
+ "topOU": {
+ "gmail_per_user_outbound_gateway": {
+ "allowUsersToUseExternalSmtpServers": false},
+ "gmail_service_status": {"serviceState": "ENABLED"},
+ }
+ },
+ "tenant_info": {
+ "topLevelOU": "topOU"
+ }
+}
+
+BadGmailApi12 := {
+ "policies": {
+ "topOU": {
+ "gmail_per_user_outbound_gateway": {
+ "allowUsersToUseExternalSmtpServers": true},
+ "gmail_service_status": {"serviceState": "ENABLED"
+ }
+ }
+ },
+ "tenant_info": {
+ "topLevelOU": "topOU"
+ }
+}
+
+test_OutGateways_Correct_1 if {
+ PolicyId := GmailId12_1
+ Output := tests with input as GoodGmailApi12
+
+ PassTestResult(PolicyId, Output)
+}
+
+test_OutGateways_Incorrect_1 if {
+ PolicyId := GmailId12_1
+ Output := tests with input as BadGmailApi12
+
+ failedOU := [{"Name": "topOU",
+ "Value": NonComplianceMessage12_1("enabled")}]
+ FailTestOUNonCompliant(PolicyId, Output, failedOU)
+}
diff --git a/scubagoggles/baselines/commoncontrols.md b/scubagoggles/baselines/commoncontrols.md
index d3cd1d92..1ba842e9 100644
--- a/scubagoggles/baselines/commoncontrols.md
+++ b/scubagoggles/baselines/commoncontrols.md
@@ -1306,6 +1306,8 @@ A custom policy SHALL be configured for Gmail to protect PII and sensitive infor
- [T1048:002: Exfiltration Over Alternative Protocol: Exfiltration Over Asymmetric Encrypted Non-C2 Protocol](https://attack.mitre.org/techniques/T1048/002/)
- [T1213: Data from Information Repositories](https://attack.mitre.org/techniques/T1213/)
+[//]: # (Keep the version suffix out of the anchor.)
+
#### GWS.COMMONCONTROLS.18.4v0.3
The action for the above DLP policies SHOULD be set to block external sharing.
@@ -1347,7 +1349,7 @@ Drive DLP and Chat DLP are available to Cloud Identity Premium users with a Goog
2. Click **Add Condition**. For **Content type to scan** select **All content**. For **What to scan for** select **Matches predefined data type**. For **Select data type** select **United States - Individual Taxpayer Identification Number**. Select the remaining condition properties according to agency need.
3. Click **Add Condition**. For **Content type to scan** select **All content**. For **What to scan for** select **Matches predefined data type**. For **Select data type** select **United States - Social Security Number***. Select the remaining condition properties according to agency need.
4. Configure other appropriate content and condition definition(s) based upon the agency's individual requirements and click **Continue**.
-5. In the **Actions** section, select **Block external sharing** (per [GWS.COMMONCONTROLS.18.4v0.3](#gwscommoncontrols184v03)).
+5. In the **Actions** section, select **Block external sharing** (per [GWS.COMMONCONTROLS.18.4](#commoncontrols184)).
6. In the **Alerting** section, choose a severity level, and optionally, check **Send to alert center to trigger notifications**.
7. Review the rule details, mark the rule as **Active**, and click **Create.**
@@ -1360,7 +1362,7 @@ Drive DLP and Chat DLP are available to Cloud Identity Premium users with a Goog
2. Click **Add Condition**. For **Content type to scan** select **All content**. For **What to scan for** select **Matches predefined data type**. For **Select data type** select **United States - Individual Taxpayer Identification Number**. Select the remaining condition properties according to agency need.
3. Click **Add Condition**. For **Content type to scan** select **All content**. For **What to scan for** select **Matches predefined data type**. For **Select data type** select **United States - Social Security Number***. Select the remaining condition properties according to agency need.
4. Configure other appropriate content and condition definition(s) based upon the agency's individual requirements and click **Continue**.
-5. In the **Actions** section, select **Block**. Under **Select when this action should apply**, select **External Conversations**, **Spaces**, **Group chats**, and **1:1 chats** (See [GWS.COMMONCONTROLS.18.4v0.3](#gwscommoncontrols184v03)).
+5. In the **Actions** section, select **Block**. Under **Select when this action should apply**, select **External Conversations**, **Spaces**, **Group chats**, and **1:1 chats** (See [GWS.COMMONCONTROLS.18.4](#commoncontrols184)).
6. In the **Alerting** section, choose a severity level, and optionally, check **Send to alert center to trigger notifications**.
7. Review the rule details, mark the rule as **Active**, and click **Create.**
@@ -1373,7 +1375,7 @@ Drive DLP and Chat DLP are available to Cloud Identity Premium users with a Goog
2. Click **Add Condition**. For **Content type to scan** select **All content**. For **What to scan for** select **Matches predefined data type**. For **Select data type** select **United States - Individual Taxpayer Identification Number**. Select the remaining condition properties according to agency need.
3. Click **Add Condition**. For **Content type to scan** select **All content**. For **What to scan for** select **Matches predefined data type**. For **Select data type** select **United States - Social Security Number***. Select the remaining condition properties according to agency need.
4. Configure other appropriate content and condition definition(s) based upon the agency's individual requirements and click **Continue**.
-5. In the **Actions** section, select **Block message**. Under **Select when this action should apply**, check **Messages sent to external recipients** (See [GWS.COMMONCONTROLS.18.4v0.3](#gwscommoncontrols184v03)).
+5. In the **Actions** section, select **Block message**. Under **Select when this action should apply**, check **Messages sent to external recipients** (See [GWS.COMMONCONTROLS.18.4](#commoncontrols184)).
6. In the **Alerting** section, choose a severity level, and optionally, check **Send to alert center to trigger notifications**.
7. Review the rule details, mark the rule as **Active**, and click **Create.**
diff --git a/scubagoggles/policy_api.py b/scubagoggles/policy_api.py
index 863a9f1f..265a2887 100644
--- a/scubagoggles/policy_api.py
+++ b/scubagoggles/policy_api.py
@@ -57,6 +57,11 @@ class PolicyAPI:
isDuration = lambda x: isinstance(x, str) and re.match(r'(?i)^\d+[hms]$', x)
+ isTimestamp = lambda x: (isinstance(x, str)
+ and re.match(r'(?i)^\d{4}(?:-\d{2}){2}T\d{2}'
+ r'(?::\d{2}){2}(?:\.\d+)?z$',
+ x))
+
# There may be duplicate policies returned for an orgunit/group and
# section. The policies must be "reduced" to single settings using
# a method. The default "reducer" method is to select the policy with the
@@ -178,11 +183,14 @@ class PolicyAPI:
'allowedIpAddresses': isListStrings}},
'gmail_enhanced_pre_delivery_message_scanning': {'settings': {
'enableImprovedSuspiciousContentDetection': isBool}},
+ 'gmail_imap_access': {'settings': {'enableImapAccess': isBool}},
'gmail_links_and_external_images': {'settings': {
'applyFutureSettingsAutomatically': isBool,
'enableAggressiveWarningsOnUntrustedLinks': isBool,
'enableExternalImageScanning': isBool,
'enableShortenerScanning': isBool}},
+ 'gmail_mail_delegation': {'settings': {'enableMailDelegation': isBool}},
+ 'gmail_pop_access': {'settings': {'enablePopAccess': isBool}},
'gmail_service_status': {'settings': {'serviceState': isState}},
'gmail_spoofing_and_authentication': {'settings': {
'applyFutureSettingsAutomatically': isBool,
@@ -196,6 +204,10 @@ class PolicyAPI:
'employeeNameSpoofingConsequence': isEnum,
'groupsSpoofingConsequence': isEnum,
'unauthenticatedEmailConsequence': isEnum}},
+ 'gmail_user_email_uploads': {'settings': {
+ 'enableMailAndContactsImport': isBool}},
+ 'gmail_workspace_sync_for_outlook': {'settings': {
+ 'enableGoogleWorkspaceSyncForMicrosoftOutlook': isBool}},
'groups_for_business_groups_sharing': {'reducer': _merge_reducer,
'settings': {
'collaborationCapability': isEnum,
@@ -245,6 +257,16 @@ class PolicyAPI:
'security_super_admin_account_recovery': {'reducer': _merge_reducer,
'settings': {
'enableAccountRecovery': isBool}},
+ 'security_two_step_verification_device_trust': {'settings': {
+ 'allowTrustingDevice': isBool}},
+ 'security_two_step_verification_enforcement': {'settings': {
+ 'enforcedFrom': isTimestamp}},
+ 'security_two_step_verification_enforcement_factor': {'settings': {
+ 'allowedSignInFactorSet': isEnum}},
+ 'security_two_step_verification_enrollment': {'settings': {
+ 'allowEnrollment': isBool}},
+ 'security_two_step_verification_grace_period': {'settings': {
+ 'enrollmentGracePeriod': isDuration}},
'security_user_account_recovery': {'reducer': _merge_reducer,
'settings': {
'enableAccountRecovery': isBool}},
diff --git a/scubagoggles/rego/Commoncontrols.rego b/scubagoggles/rego/Commoncontrols.rego
index eb4f54d7..6292347a 100644
--- a/scubagoggles/rego/Commoncontrols.rego
+++ b/scubagoggles/rego/Commoncontrols.rego
@@ -131,21 +131,36 @@ NoSuchEvent1_1 := true if {
count(Events) == 0
}
+Check1_1_OK if {
+ not PolicyApiInUse
+ not NoSuchEvent1_1
+}
+
+Check1_1_OK if {PolicyApiInUse}
+
GetFriendlyMethods(Value) := "Any" if {
- Value == "ANY"
+ Value in {"ALL", "ANY"}
} else := "Any except verification codes via text, phone call" if {
Value == "NO_TELEPHONY"
} else := "Only security key and allow security codes without remote access" if {
- Value == "SECURITY_KEY_AND_IP_BOUND_SECURITY_CODE"
+ Value in {"PASSKEY_PLUS_IP_BOUND_SECURITY_CODE", "SECURITY_KEY_AND_IP_BOUND_SECURITY_CODE"}
} else := "Only security key and allow security codes with remote access" if {
- Value == "SECURITY_KEY_AND_SECURITY_CODE"
+ Value in {"PASSKEY_PLUS_SECURITY_CODE", "SECURITY_KEY_AND_SECURITY_CODE"}
} else := Value
+NonComplianceMessage1_1a := "Users cannot enable 2-step verification (2SV)."
+
+NonComplianceMessage1_1b(value) := sprintf("Allowed methods is set to %s",
+ [value])
+
+NonComplianceMessage1_1c := "2-step verification (2SV) is not enforced."
+
NonCompliantOUs1_1 contains {
"Name": OU,
"Value": "Allow users to turn on 2-Step Verification is OFF"
}
if {
+ not PolicyApiInUse
some OU in utils.OUsWithEvents
Events := FilterEventsOU("ALLOW_STRONG_AUTHENTICATION", OU)
# Ignore OUs without any events. We're already asserting that the
@@ -161,6 +176,7 @@ NonCompliantOUs1_1 contains {
"Value": "2-Step Verification Enforcement is OFF"
}
if {
+ not PolicyApiInUse
some OU in utils.OUsWithEvents
Events := FilterEventsOU("ENFORCE_STRONG_AUTHENTICATION", OU)
# Ignore OUs without any events. We're already asserting that the
@@ -173,9 +189,10 @@ if {
NonCompliantOUs1_1 contains {
"Name": OU,
- "Value": concat("", ["Allowed methods is set to ", GetFriendlyMethods(LastEvent.NewValue)])
+ "Value": NonComplianceMessage1_1b(GetFriendlyMethods(LastEvent.NewValue))
}
if {
+ not PolicyApiInUse
some OU in utils.OUsWithEvents
Events := FilterEventsOU("CHANGE_ALLOWED_TWO_STEP_VERIFICATION_METHODS", OU)
# Ignore OUs without any events. We're already asserting that the
@@ -192,6 +209,7 @@ NonCompliantGroups1_1 contains {
"Value": "Allow users to turn on 2-Step Verification is Off"
}
if {
+ not PolicyApiInUse
some Group in utils.GroupsWithEvents
Events := FilterEventsGroup("ALLOW_STRONG_AUTHENTICATION", Group)
# Ignore Groups without any events.
@@ -205,6 +223,7 @@ NonCompliantGroups1_1 contains {
"Value": "2-Step Verification Enforcement is Off"
}
if {
+ not PolicyApiInUse
some Group in utils.GroupsWithEvents
Events := FilterEventsGroup("ENFORCE_STRONG_AUTHENTICATION", Group)
# Ignore Groups without any events.
@@ -215,9 +234,10 @@ if {
NonCompliantGroups1_1 contains {
"Name": Group,
- "Value": concat("", ["Allowed methods is set to ", GetFriendlyMethods(LastEvent.NewValue)])
+ "Value": NonComplianceMessage1_1b(GetFriendlyMethods(LastEvent.NewValue))
}
if {
+ not PolicyApiInUse
some Group in utils.GroupsWithEvents
Events := FilterEventsGroup("CHANGE_ALLOWED_TWO_STEP_VERIFICATION_METHODS", Group)
# Ignore Groups without any events.
@@ -227,6 +247,51 @@ if {
LastEvent.NewValue != "INHERIT_FROM_PARENT"
}
+# There are 3 items to check for this baseline. First, users must be allowed to
+# enroll in 2SV. If they have been enrolled, then the passkey (aka security
+# key) is the only allowed 2SV method. If the method is also OK, 2SV
+# enforcement must be enabled, and this is determined by ensuring the date
+# of enforcement is in the past (before today).
+
+NonCompliantOUs1_1 contains {
+ "Name": OU,
+ "Value": NonComplianceMessage1_1a
+}
+if {
+ some OU, settings in input.policies
+ enable2SV := settings.security_two_step_verification_enrollment.allowEnrollment
+ not enable2SV
+}
+
+NonCompliantOUs1_1 contains {
+ "Name": OU,
+ "Value": NonComplianceMessage1_1b(GetFriendlyMethods(enforceMethod))
+}
+if {
+ some OU, settings in input.policies
+ enable2SV := settings.security_two_step_verification_enrollment.allowEnrollment
+ enable2SV
+ enforceMethod := settings.security_two_step_verification_enforcement_factor.allowedSignInFactorSet
+ enforceMethod != "PASSKEY_ONLY"
+}
+
+NonCompliantOUs1_1 contains {
+ "Name": OU,
+ "Value": NonComplianceMessage1_1c
+}
+if {
+ today := time.now_ns()
+ RFC3339 := "2006-01-02T15:04:05Z07:00"
+ some OU, settings in input.policies
+ enable2SV := settings.security_two_step_verification_enrollment.allowEnrollment
+ enable2SV
+ enforceMethod := settings.security_two_step_verification_enforcement_factor.allowedSignInFactorSet
+ enforceMethod == "PASSKEY_ONLY"
+ enforce2SV := settings.security_two_step_verification_enforcement.enforcedFrom
+ enforceValue := time.parse_ns(RFC3339, enforce2SV)
+ enforceValue > today
+}
+
tests contains {
"PolicyId": CommonControlsId1_1,
"Criticality": "Shall",
@@ -236,8 +301,9 @@ tests contains {
"NoSuchEvent": true
}
if {
+ not PolicyApiInUse
DefaultSafe := false
- NoSuchEvent1_1 == true
+ not Check1_1_OK
}
tests contains {
@@ -249,7 +315,7 @@ tests contains {
"NoSuchEvent": false
}
if {
- NoSuchEvent1_1 == false
+ Check1_1_OK
Conditions := {count(NonCompliantOUs1_1) == 0, count(NonCompliantGroups1_1) == 0}
Status := (false in Conditions) == false
}
@@ -261,13 +327,29 @@ if {
CommonControlsId1_2 := utils.PolicyIdWithSuffix("GWS.COMMONCONTROLS.1.2")
+LogMessage1_2 := "CHANGE_TWO_STEP_VERIFICATION_ENROLLMENT_PERIOD_DURATION"
+
+Check1_2_OK if {
+ not PolicyApiInUse
+ events := FilterEventsOU(LogMessage1_2, utils.TopLevelOU)
+ count(events) > 0
+}
+
+Check1_2_OK if {PolicyApiInUse}
+
+NonComplianceMessage1_2(value, expected) := sprintf("New user enrollment period (%s) %s (%s)",
+ [utils.GetFriendlyDuration(value),
+ "doesn't match expected",
+ utils.GetFriendlyDuration(expected)])
+
NonCompliantOUs1_2 contains {
"Name": OU,
"Value": concat("", ["New user enrollment period is set to ", LastEvent.NewValue])
}
if {
+ not PolicyApiInUse
some OU in utils.OUsWithEvents
- Events := FilterEventsOU("CHANGE_TWO_STEP_VERIFICATION_ENROLLMENT_PERIOD_DURATION", OU)
+ Events := FilterEventsOU(LogMessage1_2, OU)
# Ignore OUs without any events. We're already asserting that the
# top-level OU has at least one event; for all other OUs we assume
# they inherit from a parent OU if they have no events.
@@ -282,8 +364,9 @@ NonCompliantGroups1_2 contains {
"Value": concat("", ["New user enrollment period is set to ", LastEvent.NewValue])
}
if {
+ not PolicyApiInUse
some Group in utils.GroupsWithEvents
- Events := FilterEventsGroup("CHANGE_TWO_STEP_VERIFICATION_ENROLLMENT_PERIOD_DURATION", Group)
+ Events := FilterEventsGroup(LogMessage1_2, Group)
# Ignore groups without any events.
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
@@ -291,6 +374,18 @@ if {
LastEvent.NewValue != "INHERIT_FROM_PARENT"
}
+NonCompliantOUs1_2 contains {
+ "Name": OU,
+ "Value": NonComplianceMessage1_2(enrollSeconds, expectedPeriod)
+}
+if {
+ expectedPeriod := utils.DurationToSeconds("7d")
+ some OU, settings in input.policies
+ enrollPeriod := settings.security_two_step_verification_grace_period.enrollmentGracePeriod
+ enrollSeconds := utils.DurationToSeconds(enrollPeriod)
+ enrollSeconds != expectedPeriod
+}
+
tests contains {
"PolicyId": CommonControlsId1_2,
"Criticality": "Shall",
@@ -300,9 +395,9 @@ tests contains {
"NoSuchEvent": true
}
if {
+ not PolicyApiInUse
DefaultSafe := false
- Events := FilterEventsOU("CHANGE_TWO_STEP_VERIFICATION_ENROLLMENT_PERIOD_DURATION", utils.TopLevelOU)
- count(Events) == 0
+ not Check1_2_OK
}
tests contains {
@@ -314,8 +409,7 @@ tests contains {
"NoSuchEvent": false
}
if {
- Events := FilterEventsOU("CHANGE_TWO_STEP_VERIFICATION_ENROLLMENT_PERIOD_DURATION", utils.TopLevelOU)
- count(Events) > 0
+ Check1_2_OK
Conditions := {count(NonCompliantOUs1_2) == 0, count(NonCompliantGroups1_2) == 0}
Status := (false in Conditions) == false
}
@@ -327,6 +421,18 @@ if {
CommonControlsId1_3 := utils.PolicyIdWithSuffix("GWS.COMMONCONTROLS.1.3")
+LogMessage1_3 := "CHANGE_TWO_STEP_VERIFICATION_FREQUENCY"
+
+Check1_3_OK if {
+ not PolicyApiInUse
+ events := FilterEventsOU(LogMessage1_3, utils.TopLevelOU)
+ count(events) > 0
+}
+
+Check1_3_OK if {PolicyApiInUse}
+
+NonComplianceMessage1_3 := "User is allowed to trust device."
+
GetFriendlyValue1_3(Value) := "ON" if {
Value == "ENABLE_USERS_TO_TRUST_DEVICE"
} else := Value
@@ -336,6 +442,7 @@ NonCompliantOUs1_3 contains {
"Value": concat("", ["Allow user to trust the device is ", GetFriendlyValue1_3(LastEvent.NewValue)])
}
if {
+ not PolicyApiInUse
some OU in utils.OUsWithEvents
Events := FilterEventsOU("CHANGE_TWO_STEP_VERIFICATION_FREQUENCY", OU)
# Ignore OUs without any events. We're already asserting that the
@@ -352,8 +459,9 @@ NonCompliantGroups1_3 contains {
"Value": concat("", ["Allow user to trust the device is ", GetFriendlyValue1_3(LastEvent.NewValue)])
}
if {
+ not PolicyApiInUse
some Group in utils.GroupsWithEvents
- Events := FilterEventsGroup("CHANGE_TWO_STEP_VERIFICATION_FREQUENCY", Group)
+ Events := FilterEventsGroup(LogMessage1_3, Group)
# Ignore groups without any events.
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
@@ -361,6 +469,16 @@ if {
LastEvent.NewValue != "INHERIT_FROM_PARENT"
}
+NonCompliantOUs1_3 contains {
+ "Name": OU,
+ "Value": NonComplianceMessage1_3
+}
+if {
+ some OU, settings in input.policies
+ trustDevice := settings.security_two_step_verification_device_trust.allowTrustingDevice
+ trustDevice
+}
+
tests contains {
"PolicyId": CommonControlsId1_3,
"Criticality": "Shall",
@@ -370,9 +488,9 @@ tests contains {
"NoSuchEvent": true
}
if {
+ not PolicyApiInUse
DefaultSafe := false
- Events := FilterEventsOU("CHANGE_TWO_STEP_VERIFICATION_FREQUENCY", utils.TopLevelOU)
- count(Events) == 0
+ not Check1_3_OK
}
tests contains {
@@ -384,8 +502,7 @@ tests contains {
"NoSuchEvent": false
}
if {
- Events := FilterEventsOU("CHANGE_TWO_STEP_VERIFICATION_FREQUENCY", utils.TopLevelOU)
- count(Events) > 0
+ Check1_3_OK
Conditions := {count(NonCompliantOUs1_3) == 0, count(NonCompliantGroups1_3) == 0}
Status := (false in Conditions) == false
}
@@ -623,17 +740,7 @@ NonComplianceMessage4_1(Value) := sprintf("Web session duration: %s",
GetFriendlyValue4_1(Value) := "Session never expires" if {
Value == 63072000
-} else := "30 days" if {
- Value == 2592000
-} else := "14 days" if {
- Value == 1209600
-} else := "7 days" if {
- Value == 604800
-} else := "24 hours" if {
- Value == 86400
-} else := "20 hours" if {
- Value == 72000
-} else := sprintf("%d seconds", [Value])
+} else := utils.GetFriendlyDuration(Value)
NonCompliantOUs4_1 contains {
"Name": OU,
@@ -657,19 +764,11 @@ NonCompliantOUs4_1 contains {
"Value": NonComplianceMessage4_1(GetFriendlyValue4_1(durationSeconds))
}
if {
- multipliers := {"s": 1, "m": 60, "h": 3600}
# This is the requirement limit for session duration:
- webSessionMax := 12 * multipliers["h"]
+ webSessionMax := utils.DurationToSeconds("12h")
some OU, settings in input.policies
duration := settings.security_session_controls.webSessionDuration
- result := regex.find_all_string_submatch_n(`(?i)^(\d+)([hms])$`,
- duration,
- 1)
- firstMatch := result[0]
- value := to_number(firstMatch[1])
- unit := firstMatch[2]
- multiplier := multipliers[lower(unit)]
- durationSeconds := value * multiplier
+ durationSeconds := utils.DurationToSeconds(duration)
durationSeconds > webSessionMax
}
@@ -1113,11 +1212,7 @@ NonCompliantOUs5_6 contains {
if {
some OU, settings in input.policies
passwordExpiration := settings.security_password.expirationDuration
- result := regex.find_all_string_submatch_n(`(?i)^(\d+)[hms]$`,
- passwordExpiration,
- -1)
- firstMatch := result[0]
- expirationValue := to_number(firstMatch[1])
+ expirationValue := utils.DurationToSeconds(passwordExpiration)
expirationValue != 0
}
@@ -2344,11 +2439,13 @@ if {
CommonControlsId16_1 := utils.PolicyIdWithSuffix("GWS.COMMONCONTROLS.16.1")
+NonComplianceMessage16_1 := "Access to additional services without individual control is turned on"
+
# NOTE: This setting cannot be controlled at the group level
NonCompliantOUs16_1 contains {
"Name": OU,
- "Value": "Access to additional services without individual control is turned on"
+ "Value": NonComplianceMessage16_1
}
if {
some OU in utils.OUsWithEvents
@@ -2412,11 +2509,26 @@ if {
CommonControlsId16_2 := utils.PolicyIdWithSuffix("GWS.COMMONCONTROLS.16.2")
+NonComplianceMessage16_2 := "Early access apps are ENABLED"
+
+Check16_2_OK if {
+ not PolicyApiInUse
+ Events := {
+ Event | some Event in ToggleServiceEvents;
+ Event.OrgUnit == utils.TopLevelOU;
+ Event.ServiceName == "Early Access Apps"
+ }
+ count(Events) > 0
+}
+
+Check16_2_OK if {PolicyApiInUse}
+
NonCompliantOUs16_2 contains {
"Name": OU,
- "Value": "Service status is ON"
+ "Value": NonComplianceMessage16_2
}
if {
+ not PolicyApiInUse
some OU in utils.OUsWithEvents
# Note that this setting requires the custom ToggleServiceEvents rule.
# Filter based on the service name of the event, otherwise all events are returned.
@@ -2438,9 +2550,10 @@ if {
NonCompliantGroups16_2 contains {
"Name": Group,
- "Value": "Service status is ON"
+ "Value": NonComplianceMessage16_2
}
if {
+ not PolicyApiInUse
some Group in utils.GroupsWithEvents
# Note that this setting requires the custom ToggleServiceEvents rule.
Events := {
@@ -2454,6 +2567,16 @@ if {
LastEvent.NewValue == "true"
}
+NonCompliantOUs16_2 contains {
+ "Name": OU,
+ "Value": NonComplianceMessage16_2
+}
+if {
+ some OU, settings in input.policies
+ appState := utils.AppExplicitStatus(input.policies, "early_access_apps", OU)
+ appState == "ENABLED"
+}
+
tests contains {
"PolicyId": CommonControlsId16_2,
"Criticality": "Should",
@@ -2463,14 +2586,9 @@ tests contains {
"NoSuchEvent": true
}
if {
+ not PolicyApiInUse
DefaultSafe := false
- # Filter based on the service name of the event, otherwise all events are returned.
- Events := {
- Event | some Event in ToggleServiceEvents;
- Event.OrgUnit == utils.TopLevelOU;
- Event.ServiceName == "Early Access Apps"
- }
- count(Events) == 0
+ not Check16_2_OK
}
tests contains {
@@ -2482,14 +2600,7 @@ tests contains {
"NoSuchEvent": false
}
if {
- # This rule should execute only when log events exist
- Events := {
- Event | some Event in ToggleServiceEvents;
- Event.OrgUnit == utils.TopLevelOU;
- Event.ServiceName == "Early Access Apps"
- }
- count(Events) > 0
-
+ Check16_2_OK
Conditions := {
count(NonCompliantOUs16_2) == 0,
count(NonCompliantGroups16_2) == 0
diff --git a/scubagoggles/rego/Gmail.rego b/scubagoggles/rego/Gmail.rego
index 77307f25..7354a769 100644
--- a/scubagoggles/rego/Gmail.rego
+++ b/scubagoggles/rego/Gmail.rego
@@ -37,23 +37,44 @@ LogEvents := utils.GetEvents("gmail_logs")
GmailId1_1 := utils.PolicyIdWithSuffix("GWS.GMAIL.1.1")
+LogMessage1_1 := "ENABLE_MAIL_DELEGATION_WITHIN_DOMAIN"
+
+Check1_1_OK if {
+ not PolicyApiInUse
+ events := utils.FilterEventsOU(LogEvents, LogMessage1_1, utils.TopLevelOU)
+ count(events) > 0
+}
+
+Check1_1_OK if {PolicyApiInUse}
+
+NonComplianceMessage1_1(value) := sprintf("Mail delegation is %s", [value])
+
# Cannot be controlled at group level
NonCompliantOUs1_1 contains {
"Name": OU,
- "Value": concat(" ", [
- "Mail delegation is set to",
- GetFriendlyEnabledValue(LastEvent.NewValue)
- ])
+ "Value": NonComplianceMessage1_1(GetFriendlyEnabledValue(LastEvent.NewValue))
}
if {
+ not PolicyApiInUse
some OU in utils.OUsWithEvents
- Events := utils.FilterEventsOU(LogEvents, "ENABLE_MAIL_DELEGATION_WITHIN_DOMAIN", OU)
+ Events := utils.FilterEventsOU(LogEvents, LogMessage1_1, OU)
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue == "true"
}
+NonCompliantOUs1_1 contains {
+ "Name": OU,
+ "Value": NonComplianceMessage1_1(GetFriendlyEnabledValue(mailDelegation))
+}
+if {
+ some OU, settings in input.policies
+ GmailEnabled(OU)
+ mailDelegation := settings.gmail_mail_delegation.enableMailDelegation
+ mailDelegation
+}
+
tests contains {
"PolicyId": GmailId1_1,
"Criticality": "Should",
@@ -63,9 +84,9 @@ tests contains {
"NoSuchEvent": true
}
if {
+ not PolicyApiInUse
DefaultSafe := true
- Events := utils.FilterEventsOU(LogEvents, "ENABLE_MAIL_DELEGATION_WITHIN_DOMAIN", utils.TopLevelOU)
- count(Events) == 0
+ not Check1_1_OK
}
tests contains {
@@ -77,8 +98,7 @@ tests contains {
"NoSuchEvent": false
}
if {
- Events := utils.FilterEventsOU(LogEvents, "ENABLE_MAIL_DELEGATION_WITHIN_DOMAIN", utils.TopLevelOU)
- count(Events) > 0
+ Check1_1_OK
Status := count(NonCompliantOUs1_1) == 0
}
#--
@@ -318,7 +338,8 @@ if {
NonCompliantOUs5_1 contains {
"Name": OU,
"Value": NonComplianceMessage5_1(GetFriendlyEnabledValue(noEncrypt))
-} if {
+}
+if {
some OU, settings in input.policies
GmailEnabled(OU)
noEncrypt := settings.gmail_email_attachment_safety.enableEncryptedAttachmentProtection
@@ -332,7 +353,8 @@ tests contains {
"ActualValue": "No relevant event in the current logs",
"RequirementMet": DefaultSafe,
"NoSuchEvent": true
-} if {
+}
+if {
not PolicyApiInUse
DefaultSafe := true
not Check5_1_OK
@@ -389,7 +411,8 @@ if {
NonCompliantOUs5_2 contains {
"Name": OU,
"Value": NonComplianceMessage5_2(GetFriendlyEnabledValue(noEncrypt))
-} if {
+}
+if {
some OU, settings in input.policies
GmailEnabled(OU)
noEncrypt := settings.gmail_email_attachment_safety.enableAttachmentWithScriptsProtection
@@ -462,7 +485,8 @@ if {
NonCompliantOUs5_3 contains {
"Name": OU,
"Value": NonComplianceMessage5_3(GetFriendlyEnabledValue(protectAtt))
-} if {
+}
+if {
some OU, settings in input.policies
GmailEnabled(OU)
protectAtt := settings.gmail_email_attachment_safety.enableAnomalousAttachmentProtection
@@ -534,7 +558,8 @@ if {
NonCompliantOUs5_4 contains {
"Name": OU,
"Value": NonComplianceMessage5_4(GetFriendlyEnabledValue(futureAtt))
-} if {
+}
+if {
some OU, settings in input.policies
GmailEnabled(OU)
futureAtt := settings.gmail_email_attachment_safety.applyFutureRecommendedSettingsAutomatically
@@ -647,7 +672,8 @@ NonCompliantOUs5_5 contains {
"Value": GetFriendlyValue5_5(LastEventEncryptedAttachment.NewValue,
LastEventAttachmentWithScripts.NewValue,
LastEventAnomalousAttachment.NewValue)
-} if {
+}
+if {
not PolicyApiInUse
some OU in utils.OUsWithEvents
EncryptedAttachmentEvents := utils.FilterEventsOU(LogEvents,
@@ -685,7 +711,8 @@ AttachConfigs := [
NonCompliantOUs5_5 contains {
"Name": OU,
"Value": NonComplianceMessage5_5(types)
-} if {
+}
+if {
some OU, settings in input.policies
GmailEnabled(OU)
types := [config.type |
@@ -769,7 +796,8 @@ NonComplianceMessage6_1(value) := sprintf("Identify links behind shortened URLs
NonCompliantOUs6_1 contains {
"Name": OU,
"Value": NonComplianceMessage6_1(GetFriendlyEnabledValue(LastEvent.NewValue))
-} if {
+}
+if {
not PolicyApiInUse
some OU in utils.OUsWithEvents
Events := utils.FilterEventsOU(LogEvents, LogMessage6_1, OU)
@@ -782,7 +810,8 @@ NonCompliantOUs6_1 contains {
NonCompliantOUs6_1 contains {
"Name": OU,
"Value": NonComplianceMessage6_1(GetFriendlyEnabledValue(shortLinks))
-} if {
+}
+if {
some OU, settings in input.policies
GmailEnabled(OU)
shortLinks := settings.gmail_links_and_external_images.enableShortenerScanning
@@ -853,7 +882,8 @@ if {
NonCompliantOUs6_2 contains {
"Name": OU,
"Value": NonComplianceMessage6_2(GetFriendlyEnabledValue(scanImages))
-} if {
+}
+if {
some OU, settings in input.policies
GmailEnabled(OU)
scanImages := settings.gmail_links_and_external_images.enableExternalImageScanning
@@ -927,7 +957,8 @@ if {
NonCompliantOUs6_3 contains {
"Name": OU,
"Value": NonComplianceMessage6_3(GetFriendlyEnabledValue(warnEnabled))
-} if {
+}
+if {
some OU, settings in input.policies
GmailEnabled(OU)
warnEnabled := settings.gmail_links_and_external_images.enableAggressiveWarningsOnUntrustedLinks
@@ -1000,7 +1031,8 @@ if {
NonCompliantOUs6_4 contains {
"Name": OU,
"Value": NonComplianceMessage6_4(GetFriendlyEnabledValue(applyFuture))
-} if {
+}
+if {
some OU, settings in input.policies
GmailEnabled(OU)
applyFuture := settings.gmail_links_and_external_images.applyFutureSettingsAutomatically
@@ -1095,7 +1127,8 @@ if {
NonCompliantOUs7_1 contains {
"Name": OU,
"Value": NonComplianceMessage7_1(GetFriendlyEnabledValue(spoofProtect))
-} if {
+}
+if {
some OU, settings in input.policies
GmailEnabled(OU)
spoofProtect := settings.gmail_spoofing_and_authentication.detectDomainNameSpoofing
@@ -1168,7 +1201,8 @@ if {
NonCompliantOUs7_2 contains {
"Name": OU,
"Value": NonComplianceMessage7_2(GetFriendlyEnabledValue(spoofProtect))
-} if {
+}
+if {
some OU, settings in input.policies
GmailEnabled(OU)
spoofProtect := settings.gmail_spoofing_and_authentication.detectEmployeeNameSpoofing
@@ -1241,7 +1275,8 @@ if {
NonCompliantOUs7_3 contains {
"Name": OU,
"Value": NonComplianceMessage7_3(GetFriendlyEnabledValue(spoofProtect))
-} if {
+}
+if {
some OU, settings in input.policies
GmailEnabled(OU)
spoofProtect := settings.gmail_spoofing_and_authentication.detectDomainSpoofingFromUnauthenticatedSenders
@@ -1314,7 +1349,8 @@ if {
NonCompliantOUs7_4 contains {
"Name": OU,
"Value": NonComplianceMessage7_4(GetFriendlyEnabledValue(unauthEmail))
-} if {
+}
+if {
some OU, settings in input.policies
GmailEnabled(OU)
unauthEmail := settings.gmail_spoofing_and_authentication.detectUnauthenticatedEmails
@@ -1387,7 +1423,8 @@ if {
NonCompliantOUs7_5 contains {
"Name": OU,
"Value": NonComplianceMessage7_5(GetFriendlyEnabledValue(detectSpoof))
-} if {
+}
+if {
some OU, settings in input.policies
GmailEnabled(OU)
detectSpoof := settings.gmail_spoofing_and_authentication.detectDomainSpoofingFromUnauthenticatedSenders
@@ -1515,7 +1552,8 @@ NonCompliantOUs7_6 contains {
"Value": GetFriendlyValue7_6(LastEventDomainNames.NewValue, LastEventEmployeeNames.NewValue,
LastEventInboundEmails.NewValue, LastEventUnauthenticatedEmails.NewValue,
LastEventGroupEmails.NewValue)
-} if {
+}
+if {
not PolicyApiInUse
some OU in utils.OUsWithEvents
@@ -1570,7 +1608,8 @@ SpoofConfigs := [
NonCompliantOUs7_6 contains {
"Name": OU,
"Value": NonComplianceMessage7_6(types)
-} if {
+}
+if {
some OU, settings in input.policies
GmailEnabled(OU)
types := [config.type |
@@ -1647,7 +1686,8 @@ if {
NonCompliantOUs7_7 contains {
"Name": OU,
"Value": NonComplianceMessage7_7(GetFriendlyEnabledValue(applyFuture))
-} if {
+}
+if {
some OU, settings in input.policies
GmailEnabled(OU)
applyFuture := settings.gmail_spoofing_and_authentication.applyFutureSettingsAutomatically
@@ -1710,21 +1750,42 @@ tests contains {
GmailId8_1 := utils.PolicyIdWithSuffix("GWS.GMAIL.8.1")
+LogMessage8_1 := "ENABLE_EMAIL_USER_IMPORT"
+
+Check8_1_OK if {
+ not PolicyApiInUse
+ events := utils.FilterEventsOU(LogEvents, LogMessage8_1, utils.TopLevelOU)
+ count(events) > 0
+}
+
+Check8_1_OK if {PolicyApiInUse}
+
+NonComplianceMessage8_1(value) := sprintf("User email uploads is %s", [value])
+
NonCompliantOUs8_1 contains {
"Name": OU,
- "Value": concat(" ", [
- "User email uploads is set to",
- GetFriendlyEnabledValue(LastEvent.NewValue)
- ])
+ "Value": NonComplianceMessage8_1(GetFriendlyEnabledValue(LastEvent.NewValue))
}
if {
+ not PolicyApiInUse
some OU in utils.OUsWithEvents
- Events := utils.FilterEventsOU(LogEvents, "ENABLE_EMAIL_USER_IMPORT", OU)
+ Events := utils.FilterEventsOU(LogEvents, LogMessage8_1, OU)
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue == "true"
}
+NonCompliantOUs8_1 contains {
+ "Name": OU,
+ "Value": NonComplianceMessage8_1(GetFriendlyEnabledValue(emailUploads))
+}
+if {
+ some OU, settings in input.policies
+ GmailEnabled(OU)
+ emailUploads := settings.gmail_user_email_uploads.enableMailAndContactsImport
+ emailUploads
+}
+
tests contains {
"PolicyId": GmailId8_1,
"Criticality": "Shall",
@@ -1734,9 +1795,9 @@ tests contains {
"NoSuchEvent": true
}
if {
+ not PolicyApiInUse
DefaultSafe := true
- Events := utils.FilterEventsOU(LogEvents, "ENABLE_EMAIL_USER_IMPORT", utils.TopLevelOU)
- count(Events) == 0
+ not Check8_1_OK
}
tests contains {
@@ -1748,8 +1809,7 @@ tests contains {
"NoSuchEvent": false
}
if {
- Events := utils.FilterEventsOU(LogEvents, "ENABLE_EMAIL_USER_IMPORT", utils.TopLevelOU)
- count(Events) > 0
+ Check8_1_OK
Status := count(NonCompliantOUs8_1) == 0
}
#--
@@ -1764,6 +1824,12 @@ if {
GmailId9_1 := utils.PolicyIdWithSuffix("GWS.GMAIL.9.1")
+Check9_1_OK if {
+ not NoSuchEvent9_1(utils.TopLevelOU)
+}
+
+Check9_1_OK if {PolicyApiInUse}
+
default NoSuchEvent9_1(_) := false
NoSuchEvent9_1(TopLevelOU) := true if {
@@ -1779,7 +1845,7 @@ NoSuchEvent9_1(TopLevelOU) := true if {
GetFriendlyValue9_1(ImapEnabled, PopEnabled) := Description if {
ImapEnabled == true
PopEnabled == true
- Description := "POP and IMAP access are enabled"
+ Description := "IMAP and POP access are enabled"
} else := Description if {
ImapEnabled == true
PopEnabled == false
@@ -1788,7 +1854,7 @@ GetFriendlyValue9_1(ImapEnabled, PopEnabled) := Description if {
ImapEnabled == false
PopEnabled == true
Description := "POP access is enabled"
-} else := "Both POP and IMAP access are disabled"
+} else := "Both IMAP and POP access are disabled"
NonCompliantOUs9_1 contains {
@@ -1796,6 +1862,7 @@ NonCompliantOUs9_1 contains {
"Value": GetFriendlyValue9_1(ImapEnabled, PopEnabled)
}
if {
+ not PolicyApiInUse
some OU in utils.OUsWithEvents
ImapEvents := utils.FilterEventsOU(LogEvents, "IMAP_ACCESS", OU)
@@ -1819,6 +1886,7 @@ NonCompliantGroups9_1 contains {
"Value": GetFriendlyValue9_1(ImapEnabled, PopEnabled)
}
if {
+ not PolicyApiInUse
some Group in utils.GroupsWithEvents
ImapEvents := utils.FilterEventsGroup(LogEvents, "IMAP_ACCESS", Group)
@@ -1837,6 +1905,25 @@ if {
}
}
+NonCompliantOUs9_1 contains {
+ "Name": OU,
+ "Value": GetFriendlyValue9_1(imapEnable, popEnable)
+}
+if {
+ some OU, settings in input.policies
+ GmailEnabled(OU)
+ imapSection := "gmail_imap_access"
+ imapSetting := "enableImapAccess"
+ popSection := "gmail_pop_access"
+ popSetting := "enablePopAccess"
+ imapSet := utils.ApiSettingExists(imapSection, imapSetting, OU)
+ popSet := utils.ApiSettingExists(popSection, popSetting, OU)
+ true in {imapSet, popSet}
+ imapEnable := utils.GetApiSettingValue(imapSection, imapSetting, OU)
+ popEnable := utils.GetApiSettingValue(popSection, popSetting, OU)
+ true in {imapEnable, popEnable}
+}
+
tests contains {
"PolicyId": GmailId9_1,
"Criticality": "Shall",
@@ -1846,8 +1933,9 @@ tests contains {
"NoSuchEvent": true
}
if {
+ not PolicyApiInUse
DefaultSafe := false
- NoSuchEvent9_1(utils.TopLevelOU)
+ not Check9_1_OK
}
tests contains {
@@ -1859,8 +1947,7 @@ tests contains {
"NoSuchEvent": false
}
if {
- not NoSuchEvent9_1(utils.TopLevelOU)
-
+ Check9_1_OK
Conditions := {count(NonCompliantOUs9_1) == 0, count(NonCompliantGroups9_1) == 0}
Status := (false in Conditions) == false
}
@@ -1876,22 +1963,44 @@ if {
GmailId10_1 := utils.PolicyIdWithSuffix("GWS.GMAIL.10.1")
+LogMessage10_1 := "ENABLE_OUTLOOK_SYNC"
+
+Check10_1_OK if {
+ not PolicyApiInUse
+ events := utils.FilterEventsOU(LogEvents, LogMessage10_1, utils.TopLevelOU)
+ count(events) > 0
+}
+
+Check10_1_OK if {PolicyApiInUse}
+
+NonComplianceMessage10_1(value) := sprintf("Google Workspace Sync is %s",
+ [value])
+
NonCompliantOUs10_1 contains {
"Name": OU,
- "Value": concat(" ", [
- "Automatically enable outlook sync is set to",
- GetFriendlyEnabledValue(LastEvent.NewValue)
- ])
+ "Value": NonComplianceMessage10_1(GetFriendlyEnabledValue(LastEvent.NewValue))
}
if {
+ not PolicyApiInUse
some OU in utils.OUsWithEvents
- Events := utils.FilterEventsOU(LogEvents, "ENABLE_OUTLOOK_SYNC", OU)
+ Events := utils.FilterEventsOU(LogEvents, LogMessage10_1, OU)
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue == "true"
LastEvent.NewValue != "INHERIT_FROM_PARENT"
}
+NonCompliantOUs10_1 contains {
+ "Name": OU,
+ "Value": NonComplianceMessage10_1(GetFriendlyEnabledValue(syncEnable))
+}
+if {
+ some OU, settings in input.policies
+ GmailEnabled(OU)
+ syncEnable := settings.gmail_workspace_sync_for_outlook.enableGoogleWorkspaceSyncForMicrosoftOutlook
+ syncEnable
+}
+
tests contains {
"PolicyId": GmailId10_1,
"Criticality": "Shall",
@@ -1901,9 +2010,9 @@ tests contains {
"NoSuchEvent": true
}
if {
+ not PolicyApiInUse
DefaultSafe := false
- Events := utils.FilterEventsOU(LogEvents, "ENABLE_OUTLOOK_SYNC", utils.TopLevelOU)
- count(Events) == 0
+ not Check10_1_OK
}
tests contains {
@@ -1915,8 +2024,7 @@ tests contains {
"NoSuchEvent": false
}
if {
- Events := utils.FilterEventsOU(LogEvents, "ENABLE_OUTLOOK_SYNC", utils.TopLevelOU)
- count(Events) > 0
+ Check10_1_OK
Status := count(NonCompliantOUs10_1) == 0
}
#--
@@ -2014,7 +2122,6 @@ if {
}
#--
-
################
# GWS.GMAIL.12 #
################
@@ -2025,21 +2132,43 @@ if {
GmailId12_1 := utils.PolicyIdWithSuffix("GWS.GMAIL.12.1")
+LogMessage12_1 := "OUTBOUND_RELAY_ENABLED"
+
+Check12_1_OK if {
+ not PolicyApiInUse
+ events := utils.FilterEventsOU(LogEvents, LogMessage12_1, utils.TopLevelOU)
+ count(events) > 0
+}
+
+Check12_1_OK if {PolicyApiInUse}
+
+NonComplianceMessage12_1(value) := sprintf("Per-user Outbound Gateways are %s",
+ [value])
+
NonCompliantOUs12_1 contains {
"Name": OU,
- "Value": concat(" ", [
- "Allow per-user outbound gateways is set to",
- GetFriendlyEnabledValue(LastEvent.NewValue)
- ])
+ "Value": NonComplianceMessage12_1(GetFriendlyEnabledValue(LastEvent.NewValue))
}
if {
+ not PolicyApiInUse
some OU in utils.OUsWithEvents
- Events := utils.FilterEventsOU(LogEvents, "OUTBOUND_RELAY_ENABLED", OU)
+ Events := utils.FilterEventsOU(LogEvents, LogMessage12_1, OU)
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue == "true"
}
+NonCompliantOUs12_1 contains {
+ "Name": OU,
+ "Value": NonComplianceMessage12_1(GetFriendlyEnabledValue(outGatewayEnable))
+}
+if {
+ some OU, settings in input.policies
+ GmailEnabled(OU)
+ outGatewayEnable := settings.gmail_per_user_outbound_gateway.allowUsersToUseExternalSmtpServers
+ outGatewayEnable
+}
+
tests contains {
"PolicyId": GmailId12_1,
"Criticality": "Shall",
@@ -2049,9 +2178,9 @@ tests contains {
"NoSuchEvent": true
}
if {
+ not PolicyApiInUse
DefaultSafe := true
- Events := utils.FilterEventsOU(LogEvents, "OUTBOUND_RELAY_ENABLED", utils.TopLevelOU)
- count(Events) == 0
+ not Check12_1_OK
}
tests contains {
@@ -2063,13 +2192,11 @@ tests contains {
"NoSuchEvent": false
}
if {
- Events := utils.FilterEventsOU(LogEvents, "OUTBOUND_RELAY_ENABLED", utils.TopLevelOU)
- count(Events) > 0
+ Check12_1_OK
Status := count(NonCompliantOUs12_1) == 0
}
#--
-
################
# GWS.GMAIL.13 #
################
@@ -2133,7 +2260,6 @@ if {
}
#--
-
################
# GWS.GMAIL.14 #
################
@@ -2269,7 +2395,8 @@ if {
NonCompliantOUs15_1 contains {
"Name": OU,
"Value": NonComplianceMessage15_1(GetFriendlyValue15_1(preScanning))
-} if {
+}
+if {
some OU, settings in input.policies
GmailEnabled(OU)
preDelivery := settings.gmail_enhanced_pre_delivery_message_scanning
diff --git a/scubagoggles/rego/Utils.rego b/scubagoggles/rego/Utils.rego
index 333a41b8..bfe4313a 100644
--- a/scubagoggles/rego/Utils.rego
+++ b/scubagoggles/rego/Utils.rego
@@ -554,6 +554,17 @@ AppEnabled(policies, appName, orgunit) if {
upper(appState) == "ENABLED"
}
+# Use the following function if you need to know if the app enable state has
+# been explicitly set in the given orgunit or group. The above functions will
+# tell you whether the app is enabled, but its state may be due to inheriting
+# the state from the top-level orgunit. In some cases, you need to know
+# whether the state has been explicitly set (not inherited).
+
+AppExplicitStatus(policies, appName, orgunit) := appState if {
+ serviceStatusName := AppServiceStatusName(appName)
+ appState := upper(policies[orgunit][serviceStatusName].serviceState)
+} else := ""
+
# There are a lot of policies that have enabled/disabled states. The states
# (values) in the log events are strings ("true", "false), while the states
# in the Policy API are booleans (true, false). This is a common function
@@ -564,3 +575,37 @@ GetFriendlyEnabledValue(Value) := "enabled" if {
} else := "disabled" if {
Value in {false, "false"}
} else := Value
+
+# This function will convert a "duration string" (e.g., "18m" for 18 minutes)
+# to an integer representing the time in seconds. This may be used for
+# comparing string durations. Typically, Google's Policy API returns duration
+# values in seconds. See CC 1.2 & CC 4.1 for examples of usage.
+
+DurationToSeconds(duration) := durationSeconds if {
+ multipliers := {"s": 1, "m": 60, "h": 3600, "d": 86400}
+ result := regex.find_all_string_submatch_n(`(?i)^(\d+)([dhms])$`,
+ duration,
+ 1)
+ firstMatch := result[0]
+ value := to_number(firstMatch[1])
+ unit := firstMatch[2]
+ multiplier := multipliers[lower(unit)]
+ durationSeconds := value * multiplier
+}
+
+# Google will often return durations in seconds, but the values correspond to
+# a "common" duration (that is usually a choice in the UI). This function
+# will convert the given seconds to a duration other than seconds that will
+# (hopefully) make more sense to the user.
+
+GetFriendlyDuration(Seconds) := "30 days" if {
+ Seconds == 2592000
+} else := "14 days" if {
+ Seconds == 1209600
+} else := "7 days" if {
+ Seconds == 604800
+} else := "24 hours" if {
+ Seconds == 86400
+} else := "20 hours" if {
+ Seconds == 72000
+} else := sprintf("%d seconds", [Seconds])