Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion checks/cloud/google/gke/enable_auto_repair.rego
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,39 @@ package builtin.google.gke.google0063
import rego.v1

import data.lib.cloud.metadata
import data.lib.cloud.value

deny contains res if {
some cluster in input.google.gke.clusters
isManaged(cluster)
autopilot_disabled(cluster)
some pool in cluster.nodepools
not pool.management.enableautorepair.value
autorepair_is_disabled_for_pool(pool)
res := result.new(
"Node pool does not have auto-repair enabled.",
metadata.obj_by_path(pool, ["management", "enableautorepair"]),
)
}

autorepair_is_disabled_for_pool(pool) if value.is_false(pool.management.enableautorepair)

autorepair_is_disabled_for_pool(pool) if not pool.management.enableautorepair

autopilot_disabled(cluster) if value.is_false(cluster.enableautpilot)

autopilot_disabled(cluster) if not cluster.enableautpilot

deny contains res if {
some cluster in input.google.gke.clusters
isManaged(cluster)
cluster.enableautpilot.value
autorepair_is_disabled(cluster)
res := result.new(
"Node pool does not have auto-repair enabled.",
metadata.obj_by_path(cluster, ["autoscaling", "autoprovisioningdefaults", "management", "enableautorepair"]),
)
}

autorepair_is_disabled(cluster) if value.is_false(cluster.autoscaling.autoprovisioningdefaults.management.enableautorepair)

autorepair_is_disabled(cluster) if not cluster.autoscaling.autoprovisioningdefaults.management.enableautorepair
37 changes: 37 additions & 0 deletions checks/cloud/google/gke/enable_auto_repair_test.rego
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,46 @@ test_deny_auto_repair_disabled if {
count(res) == 1
}

test_deny_auto_repair_disabled_for_autopilot if {
inp := {"google": {"gke": {"clusters": [{
"enableautpilot": {"value": true},
"autoscaling": {"autoprovisioningdefaults": {"management": {"enableautorepair": {"value": false}}}},
}]}}}

res := check.deny with input as inp
count(res) == 1
}

test_deny_auto_repair_missing_for_autopilot if {
inp := {"google": {"gke": {"clusters": [{"enableautpilot": {"value": true}}]}}}

res := check.deny with input as inp
count(res) == 1
}

test_allow_auto_repair_enabled if {
inp := {"google": {"gke": {"clusters": [{"nodepools": [{"management": {"enableautorepair": {"value": true}}}]}]}}}

res := check.deny with input as inp
res == set()
}

test_allow_auto_repair_enabled_for_autopilot if {
inp := {"google": {"gke": {"clusters": [{
"enableautpilot": {"value": true},
"autoscaling": {"autoprovisioningdefaults": {"management": {"enableautorepair": {"value": true}}}},
}]}}}

res := check.deny with input as inp
res == set()
}

test_allow_auto_repair_unresolvable_for_autopilot if {
inp := {"google": {"gke": {"clusters": [{
"enableautpilot": {"value": true},
"autoscaling": {"autoprovisioningdefaults": {"management": {"enableautorepair": {"value": false, "unresolvable": true}}}},
}]}}}

res := check.deny with input as inp
res == set()
}
29 changes: 27 additions & 2 deletions checks/cloud/google/gke/enable_auto_upgrade.rego
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,39 @@ package builtin.google.gke.google0058
import rego.v1

import data.lib.cloud.metadata
import data.lib.cloud.value

deny contains res if {
some cluster in input.google.gke.clusters
isManaged(cluster)
autopilot_disabled(cluster)
some pool in cluster.nodepools
not pool.management.enableautoupgrade.value
autoupgrade_is_disabled_for_pool(pool)
res := result.new(
"Node pool does not have auto-upgraade enabled.",
"Node pool does not have auto-repair enabled.",
metadata.obj_by_path(pool, ["management", "enableautoupgrade"]),
)
}

autoupgrade_is_disabled_for_pool(pool) if value.is_false(pool.management.enableautoupgrade)

autoupgrade_is_disabled_for_pool(pool) if not pool.management.enableautoupgrade

autopilot_disabled(cluster) if value.is_false(cluster.enableautpilot)

autopilot_disabled(cluster) if not cluster.enableautpilot

