@nitra/cursor 1.11.3 → 1.11.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -3
- package/bin/n-cursor.js +40 -6
- package/package.json +2 -1
- package/rules/abie/js/applies/check.mjs +4 -4
- package/rules/abie/js/env_dns/check.mjs +1 -1
- package/rules/abie/js/firebase_hosting/check.mjs +1 -1
- package/rules/abie/js/hc_pairing/check.mjs +3 -3
- package/rules/abie/js/ua_http_route/check.mjs +3 -3
- package/rules/abie/js/ua_node_selector/check.mjs +4 -2
- package/rules/abie/policy/base_deployment_preem/target.json +1 -5
- package/rules/abie/utils/enabled.mjs +1 -1
- package/rules/abie/utils/env-dns.mjs +4 -4
- package/rules/abie/utils/http-route.mjs +5 -5
- package/rules/abie/utils/k8s-tree.mjs +23 -15
- package/rules/abie/utils/kustomization-patches.mjs +20 -20
- package/rules/abie/utils/overlay-paths.mjs +8 -8
- package/rules/abie/utils/yaml.mjs +4 -4
- package/rules/adr/adr.mdc +2 -2
- package/rules/adr/js/hooks/check.mjs +5 -5
- package/rules/docker/docker.mdc +2 -2
- package/rules/docker/js/run.mjs +3 -2
- package/rules/docker/policy/package_json/package_json.rego +1 -1
- package/rules/ga/js/lint.mjs +3 -26
- package/rules/hasura/js/internal_urls/check.mjs +1 -1
- package/rules/js-bun-redis/js/imports/check.mjs +5 -1
- package/rules/js-run/js/runtime/check.mjs +4 -1
- package/rules/k8s/js/run.mjs +3 -2
- package/rules/k8s/k8s.mdc +2 -4
- package/rules/k8s/policy/base_manifest/target.json +1 -5
- package/rules/nginx-default-tpl/js/template/check.mjs +4 -2
- package/rules/npm-module/js/package_structure/check.mjs +8 -3
- package/rules/npm-module/npm-module.mdc +3 -3
- package/rules/rego/js/applies/check.mjs +2 -2
- package/rules/rego/js/lint.mjs +4 -1
- package/rules/rego/policy/package_json/package_json.rego +5 -3
- package/rules/rego/rego.mdc +3 -3
- package/rules/style-lint/js/tooling/check.mjs +1 -1
- package/rules/style-lint/style-lint.mdc +1 -1
- package/rules/tauri/js/tooling/check.mjs +3 -1
- package/rules/text/js/formatting/check.mjs +8 -24
- package/rules/text/js/lint.mjs +34 -0
- package/rules/text/js/run-shellcheck.mjs +2 -2
- package/rules/text/js/run-v8r.mjs +2 -2
- package/rules/text/text.mdc +5 -5
- package/schemas/v8r-catalog.json +6 -0
- package/scripts/auto-skills.mjs +3 -7
- package/scripts/utils/discover-checkable-rules.mjs +4 -3
- package/scripts/utils/resolve-target-files.mjs +1 -1
- package/scripts/utils/run-lint-step.mjs +33 -0
- package/scripts/utils/run-rule.mjs +5 -3
- package/skills/abie-clean/SKILL.md +13 -11
- package/skills/adr-normalize/SKILL.md +0 -1
- package/skills/fix/SKILL.md +3 -7
- package/rules/abie/policy/base_deployment_preem/base_deployment_preem_test.rego +0 -60
- package/rules/abie/policy/clean_merged_ignore_branches/clean_merged_ignore_branches_test.rego +0 -48
- package/rules/abie/policy/health_check_policy/health_check_policy_test.rego +0 -99
- package/rules/abie/policy/http_route_base/http_route_base_test.rego +0 -64
- package/rules/bun/policy/package_json/package_json_test.rego +0 -109
- package/rules/docker/policy/lint_docker_yml/lint_docker_yml_test.rego +0 -104
- package/rules/docker/policy/package_json/package_json_test.rego +0 -42
- package/rules/graphql/policy/vscode_extensions/vscode_extensions_test.rego +0 -34
- package/rules/image-avif/policy/package_json/package_json_test.rego +0 -69
- package/rules/js-lint/policy/package_json/package_json_test.rego +0 -130
- package/rules/js-run/policy/jsconfig/jsconfig_test.rego +0 -88
- package/rules/k8s/policy/base_kustomization/base_kustomization_test.rego +0 -73
- package/rules/k8s/policy/base_manifest/base_manifest_test.rego +0 -94
- package/rules/k8s/policy/gateway/gateway_test.rego +0 -122
- package/rules/k8s/policy/hasura_configmap/hasura_configmap_test.rego +0 -49
- package/rules/k8s/policy/hasura_httproute/hasura_httproute_test.rego +0 -148
- package/rules/k8s/policy/hpa_pdb/hpa_pdb_test.rego +0 -101
- package/rules/k8s/policy/kustomization/kustomization_test.rego +0 -128
- package/rules/k8s/policy/manifest/manifest_test.rego +0 -309
- package/rules/k8s/policy/svc_hl_yaml/svc_hl_yaml_test.rego +0 -42
- package/rules/k8s/policy/svc_yaml/svc_yaml_test.rego +0 -41
- package/rules/nginx-default-tpl/policy/vscode_extensions/vscode_extensions_test.rego +0 -30
- package/rules/nginx-default-tpl/policy/vscode_settings/vscode_settings_test.rego +0 -53
- package/rules/npm-module/policy/npm_package_json/npm_package_json_test.rego +0 -81
- package/rules/rego/policy/package_json/package_json_test.rego +0 -42
- package/rules/rego/policy/vscode_extensions/vscode_extensions_test.rego +0 -34
- package/rules/rego/policy/vscode_settings/vscode_settings_test.rego +0 -55
- package/rules/style-lint/policy/vscode_extensions/vscode_extensions_test.rego +0 -39
- package/rules/style-lint/policy/vscode_settings/vscode_settings_test.rego +0 -49
- package/rules/tauri/policy/vscode_extensions/vscode_extensions_test.rego +0 -44
- package/rules/text/policy/markdownlint/markdownlint_test.rego +0 -98
- package/rules/text/policy/vscode_extensions/vscode_extensions_test.rego +0 -51
- package/rules/text/policy/vscode_settings/vscode_settings_test.rego +0 -85
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
# Тести для `k8s.base_manifest`. Запуск:
|
|
2
|
-
# conftest verify -p npm/policy/k8s/base_manifest --namespace k8s.base_manifest
|
|
3
|
-
package k8s.base_manifest_test
|
|
4
|
-
|
|
5
|
-
import rego.v1
|
|
6
|
-
|
|
7
|
-
import data.k8s.base_manifest
|
|
8
|
-
|
|
9
|
-
# ── metadata.namespace required ─────────────────────────────────────────
|
|
10
|
-
|
|
11
|
-
test_deny_namespaced_kind_without_metadata if {
|
|
12
|
-
count(base_manifest.deny) > 0 with input as {
|
|
13
|
-
"apiVersion": "v1",
|
|
14
|
-
"kind": "ConfigMap",
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
test_deny_namespaced_kind_empty_namespace if {
|
|
19
|
-
count(base_manifest.deny) > 0 with input as {
|
|
20
|
-
"apiVersion": "v1",
|
|
21
|
-
"kind": "ConfigMap",
|
|
22
|
-
"metadata": {"name": "cm", "namespace": ""},
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
test_allow_cluster_scoped_kind_without_namespace if {
|
|
27
|
-
count(base_manifest.deny) == 0 with input as {
|
|
28
|
-
"apiVersion": "v1",
|
|
29
|
-
"kind": "Namespace",
|
|
30
|
-
"metadata": {"name": "dev"},
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
test_allow_namespaced_kind_with_namespace if {
|
|
35
|
-
count(base_manifest.deny) == 0 with input as {
|
|
36
|
-
"apiVersion": "v1",
|
|
37
|
-
"kind": "ConfigMap",
|
|
38
|
-
"metadata": {"name": "cm", "namespace": "dev"},
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
# ── base canon resources ─────────────────────────────────────────────────
|
|
43
|
-
|
|
44
|
-
test_deny_deployment_cpu_not_base_canon if {
|
|
45
|
-
count(base_manifest.deny) > 0 with input as {
|
|
46
|
-
"apiVersion": "apps/v1",
|
|
47
|
-
"kind": "Deployment",
|
|
48
|
-
"metadata": {"name": "api", "namespace": "dev"},
|
|
49
|
-
"spec": {"template": {"spec": {"containers": [{
|
|
50
|
-
"name": "main",
|
|
51
|
-
"image": "x",
|
|
52
|
-
"resources": {"requests": {"cpu": "100m", "memory": "128Mi"}},
|
|
53
|
-
}]}}},
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
test_deny_deployment_memory_not_base_canon if {
|
|
58
|
-
count(base_manifest.deny) > 0 with input as {
|
|
59
|
-
"apiVersion": "apps/v1",
|
|
60
|
-
"kind": "Deployment",
|
|
61
|
-
"metadata": {"name": "api", "namespace": "dev"},
|
|
62
|
-
"spec": {"template": {"spec": {"containers": [{
|
|
63
|
-
"name": "main",
|
|
64
|
-
"image": "x",
|
|
65
|
-
"resources": {"requests": {"cpu": "0.02", "memory": "256Mi"}},
|
|
66
|
-
}]}}},
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
test_allow_deployment_with_base_canon_string if {
|
|
71
|
-
count(base_manifest.deny) == 0 with input as {
|
|
72
|
-
"apiVersion": "apps/v1",
|
|
73
|
-
"kind": "Deployment",
|
|
74
|
-
"metadata": {"name": "api", "namespace": "dev"},
|
|
75
|
-
"spec": {"template": {"spec": {"containers": [{
|
|
76
|
-
"name": "main",
|
|
77
|
-
"image": "x",
|
|
78
|
-
"resources": {"requests": {"cpu": "0.02", "memory": "128Mi"}},
|
|
79
|
-
}]}}},
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
test_allow_deployment_with_base_canon_number_cpu if {
|
|
84
|
-
count(base_manifest.deny) == 0 with input as {
|
|
85
|
-
"apiVersion": "apps/v1",
|
|
86
|
-
"kind": "Deployment",
|
|
87
|
-
"metadata": {"name": "api", "namespace": "dev"},
|
|
88
|
-
"spec": {"template": {"spec": {"containers": [{
|
|
89
|
-
"name": "main",
|
|
90
|
-
"image": "x",
|
|
91
|
-
"resources": {"requests": {"cpu": 0.02, "memory": "128mi"}},
|
|
92
|
-
}]}}},
|
|
93
|
-
}
|
|
94
|
-
}
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
# Тести для `k8s.gateway`. Запуск:
|
|
2
|
-
# conftest verify -p npm/policy/k8s/gateway --namespace k8s.gateway
|
|
3
|
-
package k8s.gateway_test
|
|
4
|
-
|
|
5
|
-
import rego.v1
|
|
6
|
-
|
|
7
|
-
import data.k8s.gateway
|
|
8
|
-
|
|
9
|
-
# ── HealthCheckPolicy ─────────────────────────────────────────────────────
|
|
10
|
-
|
|
11
|
-
test_deny_hcp_targetref_without_hl_suffix if {
|
|
12
|
-
count(gateway.deny) > 0 with input as {
|
|
13
|
-
"apiVersion": "networking.gke.io/v1",
|
|
14
|
-
"kind": "HealthCheckPolicy",
|
|
15
|
-
"metadata": {"name": "hc"},
|
|
16
|
-
"spec": {"targetRef": {
|
|
17
|
-
"group": "",
|
|
18
|
-
"kind": "Service",
|
|
19
|
-
"name": "auth",
|
|
20
|
-
}},
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
test_allow_hcp_targetref_with_hl_suffix if {
|
|
25
|
-
count(gateway.deny) == 0 with input as {
|
|
26
|
-
"apiVersion": "networking.gke.io/v1",
|
|
27
|
-
"kind": "HealthCheckPolicy",
|
|
28
|
-
"metadata": {"name": "hc"},
|
|
29
|
-
"spec": {"targetRef": {
|
|
30
|
-
"group": "",
|
|
31
|
-
"kind": "Service",
|
|
32
|
-
"name": "auth-hl",
|
|
33
|
-
}},
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
test_deny_hcp_missing_targetref if {
|
|
38
|
-
count(gateway.deny) > 0 with input as {
|
|
39
|
-
"apiVersion": "networking.gke.io/v1",
|
|
40
|
-
"kind": "HealthCheckPolicy",
|
|
41
|
-
"metadata": {"name": "hc"},
|
|
42
|
-
"spec": {},
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
# Без kind=Service у targetRef правило не діє (інші kind не оцінюємо).
|
|
47
|
-
test_allow_hcp_targetref_other_kind if {
|
|
48
|
-
count(gateway.deny) == 0 with input as {
|
|
49
|
-
"apiVersion": "networking.gke.io/v1",
|
|
50
|
-
"kind": "HealthCheckPolicy",
|
|
51
|
-
"metadata": {"name": "hc"},
|
|
52
|
-
"spec": {"targetRef": {
|
|
53
|
-
"kind": "Gateway",
|
|
54
|
-
"name": "gw",
|
|
55
|
-
}},
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
# ── HTTPRoute backendRef → Service з суфіксом `-hl` ──────────────────────
|
|
60
|
-
|
|
61
|
-
test_deny_httproute_backend_without_hl if {
|
|
62
|
-
count(gateway.deny) > 0 with input as {
|
|
63
|
-
"apiVersion": "gateway.networking.k8s.io/v1",
|
|
64
|
-
"kind": "HTTPRoute",
|
|
65
|
-
"metadata": {"name": "r", "namespace": "dev"},
|
|
66
|
-
"spec": {"rules": [{"backendRefs": [{"name": "auth", "port": 8080}]}]},
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
test_allow_httproute_backend_with_hl if {
|
|
71
|
-
count(gateway.deny) == 0 with input as {
|
|
72
|
-
"apiVersion": "gateway.networking.k8s.io/v1",
|
|
73
|
-
"kind": "HTTPRoute",
|
|
74
|
-
"metadata": {"name": "r", "namespace": "dev"},
|
|
75
|
-
"spec": {"rules": [{"backendRefs": [{"name": "auth-hl", "port": 8080}]}]},
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
# ── HTTPRoute backendRef з redundant namespace ───────────────────────────
|
|
80
|
-
|
|
81
|
-
test_deny_httproute_backend_redundant_namespace if {
|
|
82
|
-
count(gateway.deny) > 0 with input as {
|
|
83
|
-
"apiVersion": "gateway.networking.k8s.io/v1",
|
|
84
|
-
"kind": "HTTPRoute",
|
|
85
|
-
"metadata": {"name": "r", "namespace": "dev"},
|
|
86
|
-
"spec": {"rules": [{"backendRefs": [{
|
|
87
|
-
"name": "auth-hl",
|
|
88
|
-
"namespace": "dev",
|
|
89
|
-
"port": 8080,
|
|
90
|
-
}]}]},
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
test_allow_httproute_backend_different_namespace if {
|
|
95
|
-
count(gateway.deny) == 0 with input as {
|
|
96
|
-
"apiVersion": "gateway.networking.k8s.io/v1",
|
|
97
|
-
"kind": "HTTPRoute",
|
|
98
|
-
"metadata": {"name": "r", "namespace": "dev"},
|
|
99
|
-
"spec": {"rules": [{"backendRefs": [{
|
|
100
|
-
"name": "auth-hl",
|
|
101
|
-
"namespace": "other",
|
|
102
|
-
"port": 8080,
|
|
103
|
-
}]}]},
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
# Перевірка не діє на HTTPHeaderMatch (немає `port`).
|
|
108
|
-
test_allow_httproute_header_match_without_port if {
|
|
109
|
-
count(gateway.deny) == 0 with input as {
|
|
110
|
-
"apiVersion": "gateway.networking.k8s.io/v1",
|
|
111
|
-
"kind": "HTTPRoute",
|
|
112
|
-
"metadata": {"name": "r", "namespace": "dev"},
|
|
113
|
-
"spec": {"rules": [{
|
|
114
|
-
"matches": [{"headers": [{
|
|
115
|
-
"type": "Exact",
|
|
116
|
-
"name": "X-Tenant",
|
|
117
|
-
"value": "acme",
|
|
118
|
-
}]}],
|
|
119
|
-
"backendRefs": [{"name": "auth-hl", "port": 8080}],
|
|
120
|
-
}]},
|
|
121
|
-
}
|
|
122
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# Тести для `k8s.hasura_configmap`. Запуск:
|
|
2
|
-
# conftest verify -p npm/policy/k8s/hasura_configmap --namespace k8s.hasura_configmap
|
|
3
|
-
package k8s.hasura_configmap_test
|
|
4
|
-
|
|
5
|
-
import rego.v1
|
|
6
|
-
|
|
7
|
-
import data.k8s.hasura_configmap
|
|
8
|
-
|
|
9
|
-
required_key := "HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS"
|
|
10
|
-
|
|
11
|
-
base_cm := {
|
|
12
|
-
"apiVersion": "v1",
|
|
13
|
-
"kind": "ConfigMap",
|
|
14
|
-
"metadata": {"name": "db-h", "namespace": "dev"},
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
with_data(value) := object.union(base_cm, {"data": {required_key: value}})
|
|
18
|
-
|
|
19
|
-
test_deny_missing_data if {
|
|
20
|
-
count(hasura_configmap.deny) > 0 with input as base_cm
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
test_deny_missing_required_key if {
|
|
24
|
-
count(hasura_configmap.deny) > 0 with input as object.union(base_cm, {"data": {"OTHER": "foo"}})
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
test_deny_required_key_value_false if {
|
|
28
|
-
count(hasura_configmap.deny) > 0 with input as with_data("false")
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
test_allow_required_key_string_true if {
|
|
32
|
-
count(hasura_configmap.deny) == 0 with input as with_data("true")
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
test_allow_required_key_boolean_true if {
|
|
36
|
-
count(hasura_configmap.deny) == 0 with input as with_data(true)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
test_allow_required_key_uppercase_true if {
|
|
40
|
-
count(hasura_configmap.deny) == 0 with input as with_data("TRUE")
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
test_allow_non_configmap if {
|
|
44
|
-
count(hasura_configmap.deny) == 0 with input as {
|
|
45
|
-
"apiVersion": "apps/v1",
|
|
46
|
-
"kind": "Deployment",
|
|
47
|
-
"metadata": {"name": "x"},
|
|
48
|
-
}
|
|
49
|
-
}
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
# Тести для `k8s.hasura_httproute`. Запуск:
|
|
2
|
-
# conftest verify -p npm/policy/k8s/hasura_httproute --namespace k8s.hasura_httproute
|
|
3
|
-
package k8s.hasura_httproute_test
|
|
4
|
-
|
|
5
|
-
import rego.v1
|
|
6
|
-
|
|
7
|
-
import data.k8s.hasura_httproute
|
|
8
|
-
|
|
9
|
-
base_route := {
|
|
10
|
-
"apiVersion": "gateway.networking.k8s.io/v1",
|
|
11
|
-
"kind": "HTTPRoute",
|
|
12
|
-
"metadata": {"name": "db-h", "namespace": "dev"},
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
rule1(prefix) := {
|
|
16
|
-
"matches": [{"path": {"type": "Exact", "value": sprintf("%s/ql", [prefix])}}],
|
|
17
|
-
"filters": [{
|
|
18
|
-
"type": "RequestRedirect",
|
|
19
|
-
"requestRedirect": {
|
|
20
|
-
"path": {"type": "ReplaceFullPath", "replaceFullPath": sprintf("%s/ql/console", [prefix])},
|
|
21
|
-
"statusCode": 302,
|
|
22
|
-
},
|
|
23
|
-
}],
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
rule2(prefix) := {
|
|
27
|
-
"matches": [{"path": {"type": "Exact", "value": sprintf("%s/ql/", [prefix])}}],
|
|
28
|
-
"filters": [{
|
|
29
|
-
"type": "RequestRedirect",
|
|
30
|
-
"requestRedirect": {
|
|
31
|
-
"path": {"type": "ReplaceFullPath", "replaceFullPath": sprintf("%s/ql/console", [prefix])},
|
|
32
|
-
"statusCode": 302,
|
|
33
|
-
},
|
|
34
|
-
}],
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
rule3(prefix, backend) := {
|
|
38
|
-
"matches": [{"path": {"type": "PathPrefix", "value": sprintf("%s/ql", [prefix])}}],
|
|
39
|
-
"filters": [{
|
|
40
|
-
"type": "URLRewrite",
|
|
41
|
-
"urlRewrite": {"path": {"type": "ReplacePrefixMatch", "replacePrefixMatch": "/"}},
|
|
42
|
-
}],
|
|
43
|
-
"backendRefs": [{"name": backend, "port": 8080}],
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
rule4(prefix, backend) := {
|
|
47
|
-
"matches": [{
|
|
48
|
-
"path": {"type": "PathPrefix", "value": sprintf("%s/ql", [prefix])},
|
|
49
|
-
"headers": [{"type": "Exact", "name": "Upgrade", "value": "websocket"}],
|
|
50
|
-
}],
|
|
51
|
-
"filters": [
|
|
52
|
-
{
|
|
53
|
-
"type": "URLRewrite",
|
|
54
|
-
"urlRewrite": {"path": {"type": "ReplacePrefixMatch", "replacePrefixMatch": "/"}},
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
"type": "RequestHeaderModifier",
|
|
58
|
-
"requestHeaderModifier": {"remove": ["Authorization"]},
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
"backendRefs": [{"name": backend, "port": 8080}],
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
# ── canonical positive case ─────────────────────────────────────────────
|
|
65
|
-
|
|
66
|
-
test_allow_canonical_route_empty_prefix if {
|
|
67
|
-
count(hasura_httproute.deny) == 0 with input as object.union(base_route, {"spec": {"rules": [
|
|
68
|
-
rule1(""),
|
|
69
|
-
rule2(""),
|
|
70
|
-
rule3("", "db-h-hl"),
|
|
71
|
-
rule4("", "db-h-hl"),
|
|
72
|
-
]}})
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
test_allow_canonical_route_with_prefix if {
|
|
76
|
-
count(hasura_httproute.deny) == 0 with input as object.union(base_route, {"spec": {"rules": [
|
|
77
|
-
rule1("/notify"),
|
|
78
|
-
rule2("/notify"),
|
|
79
|
-
rule3("/notify", "db-h-hl"),
|
|
80
|
-
rule4("/notify", "db-h-hl"),
|
|
81
|
-
]}})
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
# ── deny-кейси ───────────────────────────────────────────────────────────
|
|
85
|
-
|
|
86
|
-
test_deny_missing_spec if {
|
|
87
|
-
count(hasura_httproute.deny) > 0 with input as base_route
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
test_deny_empty_rules if {
|
|
91
|
-
count(hasura_httproute.deny) > 0 with input as object.union(base_route, {"spec": {"rules": []}})
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
test_deny_missing_rule1 if {
|
|
95
|
-
count(hasura_httproute.deny) > 0 with input as object.union(base_route, {"spec": {"rules": [{
|
|
96
|
-
"matches": [{"path": {"type": "PathPrefix", "value": "/api"}}],
|
|
97
|
-
"backendRefs": [{"name": "api-hl", "port": 8080}],
|
|
98
|
-
}]}})
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
test_deny_rule1_wrong_redirect if {
|
|
102
|
-
bad_rule1 := object.union(rule1(""), {"filters": [{
|
|
103
|
-
"type": "RequestRedirect",
|
|
104
|
-
"requestRedirect": {
|
|
105
|
-
"path": {"type": "ReplaceFullPath", "replaceFullPath": "/wrong"},
|
|
106
|
-
"statusCode": 302,
|
|
107
|
-
},
|
|
108
|
-
}]})
|
|
109
|
-
count(hasura_httproute.deny) > 0 with input as object.union(base_route, {"spec": {"rules": [
|
|
110
|
-
bad_rule1,
|
|
111
|
-
rule2(""),
|
|
112
|
-
rule3("", "db-h-hl"),
|
|
113
|
-
rule4("", "db-h-hl"),
|
|
114
|
-
]}})
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
test_deny_rule2_missing if {
|
|
118
|
-
count(hasura_httproute.deny) > 0 with input as object.union(base_route, {"spec": {"rules": [
|
|
119
|
-
rule1(""),
|
|
120
|
-
rule3("", "db-h-hl"),
|
|
121
|
-
rule4("", "db-h-hl"),
|
|
122
|
-
]}})
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
test_deny_rule3_missing if {
|
|
126
|
-
count(hasura_httproute.deny) > 0 with input as object.union(base_route, {"spec": {"rules": [
|
|
127
|
-
rule1(""),
|
|
128
|
-
rule2(""),
|
|
129
|
-
rule4("", "db-h-hl"),
|
|
130
|
-
]}})
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
test_deny_rule4_missing if {
|
|
134
|
-
count(hasura_httproute.deny) > 0 with input as object.union(base_route, {"spec": {"rules": [
|
|
135
|
-
rule1(""),
|
|
136
|
-
rule2(""),
|
|
137
|
-
rule3("", "db-h-hl"),
|
|
138
|
-
]}})
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
test_deny_rule4_wrong_backend if {
|
|
142
|
-
count(hasura_httproute.deny) > 0 with input as object.union(base_route, {"spec": {"rules": [
|
|
143
|
-
rule1(""),
|
|
144
|
-
rule2(""),
|
|
145
|
-
rule3("", "db-h-hl"),
|
|
146
|
-
rule4("", "other-hl"),
|
|
147
|
-
]}})
|
|
148
|
-
}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
# Тести для `k8s.hpa_pdb`. Запуск:
|
|
2
|
-
# conftest verify -p npm/policy/k8s/hpa_pdb --namespace k8s.hpa_pdb
|
|
3
|
-
package k8s.hpa_pdb_test
|
|
4
|
-
|
|
5
|
-
import rego.v1
|
|
6
|
-
|
|
7
|
-
import data.k8s.hpa_pdb
|
|
8
|
-
|
|
9
|
-
valid_hpa := {
|
|
10
|
-
"apiVersion": "autoscaling/v2",
|
|
11
|
-
"kind": "HorizontalPodAutoscaler",
|
|
12
|
-
"metadata": {"name": "api"},
|
|
13
|
-
"spec": {
|
|
14
|
-
"scaleTargetRef": {"apiVersion": "apps/v1", "kind": "Deployment", "name": "api"},
|
|
15
|
-
"minReplicas": 1,
|
|
16
|
-
"maxReplicas": 1,
|
|
17
|
-
"metrics": [{
|
|
18
|
-
"type": "Resource",
|
|
19
|
-
"resource": {"name": "cpu", "target": {"type": "Utilization", "averageUtilization": 75}},
|
|
20
|
-
}],
|
|
21
|
-
"behavior": {
|
|
22
|
-
"scaleUp": {"policies": [{"type": "Pods", "value": 1, "periodSeconds": 60}]},
|
|
23
|
-
"scaleDown": {"policies": [{"type": "Pods", "value": 1, "periodSeconds": 60}]},
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
valid_pdb := {
|
|
29
|
-
"apiVersion": "policy/v1",
|
|
30
|
-
"kind": "PodDisruptionBudget",
|
|
31
|
-
"metadata": {"name": "api"},
|
|
32
|
-
"spec": {
|
|
33
|
-
"minAvailable": 1,
|
|
34
|
-
"selector": {"matchLabels": {"app": "api"}},
|
|
35
|
-
},
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
# ── HPA позитив / негатив ────────────────────────────────────────────────
|
|
39
|
-
|
|
40
|
-
test_allow_valid_hpa if {
|
|
41
|
-
count(hpa_pdb.deny) == 0 with input as valid_hpa
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
test_deny_hpa_v1 if {
|
|
45
|
-
count(hpa_pdb.deny) > 0 with input as object.union(valid_hpa, {"apiVersion": "autoscaling/v1"})
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
test_deny_hpa_missing_metrics if {
|
|
49
|
-
bad := json.patch(valid_hpa, [{"op": "remove", "path": "/spec/metrics"}])
|
|
50
|
-
count(hpa_pdb.deny) > 0 with input as bad
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
test_deny_hpa_empty_metrics if {
|
|
54
|
-
bad := json.patch(valid_hpa, [{"op": "replace", "path": "/spec/metrics", "value": []}])
|
|
55
|
-
count(hpa_pdb.deny) > 0 with input as bad
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
test_deny_hpa_missing_behavior if {
|
|
59
|
-
bad := json.patch(valid_hpa, [{"op": "remove", "path": "/spec/behavior"}])
|
|
60
|
-
count(hpa_pdb.deny) > 0 with input as bad
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
test_deny_hpa_empty_scale_up_policies if {
|
|
64
|
-
bad := json.patch(valid_hpa, [{"op": "replace", "path": "/spec/behavior/scaleUp/policies", "value": []}])
|
|
65
|
-
count(hpa_pdb.deny) > 0 with input as bad
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
test_deny_hpa_missing_scale_down if {
|
|
69
|
-
bad := json.patch(valid_hpa, [{"op": "remove", "path": "/spec/behavior/scaleDown"}])
|
|
70
|
-
count(hpa_pdb.deny) > 0 with input as bad
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
# ── PDB позитив / негатив ────────────────────────────────────────────────
|
|
74
|
-
|
|
75
|
-
test_allow_valid_pdb if {
|
|
76
|
-
count(hpa_pdb.deny) == 0 with input as valid_pdb
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
test_deny_pdb_wrong_api_version if {
|
|
80
|
-
bad := object.union(valid_pdb, {"apiVersion": "policy/v1beta1"})
|
|
81
|
-
count(hpa_pdb.deny) > 0 with input as bad
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
test_deny_pdb_missing_selector if {
|
|
85
|
-
bad := json.patch(valid_pdb, [{"op": "remove", "path": "/spec/selector"}])
|
|
86
|
-
count(hpa_pdb.deny) > 0 with input as bad
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
test_deny_pdb_missing_match_labels if {
|
|
90
|
-
bad := json.patch(valid_pdb, [{"op": "replace", "path": "/spec/selector", "value": {}}])
|
|
91
|
-
count(hpa_pdb.deny) > 0 with input as bad
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
# Не той kind/apiVersion — пакет не діє.
|
|
95
|
-
test_allow_unrelated_manifest if {
|
|
96
|
-
count(hpa_pdb.deny) == 0 with input as {
|
|
97
|
-
"apiVersion": "v1",
|
|
98
|
-
"kind": "ConfigMap",
|
|
99
|
-
"metadata": {"name": "x"},
|
|
100
|
-
}
|
|
101
|
-
}
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
# Тести для `k8s.kustomization`. Запуск:
|
|
2
|
-
# conftest verify -p npm/policy/k8s/kustomization --namespace k8s.kustomization
|
|
3
|
-
package k8s.kustomization_test
|
|
4
|
-
|
|
5
|
-
import rego.v1
|
|
6
|
-
|
|
7
|
-
import data.k8s.kustomization
|
|
8
|
-
|
|
9
|
-
base_kust := {
|
|
10
|
-
"apiVersion": "kustomize.config.k8s.io/v1beta1",
|
|
11
|
-
"kind": "Kustomization",
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
# ── resources sort ───────────────────────────────────────────────────────
|
|
15
|
-
|
|
16
|
-
test_deny_resources_unsorted if {
|
|
17
|
-
count(kustomization.deny) > 0 with input as object.union(base_kust, {"resources": [
|
|
18
|
-
"deployment.yaml",
|
|
19
|
-
"configmap.yaml",
|
|
20
|
-
]})
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
test_allow_resources_sorted if {
|
|
24
|
-
count(kustomization.deny) == 0 with input as object.union(base_kust, {"resources": [
|
|
25
|
-
"configmap.yaml",
|
|
26
|
-
"deployment.yaml",
|
|
27
|
-
]})
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
test_allow_resources_case_insensitive_sorted if {
|
|
31
|
-
count(kustomization.deny) == 0 with input as object.union(base_kust, {"resources": [
|
|
32
|
-
"AAA.yaml",
|
|
33
|
-
"bbb.yaml",
|
|
34
|
-
"CCC.yaml",
|
|
35
|
-
]})
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
test_deny_resources_not_array if {
|
|
39
|
-
count(kustomization.deny) > 0 with input as object.union(base_kust, {"resources": "string-not-array"})
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
test_deny_resources_item_not_string if {
|
|
43
|
-
count(kustomization.deny) > 0 with input as object.union(base_kust, {"resources": [
|
|
44
|
-
"a.yaml",
|
|
45
|
-
{"obj": "not allowed"},
|
|
46
|
-
]})
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
# ── patches sort ─────────────────────────────────────────────────────────
|
|
50
|
-
|
|
51
|
-
test_deny_patches_unsorted_by_kind_name if {
|
|
52
|
-
count(kustomization.deny) > 0 with input as object.union(base_kust, {"patches": [
|
|
53
|
-
{"target": {"kind": "Deployment", "name": "z"}},
|
|
54
|
-
{"target": {"kind": "Deployment", "name": "a"}},
|
|
55
|
-
]})
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
test_allow_patches_sorted_by_kind_name if {
|
|
59
|
-
count(kustomization.deny) == 0 with input as object.union(base_kust, {"patches": [
|
|
60
|
-
{"target": {"kind": "Deployment", "name": "a"}},
|
|
61
|
-
{"target": {"kind": "Deployment", "name": "z"}},
|
|
62
|
-
]})
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
test_deny_patches_not_array if {
|
|
66
|
-
count(kustomization.deny) > 0 with input as object.union(base_kust, {"patches": "string-not-array"})
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
# ── JSON6902 remove+add conflict ─────────────────────────────────────────
|
|
70
|
-
|
|
71
|
-
test_deny_json6902_remove_and_add_same_path if {
|
|
72
|
-
patch_text := concat("\n", [
|
|
73
|
-
"- op: remove",
|
|
74
|
-
" path: /spec/replicas",
|
|
75
|
-
"- op: add",
|
|
76
|
-
" path: /spec/replicas",
|
|
77
|
-
" value: 3",
|
|
78
|
-
])
|
|
79
|
-
count(kustomization.deny) > 0 with input as object.union(base_kust, {"patches": [{
|
|
80
|
-
"target": {"kind": "Deployment", "name": "api"},
|
|
81
|
-
"patch": patch_text,
|
|
82
|
-
}]})
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
test_allow_json6902_replace_same_path if {
|
|
86
|
-
patch_text := concat("\n", [
|
|
87
|
-
"- op: replace",
|
|
88
|
-
" path: /spec/replicas",
|
|
89
|
-
" value: 3",
|
|
90
|
-
])
|
|
91
|
-
count(kustomization.deny) == 0 with input as object.union(base_kust, {"patches": [{
|
|
92
|
-
"target": {"kind": "Deployment", "name": "api"},
|
|
93
|
-
"patch": patch_text,
|
|
94
|
-
}]})
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
test_allow_json6902_remove_and_add_different_paths if {
|
|
98
|
-
patch_text := concat("\n", [
|
|
99
|
-
"- op: remove",
|
|
100
|
-
" path: /spec/replicas",
|
|
101
|
-
"- op: add",
|
|
102
|
-
" path: /spec/strategy",
|
|
103
|
-
" value: {}",
|
|
104
|
-
])
|
|
105
|
-
count(kustomization.deny) == 0 with input as object.union(base_kust, {"patches": [{
|
|
106
|
-
"target": {"kind": "Deployment", "name": "api"},
|
|
107
|
-
"patch": patch_text,
|
|
108
|
-
}]})
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
# Маніфест не Kustomization — правила не діють.
|
|
112
|
-
test_allow_non_kustomization if {
|
|
113
|
-
count(kustomization.deny) == 0 with input as {
|
|
114
|
-
"apiVersion": "v1",
|
|
115
|
-
"kind": "ConfigMap",
|
|
116
|
-
"metadata": {"name": "x"},
|
|
117
|
-
"data": {"key": "value"},
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
# Не той apiVersion — правила не діють.
|
|
122
|
-
test_allow_kustomization_other_api_version if {
|
|
123
|
-
count(kustomization.deny) == 0 with input as {
|
|
124
|
-
"apiVersion": "other.example.com/v1",
|
|
125
|
-
"kind": "Kustomization",
|
|
126
|
-
"resources": ["z.yaml", "a.yaml"],
|
|
127
|
-
}
|
|
128
|
-
}
|