Compare commits

..
6 Commits
Author SHA1 Message Date
renovate[bot]andlnx01 a4ca8b6c32 Update all non-major dependencies to v0.37.0 (#1237)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-03 09:51:56 -03:00
Terraform User 38d07c740a Managed by Terraform 2026-09-02 18:15:07 +00:00
dependabot[bot]andlnx01 36edfe7551 Bump nanoid from 3.3.7 to 3.3.18 in /docs (#1234)
Bumps [nanoid](https://github.com/ai/nanoid) from 3.3.7 to 3.3.18.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/3.3.18/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.3.7...3.3.18)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-version: 3.3.18
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-02 11:00:01 -03:00
5a10f509f4 Bump browserslist from 4.23.2 to 4.28.8 in /docs (#1236)
Bumps [browserslist](https://github.com/browserslist/browserslist) from 4.23.2 to 4.28.8.
- [Release notes](https://github.com/browserslist/browserslist/releases)
- [Changelog](https://github.com/browserslist/browserslist/blob/main/CHANGELOG.md)
- [Commits](https://github.com/browserslist/browserslist/compare/4.23.2...4.28.8)

---
updated-dependencies:
- dependency-name: browserslist
  dependency-version: 4.28.8
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Vitor Rodrigo Vezani <vitor.vezani@fairwinds.com>
2026-09-02 13:51:23 +00:00
ca61c42a17 Bump brace-expansion from 1.1.11 to 1.1.18 in /docs (#1223)
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 1.1.11 to 1.1.18.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/1.1.11...v1.1.18)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 1.1.18
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: jdesouza <james@fairwinds.com>
Co-authored-by: Vitor Rodrigo Vezani <vitor.vezani@fairwinds.com>
2026-09-02 10:46:15 -03:00
renovate[bot]andlnx01 d0f8e12244 Update module github.com/sirupsen/logrus to v1.10.2 (#1235)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-02 08:34:26 -03:00
42 changed files with 142 additions and 1298 deletions
-17
View File
@@ -24,15 +24,6 @@ key | default | description
`hostNetworkSet` | `warning` | Fails when `hostNetwork` attribute is configured.
`hostPortSet` | `warning` | Fails when `hostPort` attribute is configured.
`tlsSettingsMissing` | `warning` | Fails when an Ingress lacks TLS settings.
`gatewayTLSMissing` | `warning` | Fails when an HTTPS, GRPC, or terminating TLS Gateway listener lacks certificate references.
`gatewayAllowedRoutesAll` | `warning` | Fails when a Gateway listener allows Routes from every namespace.
`gatewayInsecureFrontendValidation` | `warning` | Fails when Gateway frontend client certificate validation allows insecure fallback.
`gatewayCrossNamespaceCertificateRef` | `warning` | Fails when a Gateway references a certificate in another namespace without a matching ReferenceGrant. Cluster audits only.
`httpRouteWildcardOrEmptyHost` | `warning` | Fails when an HTTPRoute omits hostnames or uses a wildcard hostname.
`httpRouteInsecureListener` | `warning` | Fails when an HTTPRoute serves application traffic over HTTP without a full HTTPS redirect. Cluster audits only.
`httpRouteCrossNamespaceBackendRef` | `warning` | Fails when an HTTPRoute references a backend in another namespace without a matching ReferenceGrant. Cluster audits only.
`httpRouteBackendTLSMissing` | `warning` | Fails when an HTTPRoute TLS backend lacks a BackendTLSPolicy or kgateway BackendConfigPolicy. Cluster audits only.
`kgatewayBackendTLSVerificationDisabled` | `warning` | Fails when a kgateway BackendConfigPolicy disables TLS certificate verification.
`sensitiveContainerEnvVar` | `danger` | Fails when the container sets potentially sensitive environment variables.
`sensitiveConfigmapContent` | `danger` | Fails when potentially sensitive content is detected in the ConfigMap keys or values.
`missingNetworkPolicy` | `warning`
@@ -49,14 +40,6 @@ key | default | description
Securing workloads in Kubernetes is an important part of overall cluster security. The overall goal should be to ensure that containers are running with as minimal privileges as possible. This includes avoiding privilege escalation, not running containers with a root user, not giving excessive access to the host network, and using read only file systems wherever possible.
### Gateway API
Gateway API separates listeners, routes, and backend TLS policy across different resources. Polaris checks standard `Gateway` and `HTTPRoute` resources for listener TLS, namespace isolation, host specificity, HTTPS redirects, cross-namespace authorization, and backend TLS. These checks work with conformant implementations such as kgateway.
`httpRouteBackendTLSMissing` also recognizes kgateway's `Backend` and `BackendConfigPolicy` resources. It identifies TLS backends from ports 443 and 8443, Service port names and `appProtocol`, and kgateway static Backend ports. `kgatewayBackendTLSVerificationDisabled` checks the kgateway-specific `insecureSkipVerify` setting. Authentication, authorization, and rate-limiting requirements are organization-specific and should be implemented as custom checks.
Checks marked "Cluster audits only" need related resources that are not available when Polaris evaluates a single admission request. They pass without a resource provider rather than rejecting an object without enough context.
A pod running with the `hostNetwork` attribute enabled will have access to the loopback device, services listening on localhost, and could be used to snoop on network activity of other pods on the same node. There are certain examples where setting `hostNetwork` to true is required, such as deploying a networking plugin like Flannel.
Setting the `hostPort` attribute on a container will ensure that it is accessible on that specific port on each node it is deployed to. Unfortunately when this is specified, it limits where a pod can actually be scheduled in a cluster.
+51 -34
View File
@@ -3860,6 +3860,19 @@
],
"license": "MIT"
},
"node_modules/baseline-browser-mapping": {
"version": "2.11.20",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.20.tgz",
"integrity": "sha512-H0ulySigv6icDJ1F7SjtdCD6PrhTpdYCmP0CactWy1+ekh0AFd0o1Wn5T8b+hnTmdBx19u9yhL6wvCylXMY7zw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"baseline-browser-mapping": "dist/cli.cjs"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/batch": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
@@ -4119,9 +4132,9 @@
}
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "1.1.18",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
"integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
@@ -4261,9 +4274,9 @@
}
},
"node_modules/browserslist": {
"version": "4.23.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz",
"integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==",
"version": "4.28.8",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz",
"integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==",
"dev": true,
"funding": [
{
@@ -4281,10 +4294,11 @@
],
"license": "MIT",
"dependencies": {
"caniuse-lite": "^1.0.30001640",
"electron-to-chromium": "^1.4.820",
"node-releases": "^2.0.14",
"update-browserslist-db": "^1.1.0"
"baseline-browser-mapping": "^2.11.12",
"caniuse-lite": "^1.0.30001809",
"electron-to-chromium": "^1.5.402",
"node-releases": "^2.0.53",
"update-browserslist-db": "^1.3.0"
},
"bin": {
"browserslist": "cli.js"
@@ -4714,9 +4728,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001642",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz",
"integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==",
"version": "1.0.30001810",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz",
"integrity": "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==",
"dev": true,
"funding": [
{
@@ -6696,9 +6710,9 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
"version": "1.4.829",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.829.tgz",
"integrity": "sha512-5qp1N2POAfW0u1qGAxXEtz6P7bO1m6gpZr5hdf5ve6lxpLM7MpiM4jIPz7xcrNlClQMafbyUDDWjlIQZ1Mw0Rw==",
"version": "1.5.420",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.420.tgz",
"integrity": "sha512-2yD6XreGusOfNV+dUcvipJEXc3n/n7fgr7996aszTG+YY5E4mqM4tOq/3uhP129cazL9YHbVWSpc79ePotWtPA==",
"dev": true,
"license": "ISC"
},
@@ -7266,9 +7280,9 @@
]
},
"node_modules/escalade": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
"integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -10773,9 +10787,9 @@
"optional": true
},
"node_modules/nanoid": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"version": "3.3.18",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
"integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
"dev": true,
"funding": [
{
@@ -10932,11 +10946,14 @@
"license": "MIT"
},
"node_modules/node-releases": {
"version": "2.0.17",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.17.tgz",
"integrity": "sha512-Ww6ZlOiEQfPfXM45v17oabk77Z7mg5bOt7AjDyzy7RjK9OrLrLC8dyZQoAPEOtFX9SaNf1Tdvr5gRJWdTJj7GA==",
"version": "2.0.54",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.54.tgz",
"integrity": "sha512-YHs7BmmcsdAI5Ozuf8JZo6PT0mv2GIWC9vMfvUC3dp65M8hn7Ux8CPL+2oBI7juNuj9d0ndhTcznq2ODBps9cQ==",
"dev": true,
"license": "MIT"
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/nopt": {
"version": "1.0.10",
@@ -11611,9 +11628,9 @@
"license": "MIT"
},
"node_modules/picocolors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
"integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true,
"license": "ISC"
},
@@ -16281,9 +16298,9 @@
}
},
"node_modules/update-browserslist-db": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
"integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.2.tgz",
"integrity": "sha512-UQ+MSxlhRm1bzjhU+DcuXfjFO1FzNtqhK5+9Yvlp90ItDLk5vT932A0rFu619nf7RVS+Y/VeaUW1jaRDqZ8VJw==",
"dev": true,
"funding": [
{
@@ -16301,8 +16318,8 @@
],
"license": "MIT",
"dependencies": {
"escalade": "^3.1.2",
"picocolors": "^1.0.1"
"escalade": "^3.2.0",
"picocolors": "^1.1.1"
},
"bin": {
"update-browserslist-db": "cli.js"
+26 -27
View File
@@ -9,15 +9,15 @@ require (
github.com/pkg/errors v0.9.1
github.com/qri-io/jsonpointer v0.1.1
github.com/qri-io/jsonschema v0.2.1
github.com/sirupsen/logrus v1.10.1
github.com/sirupsen/logrus v1.10.2
github.com/spf13/cobra v1.10.2
github.com/stretchr/testify v1.12.1
github.com/thoas/go-funk v0.9.3
gomodules.xyz/jsonpatch/v2 v2.5.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.36.4
k8s.io/apimachinery v0.36.4
k8s.io/client-go v0.36.4
k8s.io/api v0.37.0
k8s.io/apimachinery v0.37.0
k8s.io/client-go v0.37.0
sigs.k8s.io/controller-runtime v0.24.1
sigs.k8s.io/yaml v1.6.0
)
@@ -30,28 +30,27 @@ require (
github.com/evanphx/json-patch v5.9.0+incompatible // indirect
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.1 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.22.5 // indirect
github.com/go-openapi/jsonreference v0.21.5 // indirect
github.com/go-openapi/swag v0.25.5 // indirect
github.com/go-openapi/swag/cmdutils v0.25.5 // indirect
github.com/go-openapi/swag/conv v0.25.5 // indirect
github.com/go-openapi/swag/fileutils v0.25.5 // indirect
github.com/go-openapi/swag/jsonname v0.25.5 // indirect
github.com/go-openapi/swag/jsonutils v0.25.5 // indirect
github.com/go-openapi/swag/loading v0.25.5 // indirect
github.com/go-openapi/swag/mangling v0.25.5 // indirect
github.com/go-openapi/swag/netutils v0.25.5 // indirect
github.com/go-openapi/swag/stringutils v0.25.5 // indirect
github.com/go-openapi/swag/typeutils v0.25.5 // indirect
github.com/go-openapi/swag/yamlutils v0.25.5 // indirect
github.com/go-openapi/jsonpointer v1.0.0 // indirect
github.com/go-openapi/jsonreference v1.0.0 // indirect
github.com/go-openapi/swag v0.27.1 // indirect
github.com/go-openapi/swag/cmdutils v0.27.1 // indirect
github.com/go-openapi/swag/conv v0.27.1 // indirect
github.com/go-openapi/swag/fileutils v0.27.1 // indirect
github.com/go-openapi/swag/jsonutils v0.27.1 // indirect
github.com/go-openapi/swag/loading v0.27.1 // indirect
github.com/go-openapi/swag/mangling v0.27.1 // indirect
github.com/go-openapi/swag/netutils v0.27.1 // indirect
github.com/go-openapi/swag/pools v0.27.1 // indirect
github.com/go-openapi/swag/stringutils v0.27.1 // indirect
github.com/go-openapi/swag/typeutils v0.27.1 // indirect
github.com/go-openapi/swag/yamlutils v0.27.1 // indirect
github.com/google/gnostic-models v0.7.1 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
@@ -67,20 +66,20 @@ require (
github.com/x448/float16 v0.8.4 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect
go.yaml.in/yaml/v3 v3.0.5 // indirect
golang.org/x/net v0.56.0 // indirect
golang.org/x/net v0.57.0 // indirect
golang.org/x/oauth2 v0.36.0 // indirect
golang.org/x/sys v0.46.0 // indirect
golang.org/x/term v0.44.0 // indirect
golang.org/x/text v0.39.0 // indirect
golang.org/x/sys v0.47.0 // indirect
golang.org/x/term v0.45.0 // indirect
golang.org/x/text v0.40.0 // indirect
golang.org/x/time v0.15.0 // indirect
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
k8s.io/apiextensions-apiserver v0.36.0 // indirect
k8s.io/klog/v2 v2.140.0 // indirect
k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a // indirect
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 // indirect
k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad // indirect
k8s.io/utils v0.0.0-20260626114624-be93311217bd // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.3 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.4.2 // indirect
)
+60 -61
View File
@@ -5,7 +5,6 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@@ -22,8 +21,8 @@ github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w=
github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/fxamacker/cbor/v2 v2.9.1 h1:2rWm8B193Ll4VdjsJY28jxs70IdDsHRWgQYAI80+rMQ=
github.com/fxamacker/cbor/v2 v2.9.1/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@@ -31,40 +30,40 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
github.com/go-openapi/jsonpointer v0.22.5 h1:8on/0Yp4uTb9f4XvTrM2+1CPrV05QPZXu+rvu2o9jcA=
github.com/go-openapi/jsonpointer v0.22.5/go.mod h1:gyUR3sCvGSWchA2sUBJGluYMbe1zazrYWIkWPjjMUY0=
github.com/go-openapi/jsonreference v0.21.5 h1:6uCGVXU/aNF13AQNggxfysJ+5ZcU4nEAe+pJyVWRdiE=
github.com/go-openapi/jsonreference v0.21.5/go.mod h1:u25Bw85sX4E2jzFodh1FOKMTZLcfifd1Q+iKKOUxExw=
github.com/go-openapi/swag v0.25.5 h1:pNkwbUEeGwMtcgxDr+2GBPAk4kT+kJ+AaB+TMKAg+TU=
github.com/go-openapi/swag v0.25.5/go.mod h1:B3RT6l8q7X803JRxa2e59tHOiZlX1t8viplOcs9CwTA=
github.com/go-openapi/swag/cmdutils v0.25.5 h1:yh5hHrpgsw4NwM9KAEtaDTXILYzdXh/I8Whhx9hKj7c=
github.com/go-openapi/swag/cmdutils v0.25.5/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0=
github.com/go-openapi/swag/conv v0.25.5 h1:wAXBYEXJjoKwE5+vc9YHhpQOFj2JYBMF2DUi+tGu97g=
github.com/go-openapi/swag/conv v0.25.5/go.mod h1:CuJ1eWvh1c4ORKx7unQnFGyvBbNlRKbnRyAvDvzWA4k=
github.com/go-openapi/swag/fileutils v0.25.5 h1:B6JTdOcs2c0dBIs9HnkyTW+5gC+8NIhVBUwERkFhMWk=
github.com/go-openapi/swag/fileutils v0.25.5/go.mod h1:V3cT9UdMQIaH4WiTrUc9EPtVA4txS0TOmRURmhGF4kc=
github.com/go-openapi/swag/jsonname v0.25.5 h1:8p150i44rv/Drip4vWI3kGi9+4W9TdI3US3uUYSFhSo=
github.com/go-openapi/swag/jsonname v0.25.5/go.mod h1:jNqqikyiAK56uS7n8sLkdaNY/uq6+D2m2LANat09pKU=
github.com/go-openapi/swag/jsonutils v0.25.5 h1:XUZF8awQr75MXeC+/iaw5usY/iM7nXPDwdG3Jbl9vYo=
github.com/go-openapi/swag/jsonutils v0.25.5/go.mod h1:48FXUaz8YsDAA9s5AnaUvAmry1UcLcNVWUjY42XkrN4=
github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.5 h1:SX6sE4FrGb4sEnnxbFL/25yZBb5Hcg1inLeErd86Y1U=
github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.5/go.mod h1:/2KvOTrKWjVA5Xli3DZWdMCZDzz3uV/T7bXwrKWPquo=
github.com/go-openapi/swag/loading v0.25.5 h1:odQ/umlIZ1ZVRteI6ckSrvP6e2w9UTF5qgNdemJHjuU=
github.com/go-openapi/swag/loading v0.25.5/go.mod h1:I8A8RaaQ4DApxhPSWLNYWh9NvmX2YKMoB9nwvv6oW6g=
github.com/go-openapi/swag/mangling v0.25.5 h1:hyrnvbQRS7vKePQPHHDso+k6CGn5ZBs5232UqWZmJZw=
github.com/go-openapi/swag/mangling v0.25.5/go.mod h1:6hadXM/o312N/h98RwByLg088U61TPGiltQn71Iw0NY=
github.com/go-openapi/swag/netutils v0.25.5 h1:LZq2Xc2QI8+7838elRAaPCeqJnHODfSyOa7ZGfxDKlU=
github.com/go-openapi/swag/netutils v0.25.5/go.mod h1:lHbtmj4m57APG/8H7ZcMMSWzNqIQcu0RFiXrPUara14=
github.com/go-openapi/swag/stringutils v0.25.5 h1:NVkoDOA8YBgtAR/zvCx5rhJKtZF3IzXcDdwOsYzrB6M=
github.com/go-openapi/swag/stringutils v0.25.5/go.mod h1:PKK8EZdu4QJq8iezt17HM8RXnLAzY7gW0O1KKarrZII=
github.com/go-openapi/swag/typeutils v0.25.5 h1:EFJ+PCga2HfHGdo8s8VJXEVbeXRCYwzzr9u4rJk7L7E=
github.com/go-openapi/swag/typeutils v0.25.5/go.mod h1:itmFmScAYE1bSD8C4rS0W+0InZUBrB2xSPbWt6DLGuc=
github.com/go-openapi/swag/yamlutils v0.25.5 h1:kASCIS+oIeoc55j28T4o8KwlV2S4ZLPT6G0iq2SSbVQ=
github.com/go-openapi/swag/yamlutils v0.25.5/go.mod h1:Gek1/SjjfbYvM+Iq4QGwa/2lEXde9n2j4a3wI3pNuOQ=
github.com/go-openapi/testify/enable/yaml/v2 v2.4.0 h1:7SgOMTvJkM8yWrQlU8Jm18VeDPuAvB/xWrdxFJkoFag=
github.com/go-openapi/testify/enable/yaml/v2 v2.4.0/go.mod h1:14iV8jyyQlinc9StD7w1xVPW3CO3q1Gj04Jy//Kw4VM=
github.com/go-openapi/testify/v2 v2.4.0 h1:8nsPrHVCWkQ4p8h1EsRVymA2XABB4OT40gcvAu+voFM=
github.com/go-openapi/testify/v2 v2.4.0/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54=
github.com/go-openapi/jsonpointer v1.0.0 h1:kR9tHqY0CtZaOPVFm622dPVNhrvYpwr4uCxgL3h1H8s=
github.com/go-openapi/jsonpointer v1.0.0/go.mod h1:Z3rw7dWu1p9IgitXCFamSlA5lmDiklEB6vkaxcNZW5Y=
github.com/go-openapi/jsonreference v1.0.0 h1:jlmTr6torcd1YgDQvSfNmRtKzYDO4FGBkrAdlAVWnpY=
github.com/go-openapi/jsonreference v1.0.0/go.mod h1:jtwdyGbJk0Xhe5Y+rwtglQP6Sb1WZST4rT32LWB+sv0=
github.com/go-openapi/swag v0.27.1 h1:VotvOLWW8q/EAxB0YdsBBGC8XYyeL1YwBj2ungAGPNg=
github.com/go-openapi/swag v0.27.1/go.mod h1:GTkJPwHfhJp6MWr4/rCh64HVI3Ofu+tcsbfjfHmTxpE=
github.com/go-openapi/swag/cmdutils v0.27.1 h1:I7sYqaWVl5mq0NEmNQkAmFDyNin9ufvMX/p2zwtQaOE=
github.com/go-openapi/swag/cmdutils v0.27.1/go.mod h1:Sm1MVFMkF6guJJ+pQqHnQA3N0j9qALV3NxzDSv6bETM=
github.com/go-openapi/swag/conv v0.27.1 h1:8wi9ZG+olmY1wXphl93EWniPtbSPkXM/feH7FgjsvrU=
github.com/go-openapi/swag/conv v0.27.1/go.mod h1:QbqMivkpKhC3g1B1GGGOJ6ANewI3S62dbzYu3Duowqs=
github.com/go-openapi/swag/fileutils v0.27.1 h1:QQqBSoi5mW4XpU85nS0mLcA+zAE6vLzrb0QkmLKf9oM=
github.com/go-openapi/swag/fileutils v0.27.1/go.mod h1:VvJFZLTZS0AI854gEQz5tk7dBESdLjiNUMSZ/th2ry8=
github.com/go-openapi/swag/jsonutils v0.27.1 h1:SVgK3i4USzCU5mibOOS/l4ea2h9UQXy7J7RNLTjuXjU=
github.com/go-openapi/swag/jsonutils v0.27.1/go.mod h1:tdlEpZqdcQ17uj6J4YdK9vd8It5qWMwjWXOs0tjpRlk=
github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.1 h1:mJu3COL9WEaZVp/Kf2PRMi7tPszPEJfSr/OO75ynCs8=
github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.1/go.mod h1:mofwUWx70wvskwESqRJ//k/9kURmCgyJl5m5Ppoh5kY=
github.com/go-openapi/swag/loading v0.27.1 h1:/DxUgDXKbBX4bcn7r9uEXfJyzN5XpiJmZplzQTjrRCY=
github.com/go-openapi/swag/loading v0.27.1/go.mod h1:jvGh3iA2+zyUUycB5fgJWzeHnhrpvGnJJM0RVE9ZShE=
github.com/go-openapi/swag/mangling v0.27.1 h1:yC9D0HyUE8gbP+BfmGx9+AA89ikwZTMjESK3OnnoaqA=
github.com/go-openapi/swag/mangling v0.27.1/go.mod h1:jtBE2+V+3pILxOR7Vgce+Cwp6A2PgZbvVqfNntbVs0w=
github.com/go-openapi/swag/netutils v0.27.1 h1:mICMFoS82F5TZ4Zy3cqmcQk+BFeCp3Uyq3Np7GI0/qU=
github.com/go-openapi/swag/netutils v0.27.1/go.mod h1:J+WYyFMLtvtCGqa6jLv+YNUmIKI3ZRQRrvfNDMoQoEQ=
github.com/go-openapi/swag/pools v0.27.1 h1:9LeadcMyb2GJCbXX5hVQDbZ2Lq9TL4dCs/nx1j5DO0E=
github.com/go-openapi/swag/pools v0.27.1/go.mod h1:kVQefhSK5RWuRe7BXsL8htgBPAMpN7HDGpGEknqugeE=
github.com/go-openapi/swag/stringutils v0.27.1 h1:ZXePZ0r2p1qSjo8tD3Un4vFj8+FqlCkczxDrJIhYUp8=
github.com/go-openapi/swag/stringutils v0.27.1/go.mod h1:lzRN95CxXmA03XcDWHLOb6nOMcxCqR5rGY0lOgsfRoM=
github.com/go-openapi/swag/typeutils v0.27.1 h1:KSTdFlfnse4r6dP9IrEnwMldjE+zs71UeEB3//PtVXc=
github.com/go-openapi/swag/typeutils v0.27.1/go.mod h1:Srm0xFNRZ1Y+vCxJclo5qzx8aj+1pAKda/YfFPrG0dQ=
github.com/go-openapi/swag/yamlutils v0.27.1 h1:ftxv6xvXb1E3zohUc+okZ9nSqNb9StQX/FXnKZ98sQA=
github.com/go-openapi/swag/yamlutils v0.27.1/go.mod h1:bnxFIB1qewGRiZHypXGZ3fNgf13/0HfRgnS/iZBDrOo=
github.com/go-openapi/testify/enable/yaml/v2 v2.6.0 h1:gGHwAJ0R/5jU8BEGDbfRNR3hL68dAVi84WuOApp29B0=
github.com/go-openapi/testify/enable/yaml/v2 v2.6.0/go.mod h1:tY+St1SGq4NFl0QIqdTY4aEdbChAHxhyB77XQi9iJCo=
github.com/go-openapi/testify/v2 v2.6.0 h1:5PKH2HE7YJ/LuRPQGvSxBRlFXNQhSetBLlGAgUEu3ug=
github.com/go-openapi/testify/v2 v2.6.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/google/gnostic-models v0.7.1 h1:SisTfuFKJSKM5CPZkffwi6coztzzeYUhc3v4yxLWH8c=
@@ -132,8 +131,8 @@ github.com/samber/lo v1.53.0 h1:t975lj2py4kJPQ6haz1QMgtId2gtmfktACxIXArw3HM=
github.com/samber/lo v1.53.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sirupsen/logrus v1.10.1 h1:xi4336Zh11WpU14fXR6I67V3yaTPQYwRx2WEtHbRg4Q=
github.com/sirupsen/logrus v1.10.1/go.mod h1:vsQHnG7xzNsxk3NrwboUiWPnIC3dmbjcGPykD7+tiHk=
github.com/sirupsen/logrus v1.10.2 h1:G2SED73/qrAu6YwbdxOD6peLkCBI3z7L+ykJFTXJBBo=
github.com/sirupsen/logrus v1.10.2/go.mod h1:SLEg8TqYulVKKfIGHldVp2K2aYz2DKSVBq4g/H5bR7Q=
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
@@ -163,19 +162,19 @@ go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
golang.org/x/text v0.39.0 h1:UbZz4pLOvn600D6Oh6GGEI6VAmndrEBLv8/6BEXzyus=
golang.org/x/text v0.39.0/go.mod h1:3UwRclnC2g0TU9x8PZiyfOajCd1zaUNHF9cvqcQZ+ZM=
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
@@ -194,27 +193,27 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.36.4 h1:RxrvqCL6vgH5/+UnTeu1IIFqYmGfy0hnyrod1rn35Oo=
k8s.io/api v0.36.4/go.mod h1:S2B3orCFBDhrgyWbLeuKcT2QdHIpQesBkCYSlWtwUOw=
k8s.io/api v0.37.0 h1:Z//Vj9N7RA/yS2sDmxyeo7h+RR4zbUrd2vrd3Z0TbB4=
k8s.io/api v0.37.0/go.mod h1:LKXgcJWMc+f4OLbP5SFR8rulEg07zZhpi/zMULiBImk=
k8s.io/apiextensions-apiserver v0.36.0 h1:Wt7E8J+VBCbj4FjiBfDTK/neXDDjyJVJc7xfuOHImZ0=
k8s.io/apiextensions-apiserver v0.36.0/go.mod h1:kGDjH0msuiIB3tgsYRV0kS9GqpMYMUsQ3GHv7TApyug=
k8s.io/apimachinery v0.36.4 h1:PT2UzkupGuAx/+xT5XjiMJ1WGpY3fn9/hdAvjweRet4=
k8s.io/apimachinery v0.36.4/go.mod h1:p2I2dipt7JHG+quVwQ1d02d28O4GdDi77RByQ13MTpk=
k8s.io/client-go v0.36.4 h1:MDvfDNvMSt0Br94SK8neviVlwL9qifw9B26hJCpD1K0=
k8s.io/client-go v0.36.4/go.mod h1:pNK4WKELbwlEDvtbE8l22lEZL5THYF61H5EealokZmA=
k8s.io/apimachinery v0.37.0 h1:Np2AbDtf8x6RDHiD8T9LbKJ9gaegeVNa8yNm5FuGKm0=
k8s.io/apimachinery v0.37.0/go.mod h1:RN3nhprFSCxOi5Selxd7oMTXOe/c+ZbcE7Im+TS2zkE=
k8s.io/client-go v0.37.0 h1:nsN31fy8wBySuZ+QRnKmrjRSQLOG2rvoGN0tKd12zhQ=
k8s.io/client-go v0.37.0/go.mod h1:FcGqw+Ll/gNQiq+nPGY1Oyt9y7SgDh1d3MW3RFDEbn0=
k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc=
k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0=
k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a h1:xCeOEAOoGYl2jnJoHkC3hkbPJgdATINPMAxaynU2Ovg=
k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0=
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 h1:AZYQSJemyQB5eRxqcPky+/7EdBj0xi3g0ZcxxJ7vbWU=
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad h1:oXImqH8mQNk7PmvzKhmN3ddJoY6OnyM225MXwGHPm0A=
k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad/go.mod h1:0/mqHCVhlumdJ3BhCfnjSZQE037nAhNodh1/hK0T8/I=
k8s.io/utils v0.0.0-20260626114624-be93311217bd h1:Ea7fgQ5we8Y9T0OX5o0dAHzQOBRI07D/dEYRaB9ZZEs=
k8s.io/utils v0.0.0-20260626114624-be93311217bd/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
sigs.k8s.io/controller-runtime v0.24.1 h1:miPEwrmirImAvgME1L9qebGHrOnGJoVmVdtOU9fRfo4=
sigs.k8s.io/controller-runtime v0.24.1/go.mod h1:vFkfY5fGt5xAC/sKb8IBFKgWPNKG9OUG29dR8Y2wImw=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v6 v6.3.3 h1:u08YRbVUi59ri4YD6cg0UqNM4Dimn0sIl+wldcx5PYw=
sigs.k8s.io/structured-merge-diff/v6 v6.3.3/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
sigs.k8s.io/structured-merge-diff/v6 v6.4.2 h1:qdOxHwrl2Kaag1aQEarlYcOA9vSyGCp3CIki3aW8c4Q=
sigs.k8s.io/structured-merge-diff/v6 v6.4.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
-9
View File
@@ -57,15 +57,6 @@ var (
"sensitiveContainerEnvVar",
// Other checks
"tlsSettingsMissing",
"gatewayTLSMissing",
"gatewayAllowedRoutesAll",
"gatewayInsecureFrontendValidation",
"gatewayCrossNamespaceCertificateRef",
"httpRouteWildcardOrEmptyHost",
"httpRouteInsecureListener",
"httpRouteCrossNamespaceBackendRef",
"httpRouteBackendTLSMissing",
"kgatewayBackendTLSVerificationDisabled",
"pdbDisruptionsIsZero",
"metadataAndInstanceMismatched",
"missingPodDisruptionBudget",
@@ -1,25 +0,0 @@
successMessage: Gateway listeners restrict route attachment by namespace
failureMessage: Gateway listeners should not allow routes from all namespaces
category: Security
target: gateway.networking.k8s.io/Gateway
schema:
'$schema': https://json-schema.org/draft/2019-09/schema
type: object
properties:
spec:
type: object
properties:
listeners:
type: array
items:
type: object
properties:
allowedRoutes:
type: object
properties:
namespaces:
type: object
properties:
from:
not:
const: All
@@ -1,6 +0,0 @@
successMessage: Gateway cross-namespace certificate references are authorized
failureMessage: Gateway cross-namespace certificate references should have a matching ReferenceGrant
category: Security
target: gateway.networking.k8s.io/Gateway
relatedKinds:
- gateway.networking.k8s.io/ReferenceGrant
@@ -1,40 +0,0 @@
successMessage: Gateway frontend client certificate validation fails closed
failureMessage: Gateway frontend client certificate validation should not allow insecure fallback
category: Security
target: gateway.networking.k8s.io/Gateway
schema:
'$schema': https://json-schema.org/draft/2019-09/schema
type: object
properties:
spec:
type: object
properties:
tls:
type: object
properties:
frontend:
type: object
properties:
default:
type: object
properties:
validation:
type: object
properties:
mode:
not:
const: AllowInsecureFallback
perPort:
type: array
items:
type: object
properties:
tls:
type: object
properties:
validation:
type: object
properties:
mode:
not:
const: AllowInsecureFallback
-41
View File
@@ -1,41 +0,0 @@
successMessage: Gateway TLS listeners have certificates configured
failureMessage: Gateway HTTPS, GRPC, and terminating TLS listeners should configure certificateRefs
category: Security
target: gateway.networking.k8s.io/Gateway
schema:
'$schema': https://json-schema.org/draft/2019-09/schema
type: object
properties:
spec:
type: object
properties:
listeners:
type: array
items:
type: object
if:
anyOf:
- required: [protocol]
properties:
protocol:
enum: [HTTPS, GRPC]
- required: [protocol]
properties:
protocol:
const: TLS
tls:
type: object
properties:
mode:
not:
const: Passthrough
then:
required: [tls]
properties:
tls:
type: object
required: [certificateRefs]
properties:
certificateRefs:
type: array
minItems: 1
@@ -1,9 +0,0 @@
successMessage: HTTPRoute TLS backends have TLS origination configured
failureMessage: HTTPRoute backends on TLS ports should have a BackendTLSPolicy or kgateway BackendConfigPolicy
category: Security
target: gateway.networking.k8s.io/HTTPRoute
relatedKinds:
- Service
- gateway.networking.k8s.io/BackendTLSPolicy
- gateway.kgateway.dev/Backend
- gateway.kgateway.dev/BackendConfigPolicy
@@ -1,6 +0,0 @@
successMessage: HTTPRoute cross-namespace backend references are authorized
failureMessage: HTTPRoute cross-namespace backend references should have a matching ReferenceGrant
category: Security
target: gateway.networking.k8s.io/HTTPRoute
relatedKinds:
- gateway.networking.k8s.io/ReferenceGrant
@@ -1,6 +0,0 @@
successMessage: HTTPRoute uses secure listeners or redirects HTTP to HTTPS
failureMessage: HTTPRoute should not serve application traffic over an HTTP listener
category: Security
target: gateway.networking.k8s.io/HTTPRoute
relatedKinds:
- gateway.networking.k8s.io/Gateway
@@ -1,19 +0,0 @@
successMessage: HTTPRoute uses explicit hostnames
failureMessage: HTTPRoute should use explicit hostnames instead of matching every hostname
category: Security
target: gateway.networking.k8s.io/HTTPRoute
schema:
'$schema': https://json-schema.org/draft/2019-09/schema
type: object
required: [spec]
properties:
spec:
type: object
required: [hostnames]
properties:
hostnames:
type: array
minItems: 1
items:
type: string
pattern: '^[^*]+$'
@@ -1,17 +0,0 @@
successMessage: kgateway backend TLS certificate verification is enabled
failureMessage: kgateway BackendConfigPolicy should not disable TLS certificate verification
category: Security
target: gateway.kgateway.dev/BackendConfigPolicy
schema:
'$schema': https://json-schema.org/draft/2019-09/schema
type: object
properties:
spec:
type: object
properties:
tls:
type: object
properties:
insecureSkipVerify:
not:
const: true
-9
View File
@@ -38,15 +38,6 @@ checks:
hostNetworkSet: danger
hostPortSet: warning
tlsSettingsMissing: warning
gatewayTLSMissing: warning
gatewayAllowedRoutesAll: warning
gatewayInsecureFrontendValidation: warning
gatewayCrossNamespaceCertificateRef: warning
httpRouteWildcardOrEmptyHost: warning
httpRouteInsecureListener: warning
httpRouteCrossNamespaceBackendRef: warning
httpRouteBackendTLSMissing: warning
kgatewayBackendTLSVerificationDisabled: warning
sensitiveContainerEnvVar: danger
sensitiveConfigmapContent: danger
clusterrolePodExecAttach: danger
-9
View File
@@ -38,15 +38,6 @@ checks:
hostNetworkSet: danger
hostPortSet: warning
tlsSettingsMissing: warning
gatewayTLSMissing: warning
gatewayAllowedRoutesAll: warning
gatewayInsecureFrontendValidation: warning
gatewayCrossNamespaceCertificateRef: warning
httpRouteWildcardOrEmptyHost: warning
httpRouteInsecureListener: warning
httpRouteCrossNamespaceBackendRef: warning
httpRouteBackendTLSMissing: warning
kgatewayBackendTLSVerificationDisabled: warning
sensitiveContainerEnvVar: danger
sensitiveConfigmapContent: danger
clusterrolePodExecAttach: danger
-1
View File
@@ -80,7 +80,6 @@ type SchemaCheck struct {
AdditionalSchemas map[string]map[string]any `yaml:"additionalSchemas" json:"additionalSchemas"`
AdditionalSchemaStrings map[string]string `yaml:"additionalSchemaStrings" json:"additionalSchemaStrings"`
AdditionalValidators map[string]jsonschema.Schema `yaml:"-" json:"-"`
RelatedKinds []TargetKind `yaml:"relatedKinds" json:"relatedKinds"`
Mutations []Mutation `yaml:"mutations" json:"mutations"`
}
+5 -15
View File
@@ -325,22 +325,16 @@ func CreateResourceProviderFromAPI(ctx context.Context, kube kubernetes.Interfac
}
restMapper := restmapper.NewDiscoveryRESTMapper(resources)
allChecks := []conf.SchemaCheck{}
for checkID, check := range c.CustomChecks {
severity, enabled := c.Checks[checkID]
if enabled && severity.IsActionable() {
allChecks = append(allChecks, check)
}
for _, check := range c.CustomChecks {
allChecks = append(allChecks, check)
}
for checkID, check := range conf.BuiltInChecks {
severity, enabled := c.Checks[checkID]
if enabled && severity.IsActionable() {
allChecks = append(allChecks, check)
}
for _, check := range conf.BuiltInChecks {
allChecks = append(allChecks, check)
}
var additionalKinds []conf.TargetKind
for _, check := range allChecks {
neededKinds := append([]conf.TargetKind{check.Target}, check.RelatedKinds...)
neededKinds := []conf.TargetKind{check.Target}
for key := range check.AdditionalSchemas {
neededKinds = append(neededKinds, conf.TargetKind(key))
}
@@ -359,10 +353,6 @@ func CreateResourceProviderFromAPI(ctx context.Context, kube kubernetes.Interfac
groupKind := parseGroupKind(maybeTransformKindIntoGroupKind(string(kind)))
mapping, err := restMapper.RESTMapping(groupKind)
if err != nil {
if meta.IsNoMatchError(err) {
logrus.Infof("Skipping unavailable Kind %s", kind)
continue
}
logrus.Warnf("error retrieving mapping of Kind %s because of error: %v", kind, err)
return nil, err
}
-42
View File
@@ -176,45 +176,3 @@ func TestGetResourceFromAPI(t *testing.T) {
})
}
}
func TestAdditionalKindLoading(t *testing.T) {
ingress := test.MockIngress()
k8s, dynamicInterface := test.SetupTestAPI(append(test.GetMockControllers("test"), &ingress)...)
enabled := conf.Configuration{
Checks: map[string]conf.Severity{
"customIngress": conf.SeverityWarning,
},
CustomChecks: map[string]conf.SchemaCheck{
"customIngress": {Target: "networking.k8s.io/Ingress"},
},
}
resources, err := CreateResourceProviderFromAPI(context.Background(), k8s, "test", dynamicInterface, enabled)
if assert.NoError(t, err) {
assert.Len(t, resources.Resources["networking.k8s.io/Ingress"], 1)
}
ignored := enabled
ignored.Checks = map[string]conf.Severity{
"customIngress": conf.SeverityIgnore,
}
resources, err = CreateResourceProviderFromAPI(context.Background(), k8s, "test", dynamicInterface, ignored)
if assert.NoError(t, err) {
assert.Empty(t, resources.Resources["networking.k8s.io/Ingress"])
}
}
func TestUnavailableAdditionalKindDoesNotFailAudit(t *testing.T) {
k8s, dynamicInterface := test.SetupTestAPI(test.GetMockControllers("test")...)
config := conf.Configuration{
Checks: map[string]conf.Severity{
"optionalCRD": conf.SeverityWarning,
},
CustomChecks: map[string]conf.SchemaCheck{
"optionalCRD": {Target: "example.com/OptionalResource"},
},
}
_, err := CreateResourceProviderFromAPI(context.Background(), k8s, "test", dynamicInterface, config)
assert.NoError(t, err)
}
-485
View File
@@ -1,485 +0,0 @@
package validator
import (
"encoding/json"
"fmt"
"strings"
"github.com/fairwindsops/polaris/pkg/kube"
"github.com/qri-io/jsonschema"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
)
const (
gatewayAPIGroup = "gateway.networking.k8s.io"
kgatewayAPIGroup = "gateway.kgateway.dev"
)
type objectReference struct {
group string
kind string
name string
namespace string
sectionName string
port int64
}
func init() {
registerCustomChecks("httpRouteInsecureListener", httpRouteInsecureListener)
registerCustomChecks("gatewayCrossNamespaceCertificateRef", gatewayCrossNamespaceCertificateRef)
registerCustomChecks("httpRouteCrossNamespaceBackendRef", httpRouteCrossNamespaceBackendRef)
registerCustomChecks("httpRouteBackendTLSMissing", httpRouteBackendTLSMissing)
}
func httpRouteInsecureListener(test schemaTestCase) (bool, []jsonschema.KeyError, error) {
if isFullHTTPSRedirect(test.Resource.Resource.Object) || test.ResourceProvider == nil {
return true, nil, nil
}
routeNamespace := test.Resource.ObjectMeta.GetNamespace()
for _, parent := range referencesAt(test.Resource.Resource.Object, "spec", "parentRefs") {
parent = withDefaults(parent, gatewayAPIGroup, "Gateway", routeNamespace)
if parent.group != gatewayAPIGroup || parent.kind != "Gateway" {
continue
}
gateway := findResource(test.ResourceProvider.Resources[gatewayAPIGroup+"/Gateway"], parent.namespace, parent.name)
if gateway == nil {
continue
}
listeners := nestedSlice(gateway.Resource.Object, "spec", "listeners")
for _, rawListener := range listeners {
listener, ok := rawListener.(map[string]any)
if !ok || (parent.sectionName != "" && stringValue(listener["name"]) != parent.sectionName) {
continue
}
if stringValue(listener["protocol"]) == "HTTP" && listenerAcceptsHTTPRoute(listener, parent.namespace, test.Resource, test.ResourceProvider) {
return gatewayFailure("spec.parentRefs", fmt.Sprintf("HTTPRoute references HTTP listener %q on Gateway %s/%s without a full HTTPS redirect", stringValue(listener["name"]), parent.namespace, parent.name))
}
}
}
return true, nil, nil
}
func gatewayCrossNamespaceCertificateRef(test schemaTestCase) (bool, []jsonschema.KeyError, error) {
if test.ResourceProvider == nil {
return true, nil, nil
}
sourceNamespace := test.Resource.ObjectMeta.GetNamespace()
listeners := nestedSlice(test.Resource.Resource.Object, "spec", "listeners")
for _, rawListener := range listeners {
listener, ok := rawListener.(map[string]any)
if !ok {
continue
}
for _, ref := range referencesAt(listener, "tls", "certificateRefs") {
ref = withDefaults(ref, "", "Secret", sourceNamespace)
if ref.namespace != sourceNamespace && !hasReferenceGrant(test.ResourceProvider, sourceNamespace, "Gateway", ref) {
return gatewayFailure("spec.listeners.tls.certificateRefs", fmt.Sprintf("Gateway %s/%s references %s %s/%s without a matching ReferenceGrant", sourceNamespace, test.Resource.ObjectMeta.GetName(), ref.kind, ref.namespace, ref.name))
}
}
}
return true, nil, nil
}
func httpRouteCrossNamespaceBackendRef(test schemaTestCase) (bool, []jsonschema.KeyError, error) {
if test.ResourceProvider == nil {
return true, nil, nil
}
sourceNamespace := test.Resource.ObjectMeta.GetNamespace()
for _, ref := range httpRouteBackendRefs(test.Resource.Resource.Object) {
ref = withDefaults(ref, "", "Service", sourceNamespace)
if ref.namespace != sourceNamespace && !hasReferenceGrant(test.ResourceProvider, sourceNamespace, "HTTPRoute", ref) {
return gatewayFailure("spec.rules.backendRefs", fmt.Sprintf("HTTPRoute %s/%s references %s %s/%s without a matching ReferenceGrant", sourceNamespace, test.Resource.ObjectMeta.GetName(), ref.kind, ref.namespace, ref.name))
}
}
return true, nil, nil
}
func httpRouteBackendTLSMissing(test schemaTestCase) (bool, []jsonschema.KeyError, error) {
if test.ResourceProvider == nil {
return true, nil, nil
}
routeNamespace := test.Resource.ObjectMeta.GetNamespace()
for _, ref := range httpRouteBackendRefs(test.Resource.Resource.Object) {
ref = withDefaults(ref, "", "Service", routeNamespace)
if !backendUsesTLS(test.ResourceProvider, ref) {
continue
}
if hasBackendTLSPolicy(test.ResourceProvider, ref) || hasKgatewayBackendTLSPolicy(test.ResourceProvider, ref) {
continue
}
return gatewayFailure("spec.rules.backendRefs", fmt.Sprintf("HTTPRoute backend %s %s/%s appears to use TLS but has no BackendTLSPolicy or kgateway BackendConfigPolicy", ref.kind, ref.namespace, ref.name))
}
return true, nil, nil
}
func isFullHTTPSRedirect(object map[string]any) bool {
rules := nestedSlice(object, "spec", "rules")
if len(rules) == 0 {
return false
}
for _, rawRule := range rules {
rule, ok := rawRule.(map[string]any)
if !ok || len(referencesAt(rule, "backendRefs")) > 0 || !ruleMatchesAllTraffic(rule) || !hasHTTPSRedirect(rule) {
return false
}
}
return true
}
func ruleMatchesAllTraffic(rule map[string]any) bool {
matches := nestedSlice(rule, "matches")
if len(matches) == 0 {
return true
}
for _, rawMatch := range matches {
match, ok := rawMatch.(map[string]any)
if !ok || len(match) != 1 {
continue
}
path, ok := match["path"].(map[string]any)
if ok && (stringValue(path["type"]) == "" || stringValue(path["type"]) == "PathPrefix") && stringValue(path["value"]) == "/" {
return true
}
}
return false
}
func hasHTTPSRedirect(rule map[string]any) bool {
filters := nestedSlice(rule, "filters")
for _, rawFilter := range filters {
filter, ok := rawFilter.(map[string]any)
if !ok || stringValue(filter["type"]) != "RequestRedirect" {
continue
}
redirect, ok := filter["requestRedirect"].(map[string]any)
if ok && strings.EqualFold(stringValue(redirect["scheme"]), "https") {
return true
}
}
return false
}
func listenerAcceptsHTTPRoute(listener map[string]any, gatewayNamespace string, route kube.GenericResource, provider *kube.ResourceProvider) bool {
if !listenerHostnameIntersectsRoute(listener, route.Resource.Object) {
return false
}
allowedRoutes, ok := listener["allowedRoutes"].(map[string]any)
if !ok {
return route.ObjectMeta.GetNamespace() == gatewayNamespace
}
if kinds := nestedSlice(allowedRoutes, "kinds"); len(kinds) > 0 {
allowsHTTPRoute := false
for _, rawKind := range kinds {
kind, ok := rawKind.(map[string]any)
if ok && withDefaultString(stringValue(kind["group"]), gatewayAPIGroup) == gatewayAPIGroup && stringValue(kind["kind"]) == "HTTPRoute" {
allowsHTTPRoute = true
break
}
}
if !allowsHTTPRoute {
return false
}
}
namespaces, ok := allowedRoutes["namespaces"].(map[string]any)
if !ok || stringValue(namespaces["from"]) == "" || stringValue(namespaces["from"]) == "Same" {
return route.ObjectMeta.GetNamespace() == gatewayNamespace
}
if stringValue(namespaces["from"]) == "All" {
return true
}
if stringValue(namespaces["from"]) != "Selector" {
return false
}
selectorMap, ok := namespaces["selector"].(map[string]any)
if !ok {
return false
}
selector := &metav1.LabelSelector{}
selectorJSON, err := json.Marshal(selectorMap)
if err != nil {
return false
}
if err := json.Unmarshal(selectorJSON, selector); err != nil {
return false
}
compiled, err := metav1.LabelSelectorAsSelector(selector)
if err != nil {
return false
}
for _, namespace := range provider.Namespaces {
if namespace.Name == route.ObjectMeta.GetNamespace() {
return compiled.Matches(labels.Set(namespace.Labels))
}
}
return false
}
func listenerHostnameIntersectsRoute(listener, route map[string]any) bool {
listenerHostname := stringValue(listener["hostname"])
routeHostnames := nestedSlice(route, "spec", "hostnames")
if len(routeHostnames) == 0 || listenerHostname == "" {
return true
}
for _, routeHostname := range routeHostnames {
if hostnamesIntersect(listenerHostname, stringValue(routeHostname)) {
return true
}
}
return false
}
func hostnamesIntersect(left, right string) bool {
if left == "" || right == "" || left == "*" || right == "*" || strings.EqualFold(left, right) {
return true
}
leftSuffix, leftWildcard := strings.CutPrefix(strings.ToLower(left), "*.")
rightSuffix, rightWildcard := strings.CutPrefix(strings.ToLower(right), "*.")
switch {
case leftWildcard && rightWildcard:
return leftSuffix == rightSuffix || strings.HasSuffix(leftSuffix, "."+rightSuffix) || strings.HasSuffix(rightSuffix, "."+leftSuffix)
case leftWildcard:
return strings.HasSuffix(strings.ToLower(right), "."+leftSuffix)
case rightWildcard:
return strings.HasSuffix(strings.ToLower(left), "."+rightSuffix)
default:
return false
}
}
func httpRouteBackendRefs(object map[string]any) []objectReference {
var refs []objectReference
rules := nestedSlice(object, "spec", "rules")
for _, rawRule := range rules {
rule, ok := rawRule.(map[string]any)
if !ok {
continue
}
refs = append(refs, referencesAt(rule, "backendRefs")...)
filters := nestedSlice(rule, "filters")
for _, rawFilter := range filters {
filter, ok := rawFilter.(map[string]any)
if !ok || stringValue(filter["type"]) != "RequestMirror" {
continue
}
mirror, ok := filter["requestMirror"].(map[string]any)
if !ok {
continue
}
if backend, ok := mirror["backendRef"].(map[string]any); ok {
refs = append(refs, referenceFromMap(backend))
}
}
}
return refs
}
func referencesAt(object map[string]any, fields ...string) []objectReference {
items := nestedSlice(object, fields...)
if len(items) == 0 {
return nil
}
refs := make([]objectReference, 0, len(items))
for _, item := range items {
if ref, ok := item.(map[string]any); ok {
refs = append(refs, referenceFromMap(ref))
}
}
return refs
}
func referenceFromMap(ref map[string]any) objectReference {
return objectReference{
group: stringValue(ref["group"]),
kind: stringValue(ref["kind"]),
name: stringValue(ref["name"]),
namespace: stringValue(ref["namespace"]),
sectionName: stringValue(ref["sectionName"]),
port: int64Value(ref["port"]),
}
}
func withDefaults(ref objectReference, group, kind, namespace string) objectReference {
if ref.group == "" {
ref.group = group
}
if ref.kind == "" {
ref.kind = kind
}
if ref.namespace == "" {
ref.namespace = namespace
}
return ref
}
func withDefaultString(value, defaultValue string) string {
if value == "" {
return defaultValue
}
return value
}
func hasReferenceGrant(provider *kube.ResourceProvider, sourceNamespace, sourceKind string, target objectReference) bool {
for _, grant := range provider.Resources[gatewayAPIGroup+"/ReferenceGrant"] {
if grant.ObjectMeta.GetNamespace() != target.namespace {
continue
}
fromMatches := false
for _, from := range referencesAt(grant.Resource.Object, "spec", "from") {
if from.group == gatewayAPIGroup && from.kind == sourceKind && from.namespace == sourceNamespace {
fromMatches = true
break
}
}
if !fromMatches {
continue
}
for _, to := range referencesAt(grant.Resource.Object, "spec", "to") {
if to.group == target.group && to.kind == target.kind && (to.name == "" || to.name == target.name) {
return true
}
}
}
return false
}
func backendUsesTLS(provider *kube.ResourceProvider, ref objectReference) bool {
// ponytail: infer TLS from conventional ports and backend metadata; replace
// this with controller status or an implementation graph when Polaris has one.
if ref.port == 443 || ref.port == 8443 {
return true
}
groupKind := ref.kind
if ref.group != "" {
groupKind = ref.group + "/" + ref.kind
}
backend := findResource(provider.Resources[groupKind], ref.namespace, ref.name)
if backend == nil {
return false
}
if ref.group == "" && ref.kind == "Service" {
ports := nestedSlice(backend.Resource.Object, "spec", "ports")
for _, rawPort := range ports {
port, ok := rawPort.(map[string]any)
if !ok || (ref.port != 0 && int64Value(port["port"]) != ref.port) {
continue
}
name := strings.ToLower(stringValue(port["name"]))
appProtocol := strings.ToLower(stringValue(port["appProtocol"]))
if name == "https" || strings.HasPrefix(name, "https-") || appProtocol == "https" || strings.HasSuffix(appProtocol, "/https") {
return true
}
}
}
if ref.group == kgatewayAPIGroup && ref.kind == "Backend" {
hosts := nestedSlice(backend.Resource.Object, "spec", "static", "hosts")
for _, rawHost := range hosts {
host, ok := rawHost.(map[string]any)
if ok && (int64Value(host["port"]) == 443 || int64Value(host["port"]) == 8443) {
return true
}
}
}
return false
}
func hasBackendTLSPolicy(provider *kube.ResourceProvider, ref objectReference) bool {
if ref.group != "" || ref.kind != "Service" {
return false
}
for _, policy := range provider.Resources[gatewayAPIGroup+"/BackendTLSPolicy"] {
if policy.ObjectMeta.GetNamespace() == ref.namespace && policyTargets(policy, ref) {
return true
}
}
return false
}
func hasKgatewayBackendTLSPolicy(provider *kube.ResourceProvider, ref objectReference) bool {
for _, policy := range provider.Resources[kgatewayAPIGroup+"/BackendConfigPolicy"] {
if policy.ObjectMeta.GetNamespace() != ref.namespace {
continue
}
if _, found := nestedValue(policy.Resource.Object, "spec", "tls"); found && policyTargets(policy, ref) {
return true
}
}
return false
}
func policyTargets(policy kube.GenericResource, target objectReference) bool {
for _, ref := range referencesAt(policy.Resource.Object, "spec", "targetRefs") {
ref = withDefaults(ref, "", "Service", policy.ObjectMeta.GetNamespace())
if ref.group == target.group && ref.kind == target.kind && ref.name == target.name {
return true
}
}
return false
}
func findResource(resources []kube.GenericResource, namespace, name string) *kube.GenericResource {
for i := range resources {
if resources[i].ObjectMeta.GetNamespace() == namespace && resources[i].ObjectMeta.GetName() == name {
return &resources[i]
}
}
return nil
}
func stringValue(value any) string {
valueString, _ := value.(string)
return valueString
}
func int64Value(value any) int64 {
switch number := value.(type) {
case int:
return int64(number)
case int32:
return int64(number)
case int64:
return number
case float64:
return int64(number)
default:
return 0
}
}
func nestedSlice(object map[string]any, fields ...string) []any {
value, found := nestedValue(object, fields...)
if !found {
return nil
}
items, _ := value.([]any)
return items
}
func nestedValue(object map[string]any, fields ...string) (any, bool) {
var current any = object
for _, field := range fields {
currentMap, ok := current.(map[string]any)
if !ok {
return nil, false
}
current, ok = currentMap[field]
if !ok {
return nil, false
}
}
return current, true
}
func gatewayFailure(path, message string) (bool, []jsonschema.KeyError, error) {
return false, []jsonschema.KeyError{{
PropertyPath: path,
Message: message,
}}, nil
}
@@ -1,13 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: unrestricted
spec:
gatewayClassName: kgateway
listeners:
- name: https
protocol: HTTPS
port: 443
allowedRoutes:
namespaces:
from: All
@@ -1,16 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: restricted
spec:
gatewayClassName: kgateway
listeners:
- name: https
protocol: HTTPS
port: 443
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
gateway-access: "true"
@@ -1,15 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: public
namespace: infra
spec:
gatewayClassName: kgateway
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
certificateRefs:
- name: wildcard
namespace: certificates
@@ -1,30 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: public
namespace: infra
spec:
gatewayClassName: kgateway
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
certificateRefs:
- name: wildcard
namespace: certificates
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-infra-gateway
namespace: certificates
spec:
from:
- group: gateway.networking.k8s.io
kind: Gateway
namespace: infra
to:
- group: ""
kind: Secret
name: wildcard
@@ -1,15 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: fail-open
spec:
gatewayClassName: kgateway
tls:
frontend:
default:
validation:
mode: AllowInsecureFallback
listeners:
- name: https
protocol: HTTPS
port: 443
@@ -1,15 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: fail-closed
spec:
gatewayClassName: kgateway
tls:
frontend:
default:
validation:
mode: AllowValidOnly
listeners:
- name: https
protocol: HTTPS
port: 443
@@ -1,10 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: missing-tls
spec:
gatewayClassName: kgateway
listeners:
- name: https
protocol: HTTPS
port: 443
@@ -1,13 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: insecure
spec:
gatewayClassName: kgateway
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs: []
@@ -1,22 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: secure
spec:
gatewayClassName: kgateway
listeners:
- name: http
protocol: HTTP
port: 80
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: example-tls
- name: passthrough
protocol: TLS
port: 8443
tls:
mode: Passthrough
@@ -1,12 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: plaintext-to-tls-backend
namespace: app
spec:
hostnames:
- app.example.com
rules:
- backendRefs:
- name: api
port: 443
@@ -1,39 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: secure-kgateway-backend
namespace: app
spec:
hostnames:
- app.example.com
rules:
- backendRefs:
- group: gateway.kgateway.dev
kind: Backend
name: external-api
---
apiVersion: gateway.kgateway.dev/v1alpha1
kind: Backend
metadata:
name: external-api
namespace: app
spec:
type: Static
static:
hosts:
- host: api.example.com
port: 443
---
apiVersion: gateway.kgateway.dev/v1alpha1
kind: BackendConfigPolicy
metadata:
name: external-api-tls
namespace: app
spec:
targetRefs:
- group: gateway.kgateway.dev
kind: Backend
name: external-api
tls:
sni: api.example.com
wellKnownCACertificates: System
@@ -1,26 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: secure-backend
namespace: app
spec:
hostnames:
- app.example.com
rules:
- backendRefs:
- name: api
port: 443
---
apiVersion: gateway.networking.k8s.io/v1
kind: BackendTLSPolicy
metadata:
name: api-tls
namespace: app
spec:
targetRefs:
- group: ""
kind: Service
name: api
validation:
hostname: api.app.svc.cluster.local
wellKnownCACertificates: System
@@ -1,13 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: shared-api
namespace: app
spec:
hostnames:
- app.example.com
rules:
- backendRefs:
- name: api
namespace: shared
port: 8080
@@ -1,28 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: shared-api
namespace: app
spec:
hostnames:
- app.example.com
rules:
- backendRefs:
- name: api
namespace: shared
port: 8080
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-app-route
namespace: shared
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: app
to:
- group: ""
kind: Service
name: api
@@ -1,31 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: plaintext
namespace: app
spec:
parentRefs:
- name: public
namespace: infra
sectionName: http
hostnames:
- app.example.com
rules:
- backendRefs:
- name: app
port: 8080
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: public
namespace: infra
spec:
gatewayClassName: kgateway
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: All
@@ -1,31 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: secure-host-only
namespace: app
spec:
parentRefs:
- name: public
hostnames:
- app.example.com
rules:
- backendRefs:
- name: app
port: 8080
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: public
namespace: app
spec:
gatewayClassName: kgateway
listeners:
- name: unrelated-http
hostname: other.example.com
protocol: HTTP
port: 80
- name: app-https
hostname: app.example.com
protocol: HTTPS
port: 443
@@ -1,37 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: redirect
namespace: app
spec:
parentRefs:
- name: public
namespace: infra
sectionName: http
hostnames:
- app.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /
filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: public
namespace: infra
spec:
gatewayClassName: kgateway
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: All
@@ -1,9 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: every-host
spec:
rules:
- backendRefs:
- name: api
port: 8080
@@ -1,11 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: wildcard-host
spec:
hostnames:
- "*.example.com"
rules:
- backendRefs:
- name: api
port: 8080
@@ -1,11 +0,0 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: explicit-host
spec:
hostnames:
- api.example.com
rules:
- backendRefs:
- name: api
port: 8080
@@ -1,11 +0,0 @@
apiVersion: gateway.kgateway.dev/v1alpha1
kind: BackendConfigPolicy
metadata:
name: unverified
spec:
targetRefs:
- group: ""
kind: Service
name: api
tls:
insecureSkipVerify: true
@@ -1,12 +0,0 @@
apiVersion: gateway.kgateway.dev/v1alpha1
kind: BackendConfigPolicy
metadata:
name: verified
spec:
targetRefs:
- group: ""
kind: Service
name: api
tls:
sni: api.example.com
wellKnownCACertificates: System