deny contains res if {
some cluster in input.google.gke.clusters
isManaged(cluster)
cluster.enableautpilot.value
autoupgrade_is_disabled(cluster)
res := result.new(
"Node pool does not have auto-repair enabled.",
metadata.obj_by_path(cluster, ["autoscaling", "autoprovisioningdefaults", "management", "enableautoupgrade"]),
)
}

autoupgrade_is_disabled(cluster) if value.is_false(cluster.autoscaling.autoprovisioningdefaults.management.enableautoupgrade)

autoupgrade_is_disabled(cluster) if not cluster.autoscaling.autoprovisioningdefaults.management.enableautoupgrade
37 changes: 37 additions & 0 deletions checks/cloud/google/gke/enable_auto_upgrade_test.rego
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,46 @@ test_deny_auto_upgrade_disabled if {
count(res) == 1
}

test_deny_auto_repair_disabled_for_autopilot if {
inp := {"google": {"gke": {"clusters": [{
"enableautpilot": {"value": true},
"autoscaling": {"autoprovisioningdefaults": {"management": {"enableautoupgrade": {"value": false}}}},
}]}}}

res := check.deny with input as inp
count(res) == 1
}

test_deny_auto_repair_missing_for_autopilot if {
inp := {"google": {"gke": {"clusters": [{"enableautpilot": {"value": true}}]}}}

res := check.deny with input as inp
count(res) == 1
}

test_allow_auto_upgrade_enabled if {
inp := {"google": {"gke": {"clusters": [{"nodepools": [{"management": {"enableautoupgrade": {"value": true}}}]}]}}}

res := check.deny with input as inp
res == set()
}

test_allow_auto_repair_enabled_for_autopilot if {
inp := {"google": {"gke": {"clusters": [{
"enableautpilot": {"value": true},
"autoscaling": {"autoprovisioningdefaults": {"management": {"enableautoupgrade": {"value": true}}}},
}]}}}

res := check.deny with input as inp
res == set()
}

test_allow_auto_repair_unresolvable_for_autopilot if {
inp := {"google": {"gke": {"clusters": [{
"enableautpilot": {"value": true},
"autoscaling": {"autoprovisioningdefaults": {"management": {"enableautoupgrade": {"value": false, "unresolvable": true}}}},
}]}}}

res := check.deny with input as inp
res == set()
}
30 changes: 28 additions & 2 deletions checks/cloud/google/gke/node_pool_uses_cos.rego
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@
# examples: checks/cloud/google/gke/node_pool_uses_cos.yaml
package builtin.google.gke.google0054

import data.lib.cloud.value
import rego.v1

