Skip to content

Commit bb1a8b5

Browse files
committed
fix: handle Autopilot clusters in gke checks
* fix: check only managed load balancers Signed-off-by: Nikita Pivkin <[email protected]> * rest: add test cases Signed-off-by: Nikita Pivkin <[email protected]> --------- Signed-off-by: Nikita Pivkin <[email protected]>
1 parent 58afe93 commit bb1a8b5

File tree

9 files changed

+228
-31
lines changed

9 files changed

+228
-31
lines changed

checks/cloud/google/gke/enable_auto_repair.rego

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,39 @@ package builtin.google.gke.google0063
2525
import rego.v1
2626

2727
import data.lib.cloud.metadata
28+
import data.lib.cloud.value
2829

2930
deny contains res if {
3031
some cluster in input.google.gke.clusters
3132
isManaged(cluster)
33+
autopilot_disabled(cluster)
3234
some pool in cluster.nodepools
33-
not pool.management.enableautorepair.value
35+
autorepair_is_disabled_for_pool(pool)
3436
res := result.new(
3537
"Node pool does not have auto-repair enabled.",
3638
metadata.obj_by_path(pool, ["management", "enableautorepair"]),
3739
)
3840
}
41+
42+
autorepair_is_disabled_for_pool(pool) if value.is_false(pool.management.enableautorepair)
43+
44+
autorepair_is_disabled_for_pool(pool) if not pool.management.enableautorepair
45+
46+
autopilot_disabled(cluster) if value.is_false(cluster.enableautpilot)
47+
48+
autopilot_disabled(cluster) if not cluster.enableautpilot
49+
50+
deny contains res if {
51+
some cluster in input.google.gke.clusters
52+
isManaged(cluster)
53+
cluster.enableautpilot.value
54+
autorepair_is_disabled(cluster)
55+
res := result.new(
56+
"Node pool does not have auto-repair enabled.",
57+
metadata.obj_by_path(cluster, ["autoscaling", "autoprovisioningdefaults", "management", "enableautorepair"]),
58+
)
59+
}
60+
61+
autorepair_is_disabled(cluster) if value.is_false(cluster.autoscaling.autoprovisioningdefaults.management.enableautorepair)
62+
63+
autorepair_is_disabled(cluster) if not cluster.autoscaling.autoprovisioningdefaults.management.enableautorepair

checks/cloud/google/gke/enable_auto_repair_test.rego

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,46 @@ test_deny_auto_repair_disabled if {
1111
count(res) == 1
1212
}
1313

14+
test_deny_auto_repair_disabled_for_autopilot if {
15+
inp := {"google": {"gke": {"clusters": [{
16+
"enableautpilot": {"value": true},
17+
"autoscaling": {"autoprovisioningdefaults": {"management": {"enableautorepair": {"value": false}}}},
18+
}]}}}
19+
20+
res := check.deny with input as inp
21+
count(res) == 1
22+
}
23+
24+
test_deny_auto_repair_missing_for_autopilot if {
25+
inp := {"google": {"gke": {"clusters": [{"enableautpilot": {"value": true}}]}}}
26+
27+
res := check.deny with input as inp
28+
count(res) == 1
29+
}
30+
1431
test_allow_auto_repair_enabled if {
1532
inp := {"google": {"gke": {"clusters": [{"nodepools": [{"management": {"enableautorepair": {"value": true}}}]}]}}}
1633

1734
res := check.deny with input as inp
1835
res == set()
1936
}
37+
38+
test_allow_auto_repair_enabled_for_autopilot if {
39+
inp := {"google": {"gke": {"clusters": [{
40+
"enableautpilot": {"value": true},
41+
"autoscaling": {"autoprovisioningdefaults": {"management": {"enableautorepair": {"value": true}}}},
42+
}]}}}
43+
44+
res := check.deny with input as inp
45+
res == set()
46+
}
47+
48+
test_allow_auto_repair_unresolvable_for_autopilot if {
49+
inp := {"google": {"gke": {"clusters": [{
50+
"enableautpilot": {"value": true},
51+
"autoscaling": {"autoprovisioningdefaults": {"management": {"enableautorepair": {"value": false, "unresolvable": true}}}},
52+
}]}}}
53+
54+
res := check.deny with input as inp
55+
res == set()
56+
}

