diff --git a/README.md b/README.md index 68b7a85c3ac..da1e2823875 100644 --- a/README.md +++ b/README.md @@ -507,6 +507,7 @@ Platform usage. A shell script for gDNS-zDNS project bulk migration. * [GKE Billing Export](tools/gke-billing-export) - Google Kubernetes Engine fine grained billing export. +* [GKE GPU Driver Version](tools/gke-gpu-driver-version) - A tool to find the supported GPU driver version for a given GKE cluster version and GPU type. * [gmon](tools/gmon/) - A command-line interface (CLI) for Cloud Monitoring written in Python. * [Google Cloud Support Slackbot](tools/google-cloud-support-slackbot) - Slack diff --git a/examples/creative-studio/frontend/package-lock.json b/examples/creative-studio/frontend/package-lock.json index c19803aac6e..23437388fdf 100644 --- a/examples/creative-studio/frontend/package-lock.json +++ b/examples/creative-studio/frontend/package-lock.json @@ -18,9 +18,9 @@ "@angular/material": "^18.2.1", "@angular/platform-browser": "^18.1.0", "@angular/platform-browser-dynamic": "^18.1.0", - "@angular/platform-server": "^18.1.0", + "@angular/platform-server": "^18.2.14", "@angular/router": "^18.1.0", - "@angular/ssr": "^18.1.2", + "@angular/ssr": "^18.2.21", "express": "^4.18.2", "file-saver": "^2.0.5", "ngx-image-cropper": "^9.1.5", @@ -676,9 +676,10 @@ } }, "node_modules/@angular/platform-server": { - "version": "18.2.1", - "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-18.2.1.tgz", - "integrity": "sha512-xU/7EGYk/HXAY2V7VEzBx4YcVQe3rPuojXPubdgKJ8ueQ7XVtwumv/LHM72/Yn8ChvYYaoGLtM7nI2rG1MVAag==", + "version": "18.2.14", + "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-18.2.14.tgz", + "integrity": "sha512-XUErL0mOPvua5EtlmSOFllSM+Ts1wHzNIv0WNV5FJxWI3Pe6Xxs29xneKDOImC9ErYWuQqK7sQ/hyIaHO5fhOw==", + "license": "MIT", "dependencies": { "tslib": "^2.3.0", "xhr2": "^0.2.0" @@ -687,11 +688,11 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/animations": "18.2.1", - "@angular/common": "18.2.1", - "@angular/compiler": "18.2.1", - "@angular/core": "18.2.1", - "@angular/platform-browser": "18.2.1" + "@angular/animations": "18.2.14", + "@angular/common": "18.2.14", + "@angular/compiler": "18.2.14", + "@angular/core": "18.2.14", + "@angular/platform-browser": "18.2.14" } }, "node_modules/@angular/router": { @@ -712,9 +713,10 @@ } }, "node_modules/@angular/ssr": { - "version": "18.2.1", - "resolved": "https://registry.npmjs.org/@angular/ssr/-/ssr-18.2.1.tgz", - "integrity": "sha512-e+/RZZmUAUVv22JpOQ64z7RzzlCbyx2spDoKJgopp+LmfWqdR99LEvZ6H01yd8ZzynOEQtFIilPcrEWKQ1kSXg==", + "version": "18.2.21", + "resolved": "https://registry.npmjs.org/@angular/ssr/-/ssr-18.2.21.tgz", + "integrity": "sha512-0euH/xxVLv12xVPf1WkfVVmteFccsObjcomCQg/wwu6U4pp5BVqtXpLgA6kAyJByhwbjJWnJJwxovHcVMsRoig==", + "license": "MIT", "dependencies": { "critters": "0.0.24", "tslib": "^2.3.0" @@ -7977,32 +7979,24 @@ } }, "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "devOptional": true, + "license": "MIT", "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", + "bytes": "3.1.2", + "compressible": "~2.0.18", "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", "vary": "~1.1.2" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/compression/node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "devOptional": true, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/compression/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -8018,11 +8012,15 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "devOptional": true }, - "node_modules/compression/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "devOptional": true + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } }, "node_modules/concat-map": { "version": "0.0.1", @@ -16176,9 +16174,9 @@ "license": "BSD-3-Clause" }, "node_modules/morgan": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", - "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.1.tgz", + "integrity": "sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==", "devOptional": true, "license": "MIT", "dependencies": { @@ -16186,7 +16184,7 @@ "debug": "2.6.9", "depd": "~2.0.0", "on-finished": "~2.3.0", - "on-headers": "~1.0.2" + "on-headers": "~1.1.0" }, "engines": { "node": ">= 0.8.0" @@ -16889,10 +16887,11 @@ } }, "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "devOptional": true, + "license": "MIT", "engines": { "node": ">= 0.8" } diff --git a/examples/creative-studio/frontend/package.json b/examples/creative-studio/frontend/package.json index 6f35f90f82f..a3cc2d9b167 100644 --- a/examples/creative-studio/frontend/package.json +++ b/examples/creative-studio/frontend/package.json @@ -33,9 +33,9 @@ "@angular/material": "^18.2.1", "@angular/platform-browser": "^18.1.0", "@angular/platform-browser-dynamic": "^18.1.0", - "@angular/platform-server": "^18.1.0", + "@angular/platform-server": "^18.2.14", "@angular/router": "^18.1.0", - "@angular/ssr": "^18.1.2", + "@angular/ssr": "^18.2.21", "express": "^4.18.2", "file-saver": "^2.0.5", "ngx-image-cropper": "^9.1.5", diff --git a/tools/custom-organization-policy-library/.gitignore b/tools/custom-organization-policy-library/.gitignore index 7cf9b8821f2..2e59532478b 100644 --- a/tools/custom-organization-policy-library/.gitignore +++ b/tools/custom-organization-policy-library/.gitignore @@ -3,6 +3,7 @@ .terraform.tfstate* *.out *.bak +*.env */**/terraform.tfstate* terraform/ tests/venv/ diff --git a/tools/custom-organization-policy-library/build/config/services/schema.accesscontextmanager.yaml b/tools/custom-organization-policy-library/build/config/services/schema.accesscontextmanager.yaml new file mode 100644 index 00000000000..a92ce7b26d2 --- /dev/null +++ b/tools/custom-organization-policy-library/build/config/services/schema.accesscontextmanager.yaml @@ -0,0 +1,25 @@ +#! Copyright 2024 Google LLC +#! +#! Licensed under the Apache License, Version 2.0 (the "License"); +#! you may not use this file except in compliance with the License. +#! You may obtain a copy of the License at +#! +#! http://www.apache.org/licenses/LICENSE-2.0 +#! +#! Unless required by applicable law or agreed to in writing, software +#! distributed under the License is distributed on an "AS IS" BASIS, +#! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#! See the License for the specific language governing permissions and +#! limitations under the License. + +#@ load("@ytt:overlay", "overlay") +#@data/values-schema +--- +#@overlay/match missing_ok=True +accesscontextmanager: + accesscontextmanagerDisableBridgePerimeters: + #@schema/validation one_of=["default", "skip", "include", "skip-policy"] + generation: "default" + bundles: + pci-dss: false + cis: false \ No newline at end of file diff --git a/tools/custom-organization-policy-library/build/config/services/schema.cloudsql.yaml b/tools/custom-organization-policy-library/build/config/services/schema.cloudsql.yaml index aeb6bd8103d..40a36e2b1da 100644 --- a/tools/custom-organization-policy-library/build/config/services/schema.cloudsql.yaml +++ b/tools/custom-organization-policy-library/build/config/services/schema.cloudsql.yaml @@ -92,6 +92,12 @@ cloudsql: bundles: pci-dss: false cis: false + cloudsqlRequirePostgreSQLDatabaseAdditionalFlags: + #@schema/validation one_of=["default", "skip", "include", "skip-policy"] + generation: "default" + bundles: + pci-dss: true + cis: true cloudsqlRequirePostgreSQLDatabaseFlags: #@schema/validation one_of=["default", "skip", "include", "skip-policy"] generation: "default" diff --git a/tools/custom-organization-policy-library/build/config/services/schema.firewall.yaml b/tools/custom-organization-policy-library/build/config/services/schema.firewall.yaml index b6b6bf2040e..f632f9d56b2 100644 --- a/tools/custom-organization-policy-library/build/config/services/schema.firewall.yaml +++ b/tools/custom-organization-policy-library/build/config/services/schema.firewall.yaml @@ -26,6 +26,18 @@ firewall: params: #@schema/validation min_len=1 name_regex: "" + firewallEnforcePolicyRuleLogging: + #@schema/validation one_of=["default", "skip", "include", "skip-policy"] + generation: "default" + bundles: + pci-dss: false + cis: false + firewallEnforceRuleLogging: + #@schema/validation one_of=["default", "skip", "include", "skip-policy"] + generation: "default" + bundles: + pci-dss: false + cis: false firewallRequireDescription: #@schema/validation one_of=["default", "skip", "include", "skip-policy"] generation: "default" diff --git a/tools/custom-organization-policy-library/build/config/services/schema.gke.yaml b/tools/custom-organization-policy-library/build/config/services/schema.gke.yaml index 192f159034d..1622e493dd7 100644 --- a/tools/custom-organization-policy-library/build/config/services/schema.gke.yaml +++ b/tools/custom-organization-policy-library/build/config/services/schema.gke.yaml @@ -17,16 +17,6 @@ --- #@overlay/match missing_ok=True gke: - gkeAllowedInitialClusterVersions: - #@schema/validation one_of=["default", "skip", "include", "skip-policy"] - generation: "default" - bundles: - pci-dss: true - cis: false - params: - #@schema/validation min_len=1 - initial_cluster_versions: - - "" gkeAllowedNodePoolImages: #@schema/validation one_of=["default", "skip", "include", "skip-policy"] generation: "default" diff --git a/tools/custom-organization-policy-library/build/config/services/schema.iam.yaml b/tools/custom-organization-policy-library/build/config/services/schema.iam.yaml index 6a5af1a8e22..c0999c3ac97 100644 --- a/tools/custom-organization-policy-library/build/config/services/schema.iam.yaml +++ b/tools/custom-organization-policy-library/build/config/services/schema.iam.yaml @@ -33,6 +33,9 @@ iam: bundles: pci-dss: false cis: true + params: + exceptions: + - "" iamDisableBasicRoles: #@schema/validation one_of=["default", "skip", "include", "skip-policy"] generation: "default" @@ -51,9 +54,21 @@ iam: bundles: pci-dss: true cis: true + params: + exceptions: + - "" iamDisablePublicBindings: #@schema/validation one_of=["default", "skip", "include", "skip-policy"] generation: "default" bundles: pci-dss: true - cis: true \ No newline at end of file + cis: true + iamDisableRedisAdminRoles: + #@schema/validation one_of=["default", "skip", "include", "skip-policy"] + generation: "default" + bundles: + pci-dss: true + cis: true + params: + exceptions: + - "" \ No newline at end of file diff --git a/tools/custom-organization-policy-library/build/custom-constraints/accesscontextmanager/accesscontextmanagerDisableBridgePerimeters.yaml b/tools/custom-organization-policy-library/build/custom-constraints/accesscontextmanager/accesscontextmanagerDisableBridgePerimeters.yaml new file mode 100644 index 00000000000..5124ed556fa --- /dev/null +++ b/tools/custom-organization-policy-library/build/custom-constraints/accesscontextmanager/accesscontextmanagerDisableBridgePerimeters.yaml @@ -0,0 +1,15 @@ +#@ load("/constraints.lib.star", "build_constraint") +#@ constraint = build_constraint("accesscontextmanagerDisableBridgePerimeters") + +#@ if constraint.to_generate(): +name: #@ constraint.constraint_name() +resourceTypes: +- accesscontextmanager.googleapis.com/ServicePerimeter +methodTypes: +- CREATE +- UPDATE +condition: "resource.perimeterType == 'PERIMETER_TYPE_BRIDGE'" +actionType: DENY +displayName: Deny usage of perimeter bridges +description: Ensure no perimeter bridges are used. Instead, use ingress and egress rules. +#@ end \ No newline at end of file diff --git a/tools/custom-organization-policy-library/build/custom-constraints/cloudsql/cloudsqlRequirePostgreSQLDatabaseAdditionalFlags.yaml b/tools/custom-organization-policy-library/build/custom-constraints/cloudsql/cloudsqlRequirePostgreSQLDatabaseAdditionalFlags.yaml new file mode 100644 index 00000000000..328032d48be --- /dev/null +++ b/tools/custom-organization-policy-library/build/custom-constraints/cloudsql/cloudsqlRequirePostgreSQLDatabaseAdditionalFlags.yaml @@ -0,0 +1,20 @@ +#@ load("/constraints.lib.star", "build_constraint") +#@ constraint = build_constraint("cloudsqlRequirePostgreSQLDatabaseAdditionalFlags") + +#@ if constraint.to_generate(): +name: #@ constraint.constraint_name() +resourceTypes: +- sqladmin.googleapis.com/Instance +methodTypes: +- CREATE +- UPDATE +condition: >- + resource.databaseVersion.startsWith('POSTGRES') && ( + !resource.settings.databaseFlags.exists(flag, flag.name == 'log_checkpoints' && flag.value == 'on') || + !resource.settings.databaseFlags.exists(flag, flag.name == 'log_executor_stats' && flag.value == 'off') || + !resource.settings.databaseFlags.exists(flag, flag.name == 'log_lock_waits' && flag.value == 'on') + ) +actionType: DENY +display_name: Require Cloud SQL for PostgreSQL instance database flags to be configured correctly (e.g log_checkpoints, log_executor_stats, log_lock_waits) +description: Ensure Cloud SQL for PostgreSQL instance database flags are set correctly (e.g log_checkpoints, log_executor_stats, log_lock_waits) +#@ end diff --git a/tools/custom-organization-policy-library/build/custom-constraints/compute/computeAllowedInstanceLabels.yaml b/tools/custom-organization-policy-library/build/custom-constraints/compute/computeAllowedInstanceLabels.yaml index 30b375f08e5..b19a10e3726 100755 --- a/tools/custom-organization-policy-library/build/custom-constraints/compute/computeAllowedInstanceLabels.yaml +++ b/tools/custom-organization-policy-library/build/custom-constraints/compute/computeAllowedInstanceLabels.yaml @@ -2,7 +2,7 @@ #@ constraint = build_constraint("computeAllowedInstanceLabels") #@ def condition(labels): -#@ return "resource.labels.all(label, (label in " + str(labels) + ")) == false" +#@ return "resource.labels.all(label, (label in " + str(labels) + ") || label.startsWith('goog-')) == false" #@ end #@ if constraint.to_generate(): diff --git a/tools/custom-organization-policy-library/build/custom-constraints/firewall/firewallEnforceNamingConvention.yaml b/tools/custom-organization-policy-library/build/custom-constraints/firewall/firewallEnforceNamingConvention.yaml index b9d6e287813..2f5352be2c1 100644 --- a/tools/custom-organization-policy-library/build/custom-constraints/firewall/firewallEnforceNamingConvention.yaml +++ b/tools/custom-organization-policy-library/build/custom-constraints/firewall/firewallEnforceNamingConvention.yaml @@ -2,7 +2,18 @@ #@ constraint = build_constraint("firewallEnforceNamingConvention") #@ def condition(name_regex): -#@ return 'resource.name.matches("' + str(name_regex) + '") == false' +#@ lines = [ +#@ '(', +#@ ' resource.name.matches("' + str(name_regex) + '") == false &&', +#@ ' !resource.name.startsWith("gke-") &&', +#@ ' !resource.name.startsWith("k8s-") &&', +#@ ' !resource.name.endsWith("-hc") &&', +#@ ' !resource.name.startsWith("k8s2-") &&', +#@ ' !resource.name.startsWith("gkegw1-l7-") &&', +#@ ' !resource.name.startsWith("gkemcg1-l7-")', +#@ ')' +#@ ] +#@ return "\n".join(lines) #@ end #@ if constraint.to_generate(): diff --git a/tools/custom-organization-policy-library/build/custom-constraints/firewall/firewallEnforcePolicyRuleLogging.yaml b/tools/custom-organization-policy-library/build/custom-constraints/firewall/firewallEnforcePolicyRuleLogging.yaml new file mode 100644 index 00000000000..c379922dbd4 --- /dev/null +++ b/tools/custom-organization-policy-library/build/custom-constraints/firewall/firewallEnforcePolicyRuleLogging.yaml @@ -0,0 +1,15 @@ +#@ load("/constraints.lib.star", "build_constraint") +#@ constraint = build_constraint("firewallEnforcePolicyRuleLogging") + +#@ if constraint.to_generate(): +name: #@ constraint.constraint_name() +resource_types: +- compute.googleapis.com/FirewallPolicy +condition: resource.rules.exists(rule, rule.action != 'goto_next' && rule.enableLogging == false) +action_type: DENY +method_types: +- CREATE +- UPDATE +display_name: Require Firewall Policy rules to have logging enabled +description: Ensure that Firewall Policy rules have logging enabled +#@ end \ No newline at end of file diff --git a/tools/custom-organization-policy-library/build/custom-constraints/firewall/firewallEnforceRuleLogging.yaml b/tools/custom-organization-policy-library/build/custom-constraints/firewall/firewallEnforceRuleLogging.yaml new file mode 100644 index 00000000000..37344e2e030 --- /dev/null +++ b/tools/custom-organization-policy-library/build/custom-constraints/firewall/firewallEnforceRuleLogging.yaml @@ -0,0 +1,31 @@ +#@ load("/constraints.lib.star", "build_constraint") +#@ constraint = build_constraint("firewallEnforceRuleLogging") + +#@ def condition(): +#@ lines = [ +#@ '(', +#@ ' (has(resource.logConfig) == false || resource.logConfig.enable == false) &&', +#@ ' !resource.name.startsWith("gke-") &&', +#@ ' !resource.name.startsWith("k8s-") &&', +#@ ' !resource.name.endsWith("-hc") &&', +#@ ' !resource.name.startsWith("k8s2-") &&', +#@ ' !resource.name.startsWith("gkegw1-l7-") &&', +#@ ' !resource.name.startsWith("gkemcg1-l7-")', +#@ ')' +#@ ] +#@ return "\n".join(lines) +#@ end + + +#@ if constraint.to_generate(): +name: #@ constraint.constraint_name() +resource_types: +- compute.googleapis.com/Firewall +condition: #@ condition() +action_type: DENY +method_types: +- CREATE +- UPDATE +display_name: Require VPC Firewall rules to have logging enabled +description: Ensure that VPC Firewall rules have logging enabled +#@ end diff --git a/tools/custom-organization-policy-library/build/custom-constraints/firewall/firewallRequireDescription.yaml b/tools/custom-organization-policy-library/build/custom-constraints/firewall/firewallRequireDescription.yaml index 447af1eac9d..a9867476fda 100644 --- a/tools/custom-organization-policy-library/build/custom-constraints/firewall/firewallRequireDescription.yaml +++ b/tools/custom-organization-policy-library/build/custom-constraints/firewall/firewallRequireDescription.yaml @@ -1,11 +1,26 @@ #@ load("/constraints.lib.star", "build_constraint") #@ constraint = build_constraint("firewallRequireDescription") +#@ def condition(): +#@ lines = [ +#@ '(', +#@ ' resource.description == "" &&', +#@ ' !resource.name.startsWith("gke-") &&', +#@ ' !resource.name.startsWith("k8s-") &&', +#@ ' !resource.name.endsWith("-hc") &&', +#@ ' !resource.name.startsWith("k8s2-") &&', +#@ ' !resource.name.startsWith("gkegw1-l7-") &&', +#@ ' !resource.name.startsWith("gkemcg1-l7-")', +#@ ')' +#@ ] +#@ return "\n".join(lines) +#@ end + #@ if constraint.to_generate(): name: #@ constraint.constraint_name() resource_types: - compute.googleapis.com/Firewall -condition: resource.description == "" +condition: #@ condition() action_type: DENY method_types: - CREATE diff --git a/tools/custom-organization-policy-library/build/custom-constraints/gke/gkeAllowedInitialClusterVersions.yaml b/tools/custom-organization-policy-library/build/custom-constraints/gke/gkeAllowedInitialClusterVersions.yaml deleted file mode 100644 index d12a758ee60..00000000000 --- a/tools/custom-organization-policy-library/build/custom-constraints/gke/gkeAllowedInitialClusterVersions.yaml +++ /dev/null @@ -1,19 +0,0 @@ -#@ load("/constraints.lib.star", "build_constraint") -#@ constraint = build_constraint("gkeAllowedInitialClusterVersions") - -#@ def condition(initial_cluster_versions): -#@ return 'resource.initialClusterVersion.matches("(' + "|".join(initial_cluster_versions) + ')$") == false' -#@ end - -#@ if constraint.to_generate(): -name: #@ constraint.constraint_name() -resource_types: -- container.googleapis.com/Cluster -condition: #@ condition(constraint.params().initial_cluster_versions) -action_type: DENY -method_types: -- CREATE -- UPDATE -display_name: Allow only authorized cluster versions when creating GKE cluster -description: Enforce that GKE cluster are using authorized cluster versions -#@ end diff --git a/tools/custom-organization-policy-library/build/custom-constraints/iam/iamAllowedMembers.yaml b/tools/custom-organization-policy-library/build/custom-constraints/iam/iamAllowedMembers.yaml index f210e62dd36..3863ef62a32 100644 --- a/tools/custom-organization-policy-library/build/custom-constraints/iam/iamAllowedMembers.yaml +++ b/tools/custom-organization-policy-library/build/custom-constraints/iam/iamAllowedMembers.yaml @@ -1,10 +1,27 @@ #@ load("/constraints.lib.star", "build_constraint") #@ constraint = build_constraint("iamAllowedMembers") +#@ def allowed_domains(domains): +#@ quoted_domains = ["'%s'" % d for d in domains] +#@ joined_domains = ", ".join(quoted_domains) +#@ +#@ return "!MemberSubjectEndsWith(member, [%s])" % joined_domains +#@ end + #@ def condition(domains): -#@ return "resource.bindings.exists(binding, binding.members.exists(member, !MemberSubjectEndsWith(member, " + str(domains) + ")))" +#@ lines = [ +#@ "resource.bindings.exists(binding,", +#@ " binding.members.exists(member,", +#@ " {domains}", +#@ " )", +#@ ")" +#@ ] +#@ +#@ full_string = "\n".join(lines) +#@ return full_string.format(domains=allowed_domains(domains)) #@ end + #@ if constraint.to_generate(): name: #@ constraint.constraint_name() resourceTypes: @@ -12,7 +29,7 @@ resourceTypes: methodTypes: - CREATE - UPDATE -condition: #@ condition(constraint.params().domains) +condition: #@ condition(constraint.params().domains) actionType: DENY displayName: Deny principals and members outside the organization domain description: Ensure no binding are done with members outside the organization domain diff --git a/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableAdminServiceAccount.yaml b/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableAdminServiceAccount.yaml index 69ca4dde8b3..0a3b9e31ad0 100644 --- a/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableAdminServiceAccount.yaml +++ b/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableAdminServiceAccount.yaml @@ -1,6 +1,33 @@ #@ load("/constraints.lib.star", "build_constraint") #@ constraint = build_constraint("iamDisableAdminServiceAccount") +#@ def exceptions(domains): +#@ quoted_domains = ["'%s'" % d for d in domains] +#@ joined_domains = ", ".join(quoted_domains) +#@ return "!MemberSubjectMatches(member, [%s])" % joined_domains +#@ end + +#@ def condition(principal_exceptions): +#@ lines = [ +#@ "resource.bindings.exists(binding,", +#@ " binding.members.exists(member,", +#@ " {exceptions} &&", +#@ " !MemberSubjectEndsWith(member, ['@cloudservices.gserviceaccount.com']) &&", +#@ " MemberSubjectStartsWith(member, ['serviceAccount:'])", +#@ " ) &&", +#@ " (", +#@ " RoleNameMatches(binding.role, ['roles/editor']) ||", +#@ " RoleNameMatches(binding.role, ['roles/owner']) ||", +#@ " RoleNameContains(binding.role, ['admin', 'Admin'])", +#@ " )", +#@ ")" +#@ ] +#@ +#@ full_string = "\n".join(lines) +#@ return full_string.format(exceptions=exceptions(principal_exceptions)) +#@ end + + #@ if constraint.to_generate(): name: #@ constraint.constraint_name() resourceTypes: @@ -8,16 +35,7 @@ resourceTypes: methodTypes: - CREATE - UPDATE -condition: >- - resource.bindings.exists(binding, - binding.members.exists(member, !MemberSubjectEndsWith(member, ['@cloudservices.gserviceaccount.com']) && - MemberSubjectStartsWith(member, ['serviceAccount:'])) && - ( - RoleNameMatches(binding.role, ["roles/editor"]) || - RoleNameMatches(binding.role, ["roles/owner"]) || - RoleNameContains(binding.role, ['admin', "Admin"]) - ) - ) +condition: #@ condition(constraint.params().exceptions) actionType: DENY displayName: Deny use of the basic roles and usage of admin role for sevice account description: Ensure no use of the basic roles (viewer, editor and owner) and usage of admin role for sevice account diff --git a/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableProjectServiceAccountImpersonationRoles.yaml b/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableProjectServiceAccountImpersonationRoles.yaml index e561dd13575..1539cdd67ff 100644 --- a/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableProjectServiceAccountImpersonationRoles.yaml +++ b/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableProjectServiceAccountImpersonationRoles.yaml @@ -1,6 +1,30 @@ #@ load("/constraints.lib.star", "build_constraint") #@ constraint = build_constraint("iamDisableProjectServiceAccountImpersonationRoles") +#@ def exceptions(domains): +#@ quoted_domains = ["'%s'" % d for d in domains] +#@ joined_domains = ", ".join(quoted_domains) +#@ return "!MemberSubjectMatches(member, [%s])" % joined_domains +#@ end + +#@ def condition(principal_exceptions): +#@ lines = [ +#@ "resource.bindings.exists(binding,", +#@ " binding.members.exists(member,", +#@ " {exceptions} &&", +#@ " MemberSubjectStartsWith(member, ['user:', 'group:'])", +#@ " ) &&", +#@ " (", +#@ " RoleNameMatches(binding.role, ['roles/iam.serviceAccountUser']) ||", +#@ " RoleNameMatches(binding.role, ['roles/iam.serviceAccountTokenCreator'])", +#@ " )", +#@ ")" +#@ ] +#@ +#@ full_string = "\n".join(lines) +#@ return full_string.format(exceptions=exceptions(principal_exceptions)) +#@ end + #@ if constraint.to_generate(): name: #@ constraint.constraint_name() resourceTypes: @@ -8,16 +32,9 @@ resourceTypes: methodTypes: - CREATE - UPDATE -condition: >- - resource.bindings.exists(binding, - binding.members.exists(member,MemberSubjectStartsWith(member, ['user:', 'group:'])) && - ( - RoleNameMatches(binding.role, ["roles/iam.serviceAccountUser"]) || - RoleNameMatches(binding.role, ["roles/iam.serviceAccountTokenCreator"]) - ) - ) +condition: #@ condition(constraint.params().exceptions) actionType: DENY displayName: Deny assignement of the service account user or service account token creator roles to users -description: >- +description: >- Ensure that IAM Users are not assigned the service account user or service account token creator roles (requires usage of IAM Condition and tags to ensure the constraint is not applied on allowed service accounts) #@ end \ No newline at end of file diff --git a/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableRedisAdminRoles.yaml b/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableRedisAdminRoles.yaml new file mode 100644 index 00000000000..a199cd7c52c --- /dev/null +++ b/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableRedisAdminRoles.yaml @@ -0,0 +1,40 @@ +#@ load("/constraints.lib.star", "build_constraint") +#@ constraint = build_constraint("iamDisableRedisAdminRoles") + +#@ def exceptions(principals): +#@ quoted_principals = ["'%s'" % d for d in principals] +#@ joined_principals = ", ".join(quoted_principals) +#@ return "!MemberSubjectMatches(member, [%s])" % joined_principals +#@ end + +#@ def condition(principal_exceptions): +#@ lines = [ +#@ "resource.bindings.exists(binding,", +#@ " binding.members.exists(member,", +#@ " {exceptions} &&", +#@ " (", +#@ " RoleNameMatches(binding.role, ['roles/redis.admin']) ||", +#@ " RoleNameMatches(binding.role, ['roles/redis.editor']) ||", +#@ " RoleNameContains(binding.role, ['roles/redis.viewer'])", +#@ " )", +#@ " )", +#@ ")" +#@ ] +#@ +#@ full_string = "\n".join(lines) +#@ return full_string.format(exceptions=exceptions(principal_exceptions)) +#@ end + + +#@ if constraint.to_generate(): +name: #@ constraint.constraint_name() +resourceTypes: +- iam.googleapis.com/AllowPolicy +methodTypes: +- CREATE +- UPDATE +condition: #@ condition(constraint.params().exceptions) +actionType: DENY +displayName: Deny use of the basic roles +description: Ensure no use of the basic roles (viewer, editor and owner) +#@ end \ No newline at end of file diff --git a/tools/custom-organization-policy-library/build/ytt_lib/config.lib.star b/tools/custom-organization-policy-library/build/ytt_lib/config.lib.star index 4b28c5f819c..76b6d91c54d 100644 --- a/tools/custom-organization-policy-library/build/ytt_lib/config.lib.star +++ b/tools/custom-organization-policy-library/build/ytt_lib/config.lib.star @@ -16,6 +16,7 @@ load("@ytt:data", "data") load("@ytt:struct", "struct") services = [ + "accesscontextmanager", "cloudbuild", "cloudkms", "cloudrun", diff --git a/tools/custom-organization-policy-library/cloudbuild.yaml b/tools/custom-organization-policy-library/cloudbuild.yaml index 59e8929ac82..3c554f4f4b7 100644 --- a/tools/custom-organization-policy-library/cloudbuild.yaml +++ b/tools/custom-organization-policy-library/cloudbuild.yaml @@ -31,22 +31,22 @@ steps: make build dir: /workspace/tools/custom-organization-policy-library entrypoint: bash - # - name: gcr.io/cloud-builders/gcloud - # args: - # - '-c' - # - | - # apt-get update && apt-get install -y make - # make deploy-constraints - # dir: /workspace/tools/custom-organization-policy-library - # entrypoint: bash - # - name: gcr.io/cloud-builders/gcloud - # args: - # - '-c' - # - | - # apt-get update && apt-get install -y make - # make deploy-policies - # dir: /workspace/tools/custom-organization-policy-library - # entrypoint: bash + - name: gcr.io/cloud-builders/gcloud + args: + - '-c' + - | + apt-get update && apt-get install -y make + make deploy-constraints + dir: /workspace/tools/custom-organization-policy-library + entrypoint: bash + - name: gcr.io/cloud-builders/gcloud + args: + - '-c' + - | + apt-get update && apt-get install -y make + make deploy-policies + dir: /workspace/tools/custom-organization-policy-library + entrypoint: bash - name: gcr.io/cloud-builders/gcloud args: - '-c' @@ -57,7 +57,16 @@ steps: export PROJECT_ID="$_PROJECT_ID" export PROJECT_NUMBER="$_PROJECT_NUMBER" export PREFIX="$_PREFIX" + set +e pytest main.py --html=${SHORT_SHA}_report.html $_PYTEST_ARGS + PYTEST_EXIT_CODE=$$? + set -e + if [ $$PYTEST_EXIT_CODE -eq 0 ]; then + echo "✅ No error during running test" + else + echo "⚠️ Error during running tests" + fi + exit 0 dir: /workspace/tools/custom-organization-policy-library/tests entrypoint: bash timeout: '10800s' diff --git a/tools/custom-organization-policy-library/docs/index.md b/tools/custom-organization-policy-library/docs/index.md index 457e5db30fa..679be9de080 100644 --- a/tools/custom-organization-policy-library/docs/index.md +++ b/tools/custom-organization-policy-library/docs/index.md @@ -17,6 +17,7 @@ In addition to browsing al available policies, you can explore implementation of |Service |Name Preventive |Description |CIS for GCP 3.0 |CIS for GKE 1.5 |PCI-DSS 4.0 | |:--------------------:|--------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------:|:------------------------------------------------:|:----------------------------------------------------------------------------------------------------------------------:| +| Access Context |accesscontextmanagerDisableBridgePerimeters |Ensure no perimeter bridges are used. Instead, use ingress and egress rules. | | | | | Big Query |iamDisablePublicBindings |Ensure That BigQuery Datasets Are Not Anonymously or Publicly Accessible | 7.1 | | 1.3.1 | | Cloud Build |cloudbuildAllowedNetworkPeering |Enforce only authorized VPC peering connections are used for Cloud Build private pools | | | | | Cloud Build |cloudbuildAllowedPubSubTopic |Enforce authorized Pub/Sub topics configured for Cloud Build trigger | | | | @@ -52,6 +53,9 @@ In addition to browsing al available policies, you can explore implementation of | Cloud SQL |cloudsqlRequirePostgreSQLDatabaseFlags |Ensure ‘Log_min_error_statement’ Database Flag for Cloud SQL PostgreSQL Instance Is Set to ‘Error’ or Stricter | 6.2.6 | | 10.2.1, 10.2.1.2, 10.2.1.5, 9.4.5 | | Cloud SQL |cloudsqlRequirePostgreSQLDatabaseFlags |Ensure That the ‘Log_min_duration_statement’ Database Flag for Cloud SQL PostgreSQL Instance Is Set to '-1' (Disabled) | 6.2.7 | | 10.2.1, 10.2.1.2, 10.2.1.5, 9.4.5 | | Cloud SQL |cloudsqlRequirePostgreSQLDatabaseFlags |Ensure That 'cloudsql.enable_pgaudit' Database Flag for each Cloud Sql Postgresql Instance Is Set to 'on' For Centralized Logging | 6.2.8 | | | +| Cloud SQL |cloudsqlRequirePostgreSQLDatabaseAdditionalFlags |Ensure That the ‘Log_checkpoints’ Database Flag for Cloud SQL PostgreSQL Instance Is Set to ‘On’ | | | | +| Cloud SQL |cloudsqlRequirePostgreSQLDatabaseAdditionalFlags |Ensure That the ‘Log_executor_stats’ Database Flag for Cloud SQL PostgreSQL Instance Is Set to ‘Off’ | | | | +| Cloud SQL |cloudsqlRequirePostgreSQLDatabaseAdditionalFlags |Ensure That the ‘Log_lock_waits’ Database Flag for Cloud SQL PostgreSQL Instance Is Set to ‘On’ | | | | | Cloud SQL |cloudsqlRequireSQLServerDatabaseFlags |Ensure 'external scripts enabled' database flag for Cloud SQL SQL Server instance is set to 'off' | 6.3.1 | | 1.2.5, 2.2.4, 6.4.3 | | Cloud SQL |cloudsqlRequireSQLServerDatabaseFlags |Ensure that the 'cross db ownership chaining' database flag for Cloud SQL SQL Server instance is set to 'off' | 6.3.2 | | | | Cloud SQL |cloudsqlRequireSQLServerDatabaseFlags |Ensure 'user Connections' Database Flag for Cloud Sql Sql Server Instance Is Set to a Non-limiting Value | 6.3.3 | | 1.1.1, 1.2.1, 1.2.6, 1.2.7, 1.5.1, 2.1.1, 2.2.1 | @@ -90,6 +94,8 @@ In addition to browsing al available policies, you can explore implementation of | DNS |dnsRequireManageZoneLogging |Ensure that Cloud DNS logging is enabled when configuring a DNS Public Managed Zone | 3.3 | | | | DNS |dnsAllowedSigningAlgorithms |Ensure That RSASHA1 Is Not Used for the Key-Signing Key in Cloud DNS DNSSEC | 3.4 | | 1.1.1, 1.2.1, 1.2.6, 1.2.7, 1.4.2, 1.5.1, 2.1.1, 2.2.1 | | DNS |dnsAllowedSigningAlgorithms |Ensure That RSASHA1 Is Not Used for the Zone-Signing Key in Cloud DNS DNSSEC | 3.5 | | 1.1.1, 1.2.1, 1.2.6, 1.2.7, 1.4.2, 1.5.1, 2.1.1, 2.2.1 | +| Firewall |firewallEnforcePolicyRuleLogging |Enforce logging for Firewall Policy rules | | | | +| Firewall |firewallEnforceRuleLogging |Enforce logging for VPC firewall rules | | | | | Firewall |firewallRestrictSshPolicyRule |Ensure That SSH Access Is Restricted From the Internet when using Firewall Policy | 3.6 | | 1.2.1, 1.4.1 | | Firewall |firewallRestrictRdpPolicyRule |Ensure That RDP Access Is Restricted From the Internet when using Firewall Policy | 3.7 | | 1.2.1, 1.4.1 | | Firewall |firewallRestrictSshRule |Ensure That SSH Access Is Restricted From the Internet when using VPC Firewall Rule | 3.6 | | 1.2.1, 1.4.1 | @@ -126,13 +132,13 @@ In addition to browsing al available policies, you can explore implementation of | GKE |gkeRequireDataplaneV2 |Enforce that the GKE clusters is configured to use dataplane v2 | | | | | GKE |gkeRequireCOSImage |Enforce the nodes pool are using Container-Optimized OS for running containers | | | 2.2.6 | | GKE |gkeRequireRegionalClusters |Enforce the creation of regional GKE clusters | | | | -| GKE |gkeAllowedInitialClusterVersions |Enforce that GKE nodes are using authorized GKE versions for the control plane | | | 6.3.1 | | IAM |iamAllowedMembers |Ensure no binding are done with members outside the organization domain | 1.1 | | | | IAM |iamDisableBasicRoles |Ensure no usage of the basic roles (viewer, editor and owner) | | | | | IAM |iamDisableGmailMembers |Ensure no binding are done by using gmail members | | | | | IAM |iamDisablePublicBindings |Ensure no use of public bindings (allUsers, allAuthenticatedUsers) | | | | | IAM |iamDisableAdminServiceAccount |Ensure That Service Account Has No Admin Privileges | 1.5 | | | | IAM |iamDisableProjectServiceAccountImpersonationRoles |Ensure That IAM Users Are Not Assigned the Service Account User or Service Account Token Creator Roles at Project Level | 1.6 | | 1.3.1 | +| IAM |iamDisableRedisAdminRoles |Prevent the usage of Redis admin, editor and viewer roles that are assigned at the organization or folder level | | | | | Network |networkRequireBackendServiceLogging |Ensure Logging is enabled for HTTP(S) Load Balancer | 2.16 | | 10.2.1, 10.2.1.1, 10.2.1.2, 10.2.1.3, 10.2.1.4, 10.2.1.5, 10.2.1.6, 10.2.1.7, 10.2.2, 5.3.4, 6.4.1, 6.4.2 | | Network |networkDisableWeakSSLPolicy |Ensure No HTTPS or SSL Proxy Load Balancers Permit SSL Policies With Weak Cipher Suites | 3.9 | | | | Network |networkDisableTargetHTTPProxy |Ensure No HTTPS or SSL Proxy Load Balancers Permit SSL Policies With Weak Cipher Suites | 3.9 | | | diff --git a/tools/custom-organization-policy-library/samples/gcloud/constraints/accesscontextmanager/accesscontextmanagerDisableBridgePerimeters.yaml b/tools/custom-organization-policy-library/samples/gcloud/constraints/accesscontextmanager/accesscontextmanagerDisableBridgePerimeters.yaml new file mode 100755 index 00000000000..c74e1d1b692 --- /dev/null +++ b/tools/custom-organization-policy-library/samples/gcloud/constraints/accesscontextmanager/accesscontextmanagerDisableBridgePerimeters.yaml @@ -0,0 +1,10 @@ +name: organizations/11111111/customConstraints/custom.accesscontextmanagerDisableBridgePerimeters +resourceTypes: +- accesscontextmanager.googleapis.com/ServicePerimeter +methodTypes: +- CREATE +- UPDATE +condition: resource.perimeterType == 'PERIMETER_TYPE_BRIDGE' +actionType: DENY +displayName: Deny usage of perimeter bridges +description: Ensure no perimeter bridges are used. Instead, use ingress and egress rules. diff --git a/tools/custom-organization-policy-library/samples/gcloud/constraints/cloudsql/cloudsqlRequirePostgreSQLDatabaseAdditionalFlags.yaml b/tools/custom-organization-policy-library/samples/gcloud/constraints/cloudsql/cloudsqlRequirePostgreSQLDatabaseAdditionalFlags.yaml new file mode 100755 index 00000000000..9d2e0afad41 --- /dev/null +++ b/tools/custom-organization-policy-library/samples/gcloud/constraints/cloudsql/cloudsqlRequirePostgreSQLDatabaseAdditionalFlags.yaml @@ -0,0 +1,15 @@ +name: organizations/11111111/customConstraints/custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags +resourceTypes: +- sqladmin.googleapis.com/Instance +methodTypes: +- CREATE +- UPDATE +condition: |- + resource.databaseVersion.startsWith('POSTGRES') && ( + !resource.settings.databaseFlags.exists(flag, flag.name == 'log_checkpoints' && flag.value == 'on') || + !resource.settings.databaseFlags.exists(flag, flag.name == 'log_executor_stats' && flag.value == 'off') || + !resource.settings.databaseFlags.exists(flag, flag.name == 'log_lock_waits' && flag.value == 'on') + ) +actionType: DENY +display_name: Require Cloud SQL for PostgreSQL instance database flags to be configured correctly (e.g log_checkpoints, log_executor_stats, log_lock_waits) +description: Ensure Cloud SQL for PostgreSQL instance database flags are set correctly (e.g log_checkpoints, log_executor_stats, log_lock_waits) diff --git a/tools/custom-organization-policy-library/samples/gcloud/constraints/compute/computeAllowedInstanceLabels.yaml b/tools/custom-organization-policy-library/samples/gcloud/constraints/compute/computeAllowedInstanceLabels.yaml index c06f21a3264..3ff484e36ce 100755 --- a/tools/custom-organization-policy-library/samples/gcloud/constraints/compute/computeAllowedInstanceLabels.yaml +++ b/tools/custom-organization-policy-library/samples/gcloud/constraints/compute/computeAllowedInstanceLabels.yaml @@ -1,7 +1,7 @@ name: organizations/11111111/customConstraints/custom.computeAllowedInstanceLabels resource_types: - compute.googleapis.com/Instance -condition: resource.labels.all(label, (label in ["label-0", "label-1"])) == false +condition: resource.labels.all(label, (label in ["label-0", "label-1"]) || label.startsWith('goog-')) == false action_type: DENY method_types: - CREATE diff --git a/tools/custom-organization-policy-library/samples/gcloud/constraints/compute/computeRestrictDiskSize.yaml b/tools/custom-organization-policy-library/samples/gcloud/constraints/compute/computeRestrictDiskSize.yaml index e4af6b12a57..e143bf9c84d 100755 --- a/tools/custom-organization-policy-library/samples/gcloud/constraints/compute/computeRestrictDiskSize.yaml +++ b/tools/custom-organization-policy-library/samples/gcloud/constraints/compute/computeRestrictDiskSize.yaml @@ -1,7 +1,7 @@ name: organizations/11111111/customConstraints/custom.computeRestrictDiskSize resource_types: - compute.googleapis.com/Disk -condition: resource.sizeGb >= 100 +condition: resource.sizeGb >= 1000 action_type: DENY method_types: - CREATE diff --git a/tools/custom-organization-policy-library/samples/gcloud/constraints/firewall/firewallEnforceNamingConvention.yaml b/tools/custom-organization-policy-library/samples/gcloud/constraints/firewall/firewallEnforceNamingConvention.yaml index 76a961c02ad..e9d30279136 100755 --- a/tools/custom-organization-policy-library/samples/gcloud/constraints/firewall/firewallEnforceNamingConvention.yaml +++ b/tools/custom-organization-policy-library/samples/gcloud/constraints/firewall/firewallEnforceNamingConvention.yaml @@ -1,7 +1,16 @@ name: organizations/11111111/customConstraints/custom.firewallEnforceNamingConvention resource_types: - compute.googleapis.com/Firewall -condition: resource.name.matches("^(allow|deny)-(all|rdp|ssh|tcp|udp|icmp|custom)[a-z0-9-]*") == false +condition: |- + ( + resource.name.matches("^(allow|deny)-(all|rdp|ssh|tcp|udp|icmp|custom)[a-z0-9-]*") == false && + !resource.name.startsWith("gke-") && + !resource.name.startsWith("k8s-") && + !resource.name.endsWith("-hc") && + !resource.name.startsWith("k8s2-") && + !resource.name.startsWith("gkegw1-l7-") && + !resource.name.startsWith("gkemcg1-l7-") + ) action_type: DENY method_types: - CREATE diff --git a/tools/custom-organization-policy-library/samples/gcloud/constraints/firewall/firewallEnforcePolicyRuleLogging.yaml b/tools/custom-organization-policy-library/samples/gcloud/constraints/firewall/firewallEnforcePolicyRuleLogging.yaml new file mode 100755 index 00000000000..915b4fcd8f1 --- /dev/null +++ b/tools/custom-organization-policy-library/samples/gcloud/constraints/firewall/firewallEnforcePolicyRuleLogging.yaml @@ -0,0 +1,10 @@ +name: organizations/11111111/customConstraints/custom.firewallEnforcePolicyRuleLogging +resource_types: +- compute.googleapis.com/FirewallPolicy +condition: resource.rules.exists(rule, rule.action != 'goto_next' && rule.enableLogging == false) +action_type: DENY +method_types: +- CREATE +- UPDATE +display_name: Require Firewall Policy rules to have logging enabled +description: Ensure that Firewall Policy rules have logging enabled diff --git a/tools/custom-organization-policy-library/samples/gcloud/constraints/firewall/firewallEnforceRuleLogging.yaml b/tools/custom-organization-policy-library/samples/gcloud/constraints/firewall/firewallEnforceRuleLogging.yaml new file mode 100755 index 00000000000..1ac174a483a --- /dev/null +++ b/tools/custom-organization-policy-library/samples/gcloud/constraints/firewall/firewallEnforceRuleLogging.yaml @@ -0,0 +1,19 @@ +name: organizations/11111111/customConstraints/custom.firewallEnforceRuleLogging +resource_types: +- compute.googleapis.com/Firewall +condition: |- + ( + (has(resource.logConfig) == false || resource.logConfig.enable == false) && + !resource.name.startsWith("gke-") && + !resource.name.startsWith("k8s-") && + !resource.name.endsWith("-hc") && + !resource.name.startsWith("k8s2-") && + !resource.name.startsWith("gkegw1-l7-") && + !resource.name.startsWith("gkemcg1-l7-") + ) +action_type: DENY +method_types: +- CREATE +- UPDATE +display_name: Require VPC Firewall rules to have logging enabled +description: Ensure that VPC Firewall rules have logging enabled diff --git a/tools/custom-organization-policy-library/samples/gcloud/constraints/firewall/firewallRequireDescription.yaml b/tools/custom-organization-policy-library/samples/gcloud/constraints/firewall/firewallRequireDescription.yaml index a705ebc7504..6d06f0595c4 100755 --- a/tools/custom-organization-policy-library/samples/gcloud/constraints/firewall/firewallRequireDescription.yaml +++ b/tools/custom-organization-policy-library/samples/gcloud/constraints/firewall/firewallRequireDescription.yaml @@ -1,7 +1,16 @@ name: organizations/11111111/customConstraints/custom.firewallRequireDescription resource_types: - compute.googleapis.com/Firewall -condition: resource.description == "" +condition: |- + ( + resource.description == "" && + !resource.name.startsWith("gke-") && + !resource.name.startsWith("k8s-") && + !resource.name.endsWith("-hc") && + !resource.name.startsWith("k8s2-") && + !resource.name.startsWith("gkegw1-l7-") && + !resource.name.startsWith("gkemcg1-l7-") + ) action_type: DENY method_types: - CREATE diff --git a/tools/custom-organization-policy-library/samples/gcloud/constraints/gke/gkeAllowedInitialClusterVersions.yaml b/tools/custom-organization-policy-library/samples/gcloud/constraints/gke/gkeAllowedInitialClusterVersions.yaml deleted file mode 100755 index f0ae9f7fd94..00000000000 --- a/tools/custom-organization-policy-library/samples/gcloud/constraints/gke/gkeAllowedInitialClusterVersions.yaml +++ /dev/null @@ -1,10 +0,0 @@ -name: organizations/11111111/customConstraints/custom.gkeAllowedInitialClusterVersions -resource_types: -- container.googleapis.com/Cluster -condition: resource.initialClusterVersion.matches("(1.33.0-gke.2248000)$") == false -action_type: DENY -method_types: -- CREATE -- UPDATE -display_name: Allow only authorized cluster versions when creating GKE cluster -description: Enforce that GKE cluster are using authorized cluster versions diff --git a/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamAllowedMembers.yaml b/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamAllowedMembers.yaml index 59ae8f410a8..bfac23d4cb6 100755 --- a/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamAllowedMembers.yaml +++ b/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamAllowedMembers.yaml @@ -4,7 +4,12 @@ resourceTypes: methodTypes: - CREATE - UPDATE -condition: resource.bindings.exists(binding, binding.members.exists(member, !MemberSubjectEndsWith(member, ["@google.com", ".gserviceaccount.com"]))) +condition: |- + resource.bindings.exists(binding, + binding.members.exists(member, + !MemberSubjectEndsWith(member, ['@google.com', '.gserviceaccount.com']) + ) + ) actionType: DENY displayName: Deny principals and members outside the organization domain description: Ensure no binding are done with members outside the organization domain diff --git a/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableAdminServiceAccount.yaml b/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableAdminServiceAccount.yaml index f8e19f2d1c8..0f45d695d4b 100755 --- a/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableAdminServiceAccount.yaml +++ b/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableAdminServiceAccount.yaml @@ -6,12 +6,15 @@ methodTypes: - UPDATE condition: |- resource.bindings.exists(binding, - binding.members.exists(member, !MemberSubjectEndsWith(member, ['@cloudservices.gserviceaccount.com']) && - MemberSubjectStartsWith(member, ['serviceAccount:'])) && + binding.members.exists(member, + !MemberSubjectMatches(member, ['serviceAccount:my-service-account@my-project.iam.gserviceaccount.com']) && + !MemberSubjectEndsWith(member, ['@cloudservices.gserviceaccount.com']) && + MemberSubjectStartsWith(member, ['serviceAccount:']) + ) && ( - RoleNameMatches(binding.role, ["roles/editor"]) || - RoleNameMatches(binding.role, ["roles/owner"]) || - RoleNameContains(binding.role, ['admin', "Admin"]) + RoleNameMatches(binding.role, ['roles/editor']) || + RoleNameMatches(binding.role, ['roles/owner']) || + RoleNameContains(binding.role, ['admin', 'Admin']) ) ) actionType: DENY diff --git a/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableProjectServiceAccountImpersonationRoles.yaml b/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableProjectServiceAccountImpersonationRoles.yaml index a1c8eceae20..8067aee469e 100755 --- a/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableProjectServiceAccountImpersonationRoles.yaml +++ b/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableProjectServiceAccountImpersonationRoles.yaml @@ -6,10 +6,13 @@ methodTypes: - UPDATE condition: |- resource.bindings.exists(binding, - binding.members.exists(member,MemberSubjectStartsWith(member, ['user:', 'group:'])) && + binding.members.exists(member, + !MemberSubjectMatches(member, ['user:my-user@my-project.com']) && + MemberSubjectStartsWith(member, ['user:', 'group:']) + ) && ( - RoleNameMatches(binding.role, ["roles/iam.serviceAccountUser"]) || - RoleNameMatches(binding.role, ["roles/iam.serviceAccountTokenCreator"]) + RoleNameMatches(binding.role, ['roles/iam.serviceAccountUser']) || + RoleNameMatches(binding.role, ['roles/iam.serviceAccountTokenCreator']) ) ) actionType: DENY diff --git a/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableRedisAdminRoles.yaml b/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableRedisAdminRoles.yaml new file mode 100755 index 00000000000..4aaf3be7291 --- /dev/null +++ b/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableRedisAdminRoles.yaml @@ -0,0 +1,20 @@ +name: organizations/11111111/customConstraints/custom.iamDisableRedisAdminRoles +resourceTypes: +- iam.googleapis.com/AllowPolicy +methodTypes: +- CREATE +- UPDATE +condition: |- + resource.bindings.exists(binding, + binding.members.exists(member, + !MemberSubjectMatches(member, []) && + ( + RoleNameMatches(binding.role, ['roles/redis.admin']) || + RoleNameMatches(binding.role, ['roles/redis.editor']) || + RoleNameContains(binding.role, ['roles/redis.viewer']) + ) + ) + ) +actionType: DENY +displayName: Deny use of the basic roles +description: Ensure no use of the basic roles (viewer, editor and owner) diff --git a/tools/custom-organization-policy-library/samples/gcloud/policies/accesscontextmanager/custom.accesscontextmanagerDisableBridgePerimeters.yaml b/tools/custom-organization-policy-library/samples/gcloud/policies/accesscontextmanager/custom.accesscontextmanagerDisableBridgePerimeters.yaml new file mode 100644 index 00000000000..6bc92245dd8 --- /dev/null +++ b/tools/custom-organization-policy-library/samples/gcloud/policies/accesscontextmanager/custom.accesscontextmanagerDisableBridgePerimeters.yaml @@ -0,0 +1,4 @@ +name: organizations/11111111/policies/custom.accesscontextmanagerDisableBridgePerimeters +spec: + rules: + - enforce: true diff --git a/tools/custom-organization-policy-library/samples/gcloud/policies/cloudsql/custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags.yaml b/tools/custom-organization-policy-library/samples/gcloud/policies/cloudsql/custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags.yaml new file mode 100644 index 00000000000..07c78af4a8c --- /dev/null +++ b/tools/custom-organization-policy-library/samples/gcloud/policies/cloudsql/custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags.yaml @@ -0,0 +1,4 @@ +name: organizations/11111111/policies/custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags +spec: + rules: + - enforce: true diff --git a/tools/custom-organization-policy-library/samples/gcloud/policies/firewall/custom.firewallEnforcePolicyRuleLogging.yaml b/tools/custom-organization-policy-library/samples/gcloud/policies/firewall/custom.firewallEnforcePolicyRuleLogging.yaml new file mode 100644 index 00000000000..b2d76f38967 --- /dev/null +++ b/tools/custom-organization-policy-library/samples/gcloud/policies/firewall/custom.firewallEnforcePolicyRuleLogging.yaml @@ -0,0 +1,4 @@ +name: organizations/11111111/policies/custom.firewallEnforcePolicyRuleLogging +spec: + rules: + - enforce: true diff --git a/tools/custom-organization-policy-library/samples/gcloud/policies/firewall/custom.firewallEnforceRuleLogging.yaml b/tools/custom-organization-policy-library/samples/gcloud/policies/firewall/custom.firewallEnforceRuleLogging.yaml new file mode 100644 index 00000000000..493bde5ff76 --- /dev/null +++ b/tools/custom-organization-policy-library/samples/gcloud/policies/firewall/custom.firewallEnforceRuleLogging.yaml @@ -0,0 +1,4 @@ +name: organizations/11111111/policies/custom.firewallEnforceRuleLogging +spec: + rules: + - enforce: true diff --git a/tools/custom-organization-policy-library/samples/gcloud/policies/gke/custom.gkeAllowedInitialClusterVersions.yaml b/tools/custom-organization-policy-library/samples/gcloud/policies/gke/custom.gkeAllowedInitialClusterVersions.yaml deleted file mode 100644 index 42798a43fae..00000000000 --- a/tools/custom-organization-policy-library/samples/gcloud/policies/gke/custom.gkeAllowedInitialClusterVersions.yaml +++ /dev/null @@ -1,4 +0,0 @@ -name: organizations/11111111/policies/custom.gkeAllowedInitialClusterVersions -spec: - rules: - - enforce: true diff --git a/tools/custom-organization-policy-library/samples/gcloud/policies/iam/custom.iamDisableRedisAdminRoles.yaml b/tools/custom-organization-policy-library/samples/gcloud/policies/iam/custom.iamDisableRedisAdminRoles.yaml new file mode 100644 index 00000000000..fa962f73a15 --- /dev/null +++ b/tools/custom-organization-policy-library/samples/gcloud/policies/iam/custom.iamDisableRedisAdminRoles.yaml @@ -0,0 +1,4 @@ +name: organizations/11111111/policies/custom.iamDisableRedisAdminRoles +spec: + rules: + - enforce: true diff --git a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.accesscontextmanagerDisableBridgePerimeters.yaml b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.accesscontextmanagerDisableBridgePerimeters.yaml new file mode 100644 index 00000000000..2657c6a9034 --- /dev/null +++ b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.accesscontextmanagerDisableBridgePerimeters.yaml @@ -0,0 +1,12 @@ +custom.accesscontextmanagerDisableBridgePerimeters: + action_type: DENY + condition: |- + resource.perimeterType == 'PERIMETER_TYPE_BRIDGE' + description: Ensure no perimeter bridges are used. Instead, use ingress and egress + rules. + display_name: Deny usage of perimeter bridges + method_types: + - CREATE + - UPDATE + resource_types: + - accesscontextmanager.googleapis.com/ServicePerimeter diff --git a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags.yaml b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags.yaml new file mode 100644 index 00000000000..51c6d91b47a --- /dev/null +++ b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags.yaml @@ -0,0 +1,17 @@ +custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags: + action_type: DENY + condition: |- + resource.databaseVersion.startsWith('POSTGRES') && ( + !resource.settings.databaseFlags.exists(flag, flag.name == 'log_checkpoints' && flag.value == 'on') || + !resource.settings.databaseFlags.exists(flag, flag.name == 'log_executor_stats' && flag.value == 'off') || + !resource.settings.databaseFlags.exists(flag, flag.name == 'log_lock_waits' && flag.value == 'on') + ) + description: Ensure Cloud SQL for PostgreSQL instance database flags are set correctly + (e.g log_checkpoints, log_executor_stats, log_lock_waits) + display_name: Require Cloud SQL for PostgreSQL instance database flags to be configured + correctly (e.g log_checkpoints, log_executor_stats, log_lock_waits) + method_types: + - CREATE + - UPDATE + resource_types: + - sqladmin.googleapis.com/Instance diff --git a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.computeAllowedInstanceLabels.yaml b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.computeAllowedInstanceLabels.yaml index 60feec5b4d3..29da43a039d 100644 --- a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.computeAllowedInstanceLabels.yaml +++ b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.computeAllowedInstanceLabels.yaml @@ -1,7 +1,7 @@ custom.computeAllowedInstanceLabels: action_type: DENY condition: |- - resource.labels.all(label, (label in ["label-0", "label-1"])) == false + resource.labels.all(label, (label in ["label-0", "label-1"]) || label.startsWith('goog-')) == false description: Prevent the creation of VMs not having the expected labels display_name: Allow only specific labels method_types: diff --git a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.computeRestrictDiskSize.yaml b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.computeRestrictDiskSize.yaml index f6fc08e23ab..7438928fc1c 100644 --- a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.computeRestrictDiskSize.yaml +++ b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.computeRestrictDiskSize.yaml @@ -1,7 +1,7 @@ custom.computeRestrictDiskSize: action_type: DENY condition: |- - resource.sizeGb >= 100 + resource.sizeGb >= 1000 description: Prevent the creation of VMs having a disk size that are greater than what is specified display_name: Require specific disk size diff --git a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.firewallEnforceNamingConvention.yaml b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.firewallEnforceNamingConvention.yaml index cbaab68981a..4a3bda8ceae 100644 --- a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.firewallEnforceNamingConvention.yaml +++ b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.firewallEnforceNamingConvention.yaml @@ -1,7 +1,15 @@ custom.firewallEnforceNamingConvention: action_type: DENY condition: |- - resource.name.matches("^(allow|deny)-(all|rdp|ssh|tcp|udp|icmp|custom)[a-z0-9-]*") == false + ( + resource.name.matches("^(allow|deny)-(all|rdp|ssh|tcp|udp|icmp|custom)[a-z0-9-]*") == false && + !resource.name.startsWith("gke-") && + !resource.name.startsWith("k8s-") && + !resource.name.endsWith("-hc") && + !resource.name.startsWith("k8s2-") && + !resource.name.startsWith("gkegw1-l7-") && + !resource.name.startsWith("gkemcg1-l7-") + ) description: Prevent the creation of VPC Firewall rule that are not following the naming convention display_name: Enforce VPC Firewall rule naming convention diff --git a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.firewallEnforcePolicyRuleLogging.yaml b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.firewallEnforcePolicyRuleLogging.yaml new file mode 100644 index 00000000000..ef1fe18fc14 --- /dev/null +++ b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.firewallEnforcePolicyRuleLogging.yaml @@ -0,0 +1,11 @@ +custom.firewallEnforcePolicyRuleLogging: + action_type: DENY + condition: |- + resource.rules.exists(rule, rule.action != 'goto_next' && rule.enableLogging == false) + description: Ensure that Firewall Policy rules have logging enabled + display_name: Require Firewall Policy rules to have logging enabled + method_types: + - CREATE + - UPDATE + resource_types: + - compute.googleapis.com/FirewallPolicy diff --git a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.firewallEnforceRuleLogging.yaml b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.firewallEnforceRuleLogging.yaml new file mode 100644 index 00000000000..c6bcf036041 --- /dev/null +++ b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.firewallEnforceRuleLogging.yaml @@ -0,0 +1,19 @@ +custom.firewallEnforceRuleLogging: + action_type: DENY + condition: |- + ( + (has(resource.logConfig) == false || resource.logConfig.enable == false) && + !resource.name.startsWith("gke-") && + !resource.name.startsWith("k8s-") && + !resource.name.endsWith("-hc") && + !resource.name.startsWith("k8s2-") && + !resource.name.startsWith("gkegw1-l7-") && + !resource.name.startsWith("gkemcg1-l7-") + ) + description: Ensure that VPC Firewall rules have logging enabled + display_name: Require VPC Firewall rules to have logging enabled + method_types: + - CREATE + - UPDATE + resource_types: + - compute.googleapis.com/Firewall diff --git a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.firewallRequireDescription.yaml b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.firewallRequireDescription.yaml index d17ac5e6a41..4b39733786d 100644 --- a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.firewallRequireDescription.yaml +++ b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.firewallRequireDescription.yaml @@ -1,7 +1,15 @@ custom.firewallRequireDescription: action_type: DENY condition: |- - resource.description == "" + ( + resource.description == "" && + !resource.name.startsWith("gke-") && + !resource.name.startsWith("k8s-") && + !resource.name.endsWith("-hc") && + !resource.name.startsWith("k8s2-") && + !resource.name.startsWith("gkegw1-l7-") && + !resource.name.startsWith("gkemcg1-l7-") + ) description: Prevent the creation of VPC firewall rule that does not have description provided. Description can be used for auditing to refer to security control display_name: Require description on Firewall rule diff --git a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.gkeAllowedInitialClusterVersions.yaml b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.gkeAllowedInitialClusterVersions.yaml deleted file mode 100644 index 98ce64e10c7..00000000000 --- a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.gkeAllowedInitialClusterVersions.yaml +++ /dev/null @@ -1,11 +0,0 @@ -custom.gkeAllowedInitialClusterVersions: - action_type: DENY - condition: |- - resource.initialClusterVersion.matches("(1.33.0-gke.2248000)$") == false - description: Enforce that GKE cluster are using authorized cluster versions - display_name: Allow only authorized cluster versions when creating GKE cluster - method_types: - - CREATE - - UPDATE - resource_types: - - container.googleapis.com/Cluster diff --git a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamAllowedMembers.yaml b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamAllowedMembers.yaml index 2e06696d72f..cd611b2a296 100644 --- a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamAllowedMembers.yaml +++ b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamAllowedMembers.yaml @@ -1,7 +1,11 @@ custom.iamAllowedMembers: action_type: DENY condition: |- - resource.bindings.exists(binding, binding.members.exists(member, !MemberSubjectEndsWith(member, ["@google.com", ".gserviceaccount.com"]))) + resource.bindings.exists(binding, + binding.members.exists(member, + !MemberSubjectEndsWith(member, ['@google.com', '.gserviceaccount.com']) + ) + ) description: Ensure no binding are done with members outside the organization domain display_name: Deny principals and members outside the organization domain method_types: diff --git a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableAdminServiceAccount.yaml b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableAdminServiceAccount.yaml index 0043bfef4f2..339798a997c 100644 --- a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableAdminServiceAccount.yaml +++ b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableAdminServiceAccount.yaml @@ -2,12 +2,15 @@ custom.iamDisableAdminServiceAccount: action_type: DENY condition: |- resource.bindings.exists(binding, - binding.members.exists(member, !MemberSubjectEndsWith(member, ['@cloudservices.gserviceaccount.com']) && - MemberSubjectStartsWith(member, ['serviceAccount:'])) && + binding.members.exists(member, + !MemberSubjectMatches(member, ['serviceAccount:my-service-account@my-project.iam.gserviceaccount.com']) && + !MemberSubjectEndsWith(member, ['@cloudservices.gserviceaccount.com']) && + MemberSubjectStartsWith(member, ['serviceAccount:']) + ) && ( - RoleNameMatches(binding.role, ["roles/editor"]) || - RoleNameMatches(binding.role, ["roles/owner"]) || - RoleNameContains(binding.role, ['admin', "Admin"]) + RoleNameMatches(binding.role, ['roles/editor']) || + RoleNameMatches(binding.role, ['roles/owner']) || + RoleNameContains(binding.role, ['admin', 'Admin']) ) ) description: Ensure no use of the basic roles (viewer, editor and owner) and usage diff --git a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableProjectServiceAccountImpersonationRoles.yaml b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableProjectServiceAccountImpersonationRoles.yaml index 9fb8b1e2eae..b8dec1d6204 100644 --- a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableProjectServiceAccountImpersonationRoles.yaml +++ b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableProjectServiceAccountImpersonationRoles.yaml @@ -2,10 +2,13 @@ custom.iamDisableProjectServiceAccountImpersonationRoles: action_type: DENY condition: |- resource.bindings.exists(binding, - binding.members.exists(member,MemberSubjectStartsWith(member, ['user:', 'group:'])) && + binding.members.exists(member, + !MemberSubjectMatches(member, ['user:my-user@my-project.com']) && + MemberSubjectStartsWith(member, ['user:', 'group:']) + ) && ( - RoleNameMatches(binding.role, ["roles/iam.serviceAccountUser"]) || - RoleNameMatches(binding.role, ["roles/iam.serviceAccountTokenCreator"]) + RoleNameMatches(binding.role, ['roles/iam.serviceAccountUser']) || + RoleNameMatches(binding.role, ['roles/iam.serviceAccountTokenCreator']) ) ) description: Ensure that IAM Users are not assigned the service account user or diff --git a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableRedisAdminRoles.yaml b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableRedisAdminRoles.yaml new file mode 100644 index 00000000000..d7cbb8621ba --- /dev/null +++ b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableRedisAdminRoles.yaml @@ -0,0 +1,20 @@ +custom.iamDisableRedisAdminRoles: + action_type: DENY + condition: |- + resource.bindings.exists(binding, + binding.members.exists(member, + !MemberSubjectMatches(member, []) && + ( + RoleNameMatches(binding.role, ['roles/redis.admin']) || + RoleNameMatches(binding.role, ['roles/redis.editor']) || + RoleNameContains(binding.role, ['roles/redis.viewer']) + ) + ) + ) + description: Ensure no use of the basic roles (viewer, editor and owner) + display_name: Deny use of the basic roles + method_types: + - CREATE + - UPDATE + resource_types: + - iam.googleapis.com/AllowPolicy diff --git a/tools/custom-organization-policy-library/samples/tf/custom-policies/custom.accesscontextmanagerDisableBridgePerimeters.yaml b/tools/custom-organization-policy-library/samples/tf/custom-policies/custom.accesscontextmanagerDisableBridgePerimeters.yaml new file mode 100644 index 00000000000..aeecfcdc6a6 --- /dev/null +++ b/tools/custom-organization-policy-library/samples/tf/custom-policies/custom.accesscontextmanagerDisableBridgePerimeters.yaml @@ -0,0 +1,3 @@ +custom.accesscontextmanagerDisableBridgePerimeters: + rules: + - enforce: true diff --git a/tools/custom-organization-policy-library/samples/tf/custom-policies/custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags.yaml b/tools/custom-organization-policy-library/samples/tf/custom-policies/custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags.yaml new file mode 100644 index 00000000000..8a9248cb127 --- /dev/null +++ b/tools/custom-organization-policy-library/samples/tf/custom-policies/custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags.yaml @@ -0,0 +1,3 @@ +custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags: + rules: + - enforce: true diff --git a/tools/custom-organization-policy-library/samples/tf/custom-policies/custom.firewallEnforcePolicyRuleLogging.yaml b/tools/custom-organization-policy-library/samples/tf/custom-policies/custom.firewallEnforcePolicyRuleLogging.yaml new file mode 100644 index 00000000000..849a45c2ff4 --- /dev/null +++ b/tools/custom-organization-policy-library/samples/tf/custom-policies/custom.firewallEnforcePolicyRuleLogging.yaml @@ -0,0 +1,3 @@ +custom.firewallEnforcePolicyRuleLogging: + rules: + - enforce: true diff --git a/tools/custom-organization-policy-library/samples/tf/custom-policies/custom.firewallEnforceRuleLogging.yaml b/tools/custom-organization-policy-library/samples/tf/custom-policies/custom.firewallEnforceRuleLogging.yaml new file mode 100644 index 00000000000..badc6c7ab93 --- /dev/null +++ b/tools/custom-organization-policy-library/samples/tf/custom-policies/custom.firewallEnforceRuleLogging.yaml @@ -0,0 +1,3 @@ +custom.firewallEnforceRuleLogging: + rules: + - enforce: true diff --git a/tools/custom-organization-policy-library/samples/tf/custom-policies/custom.gkeAllowedInitialClusterVersions.yaml b/tools/custom-organization-policy-library/samples/tf/custom-policies/custom.gkeAllowedInitialClusterVersions.yaml deleted file mode 100644 index 021da3fec60..00000000000 --- a/tools/custom-organization-policy-library/samples/tf/custom-policies/custom.gkeAllowedInitialClusterVersions.yaml +++ /dev/null @@ -1,3 +0,0 @@ -custom.gkeAllowedInitialClusterVersions: - rules: - - enforce: true diff --git a/tools/custom-organization-policy-library/samples/tf/custom-policies/custom.iamDisableRedisAdminRoles.yaml b/tools/custom-organization-policy-library/samples/tf/custom-policies/custom.iamDisableRedisAdminRoles.yaml new file mode 100644 index 00000000000..1baf063dfa8 --- /dev/null +++ b/tools/custom-organization-policy-library/samples/tf/custom-policies/custom.iamDisableRedisAdminRoles.yaml @@ -0,0 +1,3 @@ +custom.iamDisableRedisAdminRoles: + rules: + - enforce: true diff --git a/tools/custom-organization-policy-library/tests/main.py b/tools/custom-organization-policy-library/tests/main.py index 3964a8c160b..786e89bb571 100644 --- a/tools/custom-organization-policy-library/tests/main.py +++ b/tools/custom-organization-policy-library/tests/main.py @@ -1,4 +1,5 @@ import os +import re import sys import logging import shlex @@ -115,12 +116,21 @@ def parse_gcloud_output(step, output): "Expected stdout substring: %s, got: %s", expected_stdout_substring, stdout ) return False - - expected_stderr_substring = expected_result.get("stderr", "") - if expected_stderr_substring and expected_stderr_substring not in stderr: + + expected_stderr_pattern = expected_result.get("stderr", "") + if expected_stderr_pattern and not re.search(expected_stderr_pattern, stderr): logging.debug( - "Expected stderr substring: %s, got: %s", expected_stderr_substring, stderr + "Expected stderr pattern: '%s' not found in: '%s'", + expected_stderr_pattern, + stderr, ) return False + # expected_stderr_substring = expected_result.get("stderr", "") + # if expected_stderr_substring and expected_stderr_substring not in stderr: + # logging.debug( + # "Expected stderr substring: %s, got: %s", expected_stderr_substring, stderr + # ) + # return False + return True diff --git a/tools/custom-organization-policy-library/tests/pytest.ini b/tools/custom-organization-policy-library/tests/pytest.ini index 11499052204..6d94efe129c 100644 --- a/tools/custom-organization-policy-library/tests/pytest.ini +++ b/tools/custom-organization-policy-library/tests/pytest.ini @@ -20,6 +20,7 @@ markers = firewall-vpc-rule gke iam + iam-redis mysql network network_backend_service diff --git a/tools/custom-organization-policy-library/tests/test_cases/cloudsql/postgresql.yaml b/tools/custom-organization-policy-library/tests/test_cases/cloudsql/postgresql.yaml index e3c32d3f0c4..05265c03a1e 100644 --- a/tools/custom-organization-policy-library/tests/test_cases/cloudsql/postgresql.yaml +++ b/tools/custom-organization-policy-library/tests/test_cases/cloudsql/postgresql.yaml @@ -13,7 +13,7 @@ shared_config: retained-backups-count: 10 storage-type: SSD ssl-mode: ENCRYPTED_ONLY - database-flags: log_connections=on,log_disconnections=on,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=ddl + database-flags: log_connections=on,log_disconnections=on,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=ddl,log_checkpoints=on,log_executor_stats=off,log_lock_waits=on enable-point-in-time-recovery: true enable-password-policy: true insights-config-query-insights-enabled: true @@ -71,7 +71,7 @@ cloud_psql_instance_no_query_insights: cloud_psql_instance_no_log_conn_on_flag: steps: - command_flags: - database-flags: log_connections=off,log_disconnections=on,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=ddl + database-flags: log_connections=off,log_disconnections=on,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=ddl,log_checkpoints=on,log_executor_stats=off,log_lock_waits=on expected_result: return_code: 1 stderr: "customConstraints/custom.cloudsqlRequirePostgreSQLDatabaseFlags" @@ -79,7 +79,7 @@ cloud_psql_instance_no_log_conn_on_flag: cloud_psql_instance_no_log_discon_on_flag: steps: - command_flags: - database-flags: log_connections=on,log_disconnections=off,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=ddl + database-flags: log_connections=on,log_disconnections=off,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=ddl,log_checkpoints=on,log_executor_stats=off,log_lock_waits=on expected_result: return_code: 1 stderr: "customConstraints/custom.cloudsqlRequirePostgreSQLDatabaseFlags" @@ -87,7 +87,7 @@ cloud_psql_instance_no_log_discon_on_flag: cloud_psql_instance_log_min_messages_error: steps: - command_flags: - database-flags: log_connections=on,log_disconnections=on,log_min_messages=error,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=ddl + database-flags: log_connections=on,log_disconnections=on,log_min_messages=error,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=ddl.log_checkpoints=on,log_executor_stats=off,log_lock_waits=on expected_result: return_code: 1 stderr: "customConstraints/custom.cloudsqlRequirePostgreSQLDatabaseFlags" @@ -95,7 +95,7 @@ cloud_psql_instance_log_min_messages_error: cloud_psql_instance_log_min_error_stmt_fatal: steps: - command_flags: - database-flags: log_connections=on,log_disconnections=on,log_min_messages=warning,log_min_error_statement=fatal,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=ddl + database-flags: log_connections=on,log_disconnections=on,log_min_messages=warning,log_min_error_statement=fatal,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=ddl,log_checkpoints=on,log_executor_stats=off,log_lock_waits=on expected_result: return_code: 1 stderr: "customConstraints/custom.cloudsqlRequirePostgreSQLDatabaseFlags" @@ -103,7 +103,7 @@ cloud_psql_instance_log_min_error_stmt_fatal: cloud_psql_instance_wrong_log_min_duration_statement: steps: - command_flags: - database-flags: log_connections=on,log_disconnections=on,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=3600,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=ddl + database-flags: log_connections=on,log_disconnections=on,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=3600,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=ddl,log_checkpoints=on,log_executor_stats=off,log_lock_waits=on expected_result: return_code: 1 stderr: "customConstraints/custom.cloudsqlRequirePostgreSQLDatabaseFlags" @@ -111,7 +111,7 @@ cloud_psql_instance_wrong_log_min_duration_statement: cloud_psql_instance_no_enable_pgaudit: steps: - command_flags: - database-flags: log_connections=on,log_disconnections=on,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=off,log_error_verbosity=default,log_statement=ddl + database-flags: log_connections=on,log_disconnections=on,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=off,log_error_verbosity=default,log_statement=ddl,log_checkpoints=on,log_executor_stats=off,log_lock_waits=on expected_result: return_code: 1 stderr: "customConstraints/custom.cloudsqlRequirePostgreSQLDatabaseFlags" @@ -119,7 +119,7 @@ cloud_psql_instance_no_enable_pgaudit: cloud_psql_instance_wrong_log_error_verbosity: steps: - command_flags: - database-flags: log_connections=on,log_disconnections=on,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=terse,log_statement=ddl + database-flags: log_connections=on,log_disconnections=on,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=terse,log_statement=ddl,log_checkpoints=on,log_executor_stats=off,log_lock_waits=on expected_result: return_code: 1 stderr: "customConstraints/custom.cloudsqlRequirePostgreSQLDatabaseFlags" @@ -127,8 +127,47 @@ cloud_psql_instance_wrong_log_error_verbosity: cloud_psql_instance_wrong_log_statement: steps: - command_flags: - database-flags: log_connections=on,log_disconnections=on,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=none + database-flags: log_connections=on,log_disconnections=on,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=none,log_checkpoints=on,log_executor_stats=off,log_lock_waits=on expected_result: return_code: 1 stderr: "customConstraints/custom.cloudsqlRequirePostgreSQLDatabaseFlags" +cloud_psql_instance_wrong_no_log_checkpoints: + steps: + - command_flags: + database-flags: log_connections=on,log_disconnections=on,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=ddl,log_executor_stats=off,log_lock_waits=on + expected_result: + return_code: 1 + stderr: "customConstraints/custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags" + +cloud_psql_instance_wrong_wrong_log_checkpoints: + steps: + - command_flags: + database-flags: log_connections=on,log_disconnections=on,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=ddl,log_checkpoints=off,log_executor_stats=off,log_lock_waits=on + expected_result: + return_code: 1 + stderr: "customConstraints/custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags" + +cloud_psql_instance_wrong_wrong_log_executor_stats: + steps: + - command_flags: + database-flags: log_connections=on,log_disconnections=on,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=ddl,log_checkpoints=on,log_executor_stats=on,log_lock_waits=on + expected_result: + return_code: 1 + stderr: "customConstraints/custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags" + +cloud_psql_instance_wrong_no_log_lock_waits: + steps: + - command_flags: + database-flags: log_connections=on,log_disconnections=on,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=ddl,log_checkpoints=on,log_executor_stats=off + expected_result: + return_code: 1 + stderr: "customConstraints/custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags" + +cloud_psql_instance_wrong_wrong_log_lock_waits: + steps: + - command_flags: + database-flags: log_connections=on,log_disconnections=on,log_min_messages=warning,log_min_error_statement=error,log_min_duration_statement=-1,cloudsql.enable_pgaudit=on,log_error_verbosity=default,log_statement=ddl,log_checkpoints=on,log_executor_stats=off,log_lock_waits=off + expected_result: + return_code: 1 + stderr: "customConstraints/custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags" diff --git a/tools/custom-organization-policy-library/tests/test_cases/compute/instance.yaml b/tools/custom-organization-policy-library/tests/test_cases/compute/instance.yaml index 4a6972d10fe..900bdf71998 100644 --- a/tools/custom-organization-policy-library/tests/test_cases/compute/instance.yaml +++ b/tools/custom-organization-policy-library/tests/test_cases/compute/instance.yaml @@ -1,6 +1,6 @@ shared_config: - command: gcloud compute instances create {{ identifier }} --zone asia-southeast2-a - teardown_command: gcloud compute instances delete {{ identifier }} --zone asia-southeast2-a + command: gcloud compute instances create {{ identifier }} --zone asia-southeast2-c + teardown_command: gcloud compute instances delete {{ identifier }} --zone asia-southeast2-c default_command_flags: machine-type: e2-medium # n2-standard-1 image-family: debian-11 diff --git a/tools/custom-organization-policy-library/tests/test_cases/dns/manage-zone.yaml b/tools/custom-organization-policy-library/tests/test_cases/dns/manage-zone.yaml index af762429943..bd271037c23 100644 --- a/tools/custom-organization-policy-library/tests/test_cases/dns/manage-zone.yaml +++ b/tools/custom-organization-policy-library/tests/test_cases/dns/manage-zone.yaml @@ -2,7 +2,7 @@ shared_config: command: gcloud dns managed-zones create {{ identifier }} teardown_command: gcloud dns managed-zones delete {{ identifier }} default_command_flags: - dns-name: cuop.vannick.joonix.net. + dns-name: cuop.vannick.altostrat.com. description: description visibility: public log-dns-queries: true @@ -43,7 +43,7 @@ dns_public_managed_zones_no_logging: log-dns-queries: false expected_result: return_code: 1 - stderr: 'Forbidden' # Gcloud output is not verbose enough to return the constraint blocking creation + stderr: 'HTTPError 412' # Gcloud output is not verbose enough to return the constraint blocking creation dns_public_managed_zones_absent_logging: steps: @@ -51,7 +51,7 @@ dns_public_managed_zones_absent_logging: log-dns-queries: absent expected_result: return_code: 1 - stderr: 'Forbidden' # Gcloud output is not verbose enough to return the constraint blocking creation + stderr: 'HTTPError 412' # Gcloud output is not verbose enough to return the constraint blocking creation dns_public_managed_zones_no_dnssec: steps: @@ -59,7 +59,7 @@ dns_public_managed_zones_no_dnssec: dnssec-state: "off" expected_result: return_code: 1 - stderr: 'Forbidden' # Gcloud output is not verbose enough to return the constraint blocking creation + stderr: 'HTTPError 412' # Gcloud output is not verbose enough to return the constraint blocking creation dns_public_managed_zones_absent_dnssec: steps: @@ -67,7 +67,7 @@ dns_public_managed_zones_absent_dnssec: dnssec-state: "absent" expected_result: return_code: 1 - stderr: 'Forbidden' # Gcloud output is not verbose enough to return the constraint blocking creation + stderr: 'HTTPError 412' # Gcloud output is not verbose enough to return the constraint blocking creation dns_public_managed_zones_ksk_unallowed: steps: @@ -79,7 +79,7 @@ dns_public_managed_zones_ksk_unallowed: denial-of-existence: NSEC expected_result: return_code: 1 - stderr: 'Forbidden' # Gcloud output is not verbose enough to return the constraint blocking creation + stderr: 'HTTPError 412' # Gcloud output is not verbose enough to return the constraint blocking creation dns_public_managed_zones_zsk_unallowed: steps: @@ -91,5 +91,5 @@ dns_public_managed_zones_zsk_unallowed: denial-of-existence: NSEC expected_result: return_code: 1 - stderr: 'Forbidden' # Gcloud output is not verbose enough to return the constraint blocking creation + stderr: 'HTTPError 412' # Gcloud output is not verbose enough to return the constraint blocking creation diff --git a/tools/custom-organization-policy-library/tests/test_cases/dns/policy.yaml b/tools/custom-organization-policy-library/tests/test_cases/dns/policy.yaml index c7cb465a561..7dab726bc69 100644 --- a/tools/custom-organization-policy-library/tests/test_cases/dns/policy.yaml +++ b/tools/custom-organization-policy-library/tests/test_cases/dns/policy.yaml @@ -23,7 +23,7 @@ dns_policy_no_logging: enable-logging: false expected_result: return_code: 1 - stderr: 'Forbidden' # Gcloud output is not verbose enough to return the constraint blocking creation + stderr: 'HTTPError 412' # Gcloud output is not verbose enough to return the constraint blocking creation dns_policy_absent_logging: steps: @@ -31,4 +31,4 @@ dns_policy_absent_logging: enable-logging: absent expected_result: return_code: 1 - stderr: 'Forbidden' # Gcloud output is not verbose enough to return the constraint blocking creation + stderr: 'HTTPError 412' # Gcloud output is not verbose enough to return the constraint blocking creation diff --git a/tools/custom-organization-policy-library/tests/test_cases/firewall/policy_rule_logging.yaml b/tools/custom-organization-policy-library/tests/test_cases/firewall/policy_rule_logging.yaml new file mode 100644 index 00000000000..f61181e8adb --- /dev/null +++ b/tools/custom-organization-policy-library/tests/test_cases/firewall/policy_rule_logging.yaml @@ -0,0 +1,26 @@ +shared_config: + command: gcloud compute network-firewall-policies rules create 1000 --firewall-policy cuop-fw-policy --global-firewall-policy + teardown_command: gcloud compute network-firewall-policies rules delete 1000 --firewall-policy cuop-fw-policy --global-firewall-policy + default_command_flags: + action: ALLOW + direction: INGRESS + layer4-configs: tcp:22 + enable-logging: true + src-ip-ranges: 192.168.1.0/24 + default_markers: + - firewall + - firewall-policy-log + +firewall_policy_allowed_logging_enabled: + steps: + - expected_result: + return_code: 0 + +firewall_policy_logging_disabled: + steps: + - command_flags: + enable-logging: false + expected_result: + return_code: 1 + stderr: "customConstraints/custom.firewallEnforcePolicyRuleLogging" + diff --git a/tools/custom-organization-policy-library/tests/test_cases/firewall/policy_rule_rdp.yaml b/tools/custom-organization-policy-library/tests/test_cases/firewall/policy_rule_rdp.yaml index 2051e593101..769346441d8 100644 --- a/tools/custom-organization-policy-library/tests/test_cases/firewall/policy_rule_rdp.yaml +++ b/tools/custom-organization-policy-library/tests/test_cases/firewall/policy_rule_rdp.yaml @@ -5,6 +5,7 @@ shared_config: action: ALLOW direction: INGRESS layer4-configs: tcp:3389 + enable-logging: true default_markers: - firewall - firewall-policy diff --git a/tools/custom-organization-policy-library/tests/test_cases/firewall/policy_rule_ssh.yaml b/tools/custom-organization-policy-library/tests/test_cases/firewall/policy_rule_ssh.yaml index a30eeab4c65..b6f31319998 100644 --- a/tools/custom-organization-policy-library/tests/test_cases/firewall/policy_rule_ssh.yaml +++ b/tools/custom-organization-policy-library/tests/test_cases/firewall/policy_rule_ssh.yaml @@ -5,6 +5,7 @@ shared_config: action: ALLOW direction: INGRESS layer4-configs: tcp:22 + enable-logging: true default_markers: - firewall - firewall-policy diff --git a/tools/custom-organization-policy-library/tests/test_cases/firewall/vpc_open_rule.yaml b/tools/custom-organization-policy-library/tests/test_cases/firewall/vpc_open_rule.yaml new file mode 100644 index 00000000000..bfaf721a394 --- /dev/null +++ b/tools/custom-organization-policy-library/tests/test_cases/firewall/vpc_open_rule.yaml @@ -0,0 +1,30 @@ +shared_config: + command: gcloud compute firewall-rules create allow-custom-{{ identifier }} + teardown_command: gcloud compute firewall-rules delete allow-custom-{{ identifier }} + default_command_flags: + action: ALLOW + direction: INGRESS + network: vpc-dev-cuop-library + priority: 1000 + rules: tcp:3838 + description: Testing firewall rule + enable-logging: true + default_markers: + - firewall + - firewall-vpc-rule + +firewall_vpc_allowed_custom_rule_192: + steps: + - command_flags: + source-ranges: 192.168.1.0/24 + expected_result: + return_code: 0 + +firewall_vpc_custom_rule_0_0_0_0: + steps: + - command_flags: + source-ranges: 0.0.0.0/0 + expected_result: + return_code: 1 + stderr: "customConstraints/custom.firewallRestrictOpenWorldRule" + diff --git a/tools/custom-organization-policy-library/tests/test_cases/firewall/vpc_rule_logging.yaml b/tools/custom-organization-policy-library/tests/test_cases/firewall/vpc_rule_logging.yaml new file mode 100644 index 00000000000..628596e16c2 --- /dev/null +++ b/tools/custom-organization-policy-library/tests/test_cases/firewall/vpc_rule_logging.yaml @@ -0,0 +1,29 @@ +shared_config: + command: gcloud compute firewall-rules create allow-ssh-{{ identifier }} + teardown_command: gcloud compute firewall-rules delete allow-ssh-{{ identifier }} + default_command_flags: + action: ALLOW + direction: INGRESS + network: vpc-dev-cuop-library + priority: 1000 + rules: tcp:22 + description: Testing firewall rule + enable-logging: true + source-ranges: 192.168.1.0/24 + default_markers: + - firewall + - firewall-vpc-rule + + +firewall_vpc_allowed_logging_enabled: + steps: + - expected_result: + return_code: 0 + +firewall_vpc_logging_disabled: + steps: + - command_flags: + enable-logging: false + expected_result: + return_code: 1 + stderr: "customConstraints/custom.firewallEnforceRuleLogging" diff --git a/tools/custom-organization-policy-library/tests/test_cases/firewall/vpc_rule_rdp.yaml b/tools/custom-organization-policy-library/tests/test_cases/firewall/vpc_rule_rdp.yaml index c27b4de1716..c6c2ac44853 100644 --- a/tools/custom-organization-policy-library/tests/test_cases/firewall/vpc_rule_rdp.yaml +++ b/tools/custom-organization-policy-library/tests/test_cases/firewall/vpc_rule_rdp.yaml @@ -8,6 +8,7 @@ shared_config: priority: 1000 rules: tcp:3389 description: Testing firewall rule + enable-logging: true default_markers: - firewall - firewall-vpc-rule @@ -39,7 +40,7 @@ firewall_vpc_rdp_rule_0_0_0_0: source-ranges: 0.0.0.0/0 expected_result: return_code: 1 - stderr: "customConstraints/custom.firewallRestrictRdpRule" + stderr: "customConstraints/custom.firewallRestrictRdpRule|customConstraints/custom.firewallRestrictOpenWorldRule" firewall_vpc_rdp_rule_1_0_0_0: steps: diff --git a/tools/custom-organization-policy-library/tests/test_cases/firewall/vpc_rule_ssh.yaml b/tools/custom-organization-policy-library/tests/test_cases/firewall/vpc_rule_ssh.yaml index 38b32edecab..e8b0a977ef6 100644 --- a/tools/custom-organization-policy-library/tests/test_cases/firewall/vpc_rule_ssh.yaml +++ b/tools/custom-organization-policy-library/tests/test_cases/firewall/vpc_rule_ssh.yaml @@ -8,6 +8,7 @@ shared_config: priority: 1000 rules: tcp:22 description: Testing firewall rule + enable-logging: true default_markers: - firewall - firewall-vpc-rule @@ -39,7 +40,7 @@ firewall_vpc_ssh_rule_0_0_0_0: source-ranges: 0.0.0.0/0 expected_result: return_code: 1 - stderr: "customConstraints/custom.firewallRestrictSshRule" + stderr: "customConstraints/custom.firewallRestrictSshRule|customConstraints/custom.firewallRestrictOpenWorldRule" firewall_vpc_ssh_rule_1_0_0_0: steps: diff --git a/tools/custom-organization-policy-library/tests/test_cases/fixture.yaml b/tools/custom-organization-policy-library/tests/test_cases/fixture.yaml index c8292978a83..1506b10538c 100644 --- a/tools/custom-organization-policy-library/tests/test_cases/fixture.yaml +++ b/tools/custom-organization-policy-library/tests/test_cases/fixture.yaml @@ -36,20 +36,20 @@ before_tests: # IAM Bindings - command: gcloud projects add-iam-policy-binding {{ project }} --member=serviceAccount:{{ project_number }}-compute@developer.gserviceaccount.com --role=roles/cloudbuild.builds.builder after_tests: - # General - - command: gcloud iam service-accounts delete {{ prefix }}-iam-sa@{{ project }}.iam.gserviceaccount.com - # Storage - - command: gcloud storage buckets delete gs://{{ prefix }}-cuop-bucket-cgk - # IAM CuOP - - command: gcloud iam service-accounts delete iam-sa-binding-allowed@{{ project }}.iam.gserviceaccount.com - - command: gcloud iam service-accounts delete iam-sa-binding-unallowed@{{ project }}.iam.gserviceaccount.com - # Network for VPC - - command: gcloud compute networks delete vpc-dev-cuop-library - - command: gcloud compute networks subnets delete subnet-vm --region=asia-southeast2 - - command: gcloud compute networks subnets delete subnet-gke --region=asia-southeast2 - # Network CuOP for Load Balancer - - command: gcloud compute addresses delete {{ prefix }}-cuop--ip --global - - command: gcloud compute backend-buckets delete {{ prefix }}-be-bucket - - command: gcloud compute url-maps delete {{ prefix }}-http-lb - # Firewall CuOP - - command: gcloud compute network-firewall-policies delete cuop-fw-policy --global + # General + - command: gcloud iam service-accounts delete {{ prefix }}-iam-sa@{{ project }}.iam.gserviceaccount.com + # Storage + - command: gcloud storage buckets delete gs://{{ prefix }}-cuop-bucket-cgk + # IAM CuOP + - command: gcloud iam service-accounts delete iam-sa-binding-allowed@{{ project }}.iam.gserviceaccount.com + - command: gcloud iam service-accounts delete iam-sa-binding-unallowed@{{ project }}.iam.gserviceaccount.com + # Network for VPC + - command: gcloud compute networks delete vpc-dev-cuop-library + - command: gcloud compute networks subnets delete subnet-vm --region=asia-southeast2 + - command: gcloud compute networks subnets delete subnet-gke --region=asia-southeast2 + # Network CuOP for Load Balancer + - command: gcloud compute addresses delete {{ prefix }}-cuop--ip --global + - command: gcloud compute backend-buckets delete {{ prefix }}-be-bucket + - command: gcloud compute url-maps delete {{ prefix }}-http-lb + # Firewall CuOP + - command: gcloud compute network-firewall-policies delete cuop-fw-policy --global diff --git a/tools/custom-organization-policy-library/tests/test_cases/gke/cluster.yaml b/tools/custom-organization-policy-library/tests/test_cases/gke/cluster.yaml index 6fb4d938c2c..63c0b8d88c6 100644 --- a/tools/custom-organization-policy-library/tests/test_cases/gke/cluster.yaml +++ b/tools/custom-organization-policy-library/tests/test_cases/gke/cluster.yaml @@ -3,7 +3,7 @@ shared_config: teardown_command: gcloud container clusters delete {{ identifier }} --region=asia-southeast2 default_command_flags: enable-basic-auth: false - cluster-version: 1.33.0-gke.2248000 + cluster-version: latest release-channel: regular machine-type: n2d-standard-2 image-type: COS_CONTAINERD @@ -23,7 +23,7 @@ shared_config: enable-autorepair: true workload-pool: "{{ project }}.svc.id.goog" enable-shielded-nodes: true - security-group: gke-security-groups@vannick.joonix.net + security-group: gke-security-groups@vannick.altostrat.com binauthz-evaluation-mode: PROJECT_SINGLETON_POLICY_ENFORCE boot-disk-kms-key: projects/{{ project }}/locations/asia-southeast2/keyRings/{{ prefix }}-key-ring-1/cryptoKeys/{{ prefix }}-key-1 database-encryption-key: projects/{{ project }}/locations/asia-southeast2/keyRings/{{ prefix }}-key-ring-1/cryptoKeys/{{ prefix }}-key-1 @@ -79,11 +79,3 @@ gke_absent_secure_boot: expected_result: return_code: 1 stderr: customConstraints/custom.gkeRequireSecureBoot - -gke_version_1_29: - steps: - - command_flags: - cluster-version: 1.32.4-gke.1236007 - expected_result: - return_code: 1 - stderr: customConstraints/custom.gkeAllowedInitialClusterVersions diff --git a/tools/custom-organization-policy-library/tests/test_cases/iam/redis.yaml b/tools/custom-organization-policy-library/tests/test_cases/iam/redis.yaml new file mode 100644 index 00000000000..52b76a9bca8 --- /dev/null +++ b/tools/custom-organization-policy-library/tests/test_cases/iam/redis.yaml @@ -0,0 +1,35 @@ +shared_config: + default_markers: + - iam + - iam-redis + +iam_sa_binding_admin_unallowed: + steps: + - command: >- + gcloud projects add-iam-policy-binding {{ project }} + --member='serviceAccount:iam-sa-binding-unallowed@{{ project }}.iam.gserviceaccount.com' + --role='roles/redis.admin' + expected_result: + return_code: 1 + stderr: customConstraints/custom.iamDisableRedisAdminRoles + +iam_sa_binding_editor_unallowed: + steps: + - command: >- + gcloud projects add-iam-policy-binding {{ project }} + --member='serviceAccount:iam-sa-binding-unallowed@{{ project }}.iam.gserviceaccount.com' + --role='roles/redis.editor' + expected_result: + return_code: 1 + stderr: customConstraints/custom.iamDisableRedisAdminRoles + +iam_sa_binding_owner_unallowed: + steps: + - command: >- + gcloud projects add-iam-policy-binding {{ project }} + --member='serviceAccount:iam-sa-binding-unallowed@{{ project }}.iam.gserviceaccount.com' + --role='roles/redis.viewer' + expected_result: + return_code: 1 + stderr: customConstraints/custom.iamDisableRedisAdminRoles + diff --git a/tools/custom-organization-policy-library/values.yaml b/tools/custom-organization-policy-library/values.yaml index 4af06cabee2..9d722e6d733 100644 --- a/tools/custom-organization-policy-library/values.yaml +++ b/tools/custom-organization-policy-library/values.yaml @@ -96,7 +96,7 @@ compute: - "pd-balanced" computeRestrictDiskSize: params: - max_disksize: 100 + max_disksize: 1000 dataproc: dataprocAllowedLabels: params: @@ -125,10 +125,6 @@ dns: algorithms: - ECDSAP256SHA256 gke: - gkeAllowedInitialClusterVersions: - params: - initial_cluster_versions: - - 1.33.0-gke.2248000 gkeAllowedNodePoolImages: params: images: @@ -144,6 +140,14 @@ iam: domains: - "@google.com" - ".gserviceaccount.com" + iamDisableProjectServiceAccountImpersonationRoles: + params: + exceptions: + - "user:my-user@my-project.com" + iamDisableAdminServiceAccount: + params: + exceptions: + - "serviceAccount:my-service-account@my-project.iam.gserviceaccount.com" network: networkEnforceNamingConvention: params: diff --git a/tools/gke-gpu-driver-version/.gitignore b/tools/gke-gpu-driver-version/.gitignore new file mode 100644 index 00000000000..557a54764dd --- /dev/null +++ b/tools/gke-gpu-driver-version/.gitignore @@ -0,0 +1 @@ +tools/ \ No newline at end of file diff --git a/tools/gke-gpu-driver-version/Cargo.lock b/tools/gke-gpu-driver-version/Cargo.lock new file mode 100644 index 00000000000..0628188522b --- /dev/null +++ b/tools/gke-gpu-driver-version/Cargo.lock @@ -0,0 +1,2265 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys 0.60.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.60.2", +] + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "axum" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18ed336352031311f4e0b4dd2ff392d4fbb370777c9d18d7fc9d7359f73871" +dependencies = [ + "axum-core", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde_core", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "sync_wrapper", + "tower-layer", + "tower-service", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "cc" +version = "1.2.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chrono" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-link 0.2.1", +] + +[[package]] +name = "clap" +version = "4.5.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4512b90fa68d3a9932cea5184017c5d200f5921df706d45e853537dea51508f" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0025e98baa12e766c67ba13ff4695a887a1eba19569aad00a472546795bd6730" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "find-msvc-tools" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "gke-gpu-driver-version" +version = "0.1.0" +dependencies = [ + "anyhow", + "chrono", + "clap", + "env_logger", + "log", + "prost", + "reqwest", + "serde", + "serde_json", + "serde_yml", + "tokio", + "tonic", + "tonic-prost-build", +] + +[[package]] +name = "h2" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "system-configuration", + "tokio", + "tower-service", + "tracing", + "windows-registry", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "2.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jiff" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "js-sys" +version = "0.3.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "libyml" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3302702afa434ffa30847a83305f0a69d6abd74293b6554c18ec85c7ef30c980" +dependencies = [ + "anyhow", + "version_check", +] + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mio" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.59.0", +] + +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "openssl" +version = "0.10.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24ad14dd45412269e1a30f52ad8f0664f0f4f4a89ee8fe28c3b3527021ebb654" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.110" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a9f0075ba3c21b09f8e8b2026584b1d18d49388648f2fbbf3c97ea8deced8e2" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "petgraph" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "potential_utf" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +dependencies = [ + "zerovec", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac6c3320f9abac597dcbc668774ef006702672474aad53c6d596b62e487b40b1" +dependencies = [ + "heck", + "itertools", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "pulldown-cmark", + "pulldown-cmark-to-cmark", + "regex", + "syn", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9b4db3d6da204ed77bb26ba83b6122a73aeb2e87e25fbf7ad2e84c4ccbf8f72" +dependencies = [ + "prost", +] + +[[package]] +name = "pulldown-cmark" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0" +dependencies = [ + "bitflags", + "memchr", + "unicase", +] + +[[package]] +name = "pulldown-cmark-to-cmark" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5b6a0769a491a08b31ea5c62494a8f144ee0987d86d670a8af4df1e1b7cde75" +dependencies = [ + "pulldown-cmark", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "reqwest" +version = "0.12.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "js-sys", + "log", + "mime", + "native-tls", + "percent-encoding", + "pin-project-lite", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-native-tls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustix" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "schannel" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_yml" +version = "0.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59e2dd588bf1597a252c3b920e0143eb99b0f76e4e082f4c92ce34fbc9e71ddd" +dependencies = [ + "indexmap", + "itoa", + "libyml", + "memchr", + "ryu", + "serde", + "version_check", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "slab" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +dependencies = [ + "fastrand", + "getrandom 0.3.4", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "tinystr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tonic" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203" +dependencies = [ + "async-trait", + "axum", + "base64", + "bytes", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "socket2", + "sync_wrapper", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-build" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c40aaccc9f9eccf2cd82ebc111adc13030d23e887244bc9cfa5d1d636049de3" +dependencies = [ + "prettyplease", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tonic-prost-build" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4a16cba4043dc3ff43fcb3f96b4c5c154c64cbd18ca8dce2ab2c6a451d058a2" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "prost-types", + "quote", + "syn", + "tempfile", + "tonic-build", +] + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "indexmap", + "pin-project-lite", + "slab", + "sync_wrapper", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-registry" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" +dependencies = [ + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/tools/gke-gpu-driver-version/Cargo.toml b/tools/gke-gpu-driver-version/Cargo.toml new file mode 100644 index 00000000000..351f1e2d29f --- /dev/null +++ b/tools/gke-gpu-driver-version/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "gke-gpu-driver-version" +version = "0.1.0" +edition = "2024" + +[dependencies] +anyhow = "1.0.100" +chrono = { version = "0.4.42", features = ["serde"] } +clap = { version = "4.5.48", features = ["derive"] } +env_logger = "0.11.8" +log = "0.4.28" +prost = "0.14.1" +reqwest = { version = "0.12.23", features = ["json"] } +serde = "1.0.228" +serde_json = "1.0.145" +serde_yml = "0.0.12" +tokio = { version = "1.47.1", features = ["macros", "rt-multi-thread"] } +tonic = "0.14.2" + +[build-dependencies] +tonic-prost-build = "0.14.2" diff --git a/tools/gke-gpu-driver-version/README.md b/tools/gke-gpu-driver-version/README.md new file mode 100644 index 00000000000..72e6740a64d --- /dev/null +++ b/tools/gke-gpu-driver-version/README.md @@ -0,0 +1,41 @@ +# GKE GPU Driver Version + +This tool helps you find the supported GPU driver version for a given GKE cluster version and GPU type. It automates the steps described in the [official documentation](https://cloud.google.com/kubernetes-engine/docs/how-to/gpus#map-gke-cos-gpu) for mapping GKE versions to corresponding COS and NVIDIA driver versions. + +## Prerequisites: + +1. [Install Rust](https://www.rust-lang.org/learn/get-started) +2. [Clone COS tools into this directory](https://cos.googlesource.com/cos/tools) +3. [Install protobuf compiler](https://protobuf.dev/installation) + +## Usage + +### List supported GPU types + +```bash +cargo run -- list-gpu-types --gke-version +``` + +### Get driver versions + +```bash +cargo run -- get --gke-version --gpu-type +``` + +## Example + +### List available GPU types + +```bash +cargo run -- list-gpu-types --gke-version 1.33.5-gke.1080000 +``` + +### Get driver versions + +```bash +cargo run -- get --gke-version 1.33.5-gke.1080000 --gpu-type NVIDIA_H100_80GB + +or + +cargo run -- get --gke-version v1.33.5-gke.1080000 --gpu-type NVIDIA_H100_80GB +``` \ No newline at end of file diff --git a/tools/gke-gpu-driver-version/build.rs b/tools/gke-gpu-driver-version/build.rs new file mode 100644 index 00000000000..2c29019b685 --- /dev/null +++ b/tools/gke-gpu-driver-version/build.rs @@ -0,0 +1,30 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +fn main() -> std::io::Result<()> { + let protos = vec!["tools/src/pkg/gpuconfig/proto/gpu_driver_versions.proto"]; + + tonic_prost_build::configure() + .type_attribute(".", "#[derive(serde::Serialize, serde::Deserialize)]") + .field_attribute("pb.GPUDevice.is_vgpu", "#[serde(default)]") + .field_attribute( + "pb.DriverVersion.supported_host_versions", + "#[serde(default)]", + ) + .field_attribute("pb.DriverVersion.label", "#[serde(default)]") + .include_file("cos_tools.rs") + .compile_protos(&protos, &["tools".into()])?; + + Ok(()) +} diff --git a/tools/gke-gpu-driver-version/src/main.rs b/tools/gke-gpu-driver-version/src/main.rs new file mode 100644 index 00000000000..c9f4bef7f28 --- /dev/null +++ b/tools/gke-gpu-driver-version/src/main.rs @@ -0,0 +1,152 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use anyhow::Ok; +use chrono::Utc; +use clap::Parser; +use env_logger::Env; +use log::error; + +use crate::pb::GpuDriverVersionInfoList; + +tonic::include_proto!("cos_tools"); + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + env_logger::Builder::from_env(Env::default().default_filter_or("info")) + .format_timestamp(None) + .init(); + + let gke_to_cos_versions = + reqwest::get("https://www.gstatic.com/gke-image-maps/gke-to-cos.json") + .await? + .json::() + .await?; + + let args = Args::parse(); + + let gke_version = match &args.command { + Commands::Get(cmd) => &cmd.gke_version, + Commands::ListGpuTypes(cmd) => &cmd.gke_version, + }; + + let cos_version = gke_to_cos_versions + .entries + .into_iter() + .find(|v| gke_version.contains(&v.gke_version)) + .map(|v| v.image); + + match cos_version { + Some(v) => { + let mut data = v.rsplit("-").into_iter().take(3).collect::>(); + + data.reverse(); + + let version = data.join("."); + let proto = reqwest::get(format!( + "https://storage.googleapis.com/cos-tools/{}/lakitu/gpu_driver_versions.textproto", + version + )) + .await? + .text() + .await?; + + let list: GpuDriverVersionInfoList = serde_yml::from_str(&proto)?; + + match &args.command { + Commands::Get(cmd) => { + let mut result = GpuVersionData::default(); + result.creation_time = gke_to_cos_versions.creation_time; + result.cos_version = v; + list.gpu_driver_version_info + .into_iter() + .filter(|v| match &v.gpu_device { + Some(device) => device.gpu_type == cmd.gpu_type, + None => false, + }) + .flat_map(|v| v.supported_driver_versions) + .for_each(|v| { + if v.label == "DEFAULT" { + result.default_driver_version = v.version.clone(); + } + if v.label == "LATEST" { + result.latest_driver_version = v.version.clone(); + } + }); + println!("{}", serde_json::to_string_pretty(&result)?); + } + Commands::ListGpuTypes(_cmd) => { + let gpu_types: std::collections::BTreeSet = list + .gpu_driver_version_info + .into_iter() + .filter_map(|v| v.gpu_device.map(|d| d.gpu_type)) + .collect(); + println!("{}", serde_json::to_string_pretty(&gpu_types)?); + } + } + } + None => error!("cos version not found for cluster version"), + } + + Ok(()) +} + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct Args { + #[clap(subcommand)] + command: Commands, +} + +#[derive(clap::Subcommand, Debug)] +enum Commands { + /// Get driver versions for a specific GPU type + Get(GetCommand), + /// List supported GPU types for a GKE version + ListGpuTypes(ListGpuTypesCommand), +} + +#[derive(clap::Args, Debug)] +struct GetCommand { + #[arg(long)] + gke_version: String, + #[arg(long)] + gpu_type: String, +} + +#[derive(clap::Args, Debug)] +struct ListGpuTypesCommand { + #[arg(long)] + gke_version: String, +} + +#[derive(serde::Deserialize, Debug)] +struct GkeToCos { + entries: Vec, + creation_time: chrono::DateTime, +} + +#[derive(serde::Deserialize, Debug)] +struct GkeVersionToCosImage { + gke_version: String, + image: String, +} + +#[derive(serde::Serialize, Default)] +struct GpuVersionData { + cos_version: String, + latest_driver_version: String, + default_driver_version: String, + creation_time: chrono::DateTime, +}