Skip to content

Commit

Permalink
release: 2023/10/02 (#3)
Browse files Browse the repository at this point in the history
This PR includes:

- ❇️ **Enhanced support for CIS AWS Foundations Benchmark v1.5.0**. Now
any benchmark items with automation capability can be detected with
newer prebundle workflow manifests.
- ❇️ **Enhanced support for CIS Google Cloud Platform Foundations
Benchmark**. Now any benchmark items with automation capability can be
detected with newer prebundle workflow manifests.

---

See changes for details.
  • Loading branch information
lmt-swallow authored Oct 1, 2023
1 parent 5fd7308 commit a3f9b62
Show file tree
Hide file tree
Showing 278 changed files with 23,105 additions and 266 deletions.
2 changes: 1 addition & 1 deletion sdk/rego
Submodule rego updated 96 files
+101 −0 decision/aws/cloudtrail/cloudtrail_cloudwatch_logs_integration.gen.rego
+24 −24 decision/aws/cloudtrail/cloudtrail_cmk_encryption.gen.rego
+107 −0 decision/aws/cloudtrail/cloudtrail_log_bucket_accessibility.gen.rego
+101 −0 decision/aws/cloudtrail/cloudtrail_log_file_validation.gen.rego
+25 −25 decision/aws/cloudtrail/cloudtrail_usage.gen.rego
+104 −0 decision/aws/config/config_recorder_status.gen.rego
+0 −0 decision/aws/ebs/ebs_volume_encryption_baseline.gen.rego
+104 −0 decision/aws/iam/iam_access_analyzers.gen.rego
+107 −0 decision/aws/iam/iam_account_alternate_contact.gen.rego
+110 −0 decision/aws/iam/iam_console_user_keys.gen.rego
+1 −1 decision/aws/iam/iam_credentials_inventory.gen.rego
+102 −0 decision/aws/iam/iam_role_for_support.gen.rego
+1 −1 decision/aws/iam/iam_root_user_key.gen.rego
+104 −0 decision/aws/iam/iam_server_certificates.gen.rego
+101 −0 decision/aws/iam/iam_user_available_access_keys.gen.rego
+102 −0 decision/aws/iam/iam_user_group_permission_assignment.gen.rego
+105 −0 decision/aws/iam/iam_user_mfa.gen.rego
+101 −0 decision/aws/kms/kms_symmetric_cmk_rotation.gen.rego
+101 −0 decision/aws/logmetric/logmetric_bucket_policy_changes.gen.rego
+101 −0 decision/aws/logmetric/logmetric_cloudtrail_changes.gen.rego
+101 −0 decision/aws/logmetric/logmetric_cmk_changes.gen.rego
+101 −0 decision/aws/logmetric/logmetric_config_changes.gen.rego
+101 −0 decision/aws/logmetric/logmetric_console_auth_failure.gen.rego
+101 −0 decision/aws/logmetric/logmetric_console_root_user_usage.gen.rego
+101 −0 decision/aws/logmetric/logmetric_console_signin_mfa.gen.rego
+101 −0 decision/aws/logmetric/logmetric_iam_policy_changes.gen.rego
+101 −0 decision/aws/logmetric/logmetric_nacl_changes.gen.rego
+101 −0 decision/aws/logmetric/logmetric_network_gateway_changes.gen.rego
+101 −0 decision/aws/logmetric/logmetric_organizations_changes.gen.rego
+101 −0 decision/aws/logmetric/logmetric_route_table_changes.gen.rego
+101 −0 decision/aws/logmetric/logmetric_security_group_changes.gen.rego
+101 −0 decision/aws/logmetric/logmetric_unauthorized_api_calls.gen.rego
+101 −0 decision/aws/logmetric/logmetric_vpc_changes.gen.rego
+14 −2 decision/aws/networking/networking_sg_baseline.gen.rego
+1 −1 decision/aws/networking/networking_sg_ingress_v4.gen.rego
+102 −0 decision/aws/networking/networking_vpc_flow_logging.gen.rego
+1 −1 decision/aws/rds/rds_instance_accessibility.gen.rego
+101 −0 decision/aws/s3/s3_bucket_read_trail.gen.rego
+101 −0 decision/aws/s3/s3_bucket_write_trail.gen.rego
+104 −0 decision/aws/securityhub/securityhub_usage.gen.rego
+0 −0 decision/googlecloud/appengine/appengine_http.gen.rego
+0 −0 decision/googlecloud/asset/asset_management.gen.rego
+1 −1 decision/googlecloud/bigquery/bigquery_dataset_encryption_cmek.gen.rego
+1 −1 decision/googlecloud/bigquery/bigquery_table_encryption_cmek.gen.rego
+110 −0 decision/googlecloud/compute/compute_instance_confidential_computing.gen.rego
+1 −1 decision/googlecloud/compute/compute_instance_ip_forwarding.gen.rego
+1 −1 decision/googlecloud/compute/compute_instance_serial_port.gen.rego
+1 −1 decision/googlecloud/compute/compute_instance_shielded_vm.gen.rego
+114 −0 decision/googlecloud/credential/credential_api_keys_restriction.gen.rego
+101 −0 decision/googlecloud/credential/credential_api_keys_rotation.gen.rego
+101 −0 decision/googlecloud/credential/credential_api_keys_scope.gen.rego
+101 −0 decision/googlecloud/credential/credential_api_keys_usage.gen.rego
+24 −24 decision/googlecloud/dataproc/dataproc_encryption_key.gen.rego
+104 −0 decision/googlecloud/functions/functions_environment_variables.gen.rego
+104 −0 decision/googlecloud/iam/iam_service_account_admin_separation.gen.rego
+1 −0 decision/googlecloud/iam/iam_service_account_key.gen.rego
+102 −0 decision/googlecloud/iam/iam_service_account_key_rotation.gen.rego
+104 −0 decision/googlecloud/kms/kms_admin_separation.gen.rego
+25 −25 decision/googlecloud/kms/kms_key_accessibility.gen.rego
+30 −24 decision/googlecloud/kms/kms_key_rotation.gen.rego
+0 −0 decision/googlecloud/logging/logging_api_audit.gen.rego
+107 −0 decision/googlecloud/logging/logging_bucket_retention_policy.gen.rego
+25 −25 decision/googlecloud/logging/logging_full_export.gen.rego
+101 −0 decision/googlecloud/logmetric/logmetric_audit_config_changes.gen.rego
+101 −0 decision/googlecloud/logmetric/logmetric_custom_role_changes.gen.rego
+101 −0 decision/googlecloud/logmetric/logmetric_firewall_rule_changes.gen.rego
+101 −0 decision/googlecloud/logmetric/logmetric_network_route_changes.gen.rego
+101 −0 decision/googlecloud/logmetric/logmetric_project_ownership_changes.gen.rego
+24 −24 decision/googlecloud/logmetric/logmetric_sql_config_changes.gen.rego
+101 −0 decision/googlecloud/logmetric/logmetric_storage_iam_changes.gen.rego
+101 −0 decision/googlecloud/logmetric/logmetric_vpc_network_changes.gen.rego
+2 −1 decision/googlecloud/networking/networking_dns_log.gen.rego
+101 −0 decision/googlecloud/networking/networking_fw_rule_iap.gen.rego
+27 −24 decision/googlecloud/networking/networking_legacy_network.gen.rego
+1 −0 decision/googlecloud/networking/networking_ssh_access.gen.rego
+1 −0 decision/googlecloud/networking/networking_vpc_flow_log.gen.rego
+1 −1 decision/googlecloud/sql/sql_instance_accessibility.gen.rego
+101 −0 decision/googlecloud/sql/sql_instance_mysql_local_infile.gen.rego
+101 −0 decision/googlecloud/sql/sql_instance_mysql_show_database.gen.rego
+101 −0 decision/googlecloud/sql/sql_instance_postgresql_centralized_logging.gen.rego
+101 −0 decision/googlecloud/sql/sql_instance_postgresql_log_connections.gen.rego
+101 −0 decision/googlecloud/sql/sql_instance_postgresql_log_disconnections.gen.rego
+101 −0 decision/googlecloud/sql/sql_instance_postgresql_log_error_verbosity.gen.rego
+101 −0 decision/googlecloud/sql/sql_instance_postgresql_log_hostname.gen.rego
+101 −0 decision/googlecloud/sql/sql_instance_postgresql_log_min_duration_statement.gen.rego
+101 −0 decision/googlecloud/sql/sql_instance_postgresql_log_min_error_statement.gen.rego
+101 −0 decision/googlecloud/sql/sql_instance_postgresql_log_min_messages.gen.rego
+101 −0 decision/googlecloud/sql/sql_instance_postgresql_log_statement.gen.rego
+101 −0 decision/googlecloud/sql/sql_instance_sqlserver_3625_trace_flag.gen.rego
+101 −0 decision/googlecloud/sql/sql_instance_sqlserver_contained_db_authentication.gen.rego
+101 −0 decision/googlecloud/sql/sql_instance_sqlserver_cross_db_ownership_chaining.gen.rego
+101 −0 decision/googlecloud/sql/sql_instance_sqlserver_external_scripts.gen.rego
+101 −0 decision/googlecloud/sql/sql_instance_sqlserver_remote_access.gen.rego
+101 −0 decision/googlecloud/sql/sql_instance_sqlserver_user_connections.gen.rego
+101 −0 decision/googlecloud/sql/sql_instance_sqlserver_user_options.gen.rego
+64 −0 thirdparty/aws/region.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
aws {
accounts {
cloudTrail {
trails {
metadata {
id
displayName
}
cloudWatchLogGroup {
arn
}
status {
latestCloudWatchLogsDeliveredAt
}

tags {
key
value
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package policy.aws.cloudtrail.cloudwatch_logs_integration

import data.shisho

# this policy checks if the CloudWatch has not logged within the last 1 day
# please adjust the `must_alert_if_not_log_for` variable depending on your needs
must_alert_if_not_log_for := 1

decisions[d] {
account := input.aws.accounts[_]
trail := account.cloudTrail.trails[_]

allowed := has_logs_within_recent_days(trail)
d := shisho.decision.aws.cloudtrail.cloudwatch_logs_integration({
"allowed": allow_if_excluded(allowed, trail),
"subject": trail.metadata.id,
"payload": shisho.decision.aws.cloudtrail.cloudwatch_logs_integration_payload({"integrated": allowed}),
})
}

has_logs_within_recent_days(trail) {
trail.status.latestCloudWatchLogsDeliveredAt == null
} else {
# There is a log group associated with the trail
trail.cloudWatchLogGroup.arn != ""

# The log delivery is still active within the specified days
lat := timestamp_ns(trail.status.latestCloudWatchLogsDeliveredAt)
logged_within_recent_days(lat, must_alert_if_not_log_for)
} else = false

timestamp_ns(t) := 0 {
t == null
} else := time.parse_rfc3339_ns(t)

logged_within_recent_days(ts, d) {
now := time.now_ns()
diff_ns := now - ts

# confirm the difference is less than `d` days
diff_ns < (((1000000000 * 60) * 60) * 24) * d
} else = false

allow_if_excluded(allowed, r) {
data.params != null

tag := data.params.tag_exceptions[_]
elements := split(tag, "=")

tag_key := elements[0]
tag_value := concat("=", array.slice(elements, 1, count(elements)))

t := r.tags[_]
t.key == tag_key
t.value == tag_value
} else := allowed
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package policy.aws.cloudtrail.cloudwatch_logs_integration

import data.shisho
import future.keywords

now_ns := time.now_ns()

today_string := date_string(now_ns)

two_months_ago_string := date_string(time.add_date(now_ns, 0, -2, 0))

date_string(date_ns) := date_as_string if {
date := time.date(date_ns)
date_as_string := sprintf("%d-%s-%sT00:00:00Z", [date[0], format_digit(date[1]), format_digit(date[2])])
}

format_digit(digit) = formatted_digit if {
digit < 10
formatted_digit := sprintf("0%d", [digit])
} else = sprintf("%d", [digit])

test_whether_cloudtrail_is_integrated_with_cloudwatch_logs if {
# check if the CloudTrail is integrated with CloudWatch logs
count([d |
decisions[d]
shisho.decision.is_allowed(d)
]) == 2 with input as {"aws": {"accounts": [{"cloudTrail": {"trails": [
{
"metadata": {
"id": "aws-cloudtrail-trail|ap-northeast-1|test-trail-1",
"displayName": "test-trail-1",
},
"cloudWatchLogGroup": {"arn": "arn:aws:logs:ap-northeast-1:779392177777:log-group:test-trail-1/CloudTrailLogs:*"},
"status": {"latestCloudWatchLogsDeliveredAt": null},
},
{
"metadata": {
"id": "aws-cloudtrail-trail|ap-northeast-1|test-trail-2",
"displayName": "test-trail-2",
},
"cloudWatchLogGroup": {"arn": "arn:aws:logs:ap-northeast-1:779392177777:log-group:test-trail-2/CloudTrailLogs:*"},
"status": {"latestCloudWatchLogsDeliveredAt": today_string},
},
]}}]}}

# check if the CloudTrail is not integrated with CloudWatch logs
count([d |
decisions[d]
not shisho.decision.is_allowed(d)
]) == 3 with input as {"aws": {"accounts": [{"cloudTrail": {"trails": [
{
"metadata": {
"id": "aws-cloudtrail-trail|ap-northeast-1|test-trail-1",
"displayName": "test-trail-1",
},
"cloudWatchLogGroup": {"arn": "arn:aws:logs:ap-northeast-1:779392177777:log-group:test-trail-1/CloudTrailLogs:*"},
"status": {"latestCloudWatchLogsDeliveredAt": ""},
},
{
"metadata": {
"id": "aws-cloudtrail-trail|ap-northeast-1|test-trail-2",
"displayName": "test-trail-2",
},
"cloudWatchLogGroup": {"arn": "arn:aws:logs:ap-northeast-1:779392177777:log-group:test-trail-2/CloudTrailLogs:*"},
"status": {"latestCloudWatchLogsDeliveredAt": two_months_ago_string},
},
{
"metadata": {
"id": "aws-cloudtrail-trail|ap-northeast-1|test-trail-3",
"displayName": "test-trail-3",
},
"cloudWatchLogGroup": {"arn": ""},
"status": {"latestCloudWatchLogsDeliveredAt": today_string},
},
]}}]}}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
aws {
accounts {
cloudTrail {
trails {
metadata {
id
displayName
}
kmsKeyId

tags {
key
value
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package policy.aws.cloudtrail.cmk_encryption

import data.shisho

decisions[d] {
account := input.aws.accounts[_]
trail := account.cloudTrail.trails[_]

d := shisho.decision.aws.cloudtrail.cmk_encryption({
"allowed": allow_if_excluded(trail.kmsKeyId != "", trail),
"subject": trail.metadata.id,
"payload": shisho.decision.aws.cloudtrail.cmk_encryption_payload({"kms_key_id": trail.kmsKeyId}),
})
}

allow_if_excluded(allowed, r) {
data.params != null

tag := data.params.tag_exceptions[_]
elements := split(tag, "=")

tag_key := elements[0]
tag_value := concat("=", array.slice(elements, 1, count(elements)))

t := r.tags[_]
t.key == tag_key
t.value == tag_value
} else := allowed
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package policy.aws.cloudtrail.cmk_encryption

import data.shisho
import future.keywords

test_whether_cloudtrail_is_encrypted_by_kms_cmk if {
# check if the CloudTrail is encrypted by KMS CMK
count([d |
decisions[d]
shisho.decision.is_allowed(d)
]) == 2 with input as {"aws": {"accounts": [{"cloudTrail": {"trails": [
{
"metadata": {
"id": "aws-cloudtrail-trail|ap-northeast-1|test-trail-1",
"displayName": "test-trail-1",
},
"kmsKeyId": "arn:aws:kms:ap-northeast-1:779392177777:key/6c7079dc-390c-4724-9e29-920317477777",
},
{
"metadata": {
"id": "aws-cloudtrail-trail|ap-northeast-1|test-trail-2",
"displayName": "test-trail-2",
},
"kmsKeyId": "arn:aws:kms:ap-northeast-1:779392177777:key/6c7079dc-390c-4724-9e29-920317488888",
},
]}}]}}

# check if the CloudTrail is not encrypted by KMS CMK
count([d |
decisions[d]
not shisho.decision.is_allowed(d)
]) == 2 with input as {"aws": {"accounts": [{"cloudTrail": {"trails": [
{
"metadata": {
"id": "aws-cloudtrail-trail|ap-northeast-1|test-trail-1",
"displayName": "test-trail-1",
},
"kmsKeyId": "",
},
{
"metadata": {
"id": "aws-cloudtrail-trail|ap-northeast-1|test-trail-2",
"displayName": "test-trail-2",
},
"kmsKeyId": "",
},
]}}]}}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
aws {
accounts {
cloudTrail {
trails {
metadata {
id
displayName
}
s3Bucket {
name
aclGrants {
grantee {
displayName
uri
}
permission
}
policy {
rawDocument
}
}

tags {
key
value
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package policy.aws.cloudtrail.log_bucket_accessibility

import data.shisho

decisions[d] {
account := input.aws.accounts[_]
trail := account.cloudTrail.trails[_]

accessible := is_publicly_accessible(trail.s3Bucket)
d := shisho.decision.aws.cloudtrail.log_bucket_accessibility({
"allowed": allow_if_excluded(accessible == false, trail),
"subject": trail.metadata.id,
"payload": shisho.decision.aws.cloudtrail.log_bucket_accessibility_payload({
"bucket_name": trail.s3Bucket.name,
"acl_rules": [{
"grantee_url": grant.grantee.displayName,
"permission": grant.permission,
} |
grant := trail.s3Bucket.aclGrants[_]
],
"bucket_policy_document": trail.s3Bucket.policy.rawDocument,
}),
})
}

is_publicly_accessible(s3Bucket) {
has_insecure_acl_grants(s3Bucket.aclGrants)
} else {
has_insecure_bucket_policy(s3Bucket.policy.rawDocument)
} else = false

has_insecure_acl_grants(grants) {
grant := grants[_]
denied_uris := [
"https://acs.amazonaws.com/groups/global/AllUsers",
"https://acs.amazonaws.com/groups/global/AuthenticatedUsers",
]
denied_uris[_] == grant.grantee.uri
} else = false

has_insecure_bucket_policy(raw_document) {
p := json.unmarshal(raw_document)

statement := p.Statement[_]
statement.Effect == "Allow"
is_public_principal(statement.Principal)
} else = false

is_public_principal(principal) {
principal == "*"
} else {
principal.AWS == "*"
} else = false

allow_if_excluded(allowed, r) {
data.params != null

tag := data.params.tag_exceptions[_]
elements := split(tag, "=")

tag_key := elements[0]
tag_value := concat("=", array.slice(elements, 1, count(elements)))

t := r.tags[_]
t.key == tag_key
t.value == tag_value
} else := allowed
Loading

0 comments on commit a3f9b62

Please sign in to comment.