checks/cloud/google/gke/enable_auto_upgrade.rego

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,39 @@ package builtin.google.gke.google0058
2525
import rego.v1
2626

2727
import data.lib.cloud.metadata
28+
import data.lib.cloud.value
2829

2930
deny contains res if {
3031
some cluster in input.google.gke.clusters
3132
isManaged(cluster)
33+
autopilot_disabled(cluster)
3234
some pool in cluster.nodepools
33-
not pool.management.enableautoupgrade.value
35+
autoupgrade_is_disabled_for_pool(pool)
3436
res := result.new(
35-
"Node pool does not have auto-upgraade enabled.",
37+
"Node pool does not have auto-repair enabled.",
3638
metadata.obj_by_path(pool, ["management", "enableautoupgrade"]),
3739
)
3840
}
41+
42+
autoupgrade_is_disabled_for_pool(pool) if value.is_false(pool.management.enableautoupgrade)
43+
44+
autoupgrade_is_disabled_for_pool(pool) if not pool.management.enableautoupgrade
45+
46+
autopilot_disabled(cluster) if value.is_false(cluster.enableautpilot)
47+
48+
autopilot_disabled(cluster) if not cluster.enableautpilot
49+
50+
deny contains res if {
51+
some cluster in input.google.gke.clusters
52+
isManaged(cluster)
53+
cluster.enableautpilot.value
54+
autoupgrade_is_disabled(cluster)
55+
res := result.new(
56+
"Node pool does not have auto-repair enabled.",
57+
metadata.obj_by_path(cluster, ["autoscaling", "autoprovisioningdefaults", "management", "enableautoupgrade"]),
58+
)
59+
}
60+
61+
autoupgrade_is_disabled(cluster) if value.is_false(cluster.autoscaling.autoprovisioningdefaults.management.enableautoupgrade)
62+
63+
autoupgrade_is_disabled(cluster) if not cluster.autoscaling.autoprovisioningdefaults.management.enableautoupgrade

checks/cloud/google/gke/enable_auto_upgrade_test.rego

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,46 @@ test_deny_auto_upgrade_disabled if {
1111
count(res) == 1
1212
}
1313

14+
test_deny_auto_repair_disabled_for_autopilot if {
15+
inp := {"google": {"gke": {"clusters": [{
16+
"enableautpilot": {"value": true},
17+
"autoscaling": {"autoprovisioningdefaults": {"management": {"enableautoupgrade": {"value": false}}}},
18+
}]}}}
19+
20+
res := check.deny with input as inp
21+
count(res) == 1
22+
}
23+
24+
test_deny_auto_repair_missing_for_autopilot if {
25+
inp := {"google": {"gke": {"clusters": [{"enableautpilot": {"value": true}}]}}}
26+
27+
res := check.deny with input as inp
28+
count(res) == 1
29+
}
30+
1431
test_allow_auto_upgrade_enabled if {
1532
inp := {"google": {"gke": {"clusters": [{"nodepools": [{"management": {"enableautoupgrade": {"value": true}}}]}]}}}
1633

1734
res := check.deny with input as inp
1835
res == set()
1936
}
37+
38+
test_allow_auto_repair_enabled_for_autopilot if {
39+
inp := {"google": {"gke": {"clusters": [{
40+
"enableautpilot": {"value": true},
41+
"autoscaling": {"autoprovisioningdefaults": {"management": {"enableautoupgrade": {"value": true}}}},
42+
}]}}}
43+
44+
res := check.deny with input as inp
45+
res == set()
46+
}
47+
48+
test_allow_auto_repair_unresolvable_for_autopilot if {
49+
inp := {"google": {"gke": {"clusters": [{
50+
"enableautpilot": {"value": true},
51+
"autoscaling": {"autoprovisioningdefaults": {"management": {"enableautoupgrade": {"value": false, "unresolvable": true}}}},
52+
}]}}}
53+
54+
res := check.deny with input as inp
55+
res == set()
56+
}

