Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CLOUD-233] Rule updates #336

Merged
merged 3 commits into from Jun 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 17 additions & 12 deletions rego/lib/aws/vpc/nacl_library.rego
Expand Up @@ -43,27 +43,32 @@ ingress_for_nacl[id] = nacl_rules {
nacl_rules = nacl.ingress
}

allows_port(ingress, port) {
ingress.from_port <= port
ingress.to_port >= port
} {
ingress.from_port == 0
ingress.to_port == 0
}

# Returns true if the given cidr is all zeroes
zero_cidr(cidr) {cidr == "0.0.0.0/0"} {cidr == "::/0"}
zero_cidr(ingress) {ingress.cidr_block == "0.0.0.0/0"} {ingress.ipv6_cidr_block == "::/0"}

# Returns the list of rules for a nacl for a given port open to the world
ingress_zero_cidr_by_port(nacl, port) = ret {
ret = ingress_for_nacl[nacl.id]
zero_cidr(ret[i].cidr_block)
ret[i].from_port <= port
ret[i].to_port >= port
} {
ret = ingress_for_nacl[nacl.id]
zero_cidr(ret[i].cidr_block)
ret[i].from_port == 0
ret[i].to_port == 0
ingresses = ingress_for_nacl[nacl.id]
ret = [i |
i = ingresses[_]
zero_cidr(i)
allows_port(i, port)
]
}

# Returns the lowest ALLOW numbered rule for a nacl by port open to the world
lowest_allow_ingress_zero_cidr_by_port(nacl, port) = ret {
rules = ingress_zero_cidr_by_port(nacl, port)
rule = rules[_]
arr_rule_nos = [ rule_no |
rule = rules[_]
rule_no = rule_number(rule)
rule_action(rule) == "allow"
]
Expand All @@ -77,8 +82,8 @@ lowest_allow_ingress_zero_cidr_by_port(nacl, port) = ret {
# Returns the lowest DENY numbered rule for a nacl by port open to the world
lowest_deny_ingress_zero_cidr_by_port(nacl, port) = ret {
rules = ingress_zero_cidr_by_port(nacl, port)
rule = rules[_]
arr_rule_nos = [ rule_no |
rule = rules[_]
rule_no = rule_number(rule)
rule_action(rule) == "deny"
]
Expand Down
12 changes: 6 additions & 6 deletions rego/rules/k8s/service_account_tokens.rego
Expand Up @@ -30,32 +30,32 @@ input_type := "k8s"

resource_type := "MULTIPLE"

is_valid(template) {
template.spec.automountServiceAccountToken == false
is_valid(spec) {
spec.automountServiceAccountToken == false
}

policy[j] {
obj := k8s.resources_with_pod_templates[_]
count(obj.pod_template.spec.containers) > 0
is_valid(obj.pod_template)
is_valid(obj.pod_template.spec)
j = fugue.allow_resource(obj.resource)
}

policy[j] {
obj := k8s.resources_with_pod_templates[_]
count(obj.pod_template.spec.containers) > 0
not is_valid(obj.pod_template)
not is_valid(obj.pod_template.spec)
j = fugue.deny_resource(obj.resource)
}

policy[j] {
resource := fugue.resources("ServiceAccount")
resource := fugue.resources("ServiceAccount")[_]
is_valid(resource)
j = fugue.allow_resource(resource)
}

policy[j] {
resource := fugue.resources("ServiceAccount")
resource := fugue.resources("ServiceAccount")[_]
not is_valid(resource)
j = fugue.deny_resource(resource)
}
11 changes: 11 additions & 0 deletions rego/rules/tf/aws/cloudtrail/management_events.rego
Expand Up @@ -24,8 +24,19 @@ __rego__metadoc__ := {

resource_type := "aws_cloudtrail"

contains_element(arr, elem) = true {
arr[_] = elem
} else = false { true }

default deny = false

deny {
input.event_selector[_].include_management_events == false
}

deny {
field_selectors = [i | i := input.advanced_event_selector[_].field_selector[_]]
count(field_selectors) > 0
a = [i | i := contains_element(field_selectors[_].equals, "Management")]
not any(a)
}
11 changes: 11 additions & 0 deletions rego/rules/tf/aws/s3/block_public_access.rego
Expand Up @@ -48,6 +48,7 @@ policy[j] {

buckets = fugue.resources("aws_s3_bucket")
bucket_access_blocks = fugue.resources("aws_s3_bucket_public_access_block")
account_access_blocks = fugue.resources("aws_s3_account_public_access_block")

# Using the `bucket_access_blocks`, we construct a set of bucket IDs that have
# the public access blocked.
Expand All @@ -60,7 +61,17 @@ blocked_buckets[bucket_name] {
block.restrict_public_buckets == true
}

blocked_account {
block := account_access_blocks[_]
block.block_public_acls == true
block.ignore_public_acls == true
block.block_public_policy == true
block.restrict_public_buckets == true
}

bucket_is_blocked(bucket) {
blocked_account
} {
fugue.input_type != "tf_runtime"
blocked_buckets[bucket.id]
} {
Expand Down
35 changes: 27 additions & 8 deletions rego/rules/tf/aws/s3/encryption.rego
Expand Up @@ -13,6 +13,9 @@
# limitations under the License.
package rules.tf_aws_s3_encryption

import data.fugue
import data.aws.s3.s3_library as lib

__rego__metadoc__ := {
"custom": {
"controls": {
Expand All @@ -30,16 +33,32 @@ __rego__metadoc__ := {
"title": "S3 bucket server-side encryption should be enabled"
}

is_encrypted {
count([algorithm |
algorithm = input.server_side_encryption_configuration[_].rule[_][_][_].sse_algorithm
]) >= 1
resource_type := "MULTIPLE"

buckets := fugue.resources("aws_s3_bucket")
encryption_configs := { id: config |
# This is a design-time only resource type, so make sure it exists
fugue.input_resource_types["aws_s3_bucket_server_side_encryption_configuration"]
config := fugue.resources("aws_s3_bucket_server_side_encryption_configuration")[id]
}

is_encrypted(bucket) {
_ = bucket.server_side_encryption_configuration[_].rule[_][_][_].sse_algorithm
}

resource_type := "aws_s3_bucket"
is_encrypted(bucket) {
ec := encryption_configs[_]
lib.matches_bucket_or_id(ec.bucket, bucket)
}

default allow = false
policy[j] {
bucket := buckets[_]
is_encrypted(bucket)
j := fugue.allow_resource(bucket)
}

allow {
is_encrypted
policy[j] {
bucket := buckets[_]
not is_encrypted(bucket)
j := fugue.deny_resource(bucket)
}
9 changes: 5 additions & 4 deletions rego/tests/rules/tf/aws/s3/encryption_test.rego
Expand Up @@ -16,8 +16,9 @@ package rules.tf_aws_s3_encryption
import data.tests.rules.tf.aws.s3.inputs.bucket_sse_infra_json

test_s3_encryption {
resources = bucket_sse_infra_json.mock_resources
not allow with input as resources["aws_s3_bucket.unencrypted"]
allow with input as resources["aws_s3_bucket.aes_encrypted"]
allow with input as resources["aws_s3_bucket.kms_encrypted"]
pol = policy with input as bucket_sse_infra_json.mock_input
by_resource_id = {p.id: p.valid | pol[p]}
by_resource_id["aws_s3_bucket.unencrypted"] = false
by_resource_id["aws_s3_bucket.aes_encrypted"] = true
by_resource_id["aws_s3_bucket.kms_encrypted"] = true
}