Skip to content

Commit 4e84e44

Browse files
authored
feat(securitycenter): Add Resource SCC Management API Org Security Center Service (Get, List, Update) (GoogleCloudPlatform#13098)
1 parent a0caa62 commit 4e84e44

File tree

2 files changed

+221
-0
lines changed

2 files changed

+221
-0
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
#!/usr/bin/env python
2+
#
3+
# Copyright 2025 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+
from google.api_core.exceptions import GoogleAPICallError, NotFound, RetryError
18+
from google.cloud import securitycentermanagement_v1
19+
from google.protobuf.field_mask_pb2 import FieldMask
20+
21+
22+
# [START securitycenter_get_security_center_service]
23+
def get_security_center_service(parent: str, service: str):
24+
"""
25+
Gets service settings for the specified Security Command Center service.
26+
Args:
27+
parent: Use any one of the following options:
28+
- organizations/{organization_id}/locations/{location_id}
29+
- folders/{folder_id}/locations/{location_id}
30+
- projects/{project_id}/locations/{location_id}
31+
service: Valid value of the service
32+
For the full list of valid service values, see
33+
https://cloud.google.com/security-command-center/docs/reference/security-center-management/rest/v1/organizations.locations.securityCenterServices/get#path-parameters
34+
Returns:
35+
The retrieved service setting for the specified Security Command Center service.
36+
Raises:
37+
NotFound: If the specified Security Command Center service does not exist.
38+
"""
39+
40+
try:
41+
client = securitycentermanagement_v1.SecurityCenterManagementClient()
42+
43+
request = securitycentermanagement_v1.GetSecurityCenterServiceRequest(
44+
name=f"{parent}/securityCenterServices/{service}",
45+
)
46+
47+
response = client.get_security_center_service(request=request)
48+
print(f"Retrieved SecurityCenterService Setting for : {response.name}")
49+
return response
50+
except NotFound as e:
51+
print(f"SecurityCenterService not found: {e.message}")
52+
raise e
53+
# [END securitycenter_get_security_center_service]
54+
55+
56+
# [START securitycenter_list_security_center_service]
57+
def list_security_center_service(parent: str):
58+
"""
59+
Returns a list of all Security Command Center services for the given parent.
60+
61+
Args:
62+
parent: Use any one of the following options:
63+
- organizations/{organization_id}/locations/{location_id}
64+
- folders/{folder_id}/locations/{location_id}
65+
- projects/{project_id}/locations/{location_id}
66+
Returns:
67+
List of retrieved all Security Command Center services.
68+
Raises:
69+
Exception: If an unexpected error occurs.
70+
"""
71+
72+
try:
73+
client = securitycentermanagement_v1.SecurityCenterManagementClient()
74+
75+
request = securitycentermanagement_v1.ListSecurityCenterServicesRequest(
76+
parent=parent,
77+
)
78+
79+
services = []
80+
# List all Security Command Center services present in the resource.
81+
for response in client.list_security_center_services(request=request):
82+
print(f"Security Center Service Name: {response.name}")
83+
services.append(response)
84+
return services
85+
86+
except GoogleAPICallError as api_error:
87+
print(f"API call failed: {api_error}")
88+
except RetryError as retry_error:
89+
print(f"Retry error occurred: {retry_error}")
90+
except Exception as e:
91+
print(f"An unexpected error occurred: {e}")
92+
93+
# [END securitycenter_list_security_center_service]
94+
95+
96+
# [START securitycenter_update_security_center_service]
97+
def update_security_center_service(parent: str, service: str):
98+
"""
99+
Updates a Security Command Center service using the given update mask.
100+
101+
Args:
102+
parent: Use any one of the following options:
103+
- organizations/{organization_id}/locations/{location_id}
104+
- folders/{folder_id}/locations/{location_id}
105+
- projects/{project_id}/locations/{location_id}
106+
Returns:
107+
The update service setting for the specified Security Command Center service.
108+
"""
109+
110+
try:
111+
client = securitycentermanagement_v1.SecurityCenterManagementClient()
112+
113+
service = securitycentermanagement_v1.types.SecurityCenterService(
114+
name=f"{parent}/securityCenterServices/{service}",
115+
intended_enablement_state=securitycentermanagement_v1.types.SecurityCenterService.EnablementState.DISABLED,
116+
)
117+
118+
# Create the request
119+
request = securitycentermanagement_v1.UpdateSecurityCenterServiceRequest(
120+
security_center_service=service,
121+
update_mask=FieldMask(paths=["intended_enablement_state"]),
122+
)
123+
124+
# Make the API call
125+
updated_service = client.update_security_center_service(request=request)
126+
127+
print(f"Updated SecurityCenterService: {updated_service.name} with new enablement state: {service.intended_enablement_state.name}")
128+
return updated_service
129+
130+
except GoogleAPICallError as api_error:
131+
print(f"API call failed: {api_error}")
132+
except RetryError as retry_error:
133+
print(f"Retry error occurred: {retry_error}")
134+
except Exception as e:
135+
print(f"An unexpected error occurred: {e}")
136+
137+
# [END securitycenter_update_security_center_service]
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#!/usr/bin/env python
2+
#
3+
# Copyright 2025 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+
import os
18+
19+
import backoff
20+
21+
from google.api_core.exceptions import InternalServerError, NotFound, ServiceUnavailable
22+
23+
import pytest
24+
25+
import security_center_service
26+
27+
# Replace these variables before running the sample.
28+
# GCLOUD_ORGANIZATION: The organization ID.
29+
ORGANIZATION_ID = os.environ["GCLOUD_ORGANIZATION"]
30+
LOCATION = "global"
31+
32+
33+
@pytest.fixture(scope="session", autouse=True)
34+
def setup_environment():
35+
if not ORGANIZATION_ID:
36+
pytest.fail("GCLOUD_ORGANIZATION environment variable is not set.")
37+
38+
39+
@backoff.on_exception(
40+
backoff.expo, (InternalServerError, ServiceUnavailable, NotFound), max_tries=3
41+
)
42+
def test_get_security_center_service():
43+
44+
service = "event-threat-detection"
45+
parent = f"organizations/{ORGANIZATION_ID}/locations/{LOCATION}"
46+
47+
# Retrieve the security center service
48+
response = security_center_service.get_security_center_service(parent, service)
49+
50+
assert response is not None, "Failed to retrieve the SecurityCenterService."
51+
assert service in response.name, f"Expected service ID {service} in response, got {response.name}."
52+
53+
54+
@backoff.on_exception(
55+
backoff.expo, (InternalServerError, ServiceUnavailable, NotFound), max_tries=3
56+
)
57+
def test_list_security_center_service():
58+
59+
parent = f"organizations/{ORGANIZATION_ID}/locations/{LOCATION}"
60+
# Retrieve the list of security center services
61+
response = security_center_service.list_security_center_service(parent)
62+
63+
assert response is not None, "Failed to list Security Center services."
64+
assert len(response) > 0, "No Security Center services were retrieved."
65+
assert any(ORGANIZATION_ID in service.name for service in response), \
66+
f"Expected organization ID {ORGANIZATION_ID} in one of the services, but none were found."
67+
68+
69+
@backoff.on_exception(
70+
backoff.expo, (InternalServerError, ServiceUnavailable, NotFound), max_tries=3
71+
)
72+
def test_update_security_center_service():
73+
74+
service = "event-threat-detection"
75+
parent = f"organizations/{ORGANIZATION_ID}/locations/{LOCATION}"
76+
# Update the security center service
77+
updated_service = security_center_service.update_security_center_service(parent, service)
78+
79+
assert updated_service is not None, "Failed to retrieve the Security Center service."
80+
assert ORGANIZATION_ID in updated_service.name, \
81+
f"Expected organization ID {ORGANIZATION_ID} in the updated service, got {updated_service.name}."
82+
assert service in updated_service.name, f"Expected service ID {service} in updated service, got {updated_service.name}."
83+
assert updated_service.intended_enablement_state.name == "DISABLED", \
84+
f"Expected enablement state to be 'DISABLED', got {updated_service.intended_enablement_state.name}."

0 commit comments

Comments
 (0)