Merge branch 'master' into sa-upload-crt

This commit is contained in:
Aleksandr Averbukh
2021-12-13 22:50:13 +01:00
committed by GitHub
42 changed files with 1563 additions and 690 deletions

View File

@@ -0,0 +1,23 @@
# Copyright 2021 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.
region: europe-west1
description: Sample description
ip_cidr_range: 10.128.0.0/24
private_ip_google_access: false
iam_users: ["foobar@example.com"]
iam_groups: ["lorem@example.com"]
iam_service_accounts: ["foobar@project-id.iam.gserviceaccount.com"]
secondary_ip_range:
secondary-range-a: 192.168.128.0/24

View File

@@ -15,20 +15,21 @@
*/
module "test" {
source = "../../../../modules/net-vpc"
project_id = var.project_id
name = var.name
iam = var.iam
log_configs = var.log_configs
log_config_defaults = var.log_config_defaults
peering_config = var.peering_config
routes = var.routes
shared_vpc_host = var.shared_vpc_host
shared_vpc_service_projects = var.shared_vpc_service_projects
subnets = var.subnets
subnet_descriptions = var.subnet_descriptions
subnet_flow_logs = var.subnet_flow_logs
subnet_private_access = var.subnet_private_access
auto_create_subnetworks = var.auto_create_subnetworks
private_service_networking_range = var.private_service_networking_range
source = "../../../../modules/net-vpc"
project_id = var.project_id
name = var.name
iam = var.iam
log_configs = var.log_configs
log_config_defaults = var.log_config_defaults
peering_config = var.peering_config
routes = var.routes
shared_vpc_host = var.shared_vpc_host
shared_vpc_service_projects = var.shared_vpc_service_projects
subnets = var.subnets
subnet_descriptions = var.subnet_descriptions
subnet_flow_logs = var.subnet_flow_logs
subnet_private_access = var.subnet_private_access
auto_create_subnetworks = var.auto_create_subnetworks
psn_ranges = var.psn_ranges
data_folder = var.data_folder
}

View File

