Skip to content

Commit d711031

Browse files
authored
feat(scc): add v2 samples for Sources, mute, findings, IAM permissions and security marks (GoogleCloudPlatform#12011)
* added findings v2 version * list findings * added source_v2 * changes made based on Java files * added new files * iam permissions * addressed commenets * added security marks files * bulk_mute_findings * errors fixed * comments addressed * addressed the comments * fixed lint changes * added test functions * fixed lint issues * env vars added * updated Env var * added noxconfig file * fixed pipeline errors * updated Org
1 parent b99d37e commit d711031

11 files changed

+1228
-20
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/usr/bin/env python
2+
#
3+
# Copyright 2024 Google LLC
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
18+
# [START securitycenter_set_mute_v2]
19+
def set_mute_finding(finding_path: str) -> None:
20+
"""
21+
Mute an individual finding.
22+
If a finding is already muted, muting it again has no effect.
23+
Various mute states are: MUTE_UNSPECIFIED/MUTE/UNMUTE.
24+
Args:
25+
finding_path: The relative resource name of the finding. See:
26+
https://cloud.google.com/apis/design/resource_names#relative_resource_name
27+
Use any one of the following formats:
28+
- organizations/{organization_id}/sources/{source_id}/finding/{finding_id},
29+
- folders/{folder_id}/sources/{source_id}/finding/{finding_id},
30+
- projects/{project_id}/sources/{source_id}/finding/{finding_id}.
31+
"""
32+
from google.cloud import securitycenter_v2
33+
34+
client = securitycenter_v2.SecurityCenterClient()
35+
36+
request = securitycenter_v2.SetMuteRequest()
37+
request.name = finding_path
38+
request.mute = securitycenter_v2.Finding.Mute.MUTED
39+
40+
finding = client.set_mute(request)
41+
print(f"Mute value for the finding: {finding.mute.name}")
42+
return finding
43+
44+
# [END securitycenter_set_mute_v2]
45+
46+
47+
# [START securitycenter_set_unmute_v2]
48+
def set_unmute_finding(finding_path: str) -> None:
49+
"""
50+
Unmute an individual finding.
51+
Unmuting a finding that isn't muted has no effect.
52+
Various mute states are: MUTE_UNSPECIFIED/MUTE/UNMUTE.
53+
Args:
54+
finding_path: The relative resource name of the finding. See:
55+
https://cloud.google.com/apis/design/resource_names#relative_resource_name
56+
Use any one of the following formats:
57+
- organizations/{organization_id}/sources/{source_id}/finding/{finding_id},
58+
- folders/{folder_id}/sources/{source_id}/finding/{finding_id},
59+
- projects/{project_id}/sources/{source_id}/finding/{finding_id}.
60+
"""
61+
from google.cloud import securitycenter_v2
62+
63+
client = securitycenter_v2.SecurityCenterClient()
64+
65+
request = securitycenter_v2.SetMuteRequest()
66+
request.name = finding_path
67+
request.mute = securitycenter_v2.Finding.Mute.UNMUTED
68+
69+
finding = client.set_mute(request)
70+
print(f"Mute value for the finding: {finding.mute.name}")
71+
return finding
72+
73+
# [END securitycenter_set_unmute_v2]
74+
75+
76+
# # [START securitycenter_bulk_mute_v2]
77+
# def bulk_mute_findings(parent_path: str, location_id, mute_rule: str) -> None:
78+
# """
79+
# Kicks off a long-running operation (LRO) to bulk mute findings for a parent based on a filter.
80+
# The parent can be either an organization, folder, or project. The findings
81+
# matched by the filter will be muted after the LRO is done.
82+
# Args:
83+
# parent_path: use any one of the following options:
84+
# - organizations/{organization}
85+
# - folders/{folder}
86+
# - projects/{project}
87+
# mute_rule: Expression that identifies findings that should be updated.
88+
# """
89+
# from google.cloud import securitycenter_v2
90+
#
91+
# client = securitycenter_v2.SecurityCenterClient()
92+
#
93+
# request = securitycenter_v2.BulkMuteFindingsRequest()
94+
# request.parent = parent_path+"/locations/"+location_id
95+
# # To create mute rules, see:
96+
# # https://cloud.google.com/security-command-center/docs/how-to-mute-findings#create_mute_rules
97+
# request.filter = mute_rule
98+
#
99+
# response = client.bulk_mute_findings(request)
100+
# print(f"Bulk mute findings completed successfully! : {response}")
101+
# return response
102+
# # [END securitycenter_bulk_mute_v2]
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!/usr/bin/env python
2+
#
3+
# Copyright 2024 Google LLC
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
import os
17+
18+
import backoff
19+
from google.api_core.exceptions import InternalServerError, NotFound, ServiceUnavailable
20+
21+
import pytest
22+
23+
import mute_findings_v2
24+
25+
# TODO(developer): Replace these variables before running the sample.
26+
PROJECT_ID = os.environ["GOOGLE_CLOUD_PROJECT"]
27+
ORGANIZATION_ID = os.environ["GCLOUD_ORGANIZATION"]
28+
29+
30+
@pytest.fixture
31+
def finding():
32+
import snippets_findings_v2
33+
from snippets_findings_v2 import create_finding
34+
35+
response = snippets_findings_v2.create_source(ORGANIZATION_ID)
36+
source_name = response.name
37+
finding1_path = create_finding(ORGANIZATION_ID, "global", "1testingscc", source_name, "MEDIUM_RISK_ONE").name
38+
finding2_path = create_finding(ORGANIZATION_ID, "global", "2testingscc", source_name, "MEDIUM_RISK_ONE").name
39+
40+
yield {
41+
"source": source_name,
42+
"finding1": finding1_path,
43+
"finding2": finding2_path,
44+
}
45+
46+
47+
@backoff.on_exception(
48+
backoff.expo, (InternalServerError, ServiceUnavailable, NotFound), max_tries=3
49+
)
50+
def test_set_mute_finding(finding):
51+
finding_path = finding.get("finding1")
52+
response = mute_findings_v2.set_mute_finding(finding_path)
53+
assert response.name == finding_path
54+
assert response.mute.name == "MUTED"
55+
56+
57+
@backoff.on_exception(
58+
backoff.expo, (InternalServerError, ServiceUnavailable, NotFound), max_tries=3
59+
)
60+
def test_set_unmute_finding(finding):
61+
finding_path = finding.get("finding1")
62+
response = mute_findings_v2.set_unmute_finding(finding_path)
63+
assert response.mute.name == "UNMUTED"
64+
65+
66+
# @backoff.on_exception(
67+
# backoff.expo, (InternalServerError, ServiceUnavailable, NotFound), max_tries=3
68+
# )
69+
# def test_bulk_mute_findings(finding):
70+
# # Mute findings that belong to this project.
71+
# response = mute_findings_v2.bulk_mute_findings(
72+
# f"organizations/{ORGANIZATION_ID}", "global", f'resource.project_display_name="{ORGANIZATION_ID}"'
73+
# )
74+
# assert response.done
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Copyright 2020 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Default TEST_CONFIG_OVERRIDE for python repos.
16+
17+
# You can copy this file into your directory, then it will be inported from
18+
# the noxfile.py.
19+
20+
# The source of truth:
21+
# https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/noxfile_config.py
22+
23+
TEST_CONFIG_OVERRIDE = {
24+
# You can opt out from the test for specific Python versions.
25+
"ignored_versions": ["2.7", "3.7", "3.9", "3.10", "3.11"],
26+
# An envvar key for determining the project id to use. Change it
27+
# to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a
28+
# build specific Cloud project. You can also use your own string
29+
# to use your own Cloud project.
30+
"gcloud_project_env": "GOOGLE_CLOUD_PROJECT",
31+
# "gcloud_project_env": "BUILD_SPECIFIC_GCLOUD_PROJECT",
32+
# A dictionary you want to inject into your test. Don't put any
33+
# secrets here. These values will override predefined values.
34+
"envs": {
35+
"GCLOUD_ORGANIZATION": "1081635000895",
36+
"GCLOUD_PROJECT": "project-a-id",
37+
"GCLOUD_PUBSUB_TOPIC": "projects/project-a-id/topics/notifications-sample-topic",
38+
"GCLOUD_PUBSUB_SUBSCRIPTION": "notification-sample-subscription",
39+
},
40+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
google-cloud-securitycenter==1.31.0
2-
google-cloud-bigquery==3.11.4
2+
google-cloud-bigquery==3.11.4

0 commit comments

Comments
 (0)