diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index ee94722a..7d98291c 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/cloud-devrel-public-resources/owlbot-python:latest - digest: sha256:6e7328583be8edd3ba8f35311c76a1ecbc823010279ccb6ab46b7a76e25eafcc + digest: sha256:58f73ba196b5414782605236dd0712a73541b44ff2ff4d3a36ec41092dd6fa5b diff --git a/.kokoro/samples/python3.10/common.cfg b/.kokoro/samples/python3.10/common.cfg new file mode 100644 index 00000000..c50c94ee --- /dev/null +++ b/.kokoro/samples/python3.10/common.cfg @@ -0,0 +1,40 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Build logs will be here +action { + define_artifacts { + regex: "**/*sponge_log.xml" + } +} + +# Specify which tests to run +env_vars: { + key: "RUN_TESTS_SESSION" + value: "py-3.10" +} + +# Declare build specific Cloud project. +env_vars: { + key: "BUILD_SPECIFIC_GCLOUD_PROJECT" + value: "python-docs-samples-tests-310" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-securitycenter/.kokoro/test-samples.sh" +} + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/python-samples-testing-docker" +} + +# Download secrets for samples +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples" + +# Download trampoline resources. +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" + +# Use the trampoline script to run in docker. +build_file: "python-securitycenter/.kokoro/trampoline_v2.sh" \ No newline at end of file diff --git a/.kokoro/samples/python3.10/continuous.cfg b/.kokoro/samples/python3.10/continuous.cfg new file mode 100644 index 00000000..a1c8d975 --- /dev/null +++ b/.kokoro/samples/python3.10/continuous.cfg @@ -0,0 +1,6 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} \ No newline at end of file diff --git a/.kokoro/samples/python3.10/periodic-head.cfg b/.kokoro/samples/python3.10/periodic-head.cfg new file mode 100644 index 00000000..1fa5e82f --- /dev/null +++ b/.kokoro/samples/python3.10/periodic-head.cfg @@ -0,0 +1,11 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-securitycenter/.kokoro/test-samples-against-head.sh" +} diff --git a/.kokoro/samples/python3.10/periodic.cfg b/.kokoro/samples/python3.10/periodic.cfg new file mode 100644 index 00000000..71cd1e59 --- /dev/null +++ b/.kokoro/samples/python3.10/periodic.cfg @@ -0,0 +1,6 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "False" +} diff --git a/.kokoro/samples/python3.10/presubmit.cfg b/.kokoro/samples/python3.10/presubmit.cfg new file mode 100644 index 00000000..a1c8d975 --- /dev/null +++ b/.kokoro/samples/python3.10/presubmit.cfg @@ -0,0 +1,6 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b0a8afc..42ad4e1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ [1]: https://pypi.org/project/google-cloud-securitycenter/#history +## [1.7.0](https://www.github.com/googleapis/python-securitycenter/compare/v1.6.0...v1.7.0) (2021-10-08) + + +### Features + +* Added type field to the resource which is surfaced in NotificationMessage ([a233f7a](https://www.github.com/googleapis/python-securitycenter/commit/a233f7a0d85ba1a2932a1ee8305e48eda5aafa75)) +* Added vulnerability field to Finding ([#235](https://www.github.com/googleapis/python-securitycenter/issues/235)) ([a233f7a](https://www.github.com/googleapis/python-securitycenter/commit/a233f7a0d85ba1a2932a1ee8305e48eda5aafa75)) + ## [1.6.0](https://www.github.com/googleapis/python-securitycenter/compare/v1.5.2...v1.6.0) (2021-10-07) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 9dbfc7b5..8b4b87a0 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -22,7 +22,7 @@ In order to add a feature: documentation. - The feature must work fully on the following CPython versions: - 3.6, 3.7, 3.8 and 3.9 on both UNIX and Windows. + 3.6, 3.7, 3.8, 3.9 and 3.10 on both UNIX and Windows. - The feature must not add unnecessary dependencies (where "unnecessary" is of course subjective, but new dependencies should @@ -72,7 +72,7 @@ We use `nox `__ to instrument our tests. - To run a single unit test:: - $ nox -s unit-3.9 -- -k + $ nox -s unit-3.10 -- -k .. note:: @@ -225,11 +225,13 @@ We support: - `Python 3.7`_ - `Python 3.8`_ - `Python 3.9`_ +- `Python 3.10`_ .. _Python 3.6: https://docs.python.org/3.6/ .. _Python 3.7: https://docs.python.org/3.7/ .. _Python 3.8: https://docs.python.org/3.8/ .. _Python 3.9: https://docs.python.org/3.9/ +.. _Python 3.10: https://docs.python.org/3.10/ Supported versions can be found in our ``noxfile.py`` `config`_. diff --git a/google/cloud/securitycenter/__init__.py b/google/cloud/securitycenter/__init__.py index 152da218..8b715d74 100644 --- a/google/cloud/securitycenter/__init__.py +++ b/google/cloud/securitycenter/__init__.py @@ -115,6 +115,10 @@ UpdateSourceRequest, ) from google.cloud.securitycenter_v1.types.source import Source +from google.cloud.securitycenter_v1.types.vulnerability import Cve +from google.cloud.securitycenter_v1.types.vulnerability import Cvssv3 +from google.cloud.securitycenter_v1.types.vulnerability import Reference +from google.cloud.securitycenter_v1.types.vulnerability import Vulnerability __all__ = ( "SecurityCenterClient", @@ -157,4 +161,8 @@ "UpdateSecurityMarksRequest", "UpdateSourceRequest", "Source", + "Cve", + "Cvssv3", + "Reference", + "Vulnerability", ) diff --git a/google/cloud/securitycenter_v1/__init__.py b/google/cloud/securitycenter_v1/__init__.py index 3c579dae..c1e8ab0e 100644 --- a/google/cloud/securitycenter_v1/__init__.py +++ b/google/cloud/securitycenter_v1/__init__.py @@ -55,6 +55,10 @@ from .types.securitycenter_service import UpdateSecurityMarksRequest from .types.securitycenter_service import UpdateSourceRequest from .types.source import Source +from .types.vulnerability import Cve +from .types.vulnerability import Cvssv3 +from .types.vulnerability import Reference +from .types.vulnerability import Vulnerability __all__ = ( "SecurityCenterAsyncClient", @@ -62,6 +66,8 @@ "CreateFindingRequest", "CreateNotificationConfigRequest", "CreateSourceRequest", + "Cve", + "Cvssv3", "DeleteNotificationConfigRequest", "Finding", "Folder", @@ -85,6 +91,7 @@ "NotificationConfig", "NotificationMessage", "OrganizationSettings", + "Reference", "Resource", "RunAssetDiscoveryRequest", "RunAssetDiscoveryResponse", @@ -97,4 +104,5 @@ "UpdateOrganizationSettingsRequest", "UpdateSecurityMarksRequest", "UpdateSourceRequest", + "Vulnerability", ) 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 fbe22cc0..ec6ffd95 100644 --- a/google/cloud/securitycenter_v1/services/security_center/async_client.py +++ b/google/cloud/securitycenter_v1/services/security_center/async_client.py @@ -46,6 +46,7 @@ from google.cloud.securitycenter_v1.types import securitycenter_service from google.cloud.securitycenter_v1.types import source from google.cloud.securitycenter_v1.types import source as gcs_source +from google.cloud.securitycenter_v1.types import vulnerability from google.iam.v1 import iam_policy_pb2 # type: ignore from google.iam.v1 import policy_pb2 # type: ignore from google.protobuf import empty_pb2 # type: ignore diff --git a/google/cloud/securitycenter_v1/services/security_center/client.py b/google/cloud/securitycenter_v1/services/security_center/client.py index b1785db9..5e7c6216 100644 --- a/google/cloud/securitycenter_v1/services/security_center/client.py +++ b/google/cloud/securitycenter_v1/services/security_center/client.py @@ -50,6 +50,7 @@ from google.cloud.securitycenter_v1.types import securitycenter_service from google.cloud.securitycenter_v1.types import source from google.cloud.securitycenter_v1.types import source as gcs_source +from google.cloud.securitycenter_v1.types import vulnerability from google.iam.v1 import iam_policy_pb2 # type: ignore from google.iam.v1 import policy_pb2 # type: ignore from google.protobuf import empty_pb2 # type: ignore diff --git a/google/cloud/securitycenter_v1/types/__init__.py b/google/cloud/securitycenter_v1/types/__init__.py index 5602ea30..d5eba377 100644 --- a/google/cloud/securitycenter_v1/types/__init__.py +++ b/google/cloud/securitycenter_v1/types/__init__.py @@ -53,6 +53,12 @@ UpdateSourceRequest, ) from .source import Source +from .vulnerability import ( + Cve, + Cvssv3, + Reference, + Vulnerability, +) __all__ = ( "Asset", @@ -93,4 +99,8 @@ "UpdateSecurityMarksRequest", "UpdateSourceRequest", "Source", + "Cve", + "Cvssv3", + "Reference", + "Vulnerability", ) diff --git a/google/cloud/securitycenter_v1/types/finding.py b/google/cloud/securitycenter_v1/types/finding.py index 6a3c3071..16a78faf 100644 --- a/google/cloud/securitycenter_v1/types/finding.py +++ b/google/cloud/securitycenter_v1/types/finding.py @@ -17,6 +17,7 @@ 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.cloud.securitycenter_v1.types import vulnerability as gcs_vulnerability from google.protobuf import struct_pb2 # type: ignore from google.protobuf import timestamp_pb2 # type: ignore @@ -109,6 +110,11 @@ class Finding(proto.Message): 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 + vulnerability (google.cloud.securitycenter_v1.types.Vulnerability): + Represents vulnerability specific fields like + cve, cvss scores etc. CVE stands for Common + Vulnerabilities and Exposures + (https://cve.mitre.org/about/) """ class State(proto.Enum): @@ -153,6 +159,9 @@ class FindingClass(proto.Enum): 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,) + vulnerability = proto.Field( + proto.MESSAGE, number=20, message=gcs_vulnerability.Vulnerability, + ) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/securitycenter_v1/types/resource.py b/google/cloud/securitycenter_v1/types/resource.py index 20799d7e..b1b58044 100644 --- a/google/cloud/securitycenter_v1/types/resource.py +++ b/google/cloud/securitycenter_v1/types/resource.py @@ -40,6 +40,8 @@ class Resource(proto.Message): The full resource name of resource's parent. parent_display_name (str): The human readable name of resource's parent. + type_ (str): + The full resource type of the resource. folders (Sequence[google.cloud.securitycenter_v1.types.Folder]): Output only. Contains a Folder message for each folder in the assets ancestry. The first @@ -53,6 +55,7 @@ class Resource(proto.Message): project_display_name = proto.Field(proto.STRING, number=3,) parent = proto.Field(proto.STRING, number=4,) parent_display_name = proto.Field(proto.STRING, number=5,) + type_ = proto.Field(proto.STRING, number=6,) folders = proto.RepeatedField(proto.MESSAGE, number=7, message=folder.Folder,) diff --git a/google/cloud/securitycenter_v1/types/vulnerability.py b/google/cloud/securitycenter_v1/types/vulnerability.py new file mode 100644 index 00000000..a21ffab5 --- /dev/null +++ b/google/cloud/securitycenter_v1/types/vulnerability.py @@ -0,0 +1,191 @@ +# -*- 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={"Vulnerability", "Cve", "Reference", "Cvssv3",}, +) + + +class Vulnerability(proto.Message): + r"""Refers to common vulnerability fields e.g. cve, cvss, cwe + etc. + + Attributes: + cve (google.cloud.securitycenter_v1.types.Cve): + CVE stands for Common Vulnerabilities and + Exposures (https://cve.mitre.org/about/) + """ + + cve = proto.Field(proto.MESSAGE, number=1, message="Cve",) + + +class Cve(proto.Message): + r"""CVE stands for Common Vulnerabilities and Exposures. + More information: https://cve.mitre.org + + Attributes: + id (str): + The unique identifier for the vulnerability. + e.g. CVE-2021-34527 + references (Sequence[google.cloud.securitycenter_v1.types.Reference]): + Additional information about the CVE. + e.g. https://cve.mitre.org/cgi- + bin/cvename.cgi?name=CVE-2021-34527 + cvssv3 (google.cloud.securitycenter_v1.types.Cvssv3): + Describe Common Vulnerability Scoring System + specified at + https://www.first.org/cvss/v3.1/specification- + document + """ + + id = proto.Field(proto.STRING, number=1,) + references = proto.RepeatedField(proto.MESSAGE, number=2, message="Reference",) + cvssv3 = proto.Field(proto.MESSAGE, number=3, message="Cvssv3",) + + +class Reference(proto.Message): + r"""Additional Links + + Attributes: + source (str): + Source of the reference e.g. NVD + uri (str): + Uri for the mentioned source e.g. + https://cve.mitre.org/cgi- + bin/cvename.cgi?name=CVE-2021-34527. + """ + + source = proto.Field(proto.STRING, number=1,) + uri = proto.Field(proto.STRING, number=2,) + + +class Cvssv3(proto.Message): + r"""Common Vulnerability Scoring System version 3. + + Attributes: + base_score (float): + The base score is a function of the base + metric scores. + attack_vector (google.cloud.securitycenter_v1.types.Cvssv3.AttackVector): + Base Metrics + Represents the intrinsic characteristics of a + vulnerability that are constant over time and + across user environments. This metric reflects + the context by which vulnerability exploitation + is possible. + attack_complexity (google.cloud.securitycenter_v1.types.Cvssv3.AttackComplexity): + This metric describes the conditions beyond + the attacker's control that must exist in order + to exploit the vulnerability. + privileges_required (google.cloud.securitycenter_v1.types.Cvssv3.PrivilegesRequired): + This metric describes the level of privileges + an attacker must possess before successfully + exploiting the vulnerability. + user_interaction (google.cloud.securitycenter_v1.types.Cvssv3.UserInteraction): + This metric captures the requirement for a + human user, other than the attacker, to + participate in the successful compromise of the + vulnerable component. + scope (google.cloud.securitycenter_v1.types.Cvssv3.Scope): + The Scope metric captures whether a + vulnerability in one vulnerable component + impacts resources in components beyond its + security scope. + confidentiality_impact (google.cloud.securitycenter_v1.types.Cvssv3.Impact): + This metric measures the impact to the + confidentiality of the information resources + managed by a software component due to a + successfully exploited vulnerability. + integrity_impact (google.cloud.securitycenter_v1.types.Cvssv3.Impact): + This metric measures the impact to integrity + of a successfully exploited vulnerability. + availability_impact (google.cloud.securitycenter_v1.types.Cvssv3.Impact): + This metric measures the impact to the + availability of the impacted component resulting + from a successfully exploited vulnerability. + """ + + class AttackVector(proto.Enum): + r"""This metric reflects the context by which vulnerability + exploitation is possible. + """ + ATTACK_VECTOR_UNSPECIFIED = 0 + ATTACK_VECTOR_NETWORK = 1 + ATTACK_VECTOR_ADJACENT = 2 + ATTACK_VECTOR_LOCAL = 3 + ATTACK_VECTOR_PHYSICAL = 4 + + class AttackComplexity(proto.Enum): + r"""This metric describes the conditions beyond the attacker's + control that must exist in order to exploit the vulnerability. + """ + ATTACK_COMPLEXITY_UNSPECIFIED = 0 + ATTACK_COMPLEXITY_LOW = 1 + ATTACK_COMPLEXITY_HIGH = 2 + + class PrivilegesRequired(proto.Enum): + r"""This metric describes the level of privileges an attacker + must possess before successfully exploiting the vulnerability. + """ + PRIVILEGES_REQUIRED_UNSPECIFIED = 0 + PRIVILEGES_REQUIRED_NONE = 1 + PRIVILEGES_REQUIRED_LOW = 2 + PRIVILEGES_REQUIRED_HIGH = 3 + + class UserInteraction(proto.Enum): + r"""This metric captures the requirement for a human user, other + than the attacker, to participate in the successful compromise + of the vulnerable component. + """ + USER_INTERACTION_UNSPECIFIED = 0 + USER_INTERACTION_NONE = 1 + USER_INTERACTION_REQUIRED = 2 + + class Scope(proto.Enum): + r"""The Scope metric captures whether a vulnerability in one + vulnerable component impacts resources in components beyond its + security scope. + """ + SCOPE_UNSPECIFIED = 0 + SCOPE_UNCHANGED = 1 + SCOPE_CHANGED = 2 + + class Impact(proto.Enum): + r"""The Impact metrics capture the effects of a successfully + exploited vulnerability on the component that suffers the worst + outcome that is most directly and predictably associated with + the attack. + """ + IMPACT_UNSPECIFIED = 0 + IMPACT_HIGH = 1 + IMPACT_LOW = 2 + IMPACT_NONE = 3 + + base_score = proto.Field(proto.DOUBLE, number=1,) + attack_vector = proto.Field(proto.ENUM, number=5, enum=AttackVector,) + attack_complexity = proto.Field(proto.ENUM, number=6, enum=AttackComplexity,) + privileges_required = proto.Field(proto.ENUM, number=7, enum=PrivilegesRequired,) + user_interaction = proto.Field(proto.ENUM, number=8, enum=UserInteraction,) + scope = proto.Field(proto.ENUM, number=9, enum=Scope,) + confidentiality_impact = proto.Field(proto.ENUM, number=10, enum=Impact,) + integrity_impact = proto.Field(proto.ENUM, number=11, enum=Impact,) + availability_impact = proto.Field(proto.ENUM, number=12, enum=Impact,) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/noxfile.py b/noxfile.py index 2bf3ffd7..672b28d6 100644 --- a/noxfile.py +++ b/noxfile.py @@ -29,7 +29,7 @@ DEFAULT_PYTHON_VERSION = "3.8" SYSTEM_TEST_PYTHON_VERSIONS = ["3.8"] -UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9"] +UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9", "3.10"] CURRENT_DIRECTORY = pathlib.Path(__file__).parent.absolute() diff --git a/samples/snippets/noxfile.py b/samples/snippets/noxfile.py index 1fd8956f..93a9122c 100644 --- a/samples/snippets/noxfile.py +++ b/samples/snippets/noxfile.py @@ -87,7 +87,7 @@ def get_pytest_env_vars() -> Dict[str, str]: # DO NOT EDIT - automatically generated. # All versions used to test samples. -ALL_VERSIONS = ["3.6", "3.7", "3.8", "3.9"] +ALL_VERSIONS = ["3.6", "3.7", "3.8", "3.9", "3.10"] # Any default versions that should be ignored. IGNORED_VERSIONS = TEST_CONFIG["ignored_versions"] diff --git a/samples/snippets/requirements.txt b/samples/snippets/requirements.txt index 1220d5a9..0f2be554 100644 --- a/samples/snippets/requirements.txt +++ b/samples/snippets/requirements.txt @@ -1,2 +1,2 @@ google-cloud-pubsub==2.8.0 -google-cloud-securitycenter==1.5.2 \ No newline at end of file +google-cloud-securitycenter==1.6.0 \ No newline at end of file diff --git a/setup.py b/setup.py index b9920706..731c6f7d 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ name = "google-cloud-securitycenter" description = "Cloud Security Command Center API client library" -version = "1.6.0" +version = "1.7.0" release_status = "Development Status :: 5 - Production/Stable" dependencies = [ # NOTE: Maintainers, please do not require google-api-core>=2.x.x diff --git a/tests/unit/gapic/securitycenter_v1/test_security_center.py b/tests/unit/gapic/securitycenter_v1/test_security_center.py index 6834f803..54222717 100644 --- a/tests/unit/gapic/securitycenter_v1/test_security_center.py +++ b/tests/unit/gapic/securitycenter_v1/test_security_center.py @@ -61,6 +61,7 @@ from google.cloud.securitycenter_v1.types import securitycenter_service from google.cloud.securitycenter_v1.types import source from google.cloud.securitycenter_v1.types import source as gcs_source +from google.cloud.securitycenter_v1.types import vulnerability from google.iam.v1 import iam_policy_pb2 # type: ignore from google.iam.v1 import options_pb2 # type: ignore from google.iam.v1 import policy_pb2 # type: ignore