@@ -61,6 +61,11 @@ variable "peering_config" {
default = null
}
variable "psn_ranges" {
type = list(string)
default = null
}
variable "routes" {
type = map(object({
dest_range = string
@@ -125,3 +130,9 @@ variable "private_service_networking_range" {
type = string
default = null
}
variable "data_folder" {
description = "An optional folder containing the subnet configurations in YaML format."
type = string
default = null
}

View File

@@ -88,20 +88,3 @@ def test_vpc_routes(plan_runner):
resource = [r for r in resources if r['values']
['name'] == 'my-vpc-next-hop-test'][0]
assert resource['values']['next_hop_%s' % next_hop_type]
def test_vpc_psn(plan_runner):
_, resources = plan_runner(
FIXTURES_DIR, private_service_networking_range="10.10.0.0/16"
)
assert len(resources) == 3
address = [r["values"] for r in resources if r["type"] == "google_compute_global_address"][0]
assert address["address"] == "10.10.0.0"
assert address["address_type"] == "INTERNAL"
assert address["prefix_length"] == 16
assert address["purpose"] == "VPC_PEERING"
connection = [r["values"] for r in resources if r["type"] == "google_service_networking_connection"][0]
assert connection["service"] == "servicenetworking.googleapis.com"
assert connection["reserved_peering_ranges"] == ["my-vpc-google-psn"]

View File

@@ -0,0 +1,42 @@
# Copyright 2021 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.
import os
import pytest
import tftest
FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture')
def test_single_range(plan_runner):
"Test single PSN range."
_, resources = plan_runner(FIXTURES_DIR, psn_ranges='["172.16.100.0/24"]')
assert len(resources) == 3
def test_multi_range(plan_runner):
"Test multiple PSN ranges."
_, resources = plan_runner(FIXTURES_DIR,
psn_ranges='["172.16.100.0/24", "172.16.101.0/24"]')
assert len(resources) == 4
def test_validation(plan_runner):
"Test PSN variable validation."
try:
plan_runner(FIXTURES_DIR, psn_ranges='["foobar"]')
except tftest.TerraformTestError as e:
assert 'Invalid value for variable' in e.args[0]

View File

@@ -29,6 +29,19 @@ _VAR_SUBNETS = (
']'
)
_VAR_DATA_FOLDER = "data"
def test_subnet_factory(plan_runner):
"Test subnet factory."
_, resources = plan_runner(FIXTURES_DIR, data_folder=_VAR_DATA_FOLDER)
assert len(resources) == 3
subnets = [r['values']
for r in resources if r['type'] == 'google_compute_subnetwork']
assert set(s['name'] for s in subnets) == set(
['factory-subnet'])
assert set(len(s['secondary_ip_range']) for s in subnets) == set([1])
def test_subnets_simple(plan_runner):
"Test subnets variable."
@@ -58,9 +71,9 @@ def test_subnet_log_configs(plan_runner):
for r in resources:
if r['type'] != 'google_compute_subnetwork':
continue
flow_logs[r['values']['name']] = [{key: config[key] for key in config.keys()
& {'aggregation_interval', 'flow_sampling', 'metadata'}}
for config in r['values']['log_config']]
flow_logs[r['values']['name']] = [{key: config[key] for key in config.keys()
& {'aggregation_interval', 'flow_sampling', 'metadata'}}
for config in r['values']['log_config']]
assert flow_logs == {
# enable, override one default option
'a': [{

View File

@@ -0,0 +1,13 @@
# Copyright 2021 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.

View File

@@ -0,0 +1,19 @@
# Copyright 2021 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.
healthchecks:
- 35.191.0.0/16
- 130.211.0.0/22
- 209.85.152.0/22
- 209.85.204.0/22

View File

@@ -0,0 +1,28 @@
# Copyright 2021 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.
allow-healthchecks:
description: Allow ingress from healthchecks.
direction: INGRESS
action: allow
sources: []
ranges:
- $healthchecks
targets: ["lb-backends"]
use_service_accounts: false
rules:
- protocol: tcp
ports:
- 80
- 443

View File

@@ -0,0 +1,28 @@
/**
* Copyright 2021 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.
*/
module "firewall" {
source = "../../../../modules/net-vpc-firewall"
project_id = var.project_id
network = var.network
admin_ranges = var.admin_ranges
http_source_ranges = var.http_source_ranges
https_source_ranges = var.https_source_ranges
ssh_source_ranges = var.ssh_source_ranges
custom_rules = var.custom_rules
data_folder = var.data_folder
cidr_template_file = var.cidr_template_file
}

View File

@@ -0,0 +1,97 @@
/**
* Copyright 2021 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 "admin_ranges" {
description = "IP CIDR ranges that have complete access to all subnets."
type = list(string)
default = []
}
variable "cidr_template_file" {
description = "Path for optional file containing name->cidr_list map to be used by the rules factory."
type = string
default = null
}
variable "custom_rules" {
description = "List of custom rule definitions (refer to variables file for syntax)."
type = map(object({
description = string
direction = string
action = string # (allow|deny)
ranges = list(string)
sources = list(string)
targets = list(string)
use_service_accounts = bool
rules = list(object({
protocol = string
ports = list(string)
}))
extra_attributes = map(string)
}))
default = {}
}
variable "data_folder" {
description = "Path for optional folder containing firewall rules defined as YaML objects used by the rules factory."
type = string
default = null
}
variable "http_source_ranges" {
description = "List of IP CIDR ranges for tag-based HTTP rule, defaults to the health checkers ranges."
type = list(string)
default = ["35.191.0.0/16", "130.211.0.0/22", "209.85.152.0/22", "209.85.204.0/22"]
}
variable "https_source_ranges" {
description = "List of IP CIDR ranges for tag-based HTTPS rule, defaults to the health checkers ranges."
type = list(string)
default = ["35.191.0.0/16", "130.211.0.0/22", "209.85.152.0/22", "209.85.204.0/22"]
}
variable "named_ranges" {
description = "Names that can be used of valid values for the `ranges` field of `custom_rules`"
type = map(list(string))
default = {
any = ["0.0.0.0/0"]
dns-forwarders = ["35.199.192.0/19"]
health-checkers = ["35.191.0.0/16", "130.211.0.0/22", "209.85.152.0/22", "209.85.204.0/22"]
iap-forwarders = ["35.235.240.0/20"]
private-googleapis = ["199.36.153.8/30"]
restricted-googleapis = ["199.36.153.4/30"]
rfc1918 = ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
}
}
variable "network" {
description = "Name of the network this set of firewall rules applies to."
type = string
default = "vpc"
}
variable "project_id" {
description = "Project id of the project that holds the network."
type = string
default = "project"
}
variable "ssh_source_ranges" {
description = "List of IP CIDR ranges for tag-based SSH rule, defaults to the IAP forwarders range."
type = list(string)
default = ["35.235.240.0/20"]
}

View File

@@ -0,0 +1,44 @@
# Copyright 2021 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.
import os
import pytest
FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture')
def test_vpc_firewall_simple(plan_runner):
"Test vpc with no extra options."
_, resources = plan_runner(FIXTURES_DIR)
assert len(resources) == 3
assert set([r['type'] for r in resources]) == set(
['google_compute_firewall'])
assert set([r['values']['name'] for r in resources]) == set(
['vpc-ingress-tag-http', 'vpc-ingress-tag-https', 'vpc-ingress-tag-ssh'])
assert set([r['values']['project'] for r in resources]) == set(['project'])
assert set([r['values']['network'] for r in resources]) == set(['vpc'])
def test_vpc_firewall_factory(plan_runner):
"Test shared vpc variables."
_, resources = plan_runner(
FIXTURES_DIR, data_folder="config/firewall", cidr_template_file="config/cidr_template.yaml")
assert len(resources) == 4
factory_rule = [r for r in resources if r["values"]
["name"] == "allow-healthchecks"][0]["values"]
assert set(factory_rule["source_ranges"]) == set(
["130.211.0.0/22", "209.85.152.0/22", "209.85.204.0/22", "35.191.0.0/16"])
assert set(factory_rule["target_tags"]) == set(["lb-backends"])

View File

@@ -0,0 +1,18 @@
# Copyright 2021 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.
rfc1918:
- 10.0.0.0/8
- 172.168.0.0/12
- 192.168.0.0/16

View File

@@ -0,0 +1,37 @@
# Copyright 2021 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.
allow-admins:
description: Access from the admin subnet to all subnets
direction: INGRESS
action: allow
priority: 1000
ranges:
- $rfc1918
ports:
all: []
target_resources: null
enable_logging: false
allow-ssh-from-iap:
description: Enable SSH from IAP
direction: INGRESS
action: allow
priority: 1002
ranges:
- 35.235.240.0/20
ports:
tcp: ["22"]
target_resources: null
enable_logging: false

View File

@@ -27,6 +27,7 @@ module "test" {
policy_list = var.policy_list
firewall_policies = var.firewall_policies
firewall_policy_attachments = var.firewall_policy_attachments
firewall_policy_factory = var.firewall_policy_factory
logging_sinks = var.logging_sinks
logging_exclusions = var.logging_exclusions
}

View File

@@ -79,14 +79,24 @@ variable "firewall_policy_attachments" {
default = {}
}
variable "firewall_policy_factory" {
type = object({
cidr_file = string
policy_name = string
rules_file = string
})
default = null
}
variable "logging_sinks" {
type = map(object({
destination = string
type = string
filter = string
iam = bool
include_children = bool
exclusions = map(string)
destination = string
type = string
filter = string
iam = bool
include_children = bool
bq_partitioned_table = bool
exclusions = map(string)
}))
default = {}
}

View File

@@ -110,78 +110,3 @@ def test_policy_list(plan_runner):
assert values[1]['list_policy'][0]['deny'] == [
{'all': False, 'values': ["bar"]}]
assert values[2]['restore_policy'] == [{'default': True}]
def test_firweall_policy(plan_runner):
"Test boolean folder policy."
policy = """
{
policy1 = {
allow-ingress = {
description = ""
direction = "INGRESS"
action = "allow"
priority = 100
ranges = ["10.0.0.0/8"]
ports = {
tcp = ["22"]
}
target_service_accounts = null
target_resources = null
logging = false
}
deny-egress = {
description = ""
direction = "EGRESS"
action = "deny"
priority = 200
ranges = ["192.168.0.0/24"]
ports = {
tcp = ["443"]
}
target_service_accounts = null
target_resources = null
logging = false
}
}
}
"""
attachment = '{ iap_policy = "policy1" }'
_, resources = plan_runner(FIXTURES_DIR, firewall_policies=policy,
firewall_policy_attachments=attachment)
assert len(resources) == 4
policies = [r for r in resources
if r['type'] == 'google_compute_organization_security_policy']
assert len(policies) == 1
rules = [r for r in resources
if r['type'] == 'google_compute_organization_security_policy_rule']
assert len(rules) == 2
rule_values = []
for rule in rules:
name = rule['name']
index = rule['index']
action = rule['values']['action']
direction = rule['values']['direction']
priority = rule['values']['priority']
config = rule['values']['match']
assert len(config) == 1
config = config[0]['config']
rule_values.append((name, index, action, direction, priority, config))
assert sorted(rule_values) == sorted([
('rule', 'policy1-allow-ingress', 'allow', 'INGRESS', 100, [
{
'dest_ip_ranges': None,
'layer4_config': [{'ip_protocol': 'tcp', 'ports': ['22']}],
'src_ip_ranges': ['10.0.0.0/8']
}]),
('rule', 'policy1-deny-egress', 'deny', 'EGRESS', 200, [
{
'dest_ip_ranges': ['192.168.0.0/24'],
'layer4_config': [{'ip_protocol': 'tcp', 'ports': ['443']}],
'src_ip_ranges': None
}])
])

View File

@@ -0,0 +1,137 @@
# Copyright 2021 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.
import os
import pytest
FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture')
_FACTORY = '''
{
cidr_file = "data/firewall-cidrs.yaml"
policy_name = "factory-1"
rules_file = "data/firewall-rules.yaml"
}
'''
_POLICIES = '''
{
policy1 = {
allow-ingress = {
description = ""
direction = "INGRESS"
action = "allow"
priority = 100
ranges = ["10.0.0.0/8"]
ports = {
tcp = ["22"]
}
target_service_accounts = null
target_resources = null
logging = false
}
deny-egress = {
description = ""
direction = "EGRESS"
action = "deny"
priority = 200
ranges = ["192.168.0.0/24"]
ports = {
tcp = ["443"]
}
target_service_accounts = null
target_resources = null
logging = false
}
}
policy2 = {
allow-ingress = {
description = ""
direction = "INGRESS"
action = "allow"
priority = 100
ranges = ["10.0.0.0/8"]
ports = {
tcp = ["22"]
}
target_service_accounts = null
target_resources = null
logging = false
}
}
}
'''
def test_custom(plan_runner):
'Test custom firewall policies.'
_, resources = plan_runner(FIXTURES_DIR, firewall_policies=_POLICIES)
assert len(resources) == 5
policies = [r for r in resources
if r['type'] == 'google_compute_organization_security_policy']
rules = [r for r in resources
if r['type'] == 'google_compute_organization_security_policy_rule']
assert set(r['index'] for r in policies) == set([
'policy1', 'policy2'
])
assert set(r['index'] for r in rules) == set([
'policy1-deny-egress', 'policy2-allow-ingress', 'policy1-allow-ingress'
])
def test_factory(plan_runner):
'Test firewall policy factory.'
_, resources = plan_runner(FIXTURES_DIR, firewall_policy_factory=_FACTORY)
assert len(resources) == 3
policies = [r for r in resources
if r['type'] == 'google_compute_organization_security_policy']
rules = [r for r in resources
if r['type'] == 'google_compute_organization_security_policy_rule']
assert set(r['index'] for r in policies) == set([
'factory-1'
])
assert set(r['index'] for r in rules) == set([
'factory-1-allow-admins', 'factory-1-allow-ssh-from-iap'
])
def test_factory_name(plan_runner):
'Test firewall policy factory default name.'
factory = _FACTORY.replace('"factory-1"', 'null')
_, resources = plan_runner(FIXTURES_DIR, firewall_policy_factory=factory)
assert len(resources) == 3
policies = [r for r in resources
if r['type'] == 'google_compute_organization_security_policy']
assert set(r['index'] for r in policies) == set([
'factory'
])
def test_combined(plan_runner):
'Test combined rules.'
_, resources = plan_runner(FIXTURES_DIR, firewall_policies=_POLICIES,
firewall_policy_factory=_FACTORY)
assert len(resources) == 8
policies = [r for r in resources
if r['type'] == 'google_compute_organization_security_policy']
rules = [r for r in resources
if r['type'] == 'google_compute_organization_security_policy_rule']
assert set(r['index'] for r in policies) == set([
'factory-1', 'policy1', 'policy2'
])
assert set(r['index'] for r in rules) == set([
'factory-1-allow-admins', 'factory-1-allow-ssh-from-iap',
'policy1-deny-egress', 'policy2-allow-ingress', 'policy1-allow-ingress'
])

View File

@@ -22,148 +22,154 @@ FIXTURES_DIR = os.path.join(os.path.dirname(__file__), "fixture")
def test_sinks(plan_runner):
"Test folder-level sinks."
logging_sinks = """ {
"Test folder-level sinks."
logging_sinks = """ {
warning = {
type = "gcs"
destination = "mybucket"
filter = "severity=WARNING"
iam = true
include_children = true
exclusions = {}
type = "storage"
destination = "mybucket"
filter = "severity=WARNING"
iam = true
include_children = true
bq_partitioned_table = null
exclusions = {}
}
info = {
type = "bigquery"
destination = "projects/myproject/datasets/mydataset"
filter = "severity=INFO"
iam = true
include_children = true
exclusions = {}
type = "bigquery"
destination = "projects/myproject/datasets/mydataset"
filter = "severity=INFO"
iam = true
include_children = true
bq_partitioned_table = false
exclusions = {}
}
notice = {
type = "pubsub"
destination = "projects/myproject/topics/mytopic"
filter = "severity=NOTICE"
iam = true
include_children = false
exclusions = {}
type = "pubsub"
destination = "projects/myproject/topics/mytopic"
filter = "severity=NOTICE"
iam = true
include_children = false
bq_partitioned_table = null
exclusions = {}
}
debug = {
type = "logging"
destination = "projects/myproject/locations/global/buckets/mybucket"
filter = "severity=DEBUG"
iam = true
include_children = false
exclusions = {
type = "logging"
destination = "projects/myproject/locations/global/buckets/mybucket"
filter = "severity=DEBUG"
iam = true
include_children = false
bq_partitioned_table = null
exclusions = {
no-compute = "logName:compute"
no-container = "logName:container"
}
}
}
"""
_, resources = plan_runner(FIXTURES_DIR, logging_sinks=logging_sinks)
assert len(resources) == 8
_, resources = plan_runner(FIXTURES_DIR, logging_sinks=logging_sinks)
assert len(resources) == 8
resource_types = Counter([r["type"] for r in resources])
assert resource_types == {
"google_logging_organization_sink": 4,
"google_bigquery_dataset_iam_member": 1,
"google_project_iam_member": 1,
"google_pubsub_topic_iam_member": 1,
"google_storage_bucket_iam_member": 1,
}
resource_types = Counter([r["type"] for r in resources])
assert resource_types == {
"google_logging_organization_sink": 4,
"google_bigquery_dataset_iam_member": 1,
"google_project_iam_member": 1,
"google_pubsub_topic_iam_member": 1,
"google_storage_bucket_iam_member": 1,
}
sinks = [r for r in resources if r["type"] == "google_logging_organization_sink"]
assert sorted([r["index"] for r in sinks]) == [
"debug",
"info",
"notice",
"warning",
]
values = [
(
r["index"],
r["values"]["filter"],
r["values"]["destination"],
r["values"]["include_children"],
)
for r in sinks
]
assert sorted(values) == [
(
"debug",
"severity=DEBUG",
"logging.googleapis.com/projects/myproject/locations/global/buckets/mybucket",
False,
),
(
"info",
"severity=INFO",
"bigquery.googleapis.com/projects/myproject/datasets/mydataset",
True,
),
(
"notice",
"severity=NOTICE",
"pubsub.googleapis.com/projects/myproject/topics/mytopic",
False,
),
("warning", "severity=WARNING", "storage.googleapis.com/mybucket", True),
]
sinks = [r for r in resources if r["type"]
== "google_logging_organization_sink"]
assert sorted([r["index"] for r in sinks]) == [
"debug",
"info",
"notice",
"warning",
]
values = [
(
r["index"],
r["values"]["filter"],
r["values"]["destination"],
r["values"]["include_children"],
)
for r in sinks
]
assert sorted(values) == [
(
"debug",
"severity=DEBUG",
"logging.googleapis.com/projects/myproject/locations/global/buckets/mybucket",
False,
),
(
"info",
"severity=INFO",
"bigquery.googleapis.com/projects/myproject/datasets/mydataset",
True,
),
(
"notice",
"severity=NOTICE",
"pubsub.googleapis.com/projects/myproject/topics/mytopic",
False,
),
("warning", "severity=WARNING", "storage.googleapis.com/mybucket", True),
]
bindings = [r for r in resources if "member" in r["type"]]
values = [(r["index"], r["type"], r["values"]["role"]) for r in bindings]
assert sorted(values) == [
("debug", "google_project_iam_member", "roles/logging.bucketWriter"),
("info", "google_bigquery_dataset_iam_member", "roles/bigquery.dataEditor"),
("notice", "google_pubsub_topic_iam_member", "roles/pubsub.publisher"),
("warning", "google_storage_bucket_iam_member", "roles/storage.objectCreator"),
]
bindings = [r for r in resources if "member" in r["type"]]
values = [(r["index"], r["type"], r["values"]["role"]) for r in bindings]
assert sorted(values) == [
("debug", "google_project_iam_member", "roles/logging.bucketWriter"),
("info", "google_bigquery_dataset_iam_member", "roles/bigquery.dataEditor"),
("notice", "google_pubsub_topic_iam_member", "roles/pubsub.publisher"),
("warning", "google_storage_bucket_iam_member", "roles/storage.objectCreator"),
]
exclusions = [(r["index"], r["values"]["exclusions"]) for r in sinks]
assert sorted(exclusions) == [
(
"debug",
[
{
"description": None,
"disabled": False,
"filter": "logName:compute",
"name": "no-compute",
},
{
"description": None,
"disabled": False,
"filter": "logName:container",
"name": "no-container",
},
],
),
("info", []),
("notice", []),
("warning", []),
]
exclusions = [(r["index"], r["values"]["exclusions"]) for r in sinks]
assert sorted(exclusions) == [
(
"debug",
[
{
"description": None,
"disabled": False,
"filter": "logName:compute",
"name": "no-compute",
},
{
"description": None,
"disabled": False,
"filter": "logName:container",
"name": "no-container",
},
],
),
("info", []),
("notice", []),
("warning", []),
]
def test_exclusions(plan_runner):
"Test folder-level logging exclusions."
logging_exclusions = (
"{"
'exclusion1 = "resource.type=gce_instance", '
'exclusion2 = "severity=NOTICE", '
"}"
)
_, resources = plan_runner(FIXTURES_DIR, logging_exclusions=logging_exclusions)
assert len(resources) == 2
exclusions = [
r for r in resources if r["type"] == "google_logging_organization_exclusion"
]
assert sorted([r["index"] for r in exclusions]) == [
"exclusion1",
"exclusion2",
]
values = [(r["index"], r["values"]["filter"]) for r in exclusions]
assert sorted(values) == [
("exclusion1", "resource.type=gce_instance"),
("exclusion2", "severity=NOTICE"),
]
"Test folder-level logging exclusions."
logging_exclusions = (
"{"
'exclusion1 = "resource.type=gce_instance", '
'exclusion2 = "severity=NOTICE", '
"}"
)
_, resources = plan_runner(
FIXTURES_DIR, logging_exclusions=logging_exclusions)
assert len(resources) == 2
exclusions = [
r for r in resources if r["type"] == "google_logging_organization_exclusion"
]
assert sorted([r["index"] for r in exclusions]) == [
"exclusion1",
"exclusion2",
]
values = [(r["index"], r["values"]["filter"]) for r in exclusions]
assert sorted(values) == [
("exclusion1", "resource.type=gce_instance"),
("exclusion2", "severity=NOTICE"),
]