secops-rules module (#3023)

* secops-rules module
This commit is contained in:
simonebruzzechesse
2025-04-11 15:44:31 +02:00
committed by GitHub
parent a747653e88
commit 03db2e45cf
8 changed files with 590 additions and 0 deletions

View File

@@ -0,0 +1,217 @@
# SecOps Rules
This module allows creation and management of [custom rules](https://cloud.google.com/chronicle/docs/detection/view-all-rules) as well as [reference lists](https://cloud.google.com/chronicle/docs/reference/reference-lists) in Google SecOps.
- rule definition (yaral code) and reference list entries are managed as files in data folder as per the `factories_config` variable and sample code
- rule and reference list deployments can leverage both `rules_config` and `reference_lists_config` variables or YAML file still specified in the `factories_config` variable.
<!-- BEGIN TOC -->
- [Examples](#examples)
- [Sample SecOps Rules and reference list deployment](#sample-secops-rules-and-reference-list-deployment)
- [SecOps Rules Factory](#secops-rules-factory)
- [Variables](#variables)
<!-- END TOC -->
## Examples
### Sample SecOps Rules and reference list deployment
This is a sample usage of the secops-rules module for deploying a rule (network_traffic_to_specific_country) and a reference list (private_ip_ranges), definition of the rule in yaral is available in the corresponding file in the `data/rules` folder and the reference list in the `data/reference_lists` folder. Deployment configuration for both is passed as an input to the module using the `rules_config` and `reference_lists_config` variables.
```hcl
module "secops" {
source = "./fabric/modules/secops-rules"
project_id = var.project_id
tenant_config = var.secops_tenant_config
reference_lists_config = {
"private_ip_ranges" = {
description = "Private CIDR ranges"
type = "CIDR"
}
}
rules_config = {
"network_traffic_to_specific_country" = {
enabled = true
alerting = true
archived = false
run_frequency = "LIVE"
}
}
factories_config = {
rules_defs = "./data/rules"
reference_lists_defs = "./data/reference_lists"
}
}
# tftest modules=1 resources=3 files=reference,rule inventory=basic.yaml
```
```
rule network_traffic_to_specific_country {
meta:
author = "Google Cloud Security"
description = "Identify network traffic based on target country"
type = "alert"
tags = "geoip enrichment"
data_source = "microsoft windows events"
severity = "Low"
priority = "Low"
events:
$network.metadata.event_type = "NETWORK_CONNECTION"
//Specify a country of interest to monitor or add additional countries using an or statement
$network.target.ip_geo_artifact.location.country_or_region = "France" nocase
$network.target.ip = $ip
match:
$ip over 30m
outcome:
$risk_score = max(35)
$event_count = count_distinct($network.metadata.id)
// added to populate alert graph with additional context
$principal_ip = array_distinct($network.principal.ip)
// Commented out target.ip because it is already represented in graph as match variable. If match changes, can uncomment to add to results
//$target_ip = array_distinct($network.target.ip)
$principal_process_pid = array_distinct($network.principal.process.pid)
$principal_process_command_line = array_distinct($network.principal.process.command_line)
$principal_process_file_sha256 = array_distinct($network.principal.process.file.sha256)
$principal_process_file_full_path = array_distinct($network.principal.process.file.full_path)
$principal_process_product_specfic_process_id = array_distinct($network.principal.process.product_specific_process_id)
$principal_process_parent_process_product_specfic_process_id = array_distinct($network.principal.process.parent_process.product_specific_process_id)
$target_process_pid = array_distinct($network.target.process.pid)
$target_process_command_line = array_distinct($network.target.process.command_line)
$target_process_file_sha256 = array_distinct($network.target.process.file.sha256)
$target_process_file_full_path = array_distinct($network.target.process.file.full_path)
$target_process_product_specfic_process_id = array_distinct($network.target.process.product_specific_process_id)
$target_process_parent_process_product_specfic_process_id = array_distinct($network.target.process.parent_process.product_specific_process_id)
$principal_user_userid = array_distinct($network.principal.user.userid)
$target_user_userid = array_distinct($network.target.user.userid)
condition:
$network
}
# tftest-file id=rule path=data/rules/network_traffic_to_specific_country.yaral
```
```
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
127.0.0.1/32
::1/128
fc00::/7
fe80::/10
# tftest-file id=reference path=data/reference_lists/private_ip_ranges.txt
```
### SecOps Rules Factory
The module includes a secops rules and reference list factory (see [Resource Factories](../../blueprints/factories/)) for the configuration of rules and reference lists leveraging YAML configuration files. Each configuration file for rules and reference lists contains more than one rule with a structure that reflects the `rules_config` and `reference_lists_config` variables. Again rules and reference list definition is available in the corresponding yaral and txt files in the data folder.
```hcl
module "secops" {
source = "./fabric/modules/secops-rules"
project_id = var.project_id
tenant_config = var.secops_tenant_config
factories_config = {
rules = "./secops_rules.yaml"
rules_defs = "./data/rules"
reference_lists = "./secops_reference_lists.yaml"
reference_lists_defs = "./data/reference_lists"
}
}
# tftest modules=1 resources=3 files=1,2,reference,rule inventory=factory.yaml
```
```yaml
network_traffic_to_specific_country:
enabled: true
alerting: true
archived: false
run_frequency: "DAILY"
# tftest-file id=1 path=secops_rules.yaml
```
```yaml
private_ip_ranges:
description: "Private CIDR ranges"
type: CIDR # either CIDR, STRING, REGEX
# tftest-file id=2 path=secops_reference_lists.yaml
```
```
rule network_traffic_to_specific_country {
meta:
author = "Google Cloud Security"
description = "Identify network traffic based on target country"
type = "alert"
tags = "geoip enrichment"
data_source = "microsoft windows events"
severity = "Low"
priority = "Low"
events:
$network.metadata.event_type = "NETWORK_CONNECTION"
//Specify a country of interest to monitor or add additional countries using an or statement
$network.target.ip_geo_artifact.location.country_or_region = "France" nocase
$network.target.ip = $ip
match:
$ip over 30m
outcome:
$risk_score = max(35)
$event_count = count_distinct($network.metadata.id)
// added to populate alert graph with additional context
$principal_ip = array_distinct($network.principal.ip)
// Commented out target.ip because it is already represented in graph as match variable. If match changes, can uncomment to add to results
//$target_ip = array_distinct($network.target.ip)
$principal_process_pid = array_distinct($network.principal.process.pid)
$principal_process_command_line = array_distinct($network.principal.process.command_line)
$principal_process_file_sha256 = array_distinct($network.principal.process.file.sha256)
$principal_process_file_full_path = array_distinct($network.principal.process.file.full_path)
$principal_process_product_specfic_process_id = array_distinct($network.principal.process.product_specific_process_id)
$principal_process_parent_process_product_specfic_process_id = array_distinct($network.principal.process.parent_process.product_specific_process_id)
$target_process_pid = array_distinct($network.target.process.pid)
$target_process_command_line = array_distinct($network.target.process.command_line)
$target_process_file_sha256 = array_distinct($network.target.process.file.sha256)
$target_process_file_full_path = array_distinct($network.target.process.file.full_path)
$target_process_product_specfic_process_id = array_distinct($network.target.process.product_specific_process_id)
$target_process_parent_process_product_specfic_process_id = array_distinct($network.target.process.parent_process.product_specific_process_id)
$principal_user_userid = array_distinct($network.principal.user.userid)
$target_user_userid = array_distinct($network.target.user.userid)
condition:
$network
}
# tftest-file id=rule path=data/rules/network_traffic_to_specific_country.yaral
```
```
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
127.0.0.1/32
::1/128
fc00::/7
fe80::/10
# tftest-file id=reference path=data/reference_lists/private_ip_ranges.txt
```
<!-- BEGIN TFDOC -->
## Variables
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [project_id](variables.tf#L29) | Project used for resources. | <code>string</code> | ✓ | |
| [tenant_config](variables.tf#L66) | SecOps Tenant configuration. | <code title="object&#40;&#123;&#10; customer_id &#61; string&#10; region &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [factories_config](variables.tf#L17) | Paths to YAML config expected in 'rules' and 'reference_lists'. Path to folders containing rules definitions (yaral files) and reference lists content (txt files) for the corresponding _defs keys. | <code title="object&#40;&#123;&#10; rules &#61; optional&#40;string&#41;&#10; rules_defs &#61; optional&#40;string, &#34;data&#47;rules&#34;&#41;&#10; reference_lists &#61; optional&#40;string&#41;&#10; reference_lists_defs &#61; optional&#40;string, &#34;data&#47;reference_lists&#34;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [reference_lists_config](variables.tf#L34) | SecOps Reference lists configuration. | <code title="map&#40;object&#40;&#123;&#10; description &#61; string&#10; type &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [rules_config](variables.tf#L49) | SecOps Detection rules configuration. | <code title="map&#40;object&#40;&#123;&#10; enabled &#61; optional&#40;bool, true&#41;&#10; alerting &#61; optional&#40;bool, false&#41;&#10; archived &#61; optional&#40;bool, false&#41;&#10; run_frequency : optional&#40;string&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
<!-- END TFDOC -->

View File

@@ -0,0 +1,72 @@
/**
* 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.
*/
locals {
reference_lists = try(yamldecode(file(var.factories_config.reference_lists)), var.reference_lists_config)
reference_lists_entries = {
for k, v in local.reference_lists : k => split("\n", file("${var.factories_config.reference_lists_defs}/${k}.txt"))
}
reference_list_type_mapping = {
STRING = "REFERENCE_LIST_SYNTAX_TYPE_PLAIN_TEXT_STRING"
REGEX = "REFERENCE_LIST_SYNTAX_TYPE_REGEX"
CIDR = "REFERENCE_LIST_SYNTAX_TYPE_CIDR"
}
secops_rules = {
for file_name in fileset(var.factories_config.rules_defs, "*.yaral") :
replace(file_name, ".yaral", "") => file("${var.factories_config.rules_defs}/${file_name}")
}
secops_rule_deployment = try(yamldecode(file(var.factories_config.rules)), var.rules_config)
}
resource "google_chronicle_reference_list" "default" {
for_each = local.reference_lists
project = var.project_id
location = var.tenant_config.region
instance = var.tenant_config.customer_id
reference_list_id = each.key
description = each.value.description
dynamic "entries" {
for_each = local.reference_lists_entries[each.key]
content {
value = entries.value
}
}
syntax_type = local.reference_list_type_mapping[each.value.type]
}
resource "google_chronicle_rule" "default" {
for_each = local.secops_rule_deployment
project = var.project_id
location = var.tenant_config.region
instance = var.tenant_config.customer_id
text = local.secops_rules[each.key]
deletion_policy = "FORCE"
depends_on = [
google_chronicle_reference_list.default
]
}
resource "google_chronicle_rule_deployment" "default" {
for_each = local.secops_rule_deployment
project = var.project_id
location = var.tenant_config.region
instance = var.tenant_config.customer_id
rule = google_chronicle_rule.default[each.key].rule_id
enabled = each.value.enabled
alerting = each.value.alerting
archived = each.value.archived
run_frequency = each.value.run_frequency
}

View File

@@ -0,0 +1,72 @@
/**
* Copyright 2023 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.
*/
variable "factories_config" {
description = "Paths to YAML config expected in 'rules' and 'reference_lists'. Path to folders containing rules definitions (yaral files) and reference lists content (txt files) for the corresponding _defs keys."
type = object({
rules = optional(string)
rules_defs = optional(string, "data/rules")
reference_lists = optional(string)
reference_lists_defs = optional(string, "data/reference_lists")
})
nullable = false
default = {}
}
variable "project_id" {
description = "Project used for resources."
type = string
}
variable "reference_lists_config" {
description = "SecOps Reference lists configuration."
type = map(object({
description = string
type = string
}))
default = {}
validation {
condition = alltrue([
for config in var.reference_lists_config : contains(["CIDR", "STRING", "REGEX"], config.type)
])
error_message = "The 'type' attribute for each reference list must be one of: CIDR, STRING, REGEX."
}
}
variable "rules_config" {
description = "SecOps Detection rules configuration."
type = map(object({
enabled = optional(bool, true)
alerting = optional(bool, false)
archived = optional(bool, false)
run_frequency : optional(string)
}))
default = {}
validation {
condition = alltrue([
for config in var.rules_config : contains(["LIVE", "HOURLY", "DAILY"], config.run_frequency)
])
error_message = "The 'type' attribute for each reference list must be one of: CIDR, STRING, REGEX."
}
}
variable "tenant_config" {
description = "SecOps Tenant configuration."
type = object({
customer_id = string
region = string
})
}

35
modules/secops-rules/versions.tf generated Normal file
View File

@@ -0,0 +1,35 @@
# 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
#
# https://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.
# Fabric release: v38.1.0
terraform {
required_version = ">= 1.10.2"
required_providers {
google = {
source = "hashicorp/google"
version = ">= 6.28.0, < 7.0.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 6.28.0, < 7.0.0" # tftest
}
}
provider_meta "google" {
module_name = "google-pso-tool/cloud-foundation-fabric/path:v38.1.0-tf"
}
provider_meta "google-beta" {
module_name = "google-pso-tool/cloud-foundation-fabric/path:v38.1.0-tf"
}
}

35
modules/secops-rules/versions.tofu generated Normal file
View File

@@ -0,0 +1,35 @@
# 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
#
# https://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.
# Fabric release: v38.1.0
terraform {
required_version = ">= 1.9.0"
required_providers {
google = {
source = "hashicorp/google"
version = ">= 6.28.0, < 7.0.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 6.28.0, < 7.0.0" # tftest
}
}
provider_meta "google" {
module_name = "google-pso-tool/cloud-foundation-fabric/path:v38.1.0-tofu"
}
provider_meta "google-beta" {
module_name = "google-pso-tool/cloud-foundation-fabric/path:v38.1.0-tofu"
}
}

View File

@@ -61,6 +61,13 @@ variable "regions" {
}
}
variable "secops_tenant_config" {
default = {
customer_id = "customer-id"
region = "europe"
}
}
variable "service_account" {
default = {
id = "service_account_id"

View File

@@ -0,0 +1,76 @@
# Copyright 2023 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.
values:
module.secops.google_chronicle_reference_list.default["private_ip_ranges"]:
description: Private CIDR ranges
entries:
- value: 10.0.0.0/8
- value: 172.16.0.0/12
- value: 192.168.0.0/16
- value: 127.0.0.1/32
- value: ::1/128
- value: fc00::/7
- value: fe80::/10
- value: '# tftest-file id=reference path=data/reference_lists/private_ip_ranges.txt'
- value: ''
instance: customer-id
location: europe
project: project-id
reference_list_id: private_ip_ranges
syntax_type: REFERENCE_LIST_SYNTAX_TYPE_CIDR
timeouts: null
module.secops.google_chronicle_rule.default["network_traffic_to_specific_country"]:
deletion_policy: FORCE
instance: customer-id
location: europe
project: project-id
scope: null
text: "rule network_traffic_to_specific_country {\n\nmeta:\n author = \"Google\
\ Cloud Security\"\n description = \"Identify network traffic based on target\
\ country\"\n type = \"alert\"\n tags = \"geoip enrichment\"\n data_source\
\ = \"microsoft windows events\"\n severity = \"Low\"\n priority = \"Low\"\
\n\nevents:\n $network.metadata.event_type = \"NETWORK_CONNECTION\"\n //Specify\
\ a country of interest to monitor or add additional countries using an or statement\n\
\ $network.target.ip_geo_artifact.location.country_or_region = \"France\" nocase\n\
\ $network.target.ip = $ip\n\nmatch:\n $ip over 30m\n\noutcome:\n $risk_score\
\ = max(35)\n $event_count = count_distinct($network.metadata.id)\n\n // added\
\ to populate alert graph with additional context\n $principal_ip = array_distinct($network.principal.ip)\n\
\n // Commented out target.ip because it is already represented in graph as\
\ match variable. If match changes, can uncomment to add to results\n //$target_ip\
\ = array_distinct($network.target.ip)\n $principal_process_pid = array_distinct($network.principal.process.pid)\n\
\ $principal_process_command_line = array_distinct($network.principal.process.command_line)\n\
\ $principal_process_file_sha256 = array_distinct($network.principal.process.file.sha256)\n\
\ $principal_process_file_full_path = array_distinct($network.principal.process.file.full_path)\n\
\ $principal_process_product_specfic_process_id = array_distinct($network.principal.process.product_specific_process_id)\n\
\ $principal_process_parent_process_product_specfic_process_id = array_distinct($network.principal.process.parent_process.product_specific_process_id)\n\
\ $target_process_pid = array_distinct($network.target.process.pid)\n $target_process_command_line\
\ = array_distinct($network.target.process.command_line)\n $target_process_file_sha256\
\ = array_distinct($network.target.process.file.sha256)\n $target_process_file_full_path\
\ = array_distinct($network.target.process.file.full_path)\n $target_process_product_specfic_process_id\
\ = array_distinct($network.target.process.product_specific_process_id)\n $target_process_parent_process_product_specfic_process_id\
\ = array_distinct($network.target.process.parent_process.product_specific_process_id)\n\
\ $principal_user_userid = array_distinct($network.principal.user.userid)\n\
\ $target_user_userid = array_distinct($network.target.user.userid)\n\ncondition:\n\
\ $network\n}\n# tftest-file id=rule path=data/rules/network_traffic_to_specific_country.yaral\n"
timeouts: null
module.secops.google_chronicle_rule_deployment.default["network_traffic_to_specific_country"]:
alerting: true
archived: false
enabled: true
instance: customer-id
location: europe
project: project-id
run_frequency: LIVE
timeouts: null

View File

@@ -0,0 +1,76 @@
# Copyright 2023 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.
values:
module.secops.google_chronicle_reference_list.default["private_ip_ranges"]:
description: Private CIDR ranges
entries:
- value: 10.0.0.0/8
- value: 172.16.0.0/12
- value: 192.168.0.0/16
- value: 127.0.0.1/32
- value: ::1/128
- value: fc00::/7
- value: fe80::/10
- value: '# tftest-file id=reference path=data/reference_lists/private_ip_ranges.txt'
- value: ''
instance: customer-id
location: europe
project: project-id
reference_list_id: private_ip_ranges
syntax_type: REFERENCE_LIST_SYNTAX_TYPE_CIDR
timeouts: null
module.secops.google_chronicle_rule.default["network_traffic_to_specific_country"]:
deletion_policy: FORCE
instance: customer-id
location: europe
project: project-id
scope: null
text: "rule network_traffic_to_specific_country {\n\nmeta:\n author = \"Google\
\ Cloud Security\"\n description = \"Identify network traffic based on target\
\ country\"\n type = \"alert\"\n tags = \"geoip enrichment\"\n data_source\
\ = \"microsoft windows events\"\n severity = \"Low\"\n priority = \"Low\"\
\n\nevents:\n $network.metadata.event_type = \"NETWORK_CONNECTION\"\n //Specify\
\ a country of interest to monitor or add additional countries using an or statement\n\
\ $network.target.ip_geo_artifact.location.country_or_region = \"France\" nocase\n\
\ $network.target.ip = $ip\n\nmatch:\n $ip over 30m\n\noutcome:\n $risk_score\
\ = max(35)\n $event_count = count_distinct($network.metadata.id)\n\n // added\
\ to populate alert graph with additional context\n $principal_ip = array_distinct($network.principal.ip)\n\
\n // Commented out target.ip because it is already represented in graph as\
\ match variable. If match changes, can uncomment to add to results\n //$target_ip\
\ = array_distinct($network.target.ip)\n $principal_process_pid = array_distinct($network.principal.process.pid)\n\
\ $principal_process_command_line = array_distinct($network.principal.process.command_line)\n\
\ $principal_process_file_sha256 = array_distinct($network.principal.process.file.sha256)\n\
\ $principal_process_file_full_path = array_distinct($network.principal.process.file.full_path)\n\
\ $principal_process_product_specfic_process_id = array_distinct($network.principal.process.product_specific_process_id)\n\
\ $principal_process_parent_process_product_specfic_process_id = array_distinct($network.principal.process.parent_process.product_specific_process_id)\n\
\ $target_process_pid = array_distinct($network.target.process.pid)\n $target_process_command_line\
\ = array_distinct($network.target.process.command_line)\n $target_process_file_sha256\
\ = array_distinct($network.target.process.file.sha256)\n $target_process_file_full_path\
\ = array_distinct($network.target.process.file.full_path)\n $target_process_product_specfic_process_id\
\ = array_distinct($network.target.process.product_specific_process_id)\n $target_process_parent_process_product_specfic_process_id\
\ = array_distinct($network.target.process.parent_process.product_specific_process_id)\n\
\ $principal_user_userid = array_distinct($network.principal.user.userid)\n\
\ $target_user_userid = array_distinct($network.target.user.userid)\n\ncondition:\n\
\ $network\n}\n# tftest-file id=rule path=data/rules/network_traffic_to_specific_country.yaral\n"
timeouts: null
module.secops.google_chronicle_rule_deployment.default["network_traffic_to_specific_country"]:
alerting: true
archived: false
enabled: true
instance: customer-id
location: europe
project: project-id
run_frequency: DAILY
timeouts: null