checks/cloud/google/gke/node_pool_uses_cos.rego

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@
2222
# examples: checks/cloud/google/gke/node_pool_uses_cos.yaml
2323
package builtin.google.gke.google0054
2424

25+
import data.lib.cloud.value
2526
import rego.v1
2627

2728
deny contains res if {
2829
some cluster in input.google.gke.clusters
2930
isManaged(cluster)
31+
autopilot_disabled(cluster)
3032
image_type := cluster.nodeconfig.imagetype
31-
not lower(image_type.value) in {"cos", "cos_containerd", ""}
33+
image_type_is_not_cos(image_type, {"cos", "cos_containerd", ""})
3234
res := result.new(
3335
"Cluster is not configuring node pools to use the COS containerd image type by default.",
3436
image_type,
@@ -38,11 +40,35 @@ deny contains res if {
3840
deny contains res if {
3941
some cluster in input.google.gke.clusters
4042
isManaged(cluster)
43+
autopilot_disabled(cluster)
4144
some pool in cluster.nodepools
4245
image_type := pool.nodeconfig.imagetype
43-
not lower(image_type.value) in {"cos", "cos_containerd"}
46+
image_type_is_not_cos(image_type, {"cos", "cos_containerd"})
4447
res := result.new(
4548
"Node pool is not using the COS containerd image type.",
4649
image_type,
4750
)
4851
}
52+
53+
autopilot_disabled(cluster) if value.is_false(cluster.enableautpilot)
54+
55+
autopilot_disabled(cluster) if not cluster.enableautpilot
56+
57+
deny contains res if {
58+
some cluster in input.google.gke.clusters
59+
isManaged(cluster)
60+
cluster.enableautpilot.value
61+
image_type := cluster.autoscaling.autoprovisioningdefaults.imagetype
62+
image_type_is_not_cos(image_type, {"cos", "cos_containerd"})
63+
res := result.new(
64+
"Node pool is not using the COS containerd image type.",
65+
image_type,
66+
)
67+
}
68+
69+
image_type_is_not_cos(image_type, _) if value.is_empty(image_type)
70+
71+
image_type_is_not_cos(image_type, allowed) if {
72+
value.is_not_empty(image_type)
73+
not lower(image_type.value) in allowed
74+
}

checks/cloud/google/gke/node_pool_uses_cos_test.rego

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ test_deny_node_pool_image_type_is_ubuntu if {
1818
count(res) == 1
1919
}
2020

21+
test_deny_autopilot_image_type_is_ubuntu if {
22+
inp := {"google": {"gke": {"clusters": [{
23+
"enableautpilot": {"value": true},
24+
"autoscaling": {"autoprovisioningdefaults": {"imagetype": {"value": "UBUNTU"}}},
25+
}]}}}
26+
27+
res := check.deny with input as inp
28+
count(res) == 1
29+
}
30+
2131
test_allow_node_config_image_type_is_cos if {
2232
inp := {"google": {"gke": {"clusters": [{"nodeconfig": {"imagetype": {"value": "COS"}}}]}}}
2333

@@ -31,3 +41,23 @@ test_allow_node_pool_image_type_is_cos if {
3141
res := check.deny with input as inp
3242
res == set()
3343
}
44+
45+
test_allow_autopilot_image_type_is_cos if {
46+
inp := {"google": {"gke": {"clusters": [{
47+
"enableautpilot": {"value": true},
48+
"autoscaling": {"autoprovisioningdefaults": {"imagetype": {"value": "COS"}}},
49+
}]}}}
50+
51+
res := check.deny with input as inp
52+
res == set()
53+
}
54+
55+
test_allow_autopilot_image_type_is_unresolvable if {
56+
inp := {"google": {"gke": {"clusters": [{
57+
"enableautpilot": {"value": true},
58+
"autoscaling": {"autoprovisioningdefaults": {"imagetype": {"value": "", "unresolvable": true}}},
59+
}]}}}
60+
61+
res := check.deny with input as inp
62+
res == set()
63+
}

checks/cloud/google/gke/use_service_account.rego

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import data.lib.cloud.value
3232
deny contains res if {
3333
some cluster in input.google.gke.clusters
3434
isManaged(cluster)
35+
autopilot_disabled(cluster)
3536
value.is_false(cluster.removedefaultnodepool)
3637
default_account_is_not_overrided(cluster.nodeconfig)
3738
res := result.new(
@@ -43,6 +44,7 @@ deny contains res if {
4344
deny contains res if {
4445
some cluster in input.google.gke.clusters
4546
isManaged(cluster)
47+
autopilot_disabled(cluster)
4648
some pool in cluster.nodepools
4749
default_account_is_not_overrided(pool.nodeconfig)
4850
res := result.new(
@@ -51,6 +53,21 @@ deny contains res if {
5153
)
5254
}
5355

56+
deny contains res if {
57+
some cluster in input.google.gke.clusters
58+
isManaged(cluster)
59+
cluster.enableautpilot.value
60+
default_account_is_not_overrided(cluster.autoscaling.autoprovisioningdefaults)
61+
res := result.new(
62+
"Cluster does not override the default service account.",
63+
metadata.obj_by_path(cluster, ["nodeconfig", "serviceaccount"]),
64+
)
65+
}
66+
67+
autopilot_disabled(cluster) if value.is_false(cluster.enableautpilot)
68+
69+
autopilot_disabled(cluster) if not cluster.enableautpilot
70+
5471
default_account_is_not_overrided(nodeconfig) if value.is_empty(nodeconfig.serviceaccount)
5572

5673
default_account_is_not_overrided(nodeconfig) if not nodeconfig.serviceaccount

go.mod

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ toolchain go1.24.0
66

77
require (
88
github.com/aquasecurity/iamgo v0.0.10
9-
github.com/aquasecurity/trivy v0.61.1-0.20250407075540-f1329c7ea1aa
10-
github.com/aws-cloudformation/rain v1.22.0
9+
github.com/aquasecurity/trivy v0.61.1-0.20250408211346-9792611b3627
10+
github.com/aws-cloudformation/rain v1.21.0
1111
github.com/docker/docker v28.0.4+incompatible
1212
github.com/hashicorp/hcl/v2 v2.23.0
1313
github.com/open-policy-agent/opa v1.3.0
@@ -16,8 +16,8 @@ require (
1616
github.com/spf13/viper v1.20.1
1717
github.com/stretchr/testify v1.10.0
1818
github.com/testcontainers/testcontainers-go v0.36.0
19-
github.com/testcontainers/testcontainers-go/modules/registry v0.36.0
20-
golang.org/x/text v0.24.0
19+
github.com/testcontainers/testcontainers-go/modules/registry v0.35.0
20+
golang.org/x/text v0.23.0
2121
gopkg.in/yaml.v3 v3.0.1
2222
mvdan.cc/sh/v3 v3.11.0
2323
)
@@ -385,15 +385,15 @@ require (
385385
go.uber.org/multierr v1.11.0 // indirect
386386
go.uber.org/zap v1.27.0 // indirect
387387
golang.org/x/crypto v0.36.0 // indirect
388-
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
388+
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect
389389
golang.org/x/mod v0.24.0 // indirect
390-
golang.org/x/net v0.38.0 // indirect
390+
golang.org/x/net v0.37.0 // indirect
391391
golang.org/x/oauth2 v0.26.0 // indirect
392-
golang.org/x/sync v0.13.0 // indirect
392+
golang.org/x/sync v0.12.0 // indirect
393393
golang.org/x/sys v0.31.0 // indirect
394394
golang.org/x/term v0.30.0 // indirect
395395
golang.org/x/time v0.11.0 // indirect
396-
golang.org/x/tools v0.31.0 // indirect
396+
golang.org/x/tools v0.29.0 // indirect
397397
golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 // indirect
398398
google.golang.org/api v0.218.0 // indirect
399399
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect

0 commit comments

Comments
 (0)