deny contains res if {
some cluster in input.google.gke.clusters
isManaged(cluster)
autopilot_disabled(cluster)
image_type := cluster.nodeconfig.imagetype
not lower(image_type.value) in {"cos", "cos_containerd", ""}
image_type_is_not_cos(image_type, {"cos", "cos_containerd", ""})
res := result.new(
"Cluster is not configuring node pools to use the COS containerd image type by default.",
image_type,
Expand All @@ -38,11 +40,35 @@ deny contains res if {
deny contains res if {
some cluster in input.google.gke.clusters
isManaged(cluster)
autopilot_disabled(cluster)
some pool in cluster.nodepools
image_type := pool.nodeconfig.imagetype
not lower(image_type.value) in {"cos", "cos_containerd"}
image_type_is_not_cos(image_type, {"cos", "cos_containerd"})
res := result.new(
"Node pool is not using the COS containerd image type.",
image_type,
)
}

autopilot_disabled(cluster) if value.is_false(cluster.enableautpilot)

autopilot_disabled(cluster) if not cluster.enableautpilot

deny contains res if {
some cluster in input.google.gke.clusters
isManaged(cluster)
cluster.enableautpilot.value
image_type := cluster.autoscaling.autoprovisioningdefaults.imagetype
image_type_is_not_cos(image_type, {"cos", "cos_containerd"})
res := result.new(
"Node pool is not using the COS containerd image type.",
image_type,
)
}

image_type_is_not_cos(image_type, _) if value.is_empty(image_type)

image_type_is_not_cos(image_type, allowed) if {
value.is_not_empty(image_type)
not lower(image_type.value) in allowed
}
30 changes: 30 additions & 0 deletions checks/cloud/google/gke/node_pool_uses_cos_test.rego
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ test_deny_node_pool_image_type_is_ubuntu if {
count(res) == 1
}

test_deny_autopilot_image_type_is_ubuntu if {
inp := {"google": {"gke": {"clusters": [{
"enableautpilot": {"value": true},
"autoscaling": {"autoprovisioningdefaults": {"imagetype": {"value": "UBUNTU"}}},
}]}}}

res := check.deny with input as inp
count(res) == 1
}

test_allow_node_config_image_type_is_cos if {
inp := {"google": {"gke": {"clusters": [{"nodeconfig": {"imagetype": {"value": "COS"}}}]}}}

Expand All @@ -31,3 +41,23 @@ test_allow_node_pool_image_type_is_cos if {
res := check.deny with input as inp
res == set()
}

test_allow_autopilot_image_type_is_cos if {
inp := {"google": {"gke": {"clusters": [{
"enableautpilot": {"value": true},
"autoscaling": {"autoprovisioningdefaults": {"imagetype": {"value": "COS"}}},
}]}}}

res := check.deny with input as inp
res == set()
}

test_allow_autopilot_image_type_is_unresolvable if {
inp := {"google": {"gke": {"clusters": [{
"enableautpilot": {"value": true},
"autoscaling": {"autoprovisioningdefaults": {"imagetype": {"value": "", "unresolvable": true}}},
}]}}}

res := check.deny with input as inp
res == set()
}
17 changes: 17 additions & 0 deletions checks/cloud/google/gke/use_service_account.rego
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import data.lib.cloud.value
deny contains res if {
some cluster in input.google.gke.clusters
isManaged(cluster)
autopilot_disabled(cluster)
value.is_false(cluster.removedefaultnodepool)
default_account_is_not_overrided(cluster.nodeconfig)
res := result.new(
Expand All @@ -43,6 +44,7 @@ deny contains res if {
deny contains res if {
some cluster in input.google.gke.clusters
isManaged(cluster)
autopilot_disabled(cluster)
some pool in cluster.nodepools
default_account_is_not_overrided(pool.nodeconfig)
res := result.new(
Expand All @@ -51,6 +53,21 @@ deny contains res if {
)
}

deny contains res if {
some cluster in input.google.gke.clusters
isManaged(cluster)
cluster.enableautpilot.value
default_account_is_not_overrided(cluster.autoscaling.autoprovisioningdefaults)
res := result.new(
"Cluster does not override the default service account.",
metadata.obj_by_path(cluster, ["nodeconfig", "serviceaccount"]),
)
}

autopilot_disabled(cluster) if value.is_false(cluster.enableautpilot)

autopilot_disabled(cluster) if not cluster.enableautpilot

default_account_is_not_overrided(nodeconfig) if value.is_empty(nodeconfig.serviceaccount)

default_account_is_not_overrided(nodeconfig) if not nodeconfig.serviceaccount
16 changes: 8 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ toolchain go1.24.0

require (
github.com/aquasecurity/iamgo v0.0.10
github.com/aquasecurity/trivy v0.61.1-0.20250407075540-f1329c7ea1aa
github.com/aws-cloudformation/rain v1.22.0
github.com/aquasecurity/trivy v0.61.1-0.20250408211346-9792611b3627
github.com/aws-cloudformation/rain v1.21.0
github.com/docker/docker v28.0.4+incompatible
github.com/hashicorp/hcl/v2 v2.23.0
github.com/open-policy-agent/opa v1.3.0
Expand All @@ -16,8 +16,8 @@ require (
github.com/spf13/viper v1.20.1
github.com/stretchr/testify v1.10.0
github.com/testcontainers/testcontainers-go v0.36.0
github.com/testcontainers/testcontainers-go/modules/registry v0.36.0
golang.org/x/text v0.24.0
github.com/testcontainers/testcontainers-go/modules/registry v0.35.0
golang.org/x/text v0.23.0
gopkg.in/yaml.v3 v3.0.1
mvdan.cc/sh/v3 v3.11.0
)
Expand Down Expand Up @@ -385,15 +385,15 @@ require (
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/crypto v0.36.0 // indirect
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect
golang.org/x/mod v0.24.0 // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/net v0.37.0 // indirect
golang.org/x/oauth2 v0.26.0 // indirect
golang.org/x/sync v0.13.0 // indirect
golang.org/x/sync v0.12.0 // indirect
golang.org/x/sys v0.31.0 // indirect
golang.org/x/term v0.30.0 // indirect
golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.31.0 // indirect
golang.org/x/tools v0.29.0 // indirect
golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 // indirect
google.golang.org/api v0.218.0 // indirect
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect
Expand Down
Loading