From 4af011d96bd84692a1474018675dcd616a1592bd Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Wed, 28 Jul 2021 11:28:14 +0000 Subject: [PATCH] feat: add finding_class and indicator fields in Finding (#201) finding_class field is added in order to help our customer to quickly identify and categorize the different findings (threat, vulnerability, misconfiguration, ...). And indicator field is generated to indicate the domain and IP addresses that is causing the threat. PiperOrigin-RevId: 386975549 Source-Link: https://github.com/googleapis/googleapis/commit/5bf36f20f8e49c18620bf20a45645310f5bf6950 Source-Link: https://github.com/googleapis/googleapis-gen/commit/b9ab677eb147fbf3eb3b1d501f90b9d3f8078872 --- google/cloud/securitycenter/__init__.py | 2 + google/cloud/securitycenter_v1/__init__.py | 2 + .../services/security_center/async_client.py | 1 + .../services/security_center/client.py | 1 + .../cloud/securitycenter_v1/types/__init__.py | 2 + .../cloud/securitycenter_v1/types/finding.py | 19 ++++++++ .../securitycenter_v1/types/indicator.py | 43 +++++++++++++++++++ .../securitycenter_v1/test_security_center.py | 13 ++++++ 8 files changed, 83 insertions(+) create mode 100644 google/cloud/securitycenter_v1/types/indicator.py diff --git a/google/cloud/securitycenter/__init__.py b/google/cloud/securitycenter/__init__.py index b45dff2c..152da218 100644 --- a/google/cloud/securitycenter/__init__.py +++ b/google/cloud/securitycenter/__init__.py @@ -24,6 +24,7 @@ from google.cloud.securitycenter_v1.types.asset import Asset from google.cloud.securitycenter_v1.types.finding import Finding from google.cloud.securitycenter_v1.types.folder import Folder +from google.cloud.securitycenter_v1.types.indicator import Indicator from google.cloud.securitycenter_v1.types.notification_config import NotificationConfig from google.cloud.securitycenter_v1.types.notification_message import ( NotificationMessage, @@ -121,6 +122,7 @@ "Asset", "Finding", "Folder", + "Indicator", "NotificationConfig", "NotificationMessage", "OrganizationSettings", diff --git a/google/cloud/securitycenter_v1/__init__.py b/google/cloud/securitycenter_v1/__init__.py index 9c8fa408..3c579dae 100644 --- a/google/cloud/securitycenter_v1/__init__.py +++ b/google/cloud/securitycenter_v1/__init__.py @@ -20,6 +20,7 @@ from .types.asset import Asset from .types.finding import Finding from .types.folder import Folder +from .types.indicator import Indicator from .types.notification_config import NotificationConfig from .types.notification_message import NotificationMessage from .types.organization_settings import OrganizationSettings @@ -72,6 +73,7 @@ "GroupFindingsRequest", "GroupFindingsResponse", "GroupResult", + "Indicator", "ListAssetsRequest", "ListAssetsResponse", "ListFindingsRequest", diff --git a/google/cloud/securitycenter_v1/services/security_center/async_client.py b/google/cloud/securitycenter_v1/services/security_center/async_client.py index 1fd7472a..f0338337 100644 --- a/google/cloud/securitycenter_v1/services/security_center/async_client.py +++ b/google/cloud/securitycenter_v1/services/security_center/async_client.py @@ -31,6 +31,7 @@ from google.cloud.securitycenter_v1.services.security_center import pagers from google.cloud.securitycenter_v1.types import finding from google.cloud.securitycenter_v1.types import finding as gcs_finding +from google.cloud.securitycenter_v1.types import indicator from google.cloud.securitycenter_v1.types import notification_config from google.cloud.securitycenter_v1.types import ( notification_config as gcs_notification_config, diff --git a/google/cloud/securitycenter_v1/services/security_center/client.py b/google/cloud/securitycenter_v1/services/security_center/client.py index c7546fa6..2993688f 100644 --- a/google/cloud/securitycenter_v1/services/security_center/client.py +++ b/google/cloud/securitycenter_v1/services/security_center/client.py @@ -35,6 +35,7 @@ from google.cloud.securitycenter_v1.services.security_center import pagers from google.cloud.securitycenter_v1.types import finding from google.cloud.securitycenter_v1.types import finding as gcs_finding +from google.cloud.securitycenter_v1.types import indicator from google.cloud.securitycenter_v1.types import notification_config from google.cloud.securitycenter_v1.types import ( notification_config as gcs_notification_config, diff --git a/google/cloud/securitycenter_v1/types/__init__.py b/google/cloud/securitycenter_v1/types/__init__.py index dc6a8bc3..5602ea30 100644 --- a/google/cloud/securitycenter_v1/types/__init__.py +++ b/google/cloud/securitycenter_v1/types/__init__.py @@ -16,6 +16,7 @@ from .asset import Asset from .finding import Finding from .folder import Folder +from .indicator import Indicator from .notification_config import NotificationConfig from .notification_message import NotificationMessage from .organization_settings import OrganizationSettings @@ -57,6 +58,7 @@ "Asset", "Finding", "Folder", + "Indicator", "NotificationConfig", "NotificationMessage", "OrganizationSettings", diff --git a/google/cloud/securitycenter_v1/types/finding.py b/google/cloud/securitycenter_v1/types/finding.py index 40cbb2a2..6a3c3071 100644 --- a/google/cloud/securitycenter_v1/types/finding.py +++ b/google/cloud/securitycenter_v1/types/finding.py @@ -15,6 +15,7 @@ # import proto # type: ignore +from google.cloud.securitycenter_v1.types import indicator as gcs_indicator from google.cloud.securitycenter_v1.types import security_marks as gcs_security_marks from google.protobuf import struct_pb2 # type: ignore from google.protobuf import timestamp_pb2 # type: ignore @@ -100,6 +101,14 @@ class Finding(proto.Message): "projects/{project_number}/sources/{source_id}/findings/{finding_id}", depending on the closest CRM ancestor of the resource associated with the finding. + finding_class (google.cloud.securitycenter_v1.types.Finding.FindingClass): + The class of the finding. + indicator (google.cloud.securitycenter_v1.types.Indicator): + Represents what's commonly known as an Indicator of + compromise (IoC) in computer forensics. This is an artifact + observed on a network or in an operating system that, with + high confidence, indicates a computer intrusion. Reference: + https://en.wikipedia.org/wiki/Indicator_of_compromise """ class State(proto.Enum): @@ -116,6 +125,14 @@ class Severity(proto.Enum): MEDIUM = 3 LOW = 4 + class FindingClass(proto.Enum): + r"""Represents what kind of Finding it is.""" + FINDING_CLASS_UNSPECIFIED = 0 + THREAT = 1 + VULNERABILITY = 2 + MISCONFIGURATION = 3 + OBSERVATION = 4 + name = proto.Field(proto.STRING, number=1,) parent = proto.Field(proto.STRING, number=2,) resource_name = proto.Field(proto.STRING, number=3,) @@ -134,6 +151,8 @@ class Severity(proto.Enum): ) severity = proto.Field(proto.ENUM, number=12, enum=Severity,) canonical_name = proto.Field(proto.STRING, number=14,) + finding_class = proto.Field(proto.ENUM, number=17, enum=FindingClass,) + indicator = proto.Field(proto.MESSAGE, number=18, message=gcs_indicator.Indicator,) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/securitycenter_v1/types/indicator.py b/google/cloud/securitycenter_v1/types/indicator.py new file mode 100644 index 00000000..16ead94a --- /dev/null +++ b/google/cloud/securitycenter_v1/types/indicator.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 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 proto # type: ignore + + +__protobuf__ = proto.module( + package="google.cloud.securitycenter.v1", manifest={"Indicator",}, +) + + +class Indicator(proto.Message): + r"""Represents what's commonly known as an Indicator of compromise (IoC) + in computer forensics. This is an artifact observed on a network or + in an operating system that, with high confidence, indicates a + computer intrusion. Reference: + https://en.wikipedia.org/wiki/Indicator_of_compromise + + Attributes: + ip_addresses (Sequence[str]): + List of ip addresses associated to the + Finding. + domains (Sequence[str]): + List of domains associated to the Finding. + """ + + ip_addresses = proto.RepeatedField(proto.STRING, number=1,) + domains = proto.RepeatedField(proto.STRING, number=2,) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/tests/unit/gapic/securitycenter_v1/test_security_center.py b/tests/unit/gapic/securitycenter_v1/test_security_center.py index 86b341fa..edbd7bd1 100644 --- a/tests/unit/gapic/securitycenter_v1/test_security_center.py +++ b/tests/unit/gapic/securitycenter_v1/test_security_center.py @@ -45,6 +45,7 @@ ) from google.cloud.securitycenter_v1.types import finding from google.cloud.securitycenter_v1.types import finding as gcs_finding +from google.cloud.securitycenter_v1.types import indicator from google.cloud.securitycenter_v1.types import notification_config from google.cloud.securitycenter_v1.types import ( notification_config as gcs_notification_config, @@ -771,6 +772,7 @@ def test_create_finding( external_uri="external_uri_value", severity=gcs_finding.Finding.Severity.CRITICAL, canonical_name="canonical_name_value", + finding_class=gcs_finding.Finding.FindingClass.THREAT, ) response = client.create_finding(request) @@ -789,6 +791,7 @@ def test_create_finding( assert response.external_uri == "external_uri_value" assert response.severity == gcs_finding.Finding.Severity.CRITICAL assert response.canonical_name == "canonical_name_value" + assert response.finding_class == gcs_finding.Finding.FindingClass.THREAT def test_create_finding_from_dict(): @@ -836,6 +839,7 @@ async def test_create_finding_async( external_uri="external_uri_value", severity=gcs_finding.Finding.Severity.CRITICAL, canonical_name="canonical_name_value", + finding_class=gcs_finding.Finding.FindingClass.THREAT, ) ) response = await client.create_finding(request) @@ -855,6 +859,7 @@ async def test_create_finding_async( assert response.external_uri == "external_uri_value" assert response.severity == gcs_finding.Finding.Severity.CRITICAL assert response.canonical_name == "canonical_name_value" + assert response.finding_class == gcs_finding.Finding.FindingClass.THREAT @pytest.mark.asyncio @@ -4667,6 +4672,7 @@ def test_set_finding_state( external_uri="external_uri_value", severity=finding.Finding.Severity.CRITICAL, canonical_name="canonical_name_value", + finding_class=finding.Finding.FindingClass.THREAT, ) response = client.set_finding_state(request) @@ -4685,6 +4691,7 @@ def test_set_finding_state( assert response.external_uri == "external_uri_value" assert response.severity == finding.Finding.Severity.CRITICAL assert response.canonical_name == "canonical_name_value" + assert response.finding_class == finding.Finding.FindingClass.THREAT def test_set_finding_state_from_dict(): @@ -4736,6 +4743,7 @@ async def test_set_finding_state_async( external_uri="external_uri_value", severity=finding.Finding.Severity.CRITICAL, canonical_name="canonical_name_value", + finding_class=finding.Finding.FindingClass.THREAT, ) ) response = await client.set_finding_state(request) @@ -4755,6 +4763,7 @@ async def test_set_finding_state_async( assert response.external_uri == "external_uri_value" assert response.severity == finding.Finding.Severity.CRITICAL assert response.canonical_name == "canonical_name_value" + assert response.finding_class == finding.Finding.FindingClass.THREAT @pytest.mark.asyncio @@ -5395,6 +5404,7 @@ def test_update_finding( external_uri="external_uri_value", severity=gcs_finding.Finding.Severity.CRITICAL, canonical_name="canonical_name_value", + finding_class=gcs_finding.Finding.FindingClass.THREAT, ) response = client.update_finding(request) @@ -5413,6 +5423,7 @@ def test_update_finding( assert response.external_uri == "external_uri_value" assert response.severity == gcs_finding.Finding.Severity.CRITICAL assert response.canonical_name == "canonical_name_value" + assert response.finding_class == gcs_finding.Finding.FindingClass.THREAT def test_update_finding_from_dict(): @@ -5460,6 +5471,7 @@ async def test_update_finding_async( external_uri="external_uri_value", severity=gcs_finding.Finding.Severity.CRITICAL, canonical_name="canonical_name_value", + finding_class=gcs_finding.Finding.FindingClass.THREAT, ) ) response = await client.update_finding(request) @@ -5479,6 +5491,7 @@ async def test_update_finding_async( assert response.external_uri == "external_uri_value" assert response.severity == gcs_finding.Finding.Severity.CRITICAL assert response.canonical_name == "canonical_name_value" + assert response.finding_class == gcs_finding.Finding.FindingClass.THREAT @pytest.mark.asyncio