From 93853b4b33a15b7fa59e89b0d498d1a10af7748d Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 6 Jul 2020 22:58:15 +0200 Subject: [PATCH 1/8] chore(deps): update dependency google-cloud-pubsub to v1.6.1 (#35) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [google-cloud-pubsub](https://togithub.com/googleapis/python-pubsub) | patch | `==1.6.0` -> `==1.6.1` | --- ### Release Notes
googleapis/python-pubsub ### [`v1.6.1`](https://togithub.com/googleapis/python-pubsub/blob/master/CHANGELOG.md#​161-httpswwwgithubcomgoogleapispython-pubsubcomparev160v161-2020-06-30) [Compare Source](https://togithub.com/googleapis/python-pubsub/compare/v1.6.0...v1.6.1)
--- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/python-securitycenter). --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 9b496510..42ab449b 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1 +1 @@ -google-cloud-pubsub==1.6.0 +google-cloud-pubsub==1.6.1 From 1b3058fb7c0995d8bcef0da5b358c3263efe2906 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 9 Jul 2020 16:08:52 -0700 Subject: [PATCH 2/8] chore: update protobuf and gapic-generator-csharp versions. (#40) PiperOrigin-RevId: 320411362 Source-Author: Google APIs Source-Date: Thu Jul 9 09:26:49 2020 -0700 Source-Repo: googleapis/googleapis Source-Sha: db69b46790b55a82ab7cfa473d031da787bc7591 Source-Link: https://github.com/googleapis/googleapis/commit/db69b46790b55a82ab7cfa473d031da787bc7591 --- google/cloud/securitycenter_v1/proto/asset_pb2.py | 2 +- google/cloud/securitycenter_v1/proto/finding_pb2.py | 2 +- .../securitycenter_v1/proto/notification_config_pb2.py | 2 +- .../securitycenter_v1/proto/notification_message_pb2.py | 2 +- .../securitycenter_v1/proto/organization_settings_pb2.py | 2 +- google/cloud/securitycenter_v1/proto/resource_pb2.py | 2 +- .../proto/run_asset_discovery_response_pb2.py | 2 +- google/cloud/securitycenter_v1/proto/security_marks_pb2.py | 2 +- .../securitycenter_v1/proto/securitycenter_service_pb2.py | 2 +- google/cloud/securitycenter_v1/proto/source_pb2.py | 2 +- google/cloud/securitycenter_v1beta1/proto/asset_pb2.py | 2 +- google/cloud/securitycenter_v1beta1/proto/finding_pb2.py | 2 +- .../proto/organization_settings_pb2.py | 2 +- .../proto/run_asset_discovery_response_pb2.py | 2 +- .../securitycenter_v1beta1/proto/security_marks_pb2.py | 2 +- .../proto/securitycenter_service_pb2.py | 2 +- google/cloud/securitycenter_v1beta1/proto/source_pb2.py | 2 +- google/cloud/securitycenter_v1p1beta1/proto/asset_pb2.py | 2 +- google/cloud/securitycenter_v1p1beta1/proto/finding_pb2.py | 2 +- .../proto/notification_config_pb2.py | 2 +- .../proto/notification_message_pb2.py | 2 +- .../proto/organization_settings_pb2.py | 2 +- google/cloud/securitycenter_v1p1beta1/proto/resource_pb2.py | 2 +- .../proto/run_asset_discovery_response_pb2.py | 2 +- .../securitycenter_v1p1beta1/proto/security_marks_pb2.py | 2 +- .../proto/securitycenter_service_pb2.py | 2 +- google/cloud/securitycenter_v1p1beta1/proto/source_pb2.py | 2 +- synth.metadata | 6 +++--- 28 files changed, 30 insertions(+), 30 deletions(-) diff --git a/google/cloud/securitycenter_v1/proto/asset_pb2.py b/google/cloud/securitycenter_v1/proto/asset_pb2.py index 834f4147..9f5e82a0 100644 --- a/google/cloud/securitycenter_v1/proto/asset_pb2.py +++ b/google/cloud/securitycenter_v1/proto/asset_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/asset.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1/proto/finding_pb2.py b/google/cloud/securitycenter_v1/proto/finding_pb2.py index d2589787..c88d7a09 100644 --- a/google/cloud/securitycenter_v1/proto/finding_pb2.py +++ b/google/cloud/securitycenter_v1/proto/finding_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/finding.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1/proto/notification_config_pb2.py b/google/cloud/securitycenter_v1/proto/notification_config_pb2.py index 5a318bba..bbd41547 100644 --- a/google/cloud/securitycenter_v1/proto/notification_config_pb2.py +++ b/google/cloud/securitycenter_v1/proto/notification_config_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/notification_config.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1/proto/notification_message_pb2.py b/google/cloud/securitycenter_v1/proto/notification_message_pb2.py index a7bd5d51..eeb4372c 100644 --- a/google/cloud/securitycenter_v1/proto/notification_message_pb2.py +++ b/google/cloud/securitycenter_v1/proto/notification_message_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/notification_message.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1/proto/organization_settings_pb2.py b/google/cloud/securitycenter_v1/proto/organization_settings_pb2.py index bd872c24..c8f94ad6 100644 --- a/google/cloud/securitycenter_v1/proto/organization_settings_pb2.py +++ b/google/cloud/securitycenter_v1/proto/organization_settings_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/organization_settings.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1/proto/resource_pb2.py b/google/cloud/securitycenter_v1/proto/resource_pb2.py index c9c16fef..87bfb51c 100644 --- a/google/cloud/securitycenter_v1/proto/resource_pb2.py +++ b/google/cloud/securitycenter_v1/proto/resource_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/resource.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1/proto/run_asset_discovery_response_pb2.py b/google/cloud/securitycenter_v1/proto/run_asset_discovery_response_pb2.py index c4e2b2bd..defd52f7 100644 --- a/google/cloud/securitycenter_v1/proto/run_asset_discovery_response_pb2.py +++ b/google/cloud/securitycenter_v1/proto/run_asset_discovery_response_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/run_asset_discovery_response.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1/proto/security_marks_pb2.py b/google/cloud/securitycenter_v1/proto/security_marks_pb2.py index c110683b..f455b093 100644 --- a/google/cloud/securitycenter_v1/proto/security_marks_pb2.py +++ b/google/cloud/securitycenter_v1/proto/security_marks_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/security_marks.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1/proto/securitycenter_service_pb2.py b/google/cloud/securitycenter_v1/proto/securitycenter_service_pb2.py index 4bb4b007..9cb7a6b1 100644 --- a/google/cloud/securitycenter_v1/proto/securitycenter_service_pb2.py +++ b/google/cloud/securitycenter_v1/proto/securitycenter_service_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/securitycenter_service.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1/proto/source_pb2.py b/google/cloud/securitycenter_v1/proto/source_pb2.py index 4d5792d1..8e44d1d7 100644 --- a/google/cloud/securitycenter_v1/proto/source_pb2.py +++ b/google/cloud/securitycenter_v1/proto/source_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/source.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1beta1/proto/asset_pb2.py b/google/cloud/securitycenter_v1beta1/proto/asset_pb2.py index 380827ae..e1e488ee 100644 --- a/google/cloud/securitycenter_v1beta1/proto/asset_pb2.py +++ b/google/cloud/securitycenter_v1beta1/proto/asset_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1beta1/proto/asset.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1beta1/proto/finding_pb2.py b/google/cloud/securitycenter_v1beta1/proto/finding_pb2.py index 40c04ac9..0c7b8e81 100644 --- a/google/cloud/securitycenter_v1beta1/proto/finding_pb2.py +++ b/google/cloud/securitycenter_v1beta1/proto/finding_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1beta1/proto/finding.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1beta1/proto/organization_settings_pb2.py b/google/cloud/securitycenter_v1beta1/proto/organization_settings_pb2.py index 1d18b657..779190be 100644 --- a/google/cloud/securitycenter_v1beta1/proto/organization_settings_pb2.py +++ b/google/cloud/securitycenter_v1beta1/proto/organization_settings_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1beta1/proto/organization_settings.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1beta1/proto/run_asset_discovery_response_pb2.py b/google/cloud/securitycenter_v1beta1/proto/run_asset_discovery_response_pb2.py index 6084afdf..dc17572d 100644 --- a/google/cloud/securitycenter_v1beta1/proto/run_asset_discovery_response_pb2.py +++ b/google/cloud/securitycenter_v1beta1/proto/run_asset_discovery_response_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1beta1/proto/run_asset_discovery_response.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1beta1/proto/security_marks_pb2.py b/google/cloud/securitycenter_v1beta1/proto/security_marks_pb2.py index cf81ad1b..a9cae49e 100644 --- a/google/cloud/securitycenter_v1beta1/proto/security_marks_pb2.py +++ b/google/cloud/securitycenter_v1beta1/proto/security_marks_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1beta1/proto/security_marks.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1beta1/proto/securitycenter_service_pb2.py b/google/cloud/securitycenter_v1beta1/proto/securitycenter_service_pb2.py index 8616e6cb..98f66db7 100644 --- a/google/cloud/securitycenter_v1beta1/proto/securitycenter_service_pb2.py +++ b/google/cloud/securitycenter_v1beta1/proto/securitycenter_service_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1beta1/proto/securitycenter_service.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1beta1/proto/source_pb2.py b/google/cloud/securitycenter_v1beta1/proto/source_pb2.py index ce8497d8..835fccd5 100644 --- a/google/cloud/securitycenter_v1beta1/proto/source_pb2.py +++ b/google/cloud/securitycenter_v1beta1/proto/source_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1beta1/proto/source.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1p1beta1/proto/asset_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/asset_pb2.py index 7279b30b..17685d49 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/asset_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/asset_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/asset.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1p1beta1/proto/finding_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/finding_pb2.py index 2f7a9ad6..84acbbfe 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/finding_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/finding_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/finding.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1p1beta1/proto/notification_config_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/notification_config_pb2.py index 8bbd4f58..9564eaaa 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/notification_config_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/notification_config_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/notification_config.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1p1beta1/proto/notification_message_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/notification_message_pb2.py index ad130b54..3d43d832 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/notification_message_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/notification_message_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/notification_message.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1p1beta1/proto/organization_settings_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/organization_settings_pb2.py index 544781d4..83e3bca4 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/organization_settings_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/organization_settings_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/organization_settings.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1p1beta1/proto/resource_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/resource_pb2.py index 8ed3294f..b44b1fc9 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/resource_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/resource_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/resource.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1p1beta1/proto/run_asset_discovery_response_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/run_asset_discovery_response_pb2.py index a2657770..33099e91 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/run_asset_discovery_response_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/run_asset_discovery_response_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/run_asset_discovery_response.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1p1beta1/proto/security_marks_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/security_marks_pb2.py index 76a7c221..d8d0db24 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/security_marks_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/security_marks_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/security_marks.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1p1beta1/proto/securitycenter_service_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/securitycenter_service_pb2.py index 7a20bbe9..583e5d79 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/securitycenter_service_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/securitycenter_service_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/securitycenter_service.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1p1beta1/proto/source_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/source_pb2.py index e50bfc53..33ac8a80 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/source_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/source_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/source.proto -"""Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/synth.metadata b/synth.metadata index f8f1ed06..602cd308 100644 --- a/synth.metadata +++ b/synth.metadata @@ -4,15 +4,15 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/python-securitycenter.git", - "sha": "c930e6afc6aa701761f9966e1391ca2d3ebb30f4" + "sha": "93853b4b33a15b7fa59e89b0d498d1a10af7748d" } }, { "git": { "name": "googleapis", "remote": "https://github.com/googleapis/googleapis.git", - "sha": "b882b8e6bfcd708042ff00f7adc67ce750817dd0", - "internalRef": "318028816" + "sha": "db69b46790b55a82ab7cfa473d031da787bc7591", + "internalRef": "320411362" } }, { From 1c7c210744281042f08bd41ffbe97bb85b319337 Mon Sep 17 00:00:00 2001 From: Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> Date: Tue, 14 Jul 2020 15:26:47 -0700 Subject: [PATCH 3/8] chore(samples): move samples and use standard templates for testing (#41) --- .github/CODEOWNERS | 8 + noxfile.py | 117 ++-- samples/AUTHORING_GUIDE.md | 1 + samples/CONTRIBUTING.md | 1 + samples/snippets/noxfile.py | 222 +++++++ samples/snippets/noxfile_config.py | 39 ++ samples/snippets/requirements-test.txt | 1 + samples/snippets/requirements.txt | 2 + samples/snippets/snippets_findings.py | 572 ++++++++++++++++++ samples/snippets/snippets_findings_test.py | 133 ++++ samples/snippets/snippets_list_assets.py | 205 +++++++ samples/snippets/snippets_list_assets_test.py | 64 ++ .../snippets/snippets_notification_configs.py | 138 +++++ .../snippets_notification_receiver.py | 60 ++ .../snippets/snippets_notification_test.py | 144 +++++ samples/snippets/snippets_orgs.py | 58 ++ samples/snippets/snippets_orgs_test.py | 36 ++ samples/snippets/snippets_security_marks.py | 187 ++++++ .../snippets/snippets_security_marks_test.py | 137 +++++ setup.py | 57 +- synth.metadata | 17 +- synth.py | 7 +- 22 files changed, 2091 insertions(+), 115 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 samples/AUTHORING_GUIDE.md create mode 100644 samples/CONTRIBUTING.md create mode 100644 samples/snippets/noxfile.py create mode 100644 samples/snippets/noxfile_config.py create mode 100644 samples/snippets/requirements-test.txt create mode 100644 samples/snippets/requirements.txt create mode 100644 samples/snippets/snippets_findings.py create mode 100644 samples/snippets/snippets_findings_test.py create mode 100644 samples/snippets/snippets_list_assets.py create mode 100644 samples/snippets/snippets_list_assets_test.py create mode 100644 samples/snippets/snippets_notification_configs.py create mode 100644 samples/snippets/snippets_notification_receiver.py create mode 100644 samples/snippets/snippets_notification_test.py create mode 100644 samples/snippets/snippets_orgs.py create mode 100644 samples/snippets/snippets_orgs_test.py create mode 100644 samples/snippets/snippets_security_marks.py create mode 100644 samples/snippets/snippets_security_marks_test.py diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..3b4e6804 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,8 @@ +# Code owners file. +# This file controls who is tagged for review for any given pull request. +# +# For syntax help see: +# https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax + + +/samples/ @tdh911 @googleapis/python-samples-owners \ No newline at end of file diff --git a/noxfile.py b/noxfile.py index dd4f09ef..758afabf 100644 --- a/noxfile.py +++ b/noxfile.py @@ -14,28 +14,33 @@ # See the License for the specific language governing permissions and # limitations under the License. +# Generated by synthtool. DO NOT EDIT! + from __future__ import absolute_import import os -import shutil +import shutil import nox +BLACK_VERSION = "black==19.10b0" +BLACK_PATHS = ["docs", "google", "tests", "noxfile.py", "setup.py"] + +DEFAULT_PYTHON_VERSION = "3.8" +SYSTEM_TEST_PYTHON_VERSIONS = ["2.7", "3.8"] +UNIT_TEST_PYTHON_VERSIONS = ["2.7", "3.5", "3.6", "3.7", "3.8"] + -@nox.session(python="3.7") +@nox.session(python=DEFAULT_PYTHON_VERSION) def lint(session): """Run linters. Returns a failure if the linters find linting errors or sufficiently serious code quality issues. """ - session.install("flake8", "black") + session.install("flake8", BLACK_VERSION) session.run( - "black", - "--check", - "google", - "tests", - "docs", + "black", "--check", *BLACK_PATHS, ) session.run("flake8", "google", "tests") @@ -45,21 +50,18 @@ def blacken(session): """Run black. Format code to uniform standard. - + This currently uses Python 3.6 due to the automated Kokoro run of synthtool. That run uses an image that doesn't have 3.6 installed. Before updating this check the state of the `gcp_ubuntu_config` we use for that Kokoro run. """ - session.install("black") + session.install(BLACK_VERSION) session.run( - "black", - "google", - "tests", - "docs", + "black", *BLACK_PATHS, ) -@nox.session(python="3.7") +@nox.session(python=DEFAULT_PYTHON_VERSION) def lint_setup_py(session): """Verify that setup.py is valid (including RST check).""" session.install("docutils", "pygments") @@ -75,6 +77,7 @@ def default(session): session.run( "py.test", "--quiet", + "--cov=google.cloud.securitycenter", "--cov=google.cloud", "--cov=tests.unit", "--cov-append", @@ -86,13 +89,13 @@ def default(session): ) -@nox.session(python=["2.7", "3.5", "3.6", "3.7", "3.8"]) +@nox.session(python=UNIT_TEST_PYTHON_VERSIONS) def unit(session): """Run the unit test suite.""" default(session) -@nox.session(python=["2.7", "3.7"]) +@nox.session(python=SYSTEM_TEST_PYTHON_VERSIONS) def system(session): """Run the system test suite.""" system_test_path = os.path.join("tests", "system.py") @@ -112,7 +115,9 @@ def system(session): # Install all test dependencies, then install this package into the # virtualenv's dist-packages. - session.install("mock", "pytest", "google-cloud-testutils") + session.install( + "mock", "pytest", "google-cloud-testutils", + ) session.install("-e", ".") # Run py.test against the system tests. @@ -122,7 +127,7 @@ def system(session): session.run("py.test", "--quiet", system_test_folder_path, *session.posargs) -@nox.session(python="3.7") +@nox.session(python=DEFAULT_PYTHON_VERSION) def cover(session): """Run the final coverage report. @@ -135,69 +140,23 @@ def cover(session): session.run("coverage", "erase") -@nox.session(python=["2.7", "3.5", "3.6", "3.7"]) -def snippets(session): - """Run the documentation example snippets.""" - # Sanity check: Only run snippets system tests if the environment variable - # is set. - if not os.environ.get('GOOGLE_APPLICATION_CREDENTIALS', ''): - session.skip('Credentials must be set via environment variable.') - if not os.environ.get('GCLOUD_ORGANIZATION', ''): - if 'KOKORO_GFILE_DIR' in os.environ: - session.env['GCLOUD_ORGANIZATION'] = '1081635000895' - else: - session.skip('Credentials must be set via environment variable.') - if not os.environ.get('GCLOUD_PROJECT', ''): - if 'KOKORO_GFILE_DIR' in os.environ: - session.env['GCLOUD_PROJECT'] = 'project-a-id' - else: - session.skip('Credentials must be set via environment variable.') - if not os.environ.get('GCLOUD_PUBSUB_TOPIC', ''): - if 'KOKORO_GFILE_DIR' in os.environ: - session.env['GCLOUD_PUBSUB_TOPIC'] = 'projects/project-a-id/topics/notifications-sample-topic' - else: - session.skip('Credentials must be set via environment variable.') - if not os.environ.get('GCLOUD_PUBSUB_SUBSCRIPTION', ''): - if 'KOKORO_GFILE_DIR' in os.environ: - session.env['GCLOUD_PUBSUB_SUBSCRIPTION'] = 'notification_sample_subscription' - else: - session.skip('Credentials must be set via environment variable.') - - - # Install all test dependencies, then install local packages in place. - session.install('mock', 'pytest') - session.install("-r", "docs/requirements.txt") - session.install('-e', '.') - session.run( - 'py.test', - '--quiet', - os.path.join('docs', 'snippets_list_assets.py'), - os.path.join('docs', 'snippets_security_marks.py'), - os.path.join('docs', 'snippets_orgs.py'), - os.path.join('docs', 'snippets_findings.py'), - os.path.join('docs', 'snippets_security_marks.py'), - os.path.join('docs', 'snippets_notification_test.py'), - - - *session.posargs - ) - - -@nox.session(python="3.7") +@nox.session(python=DEFAULT_PYTHON_VERSION) def docs(session): """Build the docs for this library.""" - session.install('-e', '.') - session.install('sphinx<3.0.0', 'alabaster', 'recommonmark') + session.install("-e", ".") + session.install("sphinx<3.0.0", "alabaster", "recommonmark") - shutil.rmtree(os.path.join('docs', '_build'), ignore_errors=True) + shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True) session.run( - 'sphinx-build', - '-W', # warnings as errors - '-T', # show full traceback on exception - '-N', # no colors - '-b', 'html', - '-d', os.path.join('docs', '_build', 'doctrees', ''), - os.path.join('docs', ''), - os.path.join('docs', '_build', 'html', ''), + "sphinx-build", + "-W", # warnings as errors + "-T", # show full traceback on exception + "-N", # no colors + "-b", + "html", + "-d", + os.path.join("docs", "_build", "doctrees", ""), + os.path.join("docs", ""), + os.path.join("docs", "_build", "html", ""), ) diff --git a/samples/AUTHORING_GUIDE.md b/samples/AUTHORING_GUIDE.md new file mode 100644 index 00000000..55c97b32 --- /dev/null +++ b/samples/AUTHORING_GUIDE.md @@ -0,0 +1 @@ +See https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/AUTHORING_GUIDE.md \ No newline at end of file diff --git a/samples/CONTRIBUTING.md b/samples/CONTRIBUTING.md new file mode 100644 index 00000000..34c882b6 --- /dev/null +++ b/samples/CONTRIBUTING.md @@ -0,0 +1 @@ +See https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/CONTRIBUTING.md \ No newline at end of file diff --git a/samples/snippets/noxfile.py b/samples/snippets/noxfile.py new file mode 100644 index 00000000..5660f08b --- /dev/null +++ b/samples/snippets/noxfile.py @@ -0,0 +1,222 @@ +# Copyright 2019 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. + +from __future__ import print_function + +import os +from pathlib import Path +import sys + +import nox + + +# WARNING - WARNING - WARNING - WARNING - WARNING +# WARNING - WARNING - WARNING - WARNING - WARNING +# DO NOT EDIT THIS FILE EVER! +# WARNING - WARNING - WARNING - WARNING - WARNING +# WARNING - WARNING - WARNING - WARNING - WARNING + +# Copy `noxfile_config.py` to your directory and modify it instead. + + +# `TEST_CONFIG` dict is a configuration hook that allows users to +# modify the test configurations. The values here should be in sync +# with `noxfile_config.py`. Users will copy `noxfile_config.py` into +# their directory and modify it. + +TEST_CONFIG = { + # You can opt out from the test for specific Python versions. + "ignored_versions": ["2.7"], + # An envvar key for determining the project id to use. Change it + # to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a + # build specific Cloud project. You can also use your own string + # to use your own Cloud project. + "gcloud_project_env": "GOOGLE_CLOUD_PROJECT", + # 'gcloud_project_env': 'BUILD_SPECIFIC_GCLOUD_PROJECT', + # A dictionary you want to inject into your test. Don't put any + # secrets here. These values will override predefined values. + "envs": {}, +} + + +try: + # Ensure we can import noxfile_config in the project's directory. + sys.path.append(".") + from noxfile_config import TEST_CONFIG_OVERRIDE +except ImportError as e: + print("No user noxfile_config found: detail: {}".format(e)) + TEST_CONFIG_OVERRIDE = {} + +# Update the TEST_CONFIG with the user supplied values. +TEST_CONFIG.update(TEST_CONFIG_OVERRIDE) + + +def get_pytest_env_vars(): + """Returns a dict for pytest invocation.""" + ret = {} + + # Override the GCLOUD_PROJECT and the alias. + env_key = TEST_CONFIG["gcloud_project_env"] + # This should error out if not set. + ret["GOOGLE_CLOUD_PROJECT"] = os.environ[env_key] + + # Apply user supplied envs. + ret.update(TEST_CONFIG["envs"]) + return ret + + +# DO NOT EDIT - automatically generated. +# All versions used to tested samples. +ALL_VERSIONS = ["2.7", "3.6", "3.7", "3.8"] + +# Any default versions that should be ignored. +IGNORED_VERSIONS = TEST_CONFIG["ignored_versions"] + +TESTED_VERSIONS = sorted([v for v in ALL_VERSIONS if v not in IGNORED_VERSIONS]) + +INSTALL_LIBRARY_FROM_SOURCE = bool(os.environ.get("INSTALL_LIBRARY_FROM_SOURCE", False)) +# +# Style Checks +# + + +def _determine_local_import_names(start_dir): + """Determines all import names that should be considered "local". + + This is used when running the linter to insure that import order is + properly checked. + """ + file_ext_pairs = [os.path.splitext(path) for path in os.listdir(start_dir)] + return [ + basename + for basename, extension in file_ext_pairs + if extension == ".py" + or os.path.isdir(os.path.join(start_dir, basename)) + and basename not in ("__pycache__") + ] + + +# Linting with flake8. +# +# We ignore the following rules: +# E203: whitespace before ‘:’ +# E266: too many leading ‘#’ for block comment +# E501: line too long +# I202: Additional newline in a section of imports +# +# We also need to specify the rules which are ignored by default: +# ['E226', 'W504', 'E126', 'E123', 'W503', 'E24', 'E704', 'E121'] +FLAKE8_COMMON_ARGS = [ + "--show-source", + "--builtin=gettext", + "--max-complexity=20", + "--import-order-style=google", + "--exclude=.nox,.cache,env,lib,generated_pb2,*_pb2.py,*_pb2_grpc.py", + "--ignore=E121,E123,E126,E203,E226,E24,E266,E501,E704,W503,W504,I202", + "--max-line-length=88", +] + + +@nox.session +def lint(session): + session.install("flake8", "flake8-import-order") + + local_names = _determine_local_import_names(".") + args = FLAKE8_COMMON_ARGS + [ + "--application-import-names", + ",".join(local_names), + ".", + ] + session.run("flake8", *args) + + +# +# Sample Tests +# + + +PYTEST_COMMON_ARGS = ["--junitxml=sponge_log.xml"] + + +def _session_tests(session, post_install=None): + """Runs py.test for a particular project.""" + if os.path.exists("requirements.txt"): + session.install("-r", "requirements.txt") + + if os.path.exists("requirements-test.txt"): + session.install("-r", "requirements-test.txt") + + if INSTALL_LIBRARY_FROM_SOURCE: + session.install("-e", _get_repo_root()) + + if post_install: + post_install(session) + + session.run( + "pytest", + *(PYTEST_COMMON_ARGS + session.posargs), + # Pytest will return 5 when no tests are collected. This can happen + # on travis where slow and flaky tests are excluded. + # See http://doc.pytest.org/en/latest/_modules/_pytest/main.html + success_codes=[0, 5], + env=get_pytest_env_vars() + ) + + +@nox.session(python=ALL_VERSIONS) +def py(session): + """Runs py.test for a sample using the specified version of Python.""" + if session.python in TESTED_VERSIONS: + _session_tests(session) + else: + session.skip( + "SKIPPED: {} tests are disabled for this sample.".format(session.python) + ) + + +# +# Readmegen +# + + +def _get_repo_root(): + """ Returns the root folder of the project. """ + # Get root of this repository. Assume we don't have directories nested deeper than 10 items. + p = Path(os.getcwd()) + for i in range(10): + if p is None: + break + if Path(p / ".git").exists(): + return str(p) + p = p.parent + raise Exception("Unable to detect repository root.") + + +GENERATED_READMES = sorted([x for x in Path(".").rglob("*.rst.in")]) + + +@nox.session +@nox.parametrize("path", GENERATED_READMES) +def readmegen(session, path): + """(Re-)generates the readme for a sample.""" + session.install("jinja2", "pyyaml") + dir_ = os.path.dirname(path) + + if os.path.exists(os.path.join(dir_, "requirements.txt")): + session.install("-r", os.path.join(dir_, "requirements.txt")) + + in_file = os.path.join(dir_, "README.rst.in") + session.run( + "python", _get_repo_root() + "/scripts/readme-gen/readme_gen.py", in_file + ) diff --git a/samples/snippets/noxfile_config.py b/samples/snippets/noxfile_config.py new file mode 100644 index 00000000..8e6ed132 --- /dev/null +++ b/samples/snippets/noxfile_config.py @@ -0,0 +1,39 @@ +# 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. + +# Default TEST_CONFIG_OVERRIDE for python repos. + +# You can copy this file into your directory, then it will be inported from +# the noxfile.py. + +# The source of truth: +# https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/noxfile_config.py + +TEST_CONFIG_OVERRIDE = { + # You can opt out from the test for specific Python versions. + "ignored_versions": ["2.7"], + # An envvar key for determining the project id to use. Change it + # to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a + # build specific Cloud project. You can also use your own string + # to use your own Cloud project. + # 'gcloud_project_env': 'GOOGLE_CLOUD_PROJECT', + # A dictionary you want to inject into your test. Don't put any + # secrets here. These values will override predefined values. + "envs": { + "GCLOUD_ORGANIZATION": "1081635000895", + "GCLOUD_PROJECT": "project-a-id", + "GCLOUD_PUBSUB_TOPIC": "projects/project-a-id/topics/notifications-sample-topic", + "GCLOUD_PUBSUB_SUBSCRIPTION": "notification-sample-subscription", + }, +} diff --git a/samples/snippets/requirements-test.txt b/samples/snippets/requirements-test.txt new file mode 100644 index 00000000..55b033e9 --- /dev/null +++ b/samples/snippets/requirements-test.txt @@ -0,0 +1 @@ +pytest \ No newline at end of file diff --git a/samples/snippets/requirements.txt b/samples/snippets/requirements.txt new file mode 100644 index 00000000..4b59ce29 --- /dev/null +++ b/samples/snippets/requirements.txt @@ -0,0 +1,2 @@ +google-cloud-pubsub==1.6.0 +google-cloud-securitycenter==0.6.0 \ No newline at end of file diff --git a/samples/snippets/snippets_findings.py b/samples/snippets/snippets_findings.py new file mode 100644 index 00000000..ec465f20 --- /dev/null +++ b/samples/snippets/snippets_findings.py @@ -0,0 +1,572 @@ +#!/usr/bin/env python +# +# Copyright 2019 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 +# +# https://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. + +"""Examples of working with source and findings in Cloud Security Command Center.""" + + +def create_source(organization_id): + """Create a new findings source. """ + # [START create_source] + from google.cloud import securitycenter + + client = securitycenter.SecurityCenterClient() + # organization_id is the numeric ID of the organization. e.g.: + # organization_id = "111122222444" + org_name = "organizations/{org_id}".format(org_id=organization_id) + + created = client.create_source( + org_name, + { + "display_name": "Customized Display Name", + "description": "A new custom source that does X", + }, + ) + print("Created Source: {}".format(created.name)) + # [END create_source] + + +def get_source(source_name): + """Gets an existing source.""" + # [START get_source] + from google.cloud import securitycenter + + client = securitycenter.SecurityCenterClient() + + # source_name is the resource path for a source that has been + # created previously (you can use list_sources to find a specific one). + # Its format is: + # source_name = "organizations/{organization_id}/sources/{source_id}" + # e.g.: + # source_name = "organizations/111122222444/sources/1234" + source = client.get_source(source_name) + + print("Source: {}".format(source)) + # [END get_source] + return source + + +def update_source(source_name): + """Updates a source's display name.""" + # [START update_source] + from google.cloud import securitycenter + from google.protobuf import field_mask_pb2 + + client = securitycenter.SecurityCenterClient() + + # Field mask to only update the display name. + field_mask = field_mask_pb2.FieldMask(paths=["display_name"]) + + # source_name is the resource path for a source that has been + # created previously (you can use list_sources to find a specific one). + # Its format is: + # source_name = "organizations/{organization_id}/sources/{source_id}" + # e.g.: + # source_name = "organizations/111122222444/sources/1234" + updated = client.update_source( + {"name": source_name, "display_name": "Updated Display Name"}, + update_mask=field_mask, + ) + print("Updated Source: {}".format(updated)) + # [END update_source] + return updated + + +def add_user_to_source(source_name): + """Gives a user findingsEditor permission to the source.""" + user_email = "csccclienttest@gmail.com" + # [START update_source_iam] + from google.cloud import securitycenter + from google.iam.v1 import policy_pb2 + + client = securitycenter.SecurityCenterClient() + + # source_name is the resource path for a source that has been + # created previously (you can use list_sources to find a specific one). + # Its format is: + # source_name = "organizations/{organization_id}/sources/{source_id}" + # e.g.: + # source_name = "organizations/111122222444/sources/1234" + # Get the old policy so we can do an incremental update. + old_policy = client.get_iam_policy(source_name) + print("Old Policy: {}".format(old_policy)) + + # Setup a new IAM binding. + binding = policy_pb2.Binding() + binding.role = "roles/securitycenter.findingsEditor" + # user_email is an e-mail address known to Cloud IAM (e.g. a gmail address). + # user_mail = user@somedomain.com + binding.members.append("user:{}".format(user_email)) + + # Setting the e-tag avoids over-write existing policy + updated = client.set_iam_policy( + source_name, {"etag": old_policy.etag, "bindings": [binding]} + ) + + print("Updated Policy: {}".format(updated)) + + # [END update_source_iam] + return binding, updated + + +def list_source(organization_id): + """Lists finding sources.""" + i = -1 + # [START list_sources] + from google.cloud import securitycenter + + # Create a new client. + client = securitycenter.SecurityCenterClient() + # organization_id is the numeric ID of the organization. e.g.: + # organization_id = "111122222444" + org_name = "organizations/{org_id}".format(org_id=organization_id) + + # Call the API and print out each existing source. + for i, source in enumerate(client.list_sources(org_name)): + print(i, source) + # [END list_sources] + return i + + +def create_finding(source_name): + """Creates a new finding.""" + # [START create_finding] + from google.cloud import securitycenter + from google.cloud.securitycenter_v1.proto.finding_pb2 import Finding + from google.protobuf.timestamp_pb2 import Timestamp + + # Create a new client. + client = securitycenter.SecurityCenterClient() + + # Use the current time as the finding "event time". + now_proto = Timestamp() + now_proto.GetCurrentTime() + + # source_name is the resource path for a source that has been + # created previously (you can use list_sources to find a specific one). + # Its format is: + # source_name = "organizations/{organization_id}/sources/{source_id}" + # e.g.: + # source_name = "organizations/111122222444/sources/1234" + + # Controlled by caller. + finding_id = "samplefindingid" + + # The resource this finding applies to. The CSCC UI can link + # the findings for a resource to the corresponding Asset of a resource + # if there are matches. + resource_name = "//cloudresourcemanager.googleapis.com/organizations/11232" + + # Call The API. + created_finding = client.create_finding( + source_name, + finding_id, + { + "state": Finding.ACTIVE, + "resource_name": resource_name, + "category": "MEDIUM_RISK_ONE", + "event_time": now_proto, + }, + ) + print(created_finding) + # [END create_finding] + return created_finding + + +def create_finding_with_source_properties(source_name): + """Demonstrate creating a new finding with source properties. """ + # [START create_finding_with_properties] + from google.cloud import securitycenter + from google.cloud.securitycenter_v1.proto.finding_pb2 import Finding + from google.protobuf.timestamp_pb2 import Timestamp + from google.protobuf.struct_pb2 import Value + + # Create a new client. + client = securitycenter.SecurityCenterClient() + + # source_name is the resource path for a source that has been + # created previously (you can use list_sources to find a specific one). + # Its format is: + # source_name = "organizations/{organization_id}/sources/{source_id}" + # e.g.: + # source_name = "organizations/111122222444/sources/1234" + + # Controlled by caller. + finding_id = "samplefindingid2" + + # The resource this finding applies to. The CSCC UI can link + # the findings for a resource to the corresponding Asset of a resource + # if there are matches. + resource_name = "//cloudresourcemanager.googleapis.com/organizations/11232" + + # Define source properties values as protobuf "Value" objects. + str_value = Value() + str_value.string_value = "string_example" + num_value = Value() + num_value.number_value = 1234 + + # Use the current time as the finding "event time". + now_proto = Timestamp() + now_proto.GetCurrentTime() + + created_finding = client.create_finding( + source_name, + finding_id, + { + "state": Finding.ACTIVE, + "resource_name": resource_name, + "category": "MEDIUM_RISK_ONE", + "source_properties": {"s_value": str_value, "n_value": num_value}, + "event_time": now_proto, + }, + ) + print(created_finding) + # [END create_finding_with_properties] + + +def update_finding(source_name): + # [START update_finding] + from google.cloud import securitycenter + from google.protobuf.struct_pb2 import Value + from google.protobuf import field_mask_pb2 + from google.protobuf.timestamp_pb2 import Timestamp + + client = securitycenter.SecurityCenterClient() + # Only update the specific source property and event_time. event_time + # is required for updates. + field_mask = field_mask_pb2.FieldMask( + paths=["source_properties.s_value", "event_time"] + ) + value = Value() + value.string_value = "new_string" + + # Set the update time to Now. This must be some time greater then the + # event_time on the original finding. + now_proto = Timestamp() + now_proto.GetCurrentTime() + + # source_name is the resource path for a source that has been + # created previously (you can use list_sources to find a specific one). + # Its format is: + # source_name = "organizations/{organization_id}/sources/{source_id}" + # e.g.: + # source_name = "organizations/111122222444/sources/1234" + finding_name = "{}/findings/samplefindingid2".format(source_name) + updated_finding = client.update_finding( + { + "name": finding_name, + "source_properties": {"s_value": value}, + "event_time": now_proto, + }, + update_mask=field_mask, + ) + + print( + "New Source properties: {}, Event Time {}".format( + updated_finding.source_properties, updated_finding.event_time.ToDatetime() + ) + ) + # [END update_finding] + + +def update_finding_state(source_name): + """Demonstrate updating only a finding state.""" + # [START update_finding_state] + from google.cloud import securitycenter + from google.cloud.securitycenter_v1.proto.finding_pb2 import Finding + from google.protobuf.timestamp_pb2 import Timestamp + + # Create a client. + client = securitycenter.SecurityCenterClient() + # source_name is the resource path for a source that has been + # created previously (you can use list_sources to find a specific one). + # Its format is: + # source_name = "organizations/{organization_id}/sources/{source_id}" + # e.g.: + # source_name = "organizations/111122222444/sources/1234" + finding_name = "{}/findings/samplefindingid2".format(source_name) + + now_proto = Timestamp() + now_proto.GetCurrentTime() + + # Call the API to change the finding state to inactive as of now. + new_finding = client.set_finding_state( + finding_name, Finding.INACTIVE, start_time=now_proto + ) + print("New state: {}".format(Finding.State.Name(new_finding.state))) + # [END update_finding_state] + + +def trouble_shoot(source_name): + """Demonstrate calling test_iam_permissions to determine if the + service account has the correct permisions.""" + # [START test_iam_permissions] + from google.cloud import securitycenter + + # Create a client. + client = securitycenter.SecurityCenterClient() + # source_name is the resource path for a source that has been + # created previously (you can use list_sources to find a specific one). + # Its format is: + # source_name = "organizations/{organization_id}/sources/{source_id}" + # e.g.: + # source_name = "organizations/111122222444/sources/1234" + + # Check for permssions to call create_finding or update_finding. + permission_response = client.test_iam_permissions( + source_name, ["securitycenter.findings.update"] + ) + + print( + "Permision to create or update findings? {}".format( + len(permission_response.permissions) > 0 + ) + ) + # [END test_iam_permissions] + assert len(permission_response.permissions) > 0 + # [START test_iam_permissions] + # Check for permissions necessary to call set_finding_state. + permission_response = client.test_iam_permissions( + source_name, ["securitycenter.findings.setState"] + ) + print( + "Permision to update state? {}".format(len(permission_response.permissions) > 0) + ) + # [END test_iam_permissions] + return permission_response + assert len(permission_response.permissions) > 0 + + +def list_all_findings(organization_id): + # [START list_all_findings] + from google.cloud import securitycenter + + # Create a client. + client = securitycenter.SecurityCenterClient() + + # organization_id is the numeric ID of the organization. e.g.: + # organization_id = "111122222444" + org_name = "organizations/{org_id}".format(org_id=organization_id) + # The "sources/-" suffix lists findings across all sources. You + # also use a specific source_name instead. + all_sources = "{org_name}/sources/-".format(org_name=org_name) + finding_result_iterator = client.list_findings(all_sources) + for i, finding_result in enumerate(finding_result_iterator): + print( + "{}: name: {} resource: {}".format( + i, finding_result.finding.name, finding_result.finding.resource_name + ) + ) + # [END list_all_findings] + return i + + +def list_filtered_findings(source_name): + # [START list_filtered_findings] + from google.cloud import securitycenter + + # Create a new client. + client = securitycenter.SecurityCenterClient() + + # source_name is the resource path for a source that has been + # created previously (you can use list_sources to find a specific one). + # Its format is: + # source_name = "organizations/{organization_id}/sources/{source_id}" + # e.g.: + # source_name = "organizations/111122222444/sources/1234" + # You an also use a wild-card "-" for all sources: + # source_name = "organizations/111122222444/sources/-" + finding_result_iterator = client.list_findings( + source_name, filter_='category="MEDIUM_RISK_ONE"' + ) + # Iterate an print all finding names and the resource they are + # in reference to. + for i, finding_result in enumerate(finding_result_iterator): + print( + "{}: name: {} resource: {}".format( + i, finding_result.finding.name, finding_result.finding.resource_name + ) + ) + # [END list_filtered_findings] + return i + + +def list_findings_at_time(source_name): + # [START list_findings_at_a_time] + from google.cloud import securitycenter + from google.protobuf.timestamp_pb2 import Timestamp + from datetime import timedelta, datetime + + # Create a new client. + client = securitycenter.SecurityCenterClient() + + # source_name is the resource path for a source that has been + # created previously (you can use list_sources to find a specific one). + # Its format is: + # source_name = "organizations/{organization_id}/sources/{source_id}" + # e.g.: + # source_name = "organizations/111122222444/sources/1234" + # You an also use a wild-card "-" for all sources: + # source_name = "organizations/111122222444/sources/-" + five_days_ago = Timestamp() + five_days_ago.FromDatetime(datetime.now() - timedelta(days=5)) + # [END list_findings_at_a_time] + i = -1 + five_days_ago.FromDatetime(datetime(2019, 3, 5, 0, 0, 0)) + # [START list_findings_at_a_time] + + finding_result_iterator = client.list_findings(source_name, read_time=five_days_ago) + for i, finding_result in enumerate(finding_result_iterator): + print( + "{}: name: {} resource: {}".format( + i, finding_result.finding.name, finding_result.finding.resource_name + ) + ) + # [END list_findings_at_a_time] + return i + + +def get_iam_policy(source_name): + """Gives a user findingsEditor permission to the source.""" + # [START get_source_iam] + from google.cloud import securitycenter + + client = securitycenter.SecurityCenterClient() + + # source_name is the resource path for a source that has been + # created previously (you can use list_sources to find a specific one). + # Its format is: + # source_name = "organizations/{organization_id}/sources/{source_id}" + # e.g.: + # source_name = "organizations/111122222444/sources/1234" + # Get the old policy so we can do an incremental update. + policy = client.get_iam_policy(source_name) + print("Policy: {}".format(policy)) + # [END get_source_iam] + + +def group_all_findings(organization_id): + """Demonstrates grouping all findings across an organization.""" + i = 0 + # [START group_all_findings] + from google.cloud import securitycenter + + # Create a client. + client = securitycenter.SecurityCenterClient() + + # organization_id is the numeric ID of the organization. e.g.: + # organization_id = "111122222444" + org_name = "organizations/{org_id}".format(org_id=organization_id) + # The "sources/-" suffix lists findings across all sources. You + # also use a specific source_name instead. + all_sources = "{org_name}/sources/-".format(org_name=org_name) + group_result_iterator = client.group_findings(all_sources, group_by="category") + for i, group_result in enumerate(group_result_iterator): + print((i + 1), group_result) + # [END group_all_findings] + return i + + +def group_filtered_findings(source_name): + """Demonstrates grouping all findings across an organization.""" + i = 0 + # [START group_filtered_findings] + from google.cloud import securitycenter + + # Create a client. + client = securitycenter.SecurityCenterClient() + + # source_name is the resource path for a source that has been + # created previously (you can use list_sources to find a specific one). + # Its format is: + # source_name = "organizations/{organization_id}/sources/{source_id}" + # e.g.: + # source_name = "organizations/111122222444/sources/1234" + + group_result_iterator = client.group_findings( + source_name, group_by="category", filter_='state="ACTIVE"' + ) + for i, group_result in enumerate(group_result_iterator): + print((i + 1), group_result) + # [END group_filtered_findings] + return i + + +def group_findings_at_time(source_name): + """Demonstrates grouping all findings across an organization as of + a specific time.""" + i = -1 + # [START group_findings_at_time] + from datetime import datetime, timedelta + from google.cloud import securitycenter + from google.protobuf.timestamp_pb2 import Timestamp + + # Create a client. + client = securitycenter.SecurityCenterClient() + + # source_name is the resource path for a source that has been + # created previously (you can use list_sources to find a specific one). + # Its format is: + # source_name = "organizations/{organization_id}/sources/{source_id}" + # e.g.: + # source_name = "organizations/111122222444/sources/1234" + + # Group findings as of yesterday. + read_time = datetime.utcnow() - timedelta(days=1) + timestamp_proto = Timestamp() + timestamp_proto.FromDatetime(read_time) + + group_result_iterator = client.group_findings( + source_name, group_by="category", read_time=timestamp_proto + ) + for i, group_result in enumerate(group_result_iterator): + print((i + 1), group_result) + # [END group_filtered_findings_at_time] + return i + + +def group_findings_and_changes(source_name): + """Demonstrates grouping all findings across an organization and + associated changes.""" + i = 0 + # [START group_filtered_findings_with_changes] + from datetime import timedelta + + from google.cloud import securitycenter + from google.protobuf.duration_pb2 import Duration + + # Create a client. + client = securitycenter.SecurityCenterClient() + + # source_name is the resource path for a source that has been + # created previously (you can use list_sources to find a specific one). + # Its format is: + # source_name = "organizations/{organization_id}/sources/{source_id}" + # e.g.: + # source_name = "organizations/111122222444/sources/1234" + + # List assets and their state change the last 30 days + compare_delta = timedelta(days=30) + # Convert the timedelta to a Duration + duration_proto = Duration() + duration_proto.FromTimedelta(compare_delta) + + group_result_iterator = client.group_findings( + source_name, group_by="state_change", compare_duration=duration_proto + ) + for i, group_result in enumerate(group_result_iterator): + print((i + 1), group_result) + # [END group_findings_with_changes] + return i diff --git a/samples/snippets/snippets_findings_test.py b/samples/snippets/snippets_findings_test.py new file mode 100644 index 00000000..8ac01d8c --- /dev/null +++ b/samples/snippets/snippets_findings_test.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python +# +# 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 +# +# https://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. +from itertools import chain +import os + +import pytest + +import snippets_findings + + +@pytest.fixture(scope="module") +def organization_id(): + """Get Organization ID from the environment variable """ + return os.environ["GCLOUD_ORGANIZATION"] + + +@pytest.fixture(scope="module") +def source_name(organization_id): + from google.cloud import securitycenter + + client = securitycenter.SecurityCenterClient() + org_name = "organizations/{org_id}".format(org_id=organization_id) + + source = client.create_source( + org_name, + { + "display_name": "Unit test source", + "description": "A new custom source that does X", + }, + ) + return source.name + + +def test_create_source(organization_id): + snippets_findings.create_source(organization_id) + + +def test_get_source(source_name): + source = snippets_findings.get_source(source_name) + assert source.name == source_name + + +def test_update_source(source_name): + updated = snippets_findings.update_source(source_name) + assert updated.display_name == "Updated Display Name" + + +def test_add_user_to_source(source_name): + binding, updated = snippets_findings.add_user_to_source(source_name) + assert any( + member == "user:csccclienttest@gmail.com" + for member in chain.from_iterable( + binding.members for binding in updated.bindings + ) + ) + + +def test_list_source(organization_id): + count = snippets_findings.list_source(organization_id) + assert count >= 0 + + +def test_create_finding(source_name): + created_finding = snippets_findings.create_finding(source_name) + assert len(created_finding.name) > 0 + + +def test_create_finding_with_source_properties(source_name): + snippets_findings.create_finding_with_source_properties(source_name) + + +def test_update_finding(source_name): + snippets_findings.update_finding(source_name) + + +def test_update_finding_state(source_name): + snippets_findings.update_finding_state(source_name) + + +def test_trouble_shoot(source_name): + snippets_findings.trouble_shoot(source_name) + + +def test_list_all_findings(organization_id): + count = snippets_findings.list_all_findings(organization_id) + assert count > 0 + + +def test_list_filtered_findings(source_name): + count = snippets_findings.list_filtered_findings(source_name) + assert count > 0 + + +def list_findings_at_time(source_name): + count = snippets_findings.list_findings_at_time(source_name) + assert count == -1 + + +def test_get_iam_policy(source_name): + snippets_findings.get_iam_policy(source_name) + + +def test_group_all_findings(organization_id): + count = snippets_findings.group_all_findings(organization_id) + assert count > 0 + + +def test_group_filtered_findings(source_name): + count = snippets_findings.group_filtered_findings(source_name) + assert count == 0 + + +def test_group_findings_at_time(source_name): + count = snippets_findings.group_findings_at_time(source_name) + assert count == -1 + + +def test_group_findings_and_changes(source_name): + count = snippets_findings.group_findings_and_changes(source_name) + assert count == 0 diff --git a/samples/snippets/snippets_list_assets.py b/samples/snippets/snippets_list_assets.py new file mode 100644 index 00000000..f8863802 --- /dev/null +++ b/samples/snippets/snippets_list_assets.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python +# +# Copyright 2019 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 +# +# https://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. + +""" Examples of listing assets in Cloud Security Command Center.""" + + +def list_all_assets(organization_id): + """Demonstrate listing and printing all assets.""" + i = 0 + # [START demo_list_all_assets] + from google.cloud import securitycenter + + client = securitycenter.SecurityCenterClient() + # organization_id is the numeric ID of the organization. + # organization_id = "1234567777" + org_name = "organizations/{org_id}".format(org_id=organization_id) + + # Call the API and print results. + asset_iterator = client.list_assets(org_name) + for i, asset_result in enumerate(asset_iterator): + print(i, asset_result) + # [END demo_list_all_assets] + return i + + +def list_assets_with_filters(organization_id): + """Demonstrate listing assets with a filter.""" + i = 0 + # [START demo_list_assets_with_filter] + from google.cloud import securitycenter + + client = securitycenter.SecurityCenterClient() + + # organization_id is the numeric ID of the organization. + # organization_id = "1234567777" + org_name = "organizations/{org_id}".format(org_id=organization_id) + + project_filter = ( + "security_center_properties.resource_type=" + + '"google.cloud.resourcemanager.Project"' + ) + # Call the API and print results. + asset_iterator = client.list_assets(org_name, filter_=project_filter) + for i, asset_result in enumerate(asset_iterator): + print(i, asset_result) + # [END demo_list_assets_with_filter] + return i + + +def list_assets_with_filters_and_read_time(organization_id): + """Demonstrate listing assets with a filter.""" + i = 0 + # [START demo_list_assets_with_filter_and_time] + from datetime import datetime, timedelta + + from google.protobuf.timestamp_pb2 import Timestamp + + from google.cloud import securitycenter + + client = securitycenter.SecurityCenterClient() + + # organization_id is the numeric ID of the organization. + # organization_id = "1234567777" + org_name = "organizations/{org_id}".format(org_id=organization_id) + + project_filter = ( + "security_center_properties.resource_type=" + + '"google.cloud.resourcemanager.Project"' + ) + + # Lists assets as of yesterday. + read_time = datetime.utcnow() - timedelta(days=1) + timestamp_proto = Timestamp() + timestamp_proto.FromDatetime(read_time) + + # Call the API and print results. + asset_iterator = client.list_assets( + org_name, filter_=project_filter, read_time=timestamp_proto + ) + for i, asset_result in enumerate(asset_iterator): + print(i, asset_result) + # [END demo_list_assets_with_filter_and_time] + return i + + +def list_point_in_time_changes(organization_id): + """Demonstrate listing assets along with their state changes.""" + i = 0 + # [START demo_list_assets_changes] + from datetime import timedelta + + from google.protobuf.duration_pb2 import Duration + from google.cloud import securitycenter + + client = securitycenter.SecurityCenterClient() + + # organization_id is the numeric ID of the organization. + # organization_id = "1234567777" + org_name = "organizations/{org_id}".format(org_id=organization_id) + project_filter = ( + "security_center_properties.resource_type=" + + '"google.cloud.resourcemanager.Project"' + ) + + # List assets and their state change the last 30 days + compare_delta = timedelta(days=30) + # Convert the timedelta to a Duration + duration_proto = Duration() + duration_proto.FromTimedelta(compare_delta) + # Call the API and print results. + asset_iterator = client.list_assets( + org_name, filter_=project_filter, compare_duration=duration_proto + ) + for i, asset in enumerate(asset_iterator): + print(i, asset) + + # [END demo_list_assets_changes] + return i + + +def group_assets(organization_id): + """Demonstrates grouping all assets by type. """ + i = 0 + # [START group_all_assets] + from google.cloud import securitycenter + + client = securitycenter.SecurityCenterClient() + + # organization_id is the numeric ID of the organization. + # organization_id = "1234567777" + org_name = "organizations/{org_id}".format(org_id=organization_id) + + group_by_type = "security_center_properties.resource_type" + + result_iterator = client.group_assets(org_name, group_by=group_by_type) + for i, result in enumerate(result_iterator): + print((i + 1), result) + # [END group_all_assets] + return i + + +def group_filtered_assets(organization_id): + """Demonstrates grouping assets by type with a filter. """ + i = 0 + # [START group_all_assets] + from google.cloud import securitycenter + + client = securitycenter.SecurityCenterClient() + + # organization_id is the numeric ID of the organization. + # organization_id = "1234567777" + org_name = "organizations/{org_id}".format(org_id=organization_id) + + group_by_type = "security_center_properties.resource_type" + only_projects = ( + "security_center_properties.resource_type=" + + '"google.cloud.resourcemanager.Project"' + ) + result_iterator = client.group_assets( + org_name, group_by=group_by_type, filter_=only_projects + ) + for i, result in enumerate(result_iterator): + print((i + 1), result) + # [END group_all_assets] + # only one asset type is a project + return i + + +def group_assets_by_changes(organization_id): + """Demonstrates grouping assets by there changes over a period of time.""" + i = 0 + # [START group_all_assets_by_change] + from datetime import timedelta + + from google.cloud import securitycenter + from google.protobuf.duration_pb2 import Duration + + client = securitycenter.SecurityCenterClient() + + duration_proto = Duration() + duration_proto.FromTimedelta(timedelta(days=5)) + + # organization_id is the numeric ID of the organization. + # organization_id = "1234567777" + org_name = "organizations/{org_id}".format(org_id=organization_id) + result_iterator = client.group_assets( + org_name, group_by="state_change", compare_duration=duration_proto + ) + for i, result in enumerate(result_iterator): + print((i + 1), result) + # [END group_all_assets_by_change] + return i diff --git a/samples/snippets/snippets_list_assets_test.py b/samples/snippets/snippets_list_assets_test.py new file mode 100644 index 00000000..a2646844 --- /dev/null +++ b/samples/snippets/snippets_list_assets_test.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# +# 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 +# +# https://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. +"""Tests for snippets.""" + +import os + +import pytest + +import snippets_list_assets + + +@pytest.fixture(scope="module") +def organization_id(): + """Get Organization ID from the environment variable """ + return os.environ["GCLOUD_ORGANIZATION"] + + +def test_list_all_assets(organization_id): + """Demonstrate listing and printing all assets.""" + count = snippets_list_assets.list_all_assets(organization_id) + assert count > 0 + + +def list_assets_with_filters(organization_id): + count = snippets_list_assets.list_all_assets(organization_id) + assert count > 0 + + +def test_list_assets_with_filters_and_read_time(organization_id): + count = snippets_list_assets.list_assets_with_filters_and_read_time(organization_id) + assert count > 0 + + +def test_list_point_in_time_changes(organization_id): + count = snippets_list_assets.list_point_in_time_changes(organization_id) + assert count > 0 + + +def test_group_assets(organization_id): + count = snippets_list_assets.group_assets(organization_id) + assert count >= 8 # 8 different asset types. + + +def test_group_filtered_assets(organization_id): + count = snippets_list_assets.group_filtered_assets(organization_id) + assert count == 0 + + +def test_group_assets_by_changes(organization_id): + count = snippets_list_assets.group_assets_by_changes(organization_id) + assert count >= 0 # only one asset type is a project diff --git a/samples/snippets/snippets_notification_configs.py b/samples/snippets/snippets_notification_configs.py new file mode 100644 index 00000000..acc4b8ba --- /dev/null +++ b/samples/snippets/snippets_notification_configs.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python +# +# 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 +# +# https://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. +"""Demos for working with notification configs.""" + + +def create_notification_config(organization_id, notification_config_id, pubsub_topic): + + # [START scc_create_notification_config] + from google.cloud import securitycenter as securitycenter + + client = securitycenter.SecurityCenterClient() + + # TODO: organization_id = "your-org-id" + # TODO: notification_config_id = "your-config-id" + # TODO: pubsub_topic = "projects/{your-project-id}/topics/{your-topic-ic}" + # Ensure this ServiceAccount has the "pubsub.topics.setIamPolicy" permission on the new topic. + + org_name = "organizations/{org_id}".format(org_id=organization_id) + + created_notification_config = client.create_notification_config( + org_name, + notification_config_id, + { + "description": "Notification for active findings", + "pubsub_topic": pubsub_topic, + "streaming_config": {"filter": 'state = "ACTIVE"'}, + }, + ) + + print(created_notification_config) + # [END scc_create_notification_config] + return created_notification_config + + +def delete_notification_config(organization_id, notification_config_id): + + # [START scc_delete_notification_config] + from google.cloud import securitycenter as securitycenter + + client = securitycenter.SecurityCenterClient() + + # TODO: organization_id = "your-org-id" + # TODO: notification_config_id = "your-config-id" + + notification_config_name = "organizations/{org_id}/notificationConfigs/{config_id}".format( + org_id=organization_id, config_id=notification_config_id + ) + + client.delete_notification_config(notification_config_name) + print("Deleted notification config: {}".format(notification_config_name)) + # [END scc_delete_notification_config] + return True + + +def get_notification_config(organization_id, notification_config_id): + + # [START scc_get_notification_config] + from google.cloud import securitycenter as securitycenter + + client = securitycenter.SecurityCenterClient() + + # TODO: organization_id = "your-org-id" + # TODO: notification_config_id = "your-config-id" + + notification_config_name = "organizations/{org_id}/notificationConfigs/{config_id}".format( + org_id=organization_id, config_id=notification_config_id + ) + + notification_config = client.get_notification_config(notification_config_name) + print("Got notification config: {}".format(notification_config)) + # [END scc_get_notification_config] + return notification_config + + +def list_notification_configs(organization_id): + + # [START scc_list_notification_configs] + from google.cloud import securitycenter as securitycenter + + client = securitycenter.SecurityCenterClient() + + # TODO: organization_id = "your-org-id" + org_name = "organizations/{org_id}".format(org_id=organization_id) + + notification_configs_iterator = client.list_notification_configs(org_name) + for i, config in enumerate(notification_configs_iterator): + print("{}: notification_config: {}".format(i, config)) + # [END scc_list_notification_configs] + return notification_configs_iterator + + +def update_notification_config(organization_id, notification_config_id, pubsub_topic): + # [START scc_update_notification_config] + from google.cloud import securitycenter as securitycenter + from google.protobuf import field_mask_pb2 + + client = securitycenter.SecurityCenterClient() + + # TODO organization_id = "your-org-id" + # TODO notification_config_id = "config-id-to-update" + # TODO pubsub_topic = "projects/{new-project}/topics/{new-topic}" + # If updating a pubsub_topic, ensure this ServiceAccount has the + # "pubsub.topics.setIamPolicy" permission on the new topic. + + notification_config_name = "organizations/{org_id}/notificationConfigs/{config_id}".format( + org_id=organization_id, config_id=notification_config_id + ) + + updated_description = "New updated description" + + # Only description and pubsub_topic can be updated. + field_mask = field_mask_pb2.FieldMask(paths=["description", "pubsub_topic"]) + + updated_notification_config = client.update_notification_config( + { + "name": notification_config_name, + "description": updated_description, + "pubsub_topic": pubsub_topic, + }, + update_mask=field_mask, + ) + + print(updated_notification_config) + # [END scc_update_notification_config] + return updated_notification_config diff --git a/samples/snippets/snippets_notification_receiver.py b/samples/snippets/snippets_notification_receiver.py new file mode 100644 index 00000000..aad6ba79 --- /dev/null +++ b/samples/snippets/snippets_notification_receiver.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# +# 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 +# +# https://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. +"""Demo for receiving notifications.""" + + +def receive_notifications(project_id, subscription_name): + # [START scc_receive_notifications] + # Requires https://cloud.google.com/pubsub/docs/quickstart-client-libraries#pubsub-client-libraries-python + import concurrent + + from google.cloud import pubsub_v1 + from google.cloud.securitycenter_v1.proto.notification_message_pb2 import ( + NotificationMessage, + ) + from google.protobuf import json_format + + # TODO: project_id = "your-project-id" + # TODO: subscription_name = "your-subscription-name" + + def callback(message): + print("Received message") + + notification_msg = NotificationMessage() + json_format.Parse(message.data, notification_msg) + + print( + "Notification config name: {}".format( + notification_msg.notification_config_name + ) + ) + print("Finding: {}".format(notification_msg.finding)) + + # Ack the message to prevent it from being pulled again + message.ack() + + subscriber = pubsub_v1.SubscriberClient() + subscription_path = subscriber.subscription_path(project_id, subscription_name) + + streaming_pull_future = subscriber.subscribe(subscription_path, callback=callback) + + print("Listening for messages on {}...\n".format(subscription_path)) + try: + streaming_pull_future.result(timeout=1) # Block for 1 second + except concurrent.futures.TimeoutError: + streaming_pull_future.cancel() + # [END scc_receive_notifications] + return True diff --git a/samples/snippets/snippets_notification_test.py b/samples/snippets/snippets_notification_test.py new file mode 100644 index 00000000..73ad0060 --- /dev/null +++ b/samples/snippets/snippets_notification_test.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python +# +# 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 +# +# https://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. +"""Tests for snippets.""" + +import os +import uuid + +from google.cloud import securitycenter as securitycenter +import pytest + +import snippets_notification_configs +import snippets_notification_receiver + +ORG_ID = os.environ["GCLOUD_ORGANIZATION"] +PROJECT_ID = os.environ["GCLOUD_PROJECT"] +PUBSUB_TOPIC = os.environ["GCLOUD_PUBSUB_TOPIC"] +PUBSUB_SUBSCRIPTION = os.environ["GCLOUD_PUBSUB_SUBSCRIPTION"] + +CREATE_CONFIG_ID = "new-notification-pytest" + str(uuid.uuid1()) +DELETE_CONFIG_ID = "new-notification-pytest" + str(uuid.uuid1()) +GET_CONFIG_ID = "new-notification-pytest" + str(uuid.uuid1()) +UPDATE_CONFIG_ID = "new-notification-pytest" + str(uuid.uuid1()) + + +def cleanup_notification_config(notification_config_id): + client = securitycenter.SecurityCenterClient() + + notification_config_name = "organizations/{org_id}/notificationConfigs/{config_id}".format( + org_id=ORG_ID, config_id=notification_config_id + ) + client.delete_notification_config(notification_config_name) + + +@pytest.fixture +def new_notification_config_for_update(): + client = securitycenter.SecurityCenterClient() + + org_name = "organizations/{org_id}".format(org_id=ORG_ID) + + created_notification_config = client.create_notification_config( + org_name, + UPDATE_CONFIG_ID, + { + "description": "Notification for active findings", + "pubsub_topic": PUBSUB_TOPIC, + "streaming_config": {"filter": ""}, + }, + ) + yield created_notification_config + cleanup_notification_config(UPDATE_CONFIG_ID) + + +@pytest.fixture +def new_notification_config_for_get(): + client = securitycenter.SecurityCenterClient() + + org_name = "organizations/{org_id}".format(org_id=ORG_ID) + + created_notification_config = client.create_notification_config( + org_name, + GET_CONFIG_ID, + { + "description": "Notification for active findings", + "pubsub_topic": PUBSUB_TOPIC, + "streaming_config": {"filter": ""}, + }, + ) + yield created_notification_config + cleanup_notification_config(GET_CONFIG_ID) + + +@pytest.fixture +def deleted_notification_config(): + client = securitycenter.SecurityCenterClient() + + org_name = "organizations/{org_id}".format(org_id=ORG_ID) + + created_notification_config = client.create_notification_config( + org_name, + DELETE_CONFIG_ID, + { + "description": "Notification for active findings", + "pubsub_topic": PUBSUB_TOPIC, + "streaming_config": {"filter": ""}, + }, + ) + return created_notification_config + + +def test_create_notification_config(): + created_notification_config = snippets_notification_configs.create_notification_config( + ORG_ID, CREATE_CONFIG_ID, PUBSUB_TOPIC + ) + assert created_notification_config is not None + + cleanup_notification_config(CREATE_CONFIG_ID) + + +def test_delete_notification_config(deleted_notification_config): + assert ( + snippets_notification_configs.delete_notification_config( + ORG_ID, DELETE_CONFIG_ID + ) + ) + + +def test_get_notification_config(new_notification_config_for_get): + retrieved_config = snippets_notification_configs.get_notification_config( + ORG_ID, GET_CONFIG_ID + ) + assert retrieved_config is not None + + +def test_list_notification_configs(): + iterator = snippets_notification_configs.list_notification_configs(ORG_ID) + assert iterator is not None + + +def test_update_notification_config(new_notification_config_for_update): + updated_config = snippets_notification_configs.update_notification_config( + ORG_ID, UPDATE_CONFIG_ID, PUBSUB_TOPIC + ) + assert updated_config is not None + + +def test_receive_notifications(): + assert ( + snippets_notification_receiver.receive_notifications( + PROJECT_ID, PUBSUB_SUBSCRIPTION + ) + ) diff --git a/samples/snippets/snippets_orgs.py b/samples/snippets/snippets_orgs.py new file mode 100644 index 00000000..6b95e49e --- /dev/null +++ b/samples/snippets/snippets_orgs.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# +# Copyright 2019 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 +# +# https://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. +"""Examples for working with organization settings. """ + + +def get_settings(organization_id): + """Example showing how to retreive current organization settings.""" + # [START get_org_settings] + from google.cloud import securitycenter + + client = securitycenter.SecurityCenterClient() + # organization_id is numeric ID for the organization. e.g. + # organization_id = "111112223333" + + org_settings_name = client.organization_settings_path(organization_id) + + org_settings = client.get_organization_settings(org_settings_name) + print(org_settings) + # [END get_org_settings] + + +def update_asset_discovery_org_settings(organization_id): + """Example showing how to update the asset discovery configuration + for an organization.""" + # [START update_org_settings] + from google.cloud import securitycenter + from google.protobuf import field_mask_pb2 + + # Create the client + client = securitycenter.SecurityCenterClient() + # organization_id is numeric ID for the organization. e.g. + # organization_id = "111112223333" + org_settings_name = "organizations/{org_id}/organizationSettings".format( + org_id=organization_id + ) + # Only update the enable_asset_discovery_value (leave others untouched). + field_mask = field_mask_pb2.FieldMask(paths=["enable_asset_discovery"]) + # Call the service. + updated = client.update_organization_settings( + {"name": org_settings_name, "enable_asset_discovery": True}, + update_mask=field_mask, + ) + print("Asset Discovery Enabled? {}".format(updated.enable_asset_discovery)) + # [END update_org_settings] + return updated diff --git a/samples/snippets/snippets_orgs_test.py b/samples/snippets/snippets_orgs_test.py new file mode 100644 index 00000000..fc9a3a90 --- /dev/null +++ b/samples/snippets/snippets_orgs_test.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# +# Copyright 2019 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 +# +# https://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. +"""Examples for working with organization settings. """ +import os + +import pytest + +import snippets_orgs + + +@pytest.fixture(scope="module") +def organization_id(): + """Get Organization ID from the environment variable """ + return os.environ["GCLOUD_ORGANIZATION"] + + +def test_get_settings(organization_id): + snippets_orgs.get_settings(organization_id) + + +def test_update_asset_discovery_org_settings(organization_id): + updated = snippets_orgs.update_asset_discovery_org_settings(organization_id) + assert updated.enable_asset_discovery diff --git a/samples/snippets/snippets_security_marks.py b/samples/snippets/snippets_security_marks.py new file mode 100644 index 00000000..88532341 --- /dev/null +++ b/samples/snippets/snippets_security_marks.py @@ -0,0 +1,187 @@ +#!/usr/bin/env python +# +# Copyright 2019 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 +# +# https://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. +"""Demos for working with security marks.""" + + +def add_to_asset(asset_name): + """Add new security marks to an asset.""" + # [START add_marks_to_asset] + from google.cloud import securitycenter + from google.protobuf import field_mask_pb2 + + # Create a new client. + client = securitycenter.SecurityCenterClient() + + # asset_name is the resource path for an asset that exists in CSCC. + # Its format is "organization/{organization_id}/assets/{asset_id} + # e.g.: + # asset_name = organizations/123123342/assets/12312321 + marks_name = "{}/securityMarks".format(asset_name) + + # Notice the suffix after "marks." in the field mask matches the keys + # in marks. + field_mask = field_mask_pb2.FieldMask(paths=["marks.key_a", "marks.key_b"]) + marks = {"key_a": "value_a", "key_b": "value_b"} + + updated_marks = client.update_security_marks( + {"name": marks_name, "marks": marks}, + # If this field was left empty, all marks would be cleared before adding + # the new values. + update_mask=field_mask, + ) + print(updated_marks) + # [END add_marks_to_asset] + return updated_marks, marks + + +def clear_from_asset(asset_name): + """Removes security marks from an asset.""" + # Make sure they are there first + add_to_asset(asset_name) + # [START clear_marks_asset] + from google.cloud import securitycenter + from google.protobuf import field_mask_pb2 + + # Create a new client. + client = securitycenter.SecurityCenterClient() + + # asset_name is the resource path for an asset that exists in CSCC. + # Its format is "organization/{organization_id}/assets/{asset_id} + # e.g.: + # asset_name = organizations/123123342/assets/12312321 + marks_name = "{}/securityMarks".format(asset_name) + + field_mask = field_mask_pb2.FieldMask(paths=["marks.key_a", "marks.key_b"]) + + updated_marks = client.update_security_marks( + { + "name": marks_name + # Note, no marks specified, so the specified values in + # the fields masks will be deleted. + }, + # If this field was left empty, all marks would be cleared. + update_mask=field_mask, + ) + print(updated_marks) + # [END clear_marks_asset] + return updated_marks + + +def delete_and_update_marks(asset_name): + """Updates and deletes security marks from an asset in the same call.""" + # Make sure they are there first + add_to_asset(asset_name) + # [START delete_and_update_marks] + from google.cloud import securitycenter + from google.protobuf import field_mask_pb2 + + client = securitycenter.SecurityCenterClient() + # asset_name is the resource path for an asset that exists in CSCC. + # Its format is "organization/{organization_id}/assets/{asset_id} + # e.g.: + # asset_name = organizations/123123342/assets/12312321 + marks_name = "{}/securityMarks".format(asset_name) + + field_mask = field_mask_pb2.FieldMask(paths=["marks.key_a", "marks.key_b"]) + marks = {"key_a": "new_value_for_a"} + + updated_marks = client.update_security_marks( + {"name": marks_name, "marks": marks}, update_mask=field_mask + ) + print(updated_marks) + # [END delete_and_update_marks] + return updated_marks + + +def add_to_finding(finding_name): + """Adds security marks to a finding. """ + # [START add_marks_to_finding] + from google.cloud import securitycenter + from google.protobuf import field_mask_pb2 + + client = securitycenter.SecurityCenterClient() + # finding_name is the resource path for a finding that exists in CSCC. + # Its format is + # "organizations/{org_id}/sources/{source_id}/findings/{finding_id}" + # e.g.: + # finding_name = "organizations/1112/sources/1234/findings/findingid" + finding_marks_name = "{}/securityMarks".format(finding_name) + + # Notice the suffix after "marks." in the field mask matches the keys + # in marks. + field_mask = field_mask_pb2.FieldMask( + paths=["marks.finding_key_a", "marks.finding_key_b"] + ) + marks = {"finding_key_a": "value_a", "finding_key_b": "value_b"} + + updated_marks = client.update_security_marks( + {"name": finding_marks_name, "marks": marks}, update_mask=field_mask + ) + # [END add_marks_to_finding] + return updated_marks, marks + + +def list_assets_with_query_marks(organization_id, asset_name): + """Lists assets with a filter on security marks. """ + add_to_asset(asset_name) + i = -1 + # [START demo_list_assets_with_security_marks] + from google.cloud import securitycenter + + client = securitycenter.SecurityCenterClient() + + # organization_id is the numeric ID of the organization. + # organization_id=1234567777 + org_name = "organizations/{org_id}".format(org_id=organization_id) + + marks_filter = 'security_marks.marks.key_a = "value_a"' + # Call the API and print results. + asset_iterator = client.list_assets(org_name, filter_=marks_filter) + + # Call the API and print results. + asset_iterator = client.list_assets(org_name, filter_=marks_filter) + for i, asset_result in enumerate(asset_iterator): + print(i, asset_result) + # [END demo_list_assets_with_security_marks] + return i + + +def list_findings_with_query_marks(source_name, finding_name): + """Lists findings with a filter on security marks.""" + # ensure marks are set on finding. + add_to_finding(finding_name) + i = -1 + # [START demo_list_findings_with_security_marks] + from google.cloud import securitycenter + + client = securitycenter.SecurityCenterClient() + + # source_name is the resource path for a source that has been + # created previously (you can use list_sources to find a specific one). + # Its format is: + # source_name = "organizations/{organization_id}/sources/{source_id}" + # e.g.: + # source_name = "organizations/111122222444/sources/1234" + marks_filter = 'NOT security_marks.marks.finding_key_a="value_a"' + + # Call the API and print results. + finding_iterator = client.list_findings(source_name, filter_=marks_filter) + for i, finding_result in enumerate(finding_iterator): + print(i, finding_result) + # [END demo_list_findings_with_security_marks] + # one finding should have been updated with keys, and one should be + # untouched. + return i diff --git a/samples/snippets/snippets_security_marks_test.py b/samples/snippets/snippets_security_marks_test.py new file mode 100644 index 00000000..18950f86 --- /dev/null +++ b/samples/snippets/snippets_security_marks_test.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python +# +# Copyright 2019 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 +# +# https://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. +"""Demos for working with security marks.""" +import os +import random + +import pytest + +import snippets_security_marks + + +@pytest.fixture(scope="module") +def organization_id(): + """Gets Organization ID from the environment variable """ + return os.environ["GCLOUD_ORGANIZATION"] + + +@pytest.fixture(scope="module") +def asset_name(organization_id): + """Returns a random asset name from existing assets.""" + from google.cloud import securitycenter + + client = securitycenter.SecurityCenterClient() + # organization_id is the numeric ID of the organization. + # organization_id=1234567777 + org_name = "organizations/{org_id}".format(org_id=organization_id) + assets = list(client.list_assets(org_name)) + # Select a random asset to avoid collision between integration tests. + asset = (random.sample(assets, 1)[0]).asset.name + + # Set fresh marks. + update = client.update_security_marks( + {"name": "{}/securityMarks".format(asset), "marks": {"other": "other_val"}} + ) + assert update.marks == {"other": "other_val"} + return asset + + +@pytest.fixture(scope="module") +def source_name(organization_id): + """Creates a new source in the organization.""" + from google.cloud import securitycenter + + client = securitycenter.SecurityCenterClient() + org_name = "organizations/{org_id}".format(org_id=organization_id) + source = client.create_source( + org_name, + { + "display_name": "Security marks Unit test source", + "description": "A new custom source that does X", + }, + ) + return source.name + + +@pytest.fixture(scope="module") +def finding_name(source_name): + """Creates a new finding and returns it name.""" + from google.cloud import securitycenter + from google.cloud.securitycenter_v1.proto.finding_pb2 import Finding + from google.protobuf.timestamp_pb2 import Timestamp + + client = securitycenter.SecurityCenterClient() + + now_proto = Timestamp() + now_proto.GetCurrentTime() + + finding = client.create_finding( + source_name, + "scfinding", + { + "state": Finding.ACTIVE, + "category": "C1", + "event_time": now_proto, + "resource_name": "//cloudresourcemanager.googleapis.com/organizations/1234", + }, + ) + client.create_finding( + source_name, + "untouched", + { + "state": Finding.ACTIVE, + "category": "MEDIUM_RISK_ONE", + "event_time": now_proto, + "resource_name": "//cloudresourcemanager.googleapis.com/organizations/1234", + }, + ) + + return finding.name + + +def test_add_to_asset(asset_name): + updated_marks, marks = snippets_security_marks.add_to_asset(asset_name) + assert updated_marks.marks.keys() >= marks.keys() + + +def test_clear_from_asset(asset_name): + updated_marks = snippets_security_marks.clear_from_asset(asset_name) + assert "other" in updated_marks.marks + assert len(updated_marks.marks) == 1 + + +def test_delete_and_update_marks(asset_name): + updated_marks = snippets_security_marks.delete_and_update_marks(asset_name) + assert updated_marks.marks == {"key_a": "new_value_for_a", "other": "other_val"} + + +def test_add_to_finding(finding_name): + updated_marks, marks = snippets_security_marks.add_to_finding(finding_name) + assert updated_marks.marks == marks + + +def test_list_assets_with_query_marks(organization_id, asset_name): + count = snippets_security_marks.list_assets_with_query_marks( + organization_id, asset_name + ) + assert count >= 0 + + +def test_list_findings_with_query_marks(source_name, finding_name): + count = snippets_security_marks.list_findings_with_query_marks( + source_name, finding_name + ) + assert count == 0 diff --git a/setup.py b/setup.py index d052d865..5a2cf044 100644 --- a/setup.py +++ b/setup.py @@ -19,59 +19,58 @@ import setuptools -name = 'google-cloud-securitycenter' -description = 'Cloud Security Command Center API API client library' +name = "google-cloud-securitycenter" +description = "Cloud Security Command Center API API client library" version = "0.6.0" -release_status = 'Development Status :: 3 - Alpha' +release_status = "Development Status :: 3 - Alpha" dependencies = [ - 'google-api-core[grpc] >= 1.14.0, < 2.0.0dev', - 'grpc-google-iam-v1 >= 0.12.3, < 0.13dev', + "google-api-core[grpc] >= 1.14.0, < 2.0.0dev", + "grpc-google-iam-v1 >= 0.12.3, < 0.13dev", 'enum34; python_version < "3.4"', ] package_root = os.path.abspath(os.path.dirname(__file__)) -readme_filename = os.path.join(package_root, 'README.rst') -with io.open(readme_filename, encoding='utf-8') as readme_file: +readme_filename = os.path.join(package_root, "README.rst") +with io.open(readme_filename, encoding="utf-8") as readme_file: readme = readme_file.read() packages = [ - package for package in setuptools.find_packages() - if package.startswith('google') + package for package in setuptools.find_packages() if package.startswith("google") ] -namespaces = ['google'] -if 'google.cloud' in packages: - namespaces.append('google.cloud') +namespaces = ["google"] +if "google.cloud" in packages: + namespaces.append("google.cloud") setuptools.setup( name=name, version=version, description=description, long_description=readme, - author='Google LLC', - author_email='googleapis-packages@google.com', - license='Apache 2.0', - url='https://github.com/googleapis/python-securitycenter', + author="Google LLC", + author_email="googleapis-packages@google.com", + license="Apache 2.0", + url="https://github.com/googleapis/python-securitycenter", classifiers=[ release_status, - 'Intended Audience :: Developers', - 'License :: OSI Approved :: Apache Software License', - 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Operating System :: OS Independent', - 'Topic :: Internet', + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Operating System :: OS Independent", + "Topic :: Internet", ], - platforms='Posix; MacOS X; Windows', + platforms="Posix; MacOS X; Windows", packages=packages, namespace_packages=namespaces, install_requires=dependencies, - python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*', + python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*", include_package_data=True, zip_safe=False, ) diff --git a/synth.metadata b/synth.metadata index 602cd308..c9656a59 100644 --- a/synth.metadata +++ b/synth.metadata @@ -3,23 +3,30 @@ { "git": { "name": ".", - "remote": "https://github.com/googleapis/python-securitycenter.git", - "sha": "93853b4b33a15b7fa59e89b0d498d1a10af7748d" + "remote": "git@github.com:googleapis/python-securitycenter.git", + "sha": "a30a996cafb8dd9fed3c86ef641d42ab959febe3" } }, { "git": { "name": "googleapis", "remote": "https://github.com/googleapis/googleapis.git", - "sha": "db69b46790b55a82ab7cfa473d031da787bc7591", - "internalRef": "320411362" + "sha": "50ae1c72fd94a3ae4269394b09e4b7fbb9251146", + "internalRef": "320484049" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "303271797a360f8a439203413f13a160f2f5b3b4" + "sha": "799d8e6522c1ef7cb55a70d9ea0b15e045c3d00b" + } + }, + { + "git": { + "name": "synthtool", + "remote": "https://github.com/googleapis/synthtool.git", + "sha": "799d8e6522c1ef7cb55a70d9ea0b15e045c3d00b" } } ], diff --git a/synth.py b/synth.py index 8f230a46..576b74a6 100644 --- a/synth.py +++ b/synth.py @@ -15,6 +15,7 @@ """This script is used to synthesize generated parts of this library.""" import synthtool as s from synthtool import gcp +from synthtool.languages import python gapic = gcp.GAPICBazel() common = gcp.CommonTemplates() @@ -48,8 +49,10 @@ # ---------------------------------------------------------------------------- # Add templated files # ---------------------------------------------------------------------------- -templated_files = common.py_library(cov_level=88) -s.move(templated_files, excludes=['noxfile.py']) +templated_files = common.py_library(cov_level=88, samples=True) +s.move(templated_files) + +python.py_samples(root="samples", skip_readmes=True) # TODO(busunkim): Use latest sphinx after microgenerator transition s.replace("noxfile.py", """['"]sphinx['"]""", '"sphinx<3.0.0"') From e1de422d01fa05d99ebf961ea4c99c5df91f494a Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 15 Jul 2020 02:44:31 +0200 Subject: [PATCH 4/8] chore(deps): update dependency google-cloud-pubsub to v1.7.0 (#42) --- docs/requirements.txt | 2 +- samples/snippets/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 42ab449b..7d01417f 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1 +1 @@ -google-cloud-pubsub==1.6.1 +google-cloud-pubsub==1.7.0 diff --git a/samples/snippets/requirements.txt b/samples/snippets/requirements.txt index 4b59ce29..3d83981d 100644 --- a/samples/snippets/requirements.txt +++ b/samples/snippets/requirements.txt @@ -1,2 +1,2 @@ -google-cloud-pubsub==1.6.0 +google-cloud-pubsub==1.7.0 google-cloud-securitycenter==0.6.0 \ No newline at end of file From e842237bbbafc7b8d25c16d025e085208b56274a Mon Sep 17 00:00:00 2001 From: Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> Date: Wed, 15 Jul 2020 17:56:38 -0700 Subject: [PATCH 5/8] chore: remove samples in `docs` (#46) --- docs/requirements.txt | 1 - docs/snippets_findings.py | 602 ------------------------- docs/snippets_list_assets.py | 209 --------- docs/snippets_notification_configs.py | 138 ------ docs/snippets_notification_receiver.py | 58 --- docs/snippets_notification_test.py | 146 ------ docs/snippets_orgs.py | 66 --- docs/snippets_security_marks.py | 272 ----------- 8 files changed, 1492 deletions(-) delete mode 100644 docs/requirements.txt delete mode 100644 docs/snippets_findings.py delete mode 100644 docs/snippets_list_assets.py delete mode 100644 docs/snippets_notification_configs.py delete mode 100644 docs/snippets_notification_receiver.py delete mode 100644 docs/snippets_notification_test.py delete mode 100644 docs/snippets_orgs.py delete mode 100644 docs/snippets_security_marks.py diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index 7d01417f..00000000 --- a/docs/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -google-cloud-pubsub==1.7.0 diff --git a/docs/snippets_findings.py b/docs/snippets_findings.py deleted file mode 100644 index dbd9406c..00000000 --- a/docs/snippets_findings.py +++ /dev/null @@ -1,602 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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 -# -# https://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. - -"""Examples of working with source and findings in Cloud Security Command Center.""" - -from itertools import chain -import os -import pytest - - -@pytest.fixture(scope="module") -def organization_id(): - """Get Organization ID from the environment variable """ - return os.environ["GCLOUD_ORGANIZATION"] - - -@pytest.fixture(scope="module") -def source_name(organization_id): - from google.cloud import securitycenter - - client = securitycenter.SecurityCenterClient() - org_name = "organizations/{org_id}".format(org_id=organization_id) - - source = client.create_source( - org_name, - { - "display_name": "Unit test source", - "description": "A new custom source that does X", - }, - ) - return source.name - - -def test_create_source(organization_id): - """Create a new findings source. """ - # [START create_source] - from google.cloud import securitycenter - - client = securitycenter.SecurityCenterClient() - # organization_id is the numeric ID of the organization. e.g.: - # organization_id = "111122222444" - org_name = "organizations/{org_id}".format(org_id=organization_id) - - created = client.create_source( - org_name, - { - "display_name": "Customized Display Name", - "description": "A new custom source that does X", - }, - ) - print("Created Source: {}".format(created.name)) - # [END create_source] - - -def test_get_source(source_name): - """Gets an existing source.""" - # [START get_source] - from google.cloud import securitycenter - - client = securitycenter.SecurityCenterClient() - - # source_name is the resource path for a source that has been - # created previously (you can use list_sources to find a specific one). - # Its format is: - # source_name = "organizations/{organization_id}/sources/{source_id}" - # e.g.: - # source_name = "organizations/111122222444/sources/1234" - source = client.get_source(source_name) - - print("Source: {}".format(source)) - # [END get_source] - - -def test_update_source(source_name): - """Updates a source's display name.""" - # [START update_source] - from google.cloud import securitycenter - from google.protobuf import field_mask_pb2 - - client = securitycenter.SecurityCenterClient() - - # Field mask to only update the display name. - field_mask = field_mask_pb2.FieldMask(paths=["display_name"]) - - # source_name is the resource path for a source that has been - # created previously (you can use list_sources to find a specific one). - # Its format is: - # source_name = "organizations/{organization_id}/sources/{source_id}" - # e.g.: - # source_name = "organizations/111122222444/sources/1234" - updated = client.update_source( - {"name": source_name, "display_name": "Updated Display Name"}, - update_mask=field_mask, - ) - print("Updated Source: {}".format(updated)) - # [END update_source] - assert updated.display_name == "Updated Display Name" - - -def test_add_user_to_source(source_name): - """Gives a user findingsEditor permission to the source.""" - user_email = "csccclienttest@gmail.com" - # [START update_source_iam] - from google.cloud import securitycenter - from google.iam.v1 import policy_pb2 - - client = securitycenter.SecurityCenterClient() - - # source_name is the resource path for a source that has been - # created previously (you can use list_sources to find a specific one). - # Its format is: - # source_name = "organizations/{organization_id}/sources/{source_id}" - # e.g.: - # source_name = "organizations/111122222444/sources/1234" - # Get the old policy so we can do an incremental update. - old_policy = client.get_iam_policy(source_name) - print("Old Policy: {}".format(old_policy)) - - # Setup a new IAM binding. - binding = policy_pb2.Binding() - binding.role = "roles/securitycenter.findingsEditor" - # user_email is an e-mail address known to Cloud IAM (e.g. a gmail address). - # user_mail = user@somedomain.com - binding.members.append("user:{}".format(user_email)) - - # Setting the e-tag avoids over-write existing policy - updated = client.set_iam_policy( - source_name, {"etag": old_policy.etag, "bindings": [binding]} - ) - - print("Updated Policy: {}".format(updated)) - - # [END update_source_iam] - assert any( - member == "user:csccclienttest@gmail.com" - for member in chain.from_iterable( - binding.members for binding in updated.bindings - ) - ) - - -def test_list_source(organization_id): - """Lists finding sources.""" - i = -1 - # [START list_sources] - from google.cloud import securitycenter - - # Create a new client. - client = securitycenter.SecurityCenterClient() - # organization_id is the numeric ID of the organization. e.g.: - # organization_id = "111122222444" - org_name = "organizations/{org_id}".format(org_id=organization_id) - - # Call the API and print out each existing source. - for i, source in enumerate(client.list_sources(org_name)): - print(i, source) - # [END list_sources] - assert i >= 0 - - -def test_create_finding(source_name): - """Creates a new finding.""" - # [START create_finding] - from google.cloud import securitycenter - from google.cloud.securitycenter_v1.proto.finding_pb2 import Finding - from google.protobuf.timestamp_pb2 import Timestamp - - # Create a new client. - client = securitycenter.SecurityCenterClient() - - # Use the current time as the finding "event time". - now_proto = Timestamp() - now_proto.GetCurrentTime() - - # source_name is the resource path for a source that has been - # created previously (you can use list_sources to find a specific one). - # Its format is: - # source_name = "organizations/{organization_id}/sources/{source_id}" - # e.g.: - # source_name = "organizations/111122222444/sources/1234" - - # Controlled by caller. - finding_id = "samplefindingid" - - # The resource this finding applies to. The CSCC UI can link - # the findings for a resource to the corresponding Asset of a resource - # if there are matches. - resource_name = "//cloudresourcemanager.googleapis.com/organizations/11232" - - # Call The API. - created_finding = client.create_finding( - source_name, - finding_id, - { - "state": Finding.ACTIVE, - "resource_name": resource_name, - "category": "MEDIUM_RISK_ONE", - "event_time": now_proto, - }, - ) - print(created_finding) - # [END create_finding] - assert len(created_finding.name) > 0 - - -def test_create_finding_with_source_properties(source_name): - """Demonstrate creating a new finding with source properties. """ - # [START create_finding_with_properties] - from google.cloud import securitycenter - from google.cloud.securitycenter_v1.proto.finding_pb2 import Finding - from google.protobuf.timestamp_pb2 import Timestamp - from google.protobuf.struct_pb2 import Value - - # Create a new client. - client = securitycenter.SecurityCenterClient() - - # source_name is the resource path for a source that has been - # created previously (you can use list_sources to find a specific one). - # Its format is: - # source_name = "organizations/{organization_id}/sources/{source_id}" - # e.g.: - # source_name = "organizations/111122222444/sources/1234" - - # Controlled by caller. - finding_id = "samplefindingid2" - - # The resource this finding applies to. The CSCC UI can link - # the findings for a resource to the corresponding Asset of a resource - # if there are matches. - resource_name = "//cloudresourcemanager.googleapis.com/organizations/11232" - - # Define source properties values as protobuf "Value" objects. - str_value = Value() - str_value.string_value = "string_example" - num_value = Value() - num_value.number_value = 1234 - - # Use the current time as the finding "event time". - now_proto = Timestamp() - now_proto.GetCurrentTime() - - created_finding = client.create_finding( - source_name, - finding_id, - { - "state": Finding.ACTIVE, - "resource_name": resource_name, - "category": "MEDIUM_RISK_ONE", - "source_properties": {"s_value": str_value, "n_value": num_value}, - "event_time": now_proto, - }, - ) - print(created_finding) - # [END create_finding_with_properties] - - -def test_update_finding(source_name): - # [START update_finding] - from google.cloud import securitycenter - from google.protobuf.struct_pb2 import Value - from google.protobuf import field_mask_pb2 - from google.protobuf.timestamp_pb2 import Timestamp - - client = securitycenter.SecurityCenterClient() - # Only update the specific source property and event_time. event_time - # is required for updates. - field_mask = field_mask_pb2.FieldMask( - paths=["source_properties.s_value", "event_time"] - ) - value = Value() - value.string_value = "new_string" - - # Set the update time to Now. This must be some time greater then the - # event_time on the original finding. - now_proto = Timestamp() - now_proto.GetCurrentTime() - - # source_name is the resource path for a source that has been - # created previously (you can use list_sources to find a specific one). - # Its format is: - # source_name = "organizations/{organization_id}/sources/{source_id}" - # e.g.: - # source_name = "organizations/111122222444/sources/1234" - finding_name = "{}/findings/samplefindingid2".format(source_name) - updated_finding = client.update_finding( - { - "name": finding_name, - "source_properties": {"s_value": value}, - "event_time": now_proto, - }, - update_mask=field_mask, - ) - - print( - "New Source properties: {}, Event Time {}".format( - updated_finding.source_properties, updated_finding.event_time.ToDatetime() - ) - ) - # [END update_finding] - - -def test_update_finding_state(source_name): - """Demonstrate updating only a finding state.""" - # [START update_finding_state] - from google.cloud import securitycenter - from google.cloud.securitycenter_v1.proto.finding_pb2 import Finding - from google.protobuf.timestamp_pb2 import Timestamp - from datetime import datetime - - # Create a client. - client = securitycenter.SecurityCenterClient() - # source_name is the resource path for a source that has been - # created previously (you can use list_sources to find a specific one). - # Its format is: - # source_name = "organizations/{organization_id}/sources/{source_id}" - # e.g.: - # source_name = "organizations/111122222444/sources/1234" - finding_name = "{}/findings/samplefindingid2".format(source_name) - - now_proto = Timestamp() - now_proto.GetCurrentTime() - - # Call the API to change the finding state to inactive as of now. - new_finding = client.set_finding_state( - finding_name, Finding.INACTIVE, start_time=now_proto - ) - print("New state: {}".format(Finding.State.Name(new_finding.state))) - # [END update_finding_state] - - -def test_trouble_shoot(source_name): - """Demonstrate calling test_iam_permissions to determine if the - service account has the correct permisions.""" - # [START test_iam_permissions] - from google.cloud import securitycenter - - # Create a client. - client = securitycenter.SecurityCenterClient() - # source_name is the resource path for a source that has been - # created previously (you can use list_sources to find a specific one). - # Its format is: - # source_name = "organizations/{organization_id}/sources/{source_id}" - # e.g.: - # source_name = "organizations/111122222444/sources/1234" - - # Check for permssions to call create_finding or update_finding. - permission_response = client.test_iam_permissions( - source_name, ["securitycenter.findings.update"] - ) - - print( - "Permision to create or update findings? {}".format( - len(permission_response.permissions) > 0 - ) - ) - # [END test_iam_permissions] - assert len(permission_response.permissions) > 0 - # [START test_iam_permissions] - # Check for permissions necessary to call set_finding_state. - permission_response = client.test_iam_permissions( - source_name, ["securitycenter.findings.setState"] - ) - print( - "Permision to update state? {}".format(len(permission_response.permissions) > 0) - ) - # [END test_iam_permissions] - assert len(permission_response.permissions) > 0 - - -def test_list_all_findings(organization_id): - # [START list_all_findings] - from google.cloud import securitycenter - - # Create a client. - client = securitycenter.SecurityCenterClient() - - # organization_id is the numeric ID of the organization. e.g.: - # organization_id = "111122222444" - org_name = "organizations/{org_id}".format(org_id=organization_id) - # The "sources/-" suffix lists findings across all sources. You - # also use a specific source_name instead. - all_sources = "{org_name}/sources/-".format(org_name=org_name) - finding_result_iterator = client.list_findings(all_sources) - for i, finding_result in enumerate(finding_result_iterator): - print( - "{}: name: {} resource: {}".format( - i, finding_result.finding.name, finding_result.finding.resource_name - ) - ) - # [END list_all_findings] - assert i > 0 - - -def test_list_filtered_findings(source_name): - # [START list_filtered_findings] - from google.cloud import securitycenter - - # Create a new client. - client = securitycenter.SecurityCenterClient() - - # source_name is the resource path for a source that has been - # created previously (you can use list_sources to find a specific one). - # Its format is: - # source_name = "organizations/{organization_id}/sources/{source_id}" - # e.g.: - # source_name = "organizations/111122222444/sources/1234" - # You an also use a wild-card "-" for all sources: - # source_name = "organizations/111122222444/sources/-" - finding_result_iterator = client.list_findings( - source_name, filter_='category="MEDIUM_RISK_ONE"' - ) - # Iterate an print all finding names and the resource they are - # in reference to. - for i, finding_result in enumerate(finding_result_iterator): - print( - "{}: name: {} resource: {}".format( - i, finding_result.finding.name, finding_result.finding.resource_name - ) - ) - # [END list_filtered_findings] - assert i > 0 - - -def test_list_findings_at_time(source_name): - # [START list_findings_at_a_time] - from google.cloud import securitycenter - from google.protobuf.timestamp_pb2 import Timestamp - from datetime import timedelta, datetime - - # Create a new client. - client = securitycenter.SecurityCenterClient() - - # source_name is the resource path for a source that has been - # created previously (you can use list_sources to find a specific one). - # Its format is: - # source_name = "organizations/{organization_id}/sources/{source_id}" - # e.g.: - # source_name = "organizations/111122222444/sources/1234" - # You an also use a wild-card "-" for all sources: - # source_name = "organizations/111122222444/sources/-" - five_days_ago = Timestamp() - five_days_ago.FromDatetime(datetime.now() - timedelta(days=5)) - # [END list_findings_at_a_time] - i = -1 - five_days_ago.FromDatetime(datetime(2019, 3, 5, 0, 0, 0)) - # [START list_findings_at_a_time] - - finding_result_iterator = client.list_findings(source_name, read_time=five_days_ago) - for i, finding_result in enumerate(finding_result_iterator): - print( - "{}: name: {} resource: {}".format( - i, finding_result.finding.name, finding_result.finding.resource_name - ) - ) - # [END list_findings_at_a_time] - assert i == -1 - - -def test_get_iam_policy(source_name): - """Gives a user findingsEditor permission to the source.""" - user_email = "csccclienttest@gmail.com" - # [START get_source_iam] - from google.cloud import securitycenter - from google.iam.v1 import policy_pb2 - - client = securitycenter.SecurityCenterClient() - - # source_name is the resource path for a source that has been - # created previously (you can use list_sources to find a specific one). - # Its format is: - # source_name = "organizations/{organization_id}/sources/{source_id}" - # e.g.: - # source_name = "organizations/111122222444/sources/1234" - # Get the old policy so we can do an incremental update. - policy = client.get_iam_policy(source_name) - print("Policy: {}".format(policy)) - # [END get_source_iam] - - -def test_group_all_findings(organization_id): - """Demonstrates grouping all findings across an organization.""" - # [START group_all_findings] - from google.cloud import securitycenter - - # Create a client. - client = securitycenter.SecurityCenterClient() - - # organization_id is the numeric ID of the organization. e.g.: - # organization_id = "111122222444" - org_name = "organizations/{org_id}".format(org_id=organization_id) - # The "sources/-" suffix lists findings across all sources. You - # also use a specific source_name instead. - all_sources = "{org_name}/sources/-".format(org_name=org_name) - group_result_iterator = client.group_findings(all_sources, group_by="category") - for i, group_result in enumerate(group_result_iterator): - print((i + 1), group_result) - # [END group_all_findings] - assert i > 0 - - -def test_group_filtered_findings(source_name): - """Demonstrates grouping all findings across an organization.""" - # [START group_filtered_findings] - from google.cloud import securitycenter - - # Create a client. - client = securitycenter.SecurityCenterClient() - - # source_name is the resource path for a source that has been - # created previously (you can use list_sources to find a specific one). - # Its format is: - # source_name = "organizations/{organization_id}/sources/{source_id}" - # e.g.: - # source_name = "organizations/111122222444/sources/1234" - - group_result_iterator = client.group_findings( - source_name, group_by="category", filter_='state="ACTIVE"' - ) - for i, group_result in enumerate(group_result_iterator): - print((i + 1), group_result) - # [END group_filtered_findings] - assert i == 0 - - -def test_group_findings_at_time(source_name): - """Demonstrates grouping all findings across an organization as of - a specific time.""" - i = -1 - # [START group_findings_at_time] - from datetime import datetime, timedelta - from google.cloud import securitycenter - from google.protobuf.timestamp_pb2 import Timestamp - - # Create a client. - client = securitycenter.SecurityCenterClient() - - # source_name is the resource path for a source that has been - # created previously (you can use list_sources to find a specific one). - # Its format is: - # source_name = "organizations/{organization_id}/sources/{source_id}" - # e.g.: - # source_name = "organizations/111122222444/sources/1234" - - # Group findings as of yesterday. - read_time = datetime.utcnow() - timedelta(days=1) - timestamp_proto = Timestamp() - timestamp_proto.FromDatetime(read_time) - - group_result_iterator = client.group_findings( - source_name, group_by="category", read_time=timestamp_proto - ) - for i, group_result in enumerate(group_result_iterator): - print((i + 1), group_result) - # [END group_filtered_findings_at_time] - assert i == -1 - - -def test_group_findings_and_changes(source_name): - """Demonstrates grouping all findings across an organization and - associated changes.""" - # [START group_filtered_findings_with_changes] - from datetime import timedelta - - from google.cloud import securitycenter - from google.protobuf.duration_pb2 import Duration - - # Create a client. - client = securitycenter.SecurityCenterClient() - - # source_name is the resource path for a source that has been - # created previously (you can use list_sources to find a specific one). - # Its format is: - # source_name = "organizations/{organization_id}/sources/{source_id}" - # e.g.: - # source_name = "organizations/111122222444/sources/1234" - - # List assets and their state change the last 30 days - compare_delta = timedelta(days=30) - # Convert the timedelta to a Duration - duration_proto = Duration() - duration_proto.FromTimedelta(compare_delta) - - group_result_iterator = client.group_findings( - source_name, group_by="state_change", compare_duration=duration_proto - ) - for i, group_result in enumerate(group_result_iterator): - print((i + 1), group_result) - # [END group_findings_with_changes] - assert i == 0 diff --git a/docs/snippets_list_assets.py b/docs/snippets_list_assets.py deleted file mode 100644 index ae50ff91..00000000 --- a/docs/snippets_list_assets.py +++ /dev/null @@ -1,209 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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 -# -# https://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. - -""" Examples of listing assets in Cloud Security Command Center.""" -import os -from datetime import datetime, timedelta -import pytest - - -@pytest.fixture(scope="module") -def organization_id(): - """Get Organization ID from the environment variable """ - return os.environ["GCLOUD_ORGANIZATION"] - - -def test_list_all_assets(organization_id): - """Demonstrate listing and printing all assets.""" - # [START demo_list_all_assets] - from google.cloud import securitycenter - - client = securitycenter.SecurityCenterClient() - # organization_id is the numeric ID of the organization. - # organization_id = "1234567777" - org_name = "organizations/{org_id}".format(org_id=organization_id) - - # Call the API and print results. - asset_iterator = client.list_assets(org_name) - for i, asset_result in enumerate(asset_iterator): - print(i, asset_result) - # [END demo_list_all_assets] - assert i > 0 - - -def test_list_assets_with_filters(organization_id): - """Demonstrate listing assets with a filter.""" - # [START demo_list_assets_with_filter] - from google.cloud import securitycenter - - client = securitycenter.SecurityCenterClient() - - # organization_id is the numeric ID of the organization. - # organization_id = "1234567777" - org_name = "organizations/{org_id}".format(org_id=organization_id) - - project_filter = ( - "security_center_properties.resource_type=" - + '"google.cloud.resourcemanager.Project"' - ) - # Call the API and print results. - asset_iterator = client.list_assets(org_name, filter_=project_filter) - for i, asset_result in enumerate(asset_iterator): - print(i, asset_result) - # [END demo_list_assets_with_filter] - assert i > 0 - - -def test_list_assets_with_filters_and_read_time(organization_id): - """Demonstrate listing assets with a filter.""" - # [START demo_list_assets_with_filter_and_time] - from datetime import datetime, timedelta - - from google.protobuf.timestamp_pb2 import Timestamp - - from google.cloud import securitycenter - - client = securitycenter.SecurityCenterClient() - - # organization_id is the numeric ID of the organization. - # organization_id = "1234567777" - org_name = "organizations/{org_id}".format(org_id=organization_id) - - project_filter = ( - "security_center_properties.resource_type=" - + '"google.cloud.resourcemanager.Project"' - ) - - # Lists assets as of yesterday. - read_time = datetime.utcnow() - timedelta(days=1) - timestamp_proto = Timestamp() - timestamp_proto.FromDatetime(read_time) - - # Call the API and print results. - asset_iterator = client.list_assets( - org_name, filter_=project_filter, read_time=timestamp_proto - ) - for i, asset_result in enumerate(asset_iterator): - print(i, asset_result) - # [END demo_list_assets_with_filter_and_time] - assert i > 0 - - -def test_list_point_in_time_changes(organization_id): - """Demonstrate listing assets along with their state changes.""" - # [START demo_list_assets_changes] - from datetime import timedelta - - from google.protobuf.duration_pb2 import Duration - from google.cloud import securitycenter - - client = securitycenter.SecurityCenterClient() - - # organization_id is the numeric ID of the organization. - # organization_id = "1234567777" - org_name = "organizations/{org_id}".format(org_id=organization_id) - project_filter = ( - "security_center_properties.resource_type=" - + '"google.cloud.resourcemanager.Project"' - ) - - # List assets and their state change the last 30 days - compare_delta = timedelta(days=30) - # Convert the timedelta to a Duration - duration_proto = Duration() - duration_proto.FromTimedelta(compare_delta) - # Call the API and print results. - asset_iterator = client.list_assets( - org_name, filter_=project_filter, compare_duration=duration_proto - ) - for i, asset in enumerate(asset_iterator): - print(i, asset) - - # [END demo_list_assets_changes] - assert i > 0 - - -def test_group_assets(organization_id): - """Demonstrates grouping all assets by type. """ - # [START group_all_assets] - from google.cloud import securitycenter - - client = securitycenter.SecurityCenterClient() - - # organization_id is the numeric ID of the organization. - # organization_id = "1234567777" - org_name = "organizations/{org_id}".format(org_id=organization_id) - - group_by_type = "security_center_properties.resource_type" - - result_iterator = client.group_assets(org_name, group_by=group_by_type) - for i, result in enumerate(result_iterator): - print((i + 1), result) - # [END group_all_assets] - # 8 different asset types. - assert i >= 8 - - -def test_group_filtered_assets(organization_id): - """Demonstrates grouping assets by type with a filter. """ - # [START group_all_assets] - from google.cloud import securitycenter - - client = securitycenter.SecurityCenterClient() - - # organization_id is the numeric ID of the organization. - # organization_id = "1234567777" - org_name = "organizations/{org_id}".format(org_id=organization_id) - - group_by_type = "security_center_properties.resource_type" - only_projects = ( - "security_center_properties.resource_type=" - + '"google.cloud.resourcemanager.Project"' - ) - result_iterator = client.group_assets( - org_name, group_by=group_by_type, filter_=only_projects - ) - for i, result in enumerate(result_iterator): - print((i + 1), result) - # [END group_all_assets] - # only one asset type is a project - assert i == 0 - - -def test_group_assets_by_changes(organization_id): - """Demonstrates grouping assets by there changes over a period of time.""" - # [START group_all_assets_by_change] - from datetime import timedelta - - from google.cloud import securitycenter - from google.protobuf.duration_pb2 import Duration - - client = securitycenter.SecurityCenterClient() - - duration_proto = Duration() - duration_proto.FromTimedelta(timedelta(days=5)) - - # organization_id is the numeric ID of the organization. - # organization_id = "1234567777" - org_name = "organizations/{org_id}".format(org_id=organization_id) - result_iterator = client.group_assets( - org_name, group_by="state_change", compare_duration=duration_proto - ) - for i, result in enumerate(result_iterator): - print((i + 1), result) - # [END group_all_assets_by_change] - # only one asset type is a project - assert i >= 0 diff --git a/docs/snippets_notification_configs.py b/docs/snippets_notification_configs.py deleted file mode 100644 index 42d1f70f..00000000 --- a/docs/snippets_notification_configs.py +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/env python -# -# 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 -# -# https://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. -"""Demos for working with notification configs.""" - - -def create_notification_config(organization_id, notification_config_id, pubsub_topic): - - # [START scc_create_notification_config] - from google.cloud import securitycenter as securitycenter - - client = securitycenter.SecurityCenterClient() - - # TODO: organization_id = "your-org-id" - # TODO: notification_config_id = "your-config-id" - # TODO: pubsub_topic = "projects/{your-project-id}/topics/{your-topic-ic}" - # Ensure this ServiceAccount has the "pubsub.topics.setIamPolicy" permission on the new topic. - - org_name = "organizations/{org_id}".format(org_id=organization_id) - - created_notification_config = client.create_notification_config( - org_name, - notification_config_id, - { - "description": "Notification for active findings", - "pubsub_topic": pubsub_topic, - "streaming_config": {"filter": 'state = "ACTIVE"',}, - }, - ) - - print(created_notification_config) - # [END scc_create_notification_config] - return created_notification_config - - -def delete_notification_config(organization_id, notification_config_id): - - # [START scc_delete_notification_config] - from google.cloud import securitycenter as securitycenter - - client = securitycenter.SecurityCenterClient() - - # TODO: organization_id = "your-org-id" - # TODO: notification_config_id = "your-config-id" - - notification_config_name = "organizations/{org_id}/notificationConfigs/{config_id}".format( - org_id=organization_id, config_id=notification_config_id - ) - - client.delete_notification_config(notification_config_name) - print("Deleted notification config: {}".format(notification_config_name)) - # [END scc_delete_notification_config] - return True - - -def get_notification_config(organization_id, notification_config_id): - - # [START scc_get_notification_config] - from google.cloud import securitycenter as securitycenter - - client = securitycenter.SecurityCenterClient() - - # TODO: organization_id = "your-org-id" - # TODO: notification_config_id = "your-config-id" - - notification_config_name = "organizations/{org_id}/notificationConfigs/{config_id}".format( - org_id=organization_id, config_id=notification_config_id - ) - - notification_config = client.get_notification_config(notification_config_name) - print("Got notification config: {}".format(notification_config)) - # [END scc_get_notification_config] - return notification_config - - -def list_notification_configs(organization_id): - - # [START scc_list_notification_configs] - from google.cloud import securitycenter as securitycenter - - client = securitycenter.SecurityCenterClient() - - # TODO: organization_id = "your-org-id" - org_name = "organizations/{org_id}".format(org_id=organization_id) - - notification_configs_iterator = client.list_notification_configs(org_name) - for i, config in enumerate(notification_configs_iterator): - print("{}: notification_config: {}".format(i, config)) - # [END scc_list_notification_configs] - return notification_configs_iterator - - -def update_notification_config(organization_id, notification_config_id, pubsub_topic): - # [START scc_update_notification_config] - from google.cloud import securitycenter as securitycenter - from google.protobuf import field_mask_pb2 - - client = securitycenter.SecurityCenterClient() - - # TODO organization_id = "your-org-id" - # TODO notification_config_id = "config-id-to-update" - # TODO pubsub_topic = "projects/{new-project}/topics/{new-topic}" - # If updating a pubsub_topic, ensure this ServiceAccount has the - # "pubsub.topics.setIamPolicy" permission on the new topic. - - notification_config_name = "organizations/{org_id}/notificationConfigs/{config_id}".format( - org_id=organization_id, config_id=notification_config_id - ) - - updated_description = "New updated description" - - # Only description and pubsub_topic can be updated. - field_mask = field_mask_pb2.FieldMask(paths=["description", "pubsub_topic"]) - - updated_notification_config = client.update_notification_config( - { - "name": notification_config_name, - "description": updated_description, - "pubsub_topic": pubsub_topic, - }, - update_mask=field_mask, - ) - - print(updated_notification_config) - # [END scc_update_notification_config] - return updated_notification_config diff --git a/docs/snippets_notification_receiver.py b/docs/snippets_notification_receiver.py deleted file mode 100644 index fd2fdcae..00000000 --- a/docs/snippets_notification_receiver.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python -# -# 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 -# -# https://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. -"""Demo for receiving notifications.""" - - -def receive_notifications(project_id, subscription_name): - # [START scc_receive_notifications] - # Requires https://cloud.google.com/pubsub/docs/quickstart-client-libraries#pubsub-client-libraries-python - from google.cloud import pubsub_v1 - from google.cloud.securitycenter_v1.proto.notification_message_pb2 import ( - NotificationMessage, - ) - from google.protobuf import json_format - - # TODO: project_id = "your-project-id" - # TODO: subscription_name = "your-subscription-name" - - def callback(message): - print("Received message") - - notification_msg = NotificationMessage() - json_format.Parse(message.data, notification_msg) - - print( - "Notification config name: {}".format( - notification_msg.notification_config_name - ) - ) - print("Finding: {}".format(notification_msg.finding)) - - # Ack the message to prevent it from being pulled again - message.ack() - - subscriber = pubsub_v1.SubscriberClient() - subscription_path = subscriber.subscription_path(project_id, subscription_name) - - streaming_pull_future = subscriber.subscribe(subscription_path, callback=callback) - - print("Listening for messages on {}...\n".format(subscription_path)) - try: - streaming_pull_future.result(timeout=1) # Block for 1 second - except: - streaming_pull_future.cancel() - # [END scc_receive_notifications] - return True diff --git a/docs/snippets_notification_test.py b/docs/snippets_notification_test.py deleted file mode 100644 index d24d0906..00000000 --- a/docs/snippets_notification_test.py +++ /dev/null @@ -1,146 +0,0 @@ -#!/usr/bin/env python -# -# 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 -# -# https://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. -"""Tests for snippets.""" - -import os -import uuid - -from google.cloud import securitycenter as securitycenter -import pytest - -import snippets_notification_configs -import snippets_notification_receiver - -ORG_ID = os.environ["GCLOUD_ORGANIZATION"] -PROJECT_ID = os.environ["GCLOUD_PROJECT"] -PUBSUB_TOPIC = os.environ["GCLOUD_PUBSUB_TOPIC"] -PUBSUB_SUBSCRIPTION = os.environ["GCLOUD_PUBSUB_SUBSCRIPTION"] - -CREATE_CONFIG_ID = "new-notification-pytest" + str(uuid.uuid1()) -DELETE_CONFIG_ID = "new-notification-pytest" + str(uuid.uuid1()) -GET_CONFIG_ID = "new-notification-pytest" + str(uuid.uuid1()) -UPDATE_CONFIG_ID = "new-notification-pytest" + str(uuid.uuid1()) - - -def cleanup_notification_config(notification_config_id): - client = securitycenter.SecurityCenterClient() - - notification_config_name = "organizations/{org_id}/notificationConfigs/{config_id}".format( - org_id=ORG_ID, config_id=notification_config_id - ) - client.delete_notification_config(notification_config_name) - - -@pytest.fixture -def new_notification_config_for_update(): - client = securitycenter.SecurityCenterClient() - - org_name = "organizations/{org_id}".format(org_id=ORG_ID) - - created_notification_config = client.create_notification_config( - org_name, - UPDATE_CONFIG_ID, - { - "description": "Notification for active findings", - "pubsub_topic": PUBSUB_TOPIC, - "streaming_config": {"filter": "",}, - }, - ) - yield created_notification_config - cleanup_notification_config(UPDATE_CONFIG_ID) - - -@pytest.fixture -def new_notification_config_for_get(): - client = securitycenter.SecurityCenterClient() - - org_name = "organizations/{org_id}".format(org_id=ORG_ID) - - created_notification_config = client.create_notification_config( - org_name, - GET_CONFIG_ID, - { - "description": "Notification for active findings", - "pubsub_topic": PUBSUB_TOPIC, - "streaming_config": {"filter": "",}, - }, - ) - yield created_notification_config - cleanup_notification_config(GET_CONFIG_ID) - - -@pytest.fixture -def deleted_notification_config(): - client = securitycenter.SecurityCenterClient() - - org_name = "organizations/{org_id}".format(org_id=ORG_ID) - - created_notification_config = client.create_notification_config( - org_name, - DELETE_CONFIG_ID, - { - "description": "Notification for active findings", - "pubsub_topic": PUBSUB_TOPIC, - "streaming_config": {"filter": "",}, - }, - ) - return created_notification_config - - -def test_create_notification_config(): - created_notification_config = snippets_notification_configs.create_notification_config( - ORG_ID, CREATE_CONFIG_ID, PUBSUB_TOPIC - ) - assert created_notification_config is not None - - cleanup_notification_config(CREATE_CONFIG_ID) - - -def test_delete_notification_config(deleted_notification_config): - assert ( - snippets_notification_configs.delete_notification_config( - ORG_ID, DELETE_CONFIG_ID - ) - == True - ) - - -def test_get_notification_config(new_notification_config_for_get): - retrieved_config = snippets_notification_configs.get_notification_config( - ORG_ID, GET_CONFIG_ID - ) - assert retrieved_config is not None - - -def test_list_notification_configs(): - iterator = snippets_notification_configs.list_notification_configs(ORG_ID) - assert iterator is not None - - -def test_update_notification_config(new_notification_config_for_update): - updated_config = snippets_notification_configs.update_notification_config( - ORG_ID, UPDATE_CONFIG_ID, PUBSUB_TOPIC - ) - assert updated_config is not None - - -def test_receive_notifications(): - assert ( - snippets_notification_receiver.receive_notifications( - PROJECT_ID, PUBSUB_SUBSCRIPTION - ) - == True - ) diff --git a/docs/snippets_orgs.py b/docs/snippets_orgs.py deleted file mode 100644 index 7781da11..00000000 --- a/docs/snippets_orgs.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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 -# -# https://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. -"""Examples for working with organization settings. """ -import os -import pytest - - -@pytest.fixture(scope="module") -def organization_id(): - """Get Organization ID from the environment variable """ - return os.environ["GCLOUD_ORGANIZATION"] - - -def test_get_settings(organization_id): - """Example showing how to retreive current organization settings.""" - # [START get_org_settings] - from google.cloud import securitycenter - - client = securitycenter.SecurityCenterClient() - # organization_id is numeric ID for the organization. e.g. - # organization_id = "111112223333" - - org_settings_name = client.organization_settings_path(organization_id) - - org_settings = client.get_organization_settings(org_settings_name) - print(org_settings) - # [END get_org_settings] - - -def test_update_asset_discovery_org_settings(organization_id): - """Example showing how to update the asset discovery configuration - for an organization.""" - # [START update_org_settings] - from google.cloud import securitycenter - from google.protobuf import field_mask_pb2 - - # Create the client - client = securitycenter.SecurityCenterClient() - # organization_id is numeric ID for the organization. e.g. - # organization_id = "111112223333" - org_settings_name = "organizations/{org_id}/organizationSettings".format( - org_id=organization_id - ) - # Only update the enable_asset_discovery_value (leave others untouched). - field_mask = field_mask_pb2.FieldMask(paths=["enable_asset_discovery"]) - # Call the service. - updated = client.update_organization_settings( - {"name": org_settings_name, "enable_asset_discovery": True}, - update_mask=field_mask, - ) - print("Asset Discovery Enabled? {}".format(updated.enable_asset_discovery)) - # [END update_org_settings] - assert updated.enable_asset_discovery == True diff --git a/docs/snippets_security_marks.py b/docs/snippets_security_marks.py deleted file mode 100644 index ef2f5d73..00000000 --- a/docs/snippets_security_marks.py +++ /dev/null @@ -1,272 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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 -# -# https://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. -"""Demos for working with security marks.""" -import os -import random - -import pytest - - -@pytest.fixture(scope="module") -def organization_id(): - """Gets Organization ID from the environment variable """ - return os.environ["GCLOUD_ORGANIZATION"] - - -@pytest.fixture(scope="module") -def asset_name(organization_id): - """Returns a random asset name from existing assets.""" - from google.cloud import securitycenter - - client = securitycenter.SecurityCenterClient() - # organization_id is the numeric ID of the organization. - # organization_id=1234567777 - org_name = "organizations/{org_id}".format(org_id=organization_id) - assets = list(client.list_assets(org_name)) - # Select a random asset to avoid collision between integration tests. - asset = (random.sample(assets, 1)[0]).asset.name - - # Set fresh marks. - update = client.update_security_marks( - {"name": "{}/securityMarks".format(asset), "marks": {"other": "other_val"}} - ) - assert update.marks == {"other": "other_val"} - return asset - - -@pytest.fixture(scope="module") -def source_name(organization_id): - """Creates a new source in the organization.""" - from google.cloud import securitycenter - - client = securitycenter.SecurityCenterClient() - org_name = "organizations/{org_id}".format(org_id=organization_id) - source = client.create_source( - org_name, - { - "display_name": "Security marks Unit test source", - "description": "A new custom source that does X", - }, - ) - return source.name - - -@pytest.fixture(scope="module") -def finding_name(source_name): - """Creates a new finding and returns it name.""" - from google.cloud import securitycenter - from google.cloud.securitycenter_v1.proto.finding_pb2 import Finding - from google.protobuf.timestamp_pb2 import Timestamp - - client = securitycenter.SecurityCenterClient() - - now_proto = Timestamp() - now_proto.GetCurrentTime() - - finding = client.create_finding( - source_name, - "scfinding", - { - "state": Finding.ACTIVE, - "category": "C1", - "event_time": now_proto, - "resource_name": "//cloudresourcemanager.googleapis.com/organizations/1234", - }, - ) - client.create_finding( - source_name, - "untouched", - { - "state": Finding.ACTIVE, - "category": "MEDIUM_RISK_ONE", - "event_time": now_proto, - "resource_name": "//cloudresourcemanager.googleapis.com/organizations/1234", - }, - ) - - return finding.name - - -def test_add_to_asset(asset_name): - """Add new security marks to an asset.""" - # [START add_marks_to_asset] - from google.cloud import securitycenter - from google.protobuf import field_mask_pb2 - - # Create a new client. - client = securitycenter.SecurityCenterClient() - - # asset_name is the resource path for an asset that exists in CSCC. - # Its format is "organization/{organization_id}/assets/{asset_id} - # e.g.: - # asset_name = organizations/123123342/assets/12312321 - marks_name = "{}/securityMarks".format(asset_name) - - # Notice the suffix after "marks." in the field mask matches the keys - # in marks. - field_mask = field_mask_pb2.FieldMask(paths=["marks.key_a", "marks.key_b"]) - marks = {"key_a": "value_a", "key_b": "value_b"} - - updated_marks = client.update_security_marks( - {"name": marks_name, "marks": marks}, - # If this field was left empty, all marks would be cleared before adding - # the new values. - update_mask=field_mask, - ) - print(updated_marks) - # [END add_marks_to_asset] - assert updated_marks.marks.keys() >= marks.keys() - - -def test_clear_from_asset(asset_name): - """Removes security marks from an asset.""" - # Make sure they are there first - test_add_to_asset(asset_name) - # [START clear_marks_asset] - from google.cloud import securitycenter - from google.protobuf import field_mask_pb2 - - # Create a new client. - client = securitycenter.SecurityCenterClient() - - # asset_name is the resource path for an asset that exists in CSCC. - # Its format is "organization/{organization_id}/assets/{asset_id} - # e.g.: - # asset_name = organizations/123123342/assets/12312321 - marks_name = "{}/securityMarks".format(asset_name) - - field_mask = field_mask_pb2.FieldMask(paths=["marks.key_a", "marks.key_b"]) - - updated_marks = client.update_security_marks( - { - "name": marks_name - # Note, no marks specified, so the specified values in - # the fields masks will be deleted. - }, - # If this field was left empty, all marks would be cleared. - update_mask=field_mask, - ) - print(updated_marks) - # [END clear_marks_asset] - assert "other" in updated_marks.marks - assert len(updated_marks.marks) == 1 - - -def test_delete_and_update_marks(asset_name): - """Updates and deletes security marks from an asset in the same call.""" - # Make sure they are there first - test_add_to_asset(asset_name) - # [START delete_and_update_marks] - from google.cloud import securitycenter - from google.protobuf import field_mask_pb2 - - client = securitycenter.SecurityCenterClient() - # asset_name is the resource path for an asset that exists in CSCC. - # Its format is "organization/{organization_id}/assets/{asset_id} - # e.g.: - # asset_name = organizations/123123342/assets/12312321 - marks_name = "{}/securityMarks".format(asset_name) - - field_mask = field_mask_pb2.FieldMask(paths=["marks.key_a", "marks.key_b"]) - marks = {"key_a": "new_value_for_a"} - - updated_marks = client.update_security_marks( - {"name": marks_name, "marks": marks}, update_mask=field_mask - ) - print(updated_marks) - # [END delete_and_update_marks] - assert updated_marks.marks == {"key_a": "new_value_for_a", "other": "other_val"} - - -def test_add_to_finding(finding_name): - """Adds security marks to a finding. """ - # [START add_marks_to_finding] - from google.cloud import securitycenter - from google.protobuf import field_mask_pb2 - - client = securitycenter.SecurityCenterClient() - # finding_name is the resource path for a finding that exists in CSCC. - # Its format is - # "organizations/{org_id}/sources/{source_id}/findings/{finding_id}" - # e.g.: - # finding_name = "organizations/1112/sources/1234/findings/findingid" - finding_marks_name = "{}/securityMarks".format(finding_name) - - # Notice the suffix after "marks." in the field mask matches the keys - # in marks. - field_mask = field_mask_pb2.FieldMask( - paths=["marks.finding_key_a", "marks.finding_key_b"] - ) - marks = {"finding_key_a": "value_a", "finding_key_b": "value_b"} - - updated_marks = client.update_security_marks( - {"name": finding_marks_name, "marks": marks}, update_mask=field_mask - ) - # [END add_marks_to_finding] - - assert updated_marks.marks == marks - - -def test_list_assets_with_query_marks(organization_id, asset_name): - """Lists assets with a filter on security marks. """ - test_add_to_asset(asset_name) - # [START demo_list_assets_with_security_marks] - from google.cloud import securitycenter - - client = securitycenter.SecurityCenterClient() - - # organization_id is the numeric ID of the organization. - # organization_id=1234567777 - org_name = "organizations/{org_id}".format(org_id=organization_id) - - marks_filter = 'security_marks.marks.key_a = "value_a"' - # Call the API and print results. - asset_iterator = client.list_assets(org_name, filter_=marks_filter) - - # Call the API and print results. - asset_iterator = client.list_assets(org_name, filter_=marks_filter) - for i, asset_result in enumerate(asset_iterator): - print(i, asset_result) - # [END demo_list_assets_with_security_marks] - assert i >= 0 - - -def test_list_findings_with_query_marks(source_name, finding_name): - """Lists findings with a filter on security marks.""" - # ensure marks are set on finding. - test_add_to_finding(finding_name) - i = -1 - # [START demo_list_findings_with_security_marks] - from google.cloud import securitycenter - - client = securitycenter.SecurityCenterClient() - - # source_name is the resource path for a source that has been - # created previously (you can use list_sources to find a specific one). - # Its format is: - # source_name = "organizations/{organization_id}/sources/{source_id}" - # e.g.: - # source_name = "organizations/111122222444/sources/1234" - marks_filter = 'NOT security_marks.marks.finding_key_a="value_a"' - - # Call the API and print results. - finding_iterator = client.list_findings(source_name, filter_=marks_filter) - for i, finding_result in enumerate(finding_iterator): - print(i, finding_result) - # [END demo_list_findings_with_security_marks] - # one finding should have been updated with keys, and one should be - # untouched. - assert i == 0 From c70d7904425ae5ac252ffa7317ec6d08234a6c27 Mon Sep 17 00:00:00 2001 From: hannah-tsai <64800225+hannah-tsai@users.noreply.github.com> Date: Wed, 22 Jul 2020 23:08:03 -0700 Subject: [PATCH 6/8] docs: Update Security Command Center UpdateNotificationConfig sample, adding filter to mutable field (#39) Fixes b/155346619 Add "filter" to mutable fields for UpdateNotificationConfig. --- samples/snippets/snippets_notification_configs.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/samples/snippets/snippets_notification_configs.py b/samples/snippets/snippets_notification_configs.py index acc4b8ba..09d284e9 100644 --- a/samples/snippets/snippets_notification_configs.py +++ b/samples/snippets/snippets_notification_configs.py @@ -120,15 +120,19 @@ def update_notification_config(organization_id, notification_config_id, pubsub_t ) updated_description = "New updated description" + updated_filter = 'state = "INACTIVE"' # Only description and pubsub_topic can be updated. - field_mask = field_mask_pb2.FieldMask(paths=["description", "pubsub_topic"]) + field_mask = field_mask_pb2.FieldMask( + paths=["description", "pubsub_topic", "streaming_config.fitler"] + ) updated_notification_config = client.update_notification_config( { "name": notification_config_name, "description": updated_description, "pubsub_topic": pubsub_topic, + "streaming_config": {"filter": updated_filter}, }, update_mask=field_mask, ) From 80494a915ca33d260862694be889b817869ff01a Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 10 Sep 2020 10:06:02 -0700 Subject: [PATCH 7/8] feat: add field severity to findings; update retry configs (#53) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/d5a3b809-9df8-4d37-93b2-9714b500d6ce/targets - [ ] To automatically regenerate this PR, check this box. PiperOrigin-RevId: 324294521 Source-Link: https://github.com/googleapis/googleapis/commit/868615a5c1c1059c636bb3d82a555edb1d5a251e PiperOrigin-RevId: 324035013 Source-Link: https://github.com/googleapis/googleapis/commit/8cda089accaead072caea33c5081be8a4b8f9ea7 PiperOrigin-RevId: 323803770 Source-Link: https://github.com/googleapis/googleapis/commit/706053bbfb3f16ef752e513c2898a1f26cdd8e41 PiperOrigin-RevId: 323795963 Source-Link: https://github.com/googleapis/googleapis/commit/c1b9289be1be876ef494f31c9662bc49b4f906e0 PiperOrigin-RevId: 323657371 Source-Link: https://github.com/googleapis/googleapis/commit/1907f0fdbd1c51e62d8452a4007bf2134a8bd4c2 PiperOrigin-RevId: 323630732 Source-Link: https://github.com/googleapis/googleapis/commit/74e8cf85f23d3cef04fcc75b4f59a21a2b41886c PiperOrigin-RevId: 323605868 Source-Link: https://github.com/googleapis/googleapis/commit/0c6a73081373ff3ff3d470efe554f2f1efd64041 PiperOrigin-RevId: 323472217 Source-Link: https://github.com/googleapis/googleapis/commit/6a813acf535e4746fa4a135ce23547bb6425c26d PiperOrigin-RevId: 323062460 Source-Link: https://github.com/googleapis/googleapis/commit/599ede9ebdeb33a91be48748f5f83ec13e7e692c PiperOrigin-RevId: 322867095 Source-Link: https://github.com/googleapis/googleapis/commit/e26e1839a45445d13cd45b1be3b1523defb72fee PiperOrigin-RevId: 321179885 Source-Link: https://github.com/googleapis/googleapis/commit/9362f58401cfe3b463b75a18d134bb818ad4dcb2 PiperOrigin-RevId: 321179822 Source-Link: https://github.com/googleapis/googleapis/commit/afa7f44f57e6ac33cf060d1764c9940dd404f725 --- .github/snippet-bot.yml | 0 .gitignore | 3 +- .kokoro/build.sh | 8 +- .kokoro/docker/docs/Dockerfile | 98 ++ .kokoro/docker/docs/fetch_gpg_keys.sh | 45 + .kokoro/docs/common.cfg | 21 +- .kokoro/docs/docs-presubmit.cfg | 17 + .kokoro/publish-docs.sh | 39 +- .kokoro/trampoline_v2.sh | 487 +++++++ .trampolinerc | 51 + docs/conf.py | 13 +- docs/gapic/v1beta1/api.rst | 4 +- docs/gapic/v1beta1/types.rst | 4 +- .../gapic/security_center_client.py | 1268 ++++++++--------- .../gapic/security_center_client_config.py | 169 ++- .../security_center_grpc_transport.py | 114 +- .../securitycenter_v1/proto/asset_pb2.py | 2 +- .../securitycenter_v1/proto/finding.proto | 8 +- .../securitycenter_v1/proto/finding_pb2.py | 12 +- .../proto/notification_config_pb2.py | 2 +- .../proto/notification_message_pb2.py | 2 +- .../proto/organization_settings_pb2.py | 2 +- .../securitycenter_v1/proto/resource_pb2.py | 2 +- .../proto/run_asset_discovery_response_pb2.py | 2 +- .../proto/security_marks_pb2.py | 2 +- .../proto/securitycenter_service_pb2.py | 2 +- .../securitycenter_v1/proto/source_pb2.py | 2 +- .../gapic/security_center_client_config.py | 135 +- .../securitycenter_v1beta1/proto/asset.proto | 44 +- .../securitycenter_v1beta1/proto/asset_pb2.py | 66 +- .../proto/finding.proto | 42 +- .../proto/finding_pb2.py | 41 +- .../proto/organization_settings.proto | 7 +- .../proto/organization_settings_pb2.py | 6 +- .../proto/run_asset_discovery_response.proto | 3 +- .../proto/run_asset_discovery_response_pb2.py | 2 +- .../proto/security_marks.proto | 9 +- .../proto/security_marks_pb2.py | 10 +- .../proto/securitycenter_service.proto | 3 +- .../proto/securitycenter_service_pb2.py | 2 +- .../securitycenter_v1beta1/proto/source.proto | 7 +- .../proto/source_pb2.py | 12 +- .../securitycenter_v1p1beta1/gapic/enums.py | 18 + .../gapic/security_center_client.py | 13 +- .../gapic/security_center_client_config.py | 155 +- .../proto/asset_pb2.py | 2 +- .../proto/finding.proto | 29 +- .../proto/finding_pb2.py | 104 +- .../proto/notification_config_pb2.py | 2 +- .../proto/notification_message_pb2.py | 2 +- .../proto/organization_settings_pb2.py | 2 +- .../proto/resource_pb2.py | 2 +- .../proto/run_asset_discovery_response_pb2.py | 2 +- .../proto/security_marks_pb2.py | 2 +- .../proto/securitycenter_service.proto | 111 +- .../proto/securitycenter_service_pb2.py | 93 +- .../proto/securitycenter_service_pb2_grpc.py | 6 +- .../proto/source_pb2.py | 2 +- noxfile.py | 39 + samples/snippets/noxfile.py | 26 +- scripts/decrypt-secrets.sh | 15 +- synth.metadata | 14 +- .../v1/test_security_center_client_v1.py | 380 ++--- .../test_security_center_client_v1beta1.py | 12 +- 64 files changed, 2401 insertions(+), 1398 deletions(-) create mode 100644 .github/snippet-bot.yml create mode 100644 .kokoro/docker/docs/Dockerfile create mode 100755 .kokoro/docker/docs/fetch_gpg_keys.sh create mode 100644 .kokoro/docs/docs-presubmit.cfg create mode 100755 .kokoro/trampoline_v2.sh create mode 100644 .trampolinerc diff --git a/.github/snippet-bot.yml b/.github/snippet-bot.yml new file mode 100644 index 00000000..e69de29b diff --git a/.gitignore b/.gitignore index b87e1ed5..b9daa52f 100644 --- a/.gitignore +++ b/.gitignore @@ -46,6 +46,7 @@ pip-log.txt # Built documentation docs/_build bigquery/docs/generated +docs.metadata # Virtual environment env/ @@ -57,4 +58,4 @@ system_tests/local_test_setup # Make sure a generated file isn't accidentally committed. pylintrc -pylintrc.test \ No newline at end of file +pylintrc.test diff --git a/.kokoro/build.sh b/.kokoro/build.sh index 0f29e059..662b06bc 100755 --- a/.kokoro/build.sh +++ b/.kokoro/build.sh @@ -36,4 +36,10 @@ python3.6 -m pip uninstall --yes --quiet nox-automation python3.6 -m pip install --upgrade --quiet nox python3.6 -m nox --version -python3.6 -m nox +# If NOX_SESSION is set, it only runs the specified session, +# otherwise run all the sessions. +if [[ -n "${NOX_SESSION:-}" ]]; then + python3.6 -m nox -s "${NOX_SESSION:-}" +else + python3.6 -m nox +fi diff --git a/.kokoro/docker/docs/Dockerfile b/.kokoro/docker/docs/Dockerfile new file mode 100644 index 00000000..412b0b56 --- /dev/null +++ b/.kokoro/docker/docs/Dockerfile @@ -0,0 +1,98 @@ +# 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. + +from ubuntu:20.04 + +ENV DEBIAN_FRONTEND noninteractive + +# Ensure local Python is preferred over distribution Python. +ENV PATH /usr/local/bin:$PATH + +# Install dependencies. +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + apt-transport-https \ + build-essential \ + ca-certificates \ + curl \ + dirmngr \ + git \ + gpg-agent \ + graphviz \ + libbz2-dev \ + libdb5.3-dev \ + libexpat1-dev \ + libffi-dev \ + liblzma-dev \ + libreadline-dev \ + libsnappy-dev \ + libssl-dev \ + libsqlite3-dev \ + portaudio19-dev \ + redis-server \ + software-properties-common \ + ssh \ + sudo \ + tcl \ + tcl-dev \ + tk \ + tk-dev \ + uuid-dev \ + wget \ + zlib1g-dev \ + && add-apt-repository universe \ + && apt-get update \ + && apt-get -y install jq \ + && apt-get clean autoclean \ + && apt-get autoremove -y \ + && rm -rf /var/lib/apt/lists/* \ + && rm -f /var/cache/apt/archives/*.deb + + +COPY fetch_gpg_keys.sh /tmp +# Install the desired versions of Python. +RUN set -ex \ + && export GNUPGHOME="$(mktemp -d)" \ + && echo "disable-ipv6" >> "${GNUPGHOME}/dirmngr.conf" \ + && /tmp/fetch_gpg_keys.sh \ + && for PYTHON_VERSION in 3.7.8 3.8.5; do \ + wget --no-check-certificate -O python-${PYTHON_VERSION}.tar.xz "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz" \ + && wget --no-check-certificate -O python-${PYTHON_VERSION}.tar.xz.asc "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz.asc" \ + && gpg --batch --verify python-${PYTHON_VERSION}.tar.xz.asc python-${PYTHON_VERSION}.tar.xz \ + && rm -r python-${PYTHON_VERSION}.tar.xz.asc \ + && mkdir -p /usr/src/python-${PYTHON_VERSION} \ + && tar -xJC /usr/src/python-${PYTHON_VERSION} --strip-components=1 -f python-${PYTHON_VERSION}.tar.xz \ + && rm python-${PYTHON_VERSION}.tar.xz \ + && cd /usr/src/python-${PYTHON_VERSION} \ + && ./configure \ + --enable-shared \ + # This works only on Python 2.7 and throws a warning on every other + # version, but seems otherwise harmless. + --enable-unicode=ucs4 \ + --with-system-ffi \ + --without-ensurepip \ + && make -j$(nproc) \ + && make install \ + && ldconfig \ + ; done \ + && rm -rf "${GNUPGHOME}" \ + && rm -rf /usr/src/python* \ + && rm -rf ~/.cache/ + +RUN wget -O /tmp/get-pip.py 'https://bootstrap.pypa.io/get-pip.py' \ + && python3.7 /tmp/get-pip.py \ + && python3.8 /tmp/get-pip.py \ + && rm /tmp/get-pip.py + +CMD ["python3.7"] diff --git a/.kokoro/docker/docs/fetch_gpg_keys.sh b/.kokoro/docker/docs/fetch_gpg_keys.sh new file mode 100755 index 00000000..d653dd86 --- /dev/null +++ b/.kokoro/docker/docs/fetch_gpg_keys.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# 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. + +# A script to fetch gpg keys with retry. +# Avoid jinja parsing the file. +# + +function retry { + if [[ "${#}" -le 1 ]]; then + echo "Usage: ${0} retry_count commands.." + exit 1 + fi + local retries=${1} + local command="${@:2}" + until [[ "${retries}" -le 0 ]]; do + $command && return 0 + if [[ $? -ne 0 ]]; then + echo "command failed, retrying" + ((retries--)) + fi + done + return 1 +} + +# 3.6.9, 3.7.5 (Ned Deily) +retry 3 gpg --keyserver ha.pool.sks-keyservers.net --recv-keys \ + 0D96DF4D4110E5C43FBFB17F2D347EA6AA65421D + +# 3.8.0 (Łukasz Langa) +retry 3 gpg --keyserver ha.pool.sks-keyservers.net --recv-keys \ + E3FF2839C048B25C084DEBE9B26995E310250568 + +# diff --git a/.kokoro/docs/common.cfg b/.kokoro/docs/common.cfg index 28f1b005..571f0e74 100644 --- a/.kokoro/docs/common.cfg +++ b/.kokoro/docs/common.cfg @@ -11,12 +11,12 @@ action { gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" # Use the trampoline script to run in docker. -build_file: "python-securitycenter/.kokoro/trampoline.sh" +build_file: "python-securitycenter/.kokoro/trampoline_v2.sh" # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/python-multi" + value: "gcr.io/cloud-devrel-kokoro-resources/python-lib-docs" } env_vars: { key: "TRAMPOLINE_BUILD_FILE" @@ -28,6 +28,23 @@ env_vars: { value: "docs-staging" } +env_vars: { + key: "V2_STAGING_BUCKET" + value: "docs-staging-v2-staging" +} + +# It will upload the docker image after successful builds. +env_vars: { + key: "TRAMPOLINE_IMAGE_UPLOAD" + value: "true" +} + +# It will always build the docker image. +env_vars: { + key: "TRAMPOLINE_DOCKERFILE" + value: ".kokoro/docker/docs/Dockerfile" +} + # Fetch the token needed for reporting release status to GitHub before_action { fetch_keystore { diff --git a/.kokoro/docs/docs-presubmit.cfg b/.kokoro/docs/docs-presubmit.cfg new file mode 100644 index 00000000..11181078 --- /dev/null +++ b/.kokoro/docs/docs-presubmit.cfg @@ -0,0 +1,17 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "STAGING_BUCKET" + value: "gcloud-python-test" +} + +env_vars: { + key: "V2_STAGING_BUCKET" + value: "gcloud-python-test" +} + +# We only upload the image in the main `docs` build. +env_vars: { + key: "TRAMPOLINE_IMAGE_UPLOAD" + value: "false" +} diff --git a/.kokoro/publish-docs.sh b/.kokoro/publish-docs.sh index ff7f2730..8acb14e8 100755 --- a/.kokoro/publish-docs.sh +++ b/.kokoro/publish-docs.sh @@ -18,26 +18,16 @@ set -eo pipefail # Disable buffering, so that the logs stream through. export PYTHONUNBUFFERED=1 -cd github/python-securitycenter - -# Remove old nox -python3.6 -m pip uninstall --yes --quiet nox-automation +export PATH="${HOME}/.local/bin:${PATH}" # Install nox -python3.6 -m pip install --upgrade --quiet nox -python3.6 -m nox --version +python3 -m pip install --user --upgrade --quiet nox +python3 -m nox --version # build docs nox -s docs -python3 -m pip install gcp-docuploader - -# install a json parser -sudo apt-get update -sudo apt-get -y install software-properties-common -sudo add-apt-repository universe -sudo apt-get update -sudo apt-get -y install jq +python3 -m pip install --user gcp-docuploader # create metadata python3 -m docuploader create-metadata \ @@ -52,4 +42,23 @@ python3 -m docuploader create-metadata \ cat docs.metadata # upload docs -python3 -m docuploader upload docs/_build/html --metadata-file docs.metadata --staging-bucket docs-staging +python3 -m docuploader upload docs/_build/html --metadata-file docs.metadata --staging-bucket "${STAGING_BUCKET}" + + +# docfx yaml files +nox -s docfx + +# create metadata. +python3 -m docuploader create-metadata \ + --name=$(jq --raw-output '.name // empty' .repo-metadata.json) \ + --version=$(python3 setup.py --version) \ + --language=$(jq --raw-output '.language // empty' .repo-metadata.json) \ + --distribution-name=$(python3 setup.py --name) \ + --product-page=$(jq --raw-output '.product_documentation // empty' .repo-metadata.json) \ + --github-repository=$(jq --raw-output '.repo // empty' .repo-metadata.json) \ + --issue-tracker=$(jq --raw-output '.issue_tracker // empty' .repo-metadata.json) + +cat docs.metadata + +# upload docs +python3 -m docuploader upload docs/_build/html/docfx_yaml --metadata-file docs.metadata --destination-prefix docfx --staging-bucket "${V2_STAGING_BUCKET}" diff --git a/.kokoro/trampoline_v2.sh b/.kokoro/trampoline_v2.sh new file mode 100755 index 00000000..719bcd5b --- /dev/null +++ b/.kokoro/trampoline_v2.sh @@ -0,0 +1,487 @@ +#!/usr/bin/env bash +# 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. + +# trampoline_v2.sh +# +# This script does 3 things. +# +# 1. Prepare the Docker image for the test +# 2. Run the Docker with appropriate flags to run the test +# 3. Upload the newly built Docker image +# +# in a way that is somewhat compatible with trampoline_v1. +# +# To run this script, first download few files from gcs to /dev/shm. +# (/dev/shm is passed into the container as KOKORO_GFILE_DIR). +# +# gsutil cp gs://cloud-devrel-kokoro-resources/python-docs-samples/secrets_viewer_service_account.json /dev/shm +# gsutil cp gs://cloud-devrel-kokoro-resources/python-docs-samples/automl_secrets.txt /dev/shm +# +# Then run the script. +# .kokoro/trampoline_v2.sh +# +# These environment variables are required: +# TRAMPOLINE_IMAGE: The docker image to use. +# TRAMPOLINE_DOCKERFILE: The location of the Dockerfile. +# +# You can optionally change these environment variables: +# TRAMPOLINE_IMAGE_UPLOAD: +# (true|false): Whether to upload the Docker image after the +# successful builds. +# TRAMPOLINE_BUILD_FILE: The script to run in the docker container. +# TRAMPOLINE_WORKSPACE: The workspace path in the docker container. +# Defaults to /workspace. +# Potentially there are some repo specific envvars in .trampolinerc in +# the project root. + + +set -euo pipefail + +TRAMPOLINE_VERSION="2.0.5" + +if command -v tput >/dev/null && [[ -n "${TERM:-}" ]]; then + readonly IO_COLOR_RED="$(tput setaf 1)" + readonly IO_COLOR_GREEN="$(tput setaf 2)" + readonly IO_COLOR_YELLOW="$(tput setaf 3)" + readonly IO_COLOR_RESET="$(tput sgr0)" +else + readonly IO_COLOR_RED="" + readonly IO_COLOR_GREEN="" + readonly IO_COLOR_YELLOW="" + readonly IO_COLOR_RESET="" +fi + +function function_exists { + [ $(LC_ALL=C type -t $1)"" == "function" ] +} + +# Logs a message using the given color. The first argument must be one +# of the IO_COLOR_* variables defined above, such as +# "${IO_COLOR_YELLOW}". The remaining arguments will be logged in the +# given color. The log message will also have an RFC-3339 timestamp +# prepended (in UTC). You can disable the color output by setting +# TERM=vt100. +function log_impl() { + local color="$1" + shift + local timestamp="$(date -u "+%Y-%m-%dT%H:%M:%SZ")" + echo "================================================================" + echo "${color}${timestamp}:" "$@" "${IO_COLOR_RESET}" + echo "================================================================" +} + +# Logs the given message with normal coloring and a timestamp. +function log() { + log_impl "${IO_COLOR_RESET}" "$@" +} + +# Logs the given message in green with a timestamp. +function log_green() { + log_impl "${IO_COLOR_GREEN}" "$@" +} + +# Logs the given message in yellow with a timestamp. +function log_yellow() { + log_impl "${IO_COLOR_YELLOW}" "$@" +} + +# Logs the given message in red with a timestamp. +function log_red() { + log_impl "${IO_COLOR_RED}" "$@" +} + +readonly tmpdir=$(mktemp -d -t ci-XXXXXXXX) +readonly tmphome="${tmpdir}/h" +mkdir -p "${tmphome}" + +function cleanup() { + rm -rf "${tmpdir}" +} +trap cleanup EXIT + +RUNNING_IN_CI="${RUNNING_IN_CI:-false}" + +# The workspace in the container, defaults to /workspace. +TRAMPOLINE_WORKSPACE="${TRAMPOLINE_WORKSPACE:-/workspace}" + +pass_down_envvars=( + # TRAMPOLINE_V2 variables. + # Tells scripts whether they are running as part of CI or not. + "RUNNING_IN_CI" + # Indicates which CI system we're in. + "TRAMPOLINE_CI" + # Indicates the version of the script. + "TRAMPOLINE_VERSION" +) + +log_yellow "Building with Trampoline ${TRAMPOLINE_VERSION}" + +# Detect which CI systems we're in. If we're in any of the CI systems +# we support, `RUNNING_IN_CI` will be true and `TRAMPOLINE_CI` will be +# the name of the CI system. Both envvars will be passing down to the +# container for telling which CI system we're in. +if [[ -n "${KOKORO_BUILD_ID:-}" ]]; then + # descriptive env var for indicating it's on CI. + RUNNING_IN_CI="true" + TRAMPOLINE_CI="kokoro" + if [[ "${TRAMPOLINE_USE_LEGACY_SERVICE_ACCOUNT:-}" == "true" ]]; then + if [[ ! -f "${KOKORO_GFILE_DIR}/kokoro-trampoline.service-account.json" ]]; then + log_red "${KOKORO_GFILE_DIR}/kokoro-trampoline.service-account.json does not exist. Did you forget to mount cloud-devrel-kokoro-resources/trampoline? Aborting." + exit 1 + fi + # This service account will be activated later. + TRAMPOLINE_SERVICE_ACCOUNT="${KOKORO_GFILE_DIR}/kokoro-trampoline.service-account.json" + else + if [[ "${TRAMPOLINE_VERBOSE:-}" == "true" ]]; then + gcloud auth list + fi + log_yellow "Configuring Container Registry access" + gcloud auth configure-docker --quiet + fi + pass_down_envvars+=( + # KOKORO dynamic variables. + "KOKORO_BUILD_NUMBER" + "KOKORO_BUILD_ID" + "KOKORO_JOB_NAME" + "KOKORO_GIT_COMMIT" + "KOKORO_GITHUB_COMMIT" + "KOKORO_GITHUB_PULL_REQUEST_NUMBER" + "KOKORO_GITHUB_PULL_REQUEST_COMMIT" + # For Build Cop Bot + "KOKORO_GITHUB_COMMIT_URL" + "KOKORO_GITHUB_PULL_REQUEST_URL" + ) +elif [[ "${TRAVIS:-}" == "true" ]]; then + RUNNING_IN_CI="true" + TRAMPOLINE_CI="travis" + pass_down_envvars+=( + "TRAVIS_BRANCH" + "TRAVIS_BUILD_ID" + "TRAVIS_BUILD_NUMBER" + "TRAVIS_BUILD_WEB_URL" + "TRAVIS_COMMIT" + "TRAVIS_COMMIT_MESSAGE" + "TRAVIS_COMMIT_RANGE" + "TRAVIS_JOB_NAME" + "TRAVIS_JOB_NUMBER" + "TRAVIS_JOB_WEB_URL" + "TRAVIS_PULL_REQUEST" + "TRAVIS_PULL_REQUEST_BRANCH" + "TRAVIS_PULL_REQUEST_SHA" + "TRAVIS_PULL_REQUEST_SLUG" + "TRAVIS_REPO_SLUG" + "TRAVIS_SECURE_ENV_VARS" + "TRAVIS_TAG" + ) +elif [[ -n "${GITHUB_RUN_ID:-}" ]]; then + RUNNING_IN_CI="true" + TRAMPOLINE_CI="github-workflow" + pass_down_envvars+=( + "GITHUB_WORKFLOW" + "GITHUB_RUN_ID" + "GITHUB_RUN_NUMBER" + "GITHUB_ACTION" + "GITHUB_ACTIONS" + "GITHUB_ACTOR" + "GITHUB_REPOSITORY" + "GITHUB_EVENT_NAME" + "GITHUB_EVENT_PATH" + "GITHUB_SHA" + "GITHUB_REF" + "GITHUB_HEAD_REF" + "GITHUB_BASE_REF" + ) +elif [[ "${CIRCLECI:-}" == "true" ]]; then + RUNNING_IN_CI="true" + TRAMPOLINE_CI="circleci" + pass_down_envvars+=( + "CIRCLE_BRANCH" + "CIRCLE_BUILD_NUM" + "CIRCLE_BUILD_URL" + "CIRCLE_COMPARE_URL" + "CIRCLE_JOB" + "CIRCLE_NODE_INDEX" + "CIRCLE_NODE_TOTAL" + "CIRCLE_PREVIOUS_BUILD_NUM" + "CIRCLE_PROJECT_REPONAME" + "CIRCLE_PROJECT_USERNAME" + "CIRCLE_REPOSITORY_URL" + "CIRCLE_SHA1" + "CIRCLE_STAGE" + "CIRCLE_USERNAME" + "CIRCLE_WORKFLOW_ID" + "CIRCLE_WORKFLOW_JOB_ID" + "CIRCLE_WORKFLOW_UPSTREAM_JOB_IDS" + "CIRCLE_WORKFLOW_WORKSPACE_ID" + ) +fi + +# Configure the service account for pulling the docker image. +function repo_root() { + local dir="$1" + while [[ ! -d "${dir}/.git" ]]; do + dir="$(dirname "$dir")" + done + echo "${dir}" +} + +# Detect the project root. In CI builds, we assume the script is in +# the git tree and traverse from there, otherwise, traverse from `pwd` +# to find `.git` directory. +if [[ "${RUNNING_IN_CI:-}" == "true" ]]; then + PROGRAM_PATH="$(realpath "$0")" + PROGRAM_DIR="$(dirname "${PROGRAM_PATH}")" + PROJECT_ROOT="$(repo_root "${PROGRAM_DIR}")" +else + PROJECT_ROOT="$(repo_root $(pwd))" +fi + +log_yellow "Changing to the project root: ${PROJECT_ROOT}." +cd "${PROJECT_ROOT}" + +# To support relative path for `TRAMPOLINE_SERVICE_ACCOUNT`, we need +# to use this environment variable in `PROJECT_ROOT`. +if [[ -n "${TRAMPOLINE_SERVICE_ACCOUNT:-}" ]]; then + + mkdir -p "${tmpdir}/gcloud" + gcloud_config_dir="${tmpdir}/gcloud" + + log_yellow "Using isolated gcloud config: ${gcloud_config_dir}." + export CLOUDSDK_CONFIG="${gcloud_config_dir}" + + log_yellow "Using ${TRAMPOLINE_SERVICE_ACCOUNT} for authentication." + gcloud auth activate-service-account \ + --key-file "${TRAMPOLINE_SERVICE_ACCOUNT}" + log_yellow "Configuring Container Registry access" + gcloud auth configure-docker --quiet +fi + +required_envvars=( + # The basic trampoline configurations. + "TRAMPOLINE_IMAGE" + "TRAMPOLINE_BUILD_FILE" +) + +if [[ -f "${PROJECT_ROOT}/.trampolinerc" ]]; then + source "${PROJECT_ROOT}/.trampolinerc" +fi + +log_yellow "Checking environment variables." +for e in "${required_envvars[@]}" +do + if [[ -z "${!e:-}" ]]; then + log "Missing ${e} env var. Aborting." + exit 1 + fi +done + +# We want to support legacy style TRAMPOLINE_BUILD_FILE used with V1 +# script: e.g. "github/repo-name/.kokoro/run_tests.sh" +TRAMPOLINE_BUILD_FILE="${TRAMPOLINE_BUILD_FILE#github/*/}" +log_yellow "Using TRAMPOLINE_BUILD_FILE: ${TRAMPOLINE_BUILD_FILE}" + +# ignore error on docker operations and test execution +set +e + +log_yellow "Preparing Docker image." +# We only download the docker image in CI builds. +if [[ "${RUNNING_IN_CI:-}" == "true" ]]; then + # Download the docker image specified by `TRAMPOLINE_IMAGE` + + # We may want to add --max-concurrent-downloads flag. + + log_yellow "Start pulling the Docker image: ${TRAMPOLINE_IMAGE}." + if docker pull "${TRAMPOLINE_IMAGE}"; then + log_green "Finished pulling the Docker image: ${TRAMPOLINE_IMAGE}." + has_image="true" + else + log_red "Failed pulling the Docker image: ${TRAMPOLINE_IMAGE}." + has_image="false" + fi +else + # For local run, check if we have the image. + if docker images "${TRAMPOLINE_IMAGE}:latest" | grep "${TRAMPOLINE_IMAGE}"; then + has_image="true" + else + has_image="false" + fi +fi + + +# The default user for a Docker container has uid 0 (root). To avoid +# creating root-owned files in the build directory we tell docker to +# use the current user ID. +user_uid="$(id -u)" +user_gid="$(id -g)" +user_name="$(id -un)" + +# To allow docker in docker, we add the user to the docker group in +# the host os. +docker_gid=$(cut -d: -f3 < <(getent group docker)) + +update_cache="false" +if [[ "${TRAMPOLINE_DOCKERFILE:-none}" != "none" ]]; then + # Build the Docker image from the source. + context_dir=$(dirname "${TRAMPOLINE_DOCKERFILE}") + docker_build_flags=( + "-f" "${TRAMPOLINE_DOCKERFILE}" + "-t" "${TRAMPOLINE_IMAGE}" + "--build-arg" "UID=${user_uid}" + "--build-arg" "USERNAME=${user_name}" + ) + if [[ "${has_image}" == "true" ]]; then + docker_build_flags+=("--cache-from" "${TRAMPOLINE_IMAGE}") + fi + + log_yellow "Start building the docker image." + if [[ "${TRAMPOLINE_VERBOSE:-false}" == "true" ]]; then + echo "docker build" "${docker_build_flags[@]}" "${context_dir}" + fi + + # ON CI systems, we want to suppress docker build logs, only + # output the logs when it fails. + if [[ "${RUNNING_IN_CI:-}" == "true" ]]; then + if docker build "${docker_build_flags[@]}" "${context_dir}" \ + > "${tmpdir}/docker_build.log" 2>&1; then + if [[ "${TRAMPOLINE_VERBOSE:-}" == "true" ]]; then + cat "${tmpdir}/docker_build.log" + fi + + log_green "Finished building the docker image." + update_cache="true" + else + log_red "Failed to build the Docker image, aborting." + log_yellow "Dumping the build logs:" + cat "${tmpdir}/docker_build.log" + exit 1 + fi + else + if docker build "${docker_build_flags[@]}" "${context_dir}"; then + log_green "Finished building the docker image." + update_cache="true" + else + log_red "Failed to build the Docker image, aborting." + exit 1 + fi + fi +else + if [[ "${has_image}" != "true" ]]; then + log_red "We do not have ${TRAMPOLINE_IMAGE} locally, aborting." + exit 1 + fi +fi + +# We use an array for the flags so they are easier to document. +docker_flags=( + # Remove the container after it exists. + "--rm" + + # Use the host network. + "--network=host" + + # Run in priviledged mode. We are not using docker for sandboxing or + # isolation, just for packaging our dev tools. + "--privileged" + + # Run the docker script with the user id. Because the docker image gets to + # write in ${PWD} you typically want this to be your user id. + # To allow docker in docker, we need to use docker gid on the host. + "--user" "${user_uid}:${docker_gid}" + + # Pass down the USER. + "--env" "USER=${user_name}" + + # Mount the project directory inside the Docker container. + "--volume" "${PROJECT_ROOT}:${TRAMPOLINE_WORKSPACE}" + "--workdir" "${TRAMPOLINE_WORKSPACE}" + "--env" "PROJECT_ROOT=${TRAMPOLINE_WORKSPACE}" + + # Mount the temporary home directory. + "--volume" "${tmphome}:/h" + "--env" "HOME=/h" + + # Allow docker in docker. + "--volume" "/var/run/docker.sock:/var/run/docker.sock" + + # Mount the /tmp so that docker in docker can mount the files + # there correctly. + "--volume" "/tmp:/tmp" + # Pass down the KOKORO_GFILE_DIR and KOKORO_KEYSTORE_DIR + # TODO(tmatsuo): This part is not portable. + "--env" "TRAMPOLINE_SECRET_DIR=/secrets" + "--volume" "${KOKORO_GFILE_DIR:-/dev/shm}:/secrets/gfile" + "--env" "KOKORO_GFILE_DIR=/secrets/gfile" + "--volume" "${KOKORO_KEYSTORE_DIR:-/dev/shm}:/secrets/keystore" + "--env" "KOKORO_KEYSTORE_DIR=/secrets/keystore" +) + +# Add an option for nicer output if the build gets a tty. +if [[ -t 0 ]]; then + docker_flags+=("-it") +fi + +# Passing down env vars +for e in "${pass_down_envvars[@]}" +do + if [[ -n "${!e:-}" ]]; then + docker_flags+=("--env" "${e}=${!e}") + fi +done + +# If arguments are given, all arguments will become the commands run +# in the container, otherwise run TRAMPOLINE_BUILD_FILE. +if [[ $# -ge 1 ]]; then + log_yellow "Running the given commands '" "${@:1}" "' in the container." + readonly commands=("${@:1}") + if [[ "${TRAMPOLINE_VERBOSE:-}" == "true" ]]; then + echo docker run "${docker_flags[@]}" "${TRAMPOLINE_IMAGE}" "${commands[@]}" + fi + docker run "${docker_flags[@]}" "${TRAMPOLINE_IMAGE}" "${commands[@]}" +else + log_yellow "Running the tests in a Docker container." + docker_flags+=("--entrypoint=${TRAMPOLINE_BUILD_FILE}") + if [[ "${TRAMPOLINE_VERBOSE:-}" == "true" ]]; then + echo docker run "${docker_flags[@]}" "${TRAMPOLINE_IMAGE}" + fi + docker run "${docker_flags[@]}" "${TRAMPOLINE_IMAGE}" +fi + + +test_retval=$? + +if [[ ${test_retval} -eq 0 ]]; then + log_green "Build finished with ${test_retval}" +else + log_red "Build finished with ${test_retval}" +fi + +# Only upload it when the test passes. +if [[ "${update_cache}" == "true" ]] && \ + [[ $test_retval == 0 ]] && \ + [[ "${TRAMPOLINE_IMAGE_UPLOAD:-false}" == "true" ]]; then + log_yellow "Uploading the Docker image." + if docker push "${TRAMPOLINE_IMAGE}"; then + log_green "Finished uploading the Docker image." + else + log_red "Failed uploading the Docker image." + fi + # Call trampoline_after_upload_hook if it's defined. + if function_exists trampoline_after_upload_hook; then + trampoline_after_upload_hook + fi + +fi + +exit "${test_retval}" diff --git a/.trampolinerc b/.trampolinerc new file mode 100644 index 00000000..995ee291 --- /dev/null +++ b/.trampolinerc @@ -0,0 +1,51 @@ +# 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. + +# Template for .trampolinerc + +# Add required env vars here. +required_envvars+=( + "STAGING_BUCKET" + "V2_STAGING_BUCKET" +) + +# Add env vars which are passed down into the container here. +pass_down_envvars+=( + "STAGING_BUCKET" + "V2_STAGING_BUCKET" +) + +# Prevent unintentional override on the default image. +if [[ "${TRAMPOLINE_IMAGE_UPLOAD:-false}" == "true" ]] && \ + [[ -z "${TRAMPOLINE_IMAGE:-}" ]]; then + echo "Please set TRAMPOLINE_IMAGE if you want to upload the Docker image." + exit 1 +fi + +# Define the default value if it makes sense. +if [[ -z "${TRAMPOLINE_IMAGE_UPLOAD:-}" ]]; then + TRAMPOLINE_IMAGE_UPLOAD="" +fi + +if [[ -z "${TRAMPOLINE_IMAGE:-}" ]]; then + TRAMPOLINE_IMAGE="" +fi + +if [[ -z "${TRAMPOLINE_DOCKERFILE:-}" ]]; then + TRAMPOLINE_DOCKERFILE="" +fi + +if [[ -z "${TRAMPOLINE_BUILD_FILE:-}" ]]; then + TRAMPOLINE_BUILD_FILE="" +fi diff --git a/docs/conf.py b/docs/conf.py index 475bfeb1..7341e8bd 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -20,12 +20,16 @@ # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath("..")) +# For plugins that can not read conf.py. +# See also: https://github.com/docascode/sphinx-docfx-yaml/issues/85 +sys.path.insert(0, os.path.abspath(".")) + __version__ = "" # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -needs_sphinx = "1.6.3" +needs_sphinx = "1.5.5" # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom @@ -90,7 +94,12 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ["_build"] +exclude_patterns = [ + "_build", + "samples/AUTHORING_GUIDE.md", + "samples/CONTRIBUTING.md", + "samples/snippets/README.rst", +] # The reST default role (used for this markup: `text`) to use for all # documents. diff --git a/docs/gapic/v1beta1/api.rst b/docs/gapic/v1beta1/api.rst index 5bf656fe..89fdb487 100644 --- a/docs/gapic/v1beta1/api.rst +++ b/docs/gapic/v1beta1/api.rst @@ -1,5 +1,5 @@ -Client for Cloud Security Command Center API -============================================ +Client for Security Command Center API +====================================== .. automodule:: google.cloud.securitycenter_v1beta1 :members: diff --git a/docs/gapic/v1beta1/types.rst b/docs/gapic/v1beta1/types.rst index 4af19d8c..1ec286a2 100644 --- a/docs/gapic/v1beta1/types.rst +++ b/docs/gapic/v1beta1/types.rst @@ -1,5 +1,5 @@ -Types for Cloud Security Command Center API Client -================================================== +Types for Security Command Center API Client +============================================ .. automodule:: google.cloud.securitycenter_v1beta1.types :members: \ No newline at end of file diff --git a/google/cloud/securitycenter_v1/gapic/security_center_client.py b/google/cloud/securitycenter_v1/gapic/security_center_client.py index 9c1f9104..e6c19fcd 100644 --- a/google/cloud/securitycenter_v1/gapic/security_center_client.py +++ b/google/cloud/securitycenter_v1/gapic/security_center_client.py @@ -282,35 +282,37 @@ def __init__( self._inner_api_calls = {} # Service calls - def get_iam_policy( + def create_source( self, - resource, - options_=None, + parent, + source, retry=google.api_core.gapic_v1.method.DEFAULT, timeout=google.api_core.gapic_v1.method.DEFAULT, metadata=None, ): """ - Gets the access control policy on the specified Source. + Creates a source. Example: >>> from google.cloud import securitycenter_v1 >>> >>> client = securitycenter_v1.SecurityCenterClient() >>> - >>> # TODO: Initialize `resource`: - >>> resource = '' + >>> parent = client.organization_path('[ORGANIZATION]') >>> - >>> response = client.get_iam_policy(resource) + >>> # TODO: Initialize `source`: + >>> source = {} + >>> + >>> response = client.create_source(parent, source) Args: - resource (str): REQUIRED: The resource for which the policy is being requested. - See the operation documentation for the appropriate value for this field. - options_ (Union[dict, ~google.cloud.securitycenter_v1.types.GetPolicyOptions]): OPTIONAL: A ``GetPolicyOptions`` object for specifying options to - ``GetIamPolicy``. This field is only used by Cloud IAM. + parent (str): Required. Resource name of the new source's parent. Its format + should be "organizations/[organization_id]". + source (Union[dict, ~google.cloud.securitycenter_v1.types.Source]): Required. The Source being created, only the display_name and + description will be used. All other fields will be ignored. If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.securitycenter_v1.types.GetPolicyOptions` + message :class:`~google.cloud.securitycenter_v1.types.Source` retry (Optional[google.api_core.retry.Retry]): A retry object used to retry requests. If ``None`` is specified, requests will be retried using a default configuration. @@ -321,7 +323,7 @@ def get_iam_policy( that is provided to the method. Returns: - A :class:`~google.cloud.securitycenter_v1.types.Policy` instance. + A :class:`~google.cloud.securitycenter_v1.types.Source` instance. Raises: google.api_core.exceptions.GoogleAPICallError: If the request @@ -331,24 +333,24 @@ def get_iam_policy( ValueError: If the parameters are invalid. """ # Wrap the transport method to add retry and timeout logic. - if "get_iam_policy" not in self._inner_api_calls: + if "create_source" not in self._inner_api_calls: self._inner_api_calls[ - "get_iam_policy" + "create_source" ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.get_iam_policy, - default_retry=self._method_configs["GetIamPolicy"].retry, - default_timeout=self._method_configs["GetIamPolicy"].timeout, + self.transport.create_source, + default_retry=self._method_configs["CreateSource"].retry, + default_timeout=self._method_configs["CreateSource"].timeout, client_info=self._client_info, ) - request = iam_policy_pb2.GetIamPolicyRequest( - resource=resource, options=options_, + request = securitycenter_service_pb2.CreateSourceRequest( + parent=parent, source=source, ) if metadata is None: metadata = [] metadata = list(metadata) try: - routing_header = [("resource", resource)] + routing_header = [("parent", parent)] except AttributeError: pass else: @@ -357,186 +359,49 @@ def get_iam_policy( ) metadata.append(routing_metadata) - return self._inner_api_calls["get_iam_policy"]( + return self._inner_api_calls["create_source"]( request, retry=retry, timeout=timeout, metadata=metadata ) - def group_assets( + def create_finding( self, parent, - group_by, - filter_=None, - compare_duration=None, - read_time=None, - page_size=None, + finding_id, + finding, retry=google.api_core.gapic_v1.method.DEFAULT, timeout=google.api_core.gapic_v1.method.DEFAULT, metadata=None, ): """ - Filters an organization's assets and groups them by their specified - properties. + Creates a finding. The corresponding source must exist for finding creation + to succeed. Example: >>> from google.cloud import securitycenter_v1 >>> >>> client = securitycenter_v1.SecurityCenterClient() >>> - >>> parent = client.organization_path('[ORGANIZATION]') - >>> - >>> # TODO: Initialize `group_by`: - >>> group_by = '' - >>> - >>> # Iterate over all results - >>> for element in client.group_assets(parent, group_by): - ... # process element - ... pass + >>> parent = client.source_path('[ORGANIZATION]', '[SOURCE]') >>> + >>> # TODO: Initialize `finding_id`: + >>> finding_id = '' >>> - >>> # Alternatively: + >>> # TODO: Initialize `finding`: + >>> finding = {} >>> - >>> # Iterate over results one page at a time - >>> for page in client.group_assets(parent, group_by).pages: - ... for element in page: - ... # process element - ... pass + >>> response = client.create_finding(parent, finding_id, finding) Args: - parent (str): Required. Name of the organization to groupBy. Its format is - "organizations/[organization_id]". - group_by (str): Required. Expression that defines what assets fields to use for - grouping. The string value should follow SQL syntax: comma separated - list of fields. For example: - "security_center_properties.resource_project,security_center_properties.project". - - The following fields are supported when compare_duration is not set: - - - security_center_properties.resource_project - - security_center_properties.resource_project_display_name - - security_center_properties.resource_type - - security_center_properties.resource_parent - - security_center_properties.resource_parent_display_name - - The following fields are supported when compare_duration is set: - - - security_center_properties.resource_type - - security_center_properties.resource_project_display_name - - security_center_properties.resource_parent_display_name - filter_ (str): Expression that defines the filter to apply across assets. The - expression is a list of zero or more restrictions combined via logical - operators ``AND`` and ``OR``. Parentheses are supported, and ``OR`` has - higher precedence than ``AND``. - - Restrictions have the form `` `` and may have a - ``-`` character in front of them to indicate negation. The fields map to - those defined in the Asset resource. Examples include: - - - name - - security_center_properties.resource_name - - resource_properties.a_property - - security_marks.marks.marka - - The supported operators are: - - - ``=`` for all value types. - - ``>``, ``<``, ``>=``, ``<=`` for integer values. - - ``:``, meaning substring matching, for strings. - - The supported value types are: - - - string literals in quotes. - - integer literals without quotes. - - boolean literals ``true`` and ``false`` without quotes. - - The following field and operator combinations are supported: - - - name: ``=`` - - - update_time: ``=``, ``>``, ``<``, ``>=``, ``<=`` - - Usage: This should be milliseconds since epoch or an RFC3339 string. - Examples: ``update_time = "2019-06-10T16:07:18-07:00"`` - ``update_time = 1560208038000`` - - - create_time: ``=``, ``>``, ``<``, ``>=``, ``<=`` - - Usage: This should be milliseconds since epoch or an RFC3339 string. - Examples: ``create_time = "2019-06-10T16:07:18-07:00"`` - ``create_time = 1560208038000`` - - - iam_policy.policy_blob: ``=``, ``:`` - - - resource_properties: ``=``, ``:``, ``>``, ``<``, ``>=``, ``<=`` - - - security_marks.marks: ``=``, ``:`` - - - security_center_properties.resource_name: ``=``, ``:`` - - - security_center_properties.resource_display_name: ``=``, ``:`` - - - security_center_properties.resource_type: ``=``, ``:`` - - - security_center_properties.resource_parent: ``=``, ``:`` - - - security_center_properties.resource_parent_display_name: ``=``, ``:`` - - - security_center_properties.resource_project: ``=``, ``:`` - - - security_center_properties.resource_project_display_name: ``=``, - ``:`` - - - security_center_properties.resource_owners: ``=``, ``:`` - - For example, ``resource_properties.size = 100`` is a valid filter - string. - - Use a partial match on the empty string to filter based on a property - existing:\ ``resource_properties.my_property : ""`` - - Use a negated partial match on the empty string to filter based on a - property not existing: ``-resource_properties.my_property : ""`` - compare_duration (Union[dict, ~google.cloud.securitycenter_v1.types.Duration]): When compare_duration is set, the GroupResult's "state_change" - property is updated to indicate whether the asset was added, removed, or - remained present during the compare_duration period of time that - precedes the read_time. This is the time between (read_time - - compare_duration) and read_time. - - The state change value is derived based on the presence of the asset at - the two points in time. Intermediate state changes between the two times - don't affect the result. For example, the results aren't affected if the - asset is removed and re-created again. - - Possible "state_change" values when compare_duration is specified: - - - "ADDED": indicates that the asset was not present at the start of - compare_duration, but present at reference_time. - - "REMOVED": indicates that the asset was present at the start of - compare_duration, but not present at reference_time. - - "ACTIVE": indicates that the asset was present at both the start and - the end of the time period defined by compare_duration and - reference_time. - - If compare_duration is not specified, then the only possible - state_change is "UNUSED", which will be the state_change set for all - assets present at read_time. - - If this field is set then ``state_change`` must be a specified field in - ``group_by``. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.securitycenter_v1.types.Duration` - read_time (Union[dict, ~google.cloud.securitycenter_v1.types.Timestamp]): Time used as a reference point when filtering assets. The filter is limited - to assets existing at the supplied time and their values are those at that - specific time. Absence of this field will default to the API's version of - NOW. + parent (str): Required. Resource name of the new finding's parent. Its format + should be "organizations/[organization_id]/sources/[source_id]". + finding_id (str): Required. Unique identifier provided by the client within the parent scope. + It must be alphanumeric and less than or equal to 32 characters and + greater than 0 characters in length. + finding (Union[dict, ~google.cloud.securitycenter_v1.types.Finding]): Required. The Finding being created. The name and security_marks + will be ignored as they are both output only fields on this resource. If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.securitycenter_v1.types.Timestamp` - page_size (int): The maximum number of resources contained in the - underlying API response. If page streaming is performed per- - resource, this parameter does not affect the return value. If page - streaming is performed per-page, this determines the maximum number - of resources in a page. + message :class:`~google.cloud.securitycenter_v1.types.Finding` retry (Optional[google.api_core.retry.Retry]): A retry object used to retry requests. If ``None`` is specified, requests will be retried using a default configuration. @@ -547,10 +412,7 @@ def group_assets( that is provided to the method. Returns: - A :class:`~google.api_core.page_iterator.PageIterator` instance. - An iterable of :class:`~google.cloud.securitycenter_v1.types.GroupResult` instances. - You can also iterate over the pages of the response - using its `pages` property. + A :class:`~google.cloud.securitycenter_v1.types.Finding` instance. Raises: google.api_core.exceptions.GoogleAPICallError: If the request @@ -560,23 +422,18 @@ def group_assets( ValueError: If the parameters are invalid. """ # Wrap the transport method to add retry and timeout logic. - if "group_assets" not in self._inner_api_calls: + if "create_finding" not in self._inner_api_calls: self._inner_api_calls[ - "group_assets" + "create_finding" ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.group_assets, - default_retry=self._method_configs["GroupAssets"].retry, - default_timeout=self._method_configs["GroupAssets"].timeout, + self.transport.create_finding, + default_retry=self._method_configs["CreateFinding"].retry, + default_timeout=self._method_configs["CreateFinding"].timeout, client_info=self._client_info, ) - request = securitycenter_service_pb2.GroupAssetsRequest( - parent=parent, - group_by=group_by, - filter=filter_, - compare_duration=compare_duration, - read_time=read_time, - page_size=page_size, + request = securitycenter_service_pb2.CreateFindingRequest( + parent=parent, finding_id=finding_id, finding=finding, ) if metadata is None: metadata = [] @@ -591,187 +448,50 @@ def group_assets( ) metadata.append(routing_metadata) - iterator = google.api_core.page_iterator.GRPCIterator( - client=None, - method=functools.partial( - self._inner_api_calls["group_assets"], - retry=retry, - timeout=timeout, - metadata=metadata, - ), - request=request, - items_field="group_by_results", - request_token_field="page_token", - response_token_field="next_page_token", + return self._inner_api_calls["create_finding"]( + request, retry=retry, timeout=timeout, metadata=metadata ) - return iterator - def group_findings( + def create_notification_config( self, parent, - group_by, - filter_=None, - read_time=None, - compare_duration=None, - page_size=None, + config_id, + notification_config, retry=google.api_core.gapic_v1.method.DEFAULT, timeout=google.api_core.gapic_v1.method.DEFAULT, metadata=None, ): """ - Filters an organization or source's findings and groups them by - their specified properties. - - To group across all sources provide a ``-`` as the source id. Example: - /v1/organizations/{organization_id}/sources/-/findings + Creates a notification config. Example: >>> from google.cloud import securitycenter_v1 >>> >>> client = securitycenter_v1.SecurityCenterClient() >>> - >>> parent = client.source_path('[ORGANIZATION]', '[SOURCE]') - >>> - >>> # TODO: Initialize `group_by`: - >>> group_by = '' - >>> - >>> # Iterate over all results - >>> for element in client.group_findings(parent, group_by): - ... # process element - ... pass + >>> parent = client.organization_path('[ORGANIZATION]') >>> + >>> # TODO: Initialize `config_id`: + >>> config_id = '' >>> - >>> # Alternatively: + >>> # TODO: Initialize `notification_config`: + >>> notification_config = {} >>> - >>> # Iterate over results one page at a time - >>> for page in client.group_findings(parent, group_by).pages: - ... for element in page: - ... # process element - ... pass + >>> response = client.create_notification_config(parent, config_id, notification_config) Args: - parent (str): Required. Name of the source to groupBy. Its format is - "organizations/[organization_id]/sources/[source_id]". To groupBy across - all sources provide a source_id of ``-``. For example: - organizations/{organization_id}/sources/- - group_by (str): Required. Expression that defines what assets fields to use for - grouping (including ``state_change``). The string value should follow - SQL syntax: comma separated list of fields. For example: - "parent,resource_name". - - The following fields are supported: - - - resource_name - - category - - state - - parent - - The following fields are supported when compare_duration is set: - - - state_change - filter_ (str): Expression that defines the filter to apply across findings. The - expression is a list of one or more restrictions combined via logical - operators ``AND`` and ``OR``. Parentheses are supported, and ``OR`` has - higher precedence than ``AND``. - - Restrictions have the form `` `` and may have a - ``-`` character in front of them to indicate negation. Examples include: - - - name - - source_properties.a_property - - security_marks.marks.marka - - The supported operators are: - - - ``=`` for all value types. - - ``>``, ``<``, ``>=``, ``<=`` for integer values. - - ``:``, meaning substring matching, for strings. - - The supported value types are: - - - string literals in quotes. - - integer literals without quotes. - - boolean literals ``true`` and ``false`` without quotes. - - The following field and operator combinations are supported: - - - name: ``=`` - - - parent: ``=``, ``:`` - - - resource_name: ``=``, ``:`` - - - state: ``=``, ``:`` - - - category: ``=``, ``:`` - - - external_uri: ``=``, ``:`` - - - event_time: ``=``, ``>``, ``<``, ``>=``, ``<=`` - - Usage: This should be milliseconds since epoch or an RFC3339 string. - Examples: ``event_time = "2019-06-10T16:07:18-07:00"`` - ``event_time = 1560208038000`` - - - security_marks.marks: ``=``, ``:`` - - - source_properties: ``=``, ``:``, ``>``, ``<``, ``>=``, ``<=`` - - For example, ``source_properties.size = 100`` is a valid filter string. - - Use a partial match on the empty string to filter based on a property - existing: ``source_properties.my_property : ""`` - - Use a negated partial match on the empty string to filter based on a - property not existing: ``-source_properties.my_property : ""`` - read_time (Union[dict, ~google.cloud.securitycenter_v1.types.Timestamp]): Time used as a reference point when filtering findings. The filter is - limited to findings existing at the supplied time and their values are - those at that specific time. Absence of this field will default to the - API's version of NOW. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.securitycenter_v1.types.Timestamp` - compare_duration (Union[dict, ~google.cloud.securitycenter_v1.types.Duration]): When compare_duration is set, the GroupResult's "state_change" - attribute is updated to indicate whether the finding had its state - changed, the finding's state remained unchanged, or if the finding was - added during the compare_duration period of time that precedes the - read_time. This is the time between (read_time - compare_duration) and - read_time. - - The state_change value is derived based on the presence and state of the - finding at the two points in time. Intermediate state changes between - the two times don't affect the result. For example, the results aren't - affected if the finding is made inactive and then active again. - - Possible "state_change" values when compare_duration is specified: - - - "CHANGED": indicates that the finding was present and matched the - given filter at the start of compare_duration, but changed its state - at read_time. - - "UNCHANGED": indicates that the finding was present and matched the - given filter at the start of compare_duration and did not change - state at read_time. - - "ADDED": indicates that the finding did not match the given filter or - was not present at the start of compare_duration, but was present at - read_time. - - "REMOVED": indicates that the finding was present and matched the - filter at the start of compare_duration, but did not match the filter - at read_time. - - If compare_duration is not specified, then the only possible - state_change is "UNUSED", which will be the state_change set for all - findings present at read_time. - - If this field is set then ``state_change`` must be a specified field in - ``group_by``. + parent (str): Required. Resource name of the new notification config's parent. Its + format is "organizations/[organization_id]". + config_id (str): Required. + Unique identifier provided by the client within the parent scope. + It must be between 1 and 128 characters, and contains alphanumeric + characters, underscores or hyphens only. + notification_config (Union[dict, ~google.cloud.securitycenter_v1.types.NotificationConfig]): Required. The notification config being created. The name and the service + account will be ignored as they are both output only fields on this + resource. If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.securitycenter_v1.types.Duration` - page_size (int): The maximum number of resources contained in the - underlying API response. If page streaming is performed per- - resource, this parameter does not affect the return value. If page - streaming is performed per-page, this determines the maximum number - of resources in a page. + message :class:`~google.cloud.securitycenter_v1.types.NotificationConfig` retry (Optional[google.api_core.retry.Retry]): A retry object used to retry requests. If ``None`` is specified, requests will be retried using a default configuration. @@ -782,10 +502,7 @@ def group_findings( that is provided to the method. Returns: - A :class:`~google.api_core.page_iterator.PageIterator` instance. - An iterable of :class:`~google.cloud.securitycenter_v1.types.GroupResult` instances. - You can also iterate over the pages of the response - using its `pages` property. + A :class:`~google.cloud.securitycenter_v1.types.NotificationConfig` instance. Raises: google.api_core.exceptions.GoogleAPICallError: If the request @@ -795,23 +512,20 @@ def group_findings( ValueError: If the parameters are invalid. """ # Wrap the transport method to add retry and timeout logic. - if "group_findings" not in self._inner_api_calls: + if "create_notification_config" not in self._inner_api_calls: self._inner_api_calls[ - "group_findings" + "create_notification_config" ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.group_findings, - default_retry=self._method_configs["GroupFindings"].retry, - default_timeout=self._method_configs["GroupFindings"].timeout, + self.transport.create_notification_config, + default_retry=self._method_configs["CreateNotificationConfig"].retry, + default_timeout=self._method_configs[ + "CreateNotificationConfig" + ].timeout, client_info=self._client_info, ) - request = securitycenter_service_pb2.GroupFindingsRequest( - parent=parent, - group_by=group_by, - filter=filter_, - read_time=read_time, - compare_duration=compare_duration, - page_size=page_size, + request = securitycenter_service_pb2.CreateNotificationConfigRequest( + parent=parent, config_id=config_id, notification_config=notification_config, ) if metadata is None: metadata = [] @@ -826,52 +540,32 @@ def group_findings( ) metadata.append(routing_metadata) - iterator = google.api_core.page_iterator.GRPCIterator( - client=None, - method=functools.partial( - self._inner_api_calls["group_findings"], - retry=retry, - timeout=timeout, - metadata=metadata, - ), - request=request, - items_field="group_by_results", - request_token_field="page_token", - response_token_field="next_page_token", + return self._inner_api_calls["create_notification_config"]( + request, retry=retry, timeout=timeout, metadata=metadata ) - return iterator - def test_iam_permissions( + def delete_notification_config( self, - resource, - permissions, + name, retry=google.api_core.gapic_v1.method.DEFAULT, timeout=google.api_core.gapic_v1.method.DEFAULT, metadata=None, ): """ - Returns the permissions that a caller has on the specified source. + Deletes a notification config. Example: >>> from google.cloud import securitycenter_v1 >>> >>> client = securitycenter_v1.SecurityCenterClient() >>> - >>> # TODO: Initialize `resource`: - >>> resource = '' - >>> - >>> # TODO: Initialize `permissions`: - >>> permissions = [] + >>> name = client.notification_config_path('[ORGANIZATION]', '[NOTIFICATION_CONFIG]') >>> - >>> response = client.test_iam_permissions(resource, permissions) + >>> client.delete_notification_config(name) Args: - resource (str): REQUIRED: The resource for which the policy detail is being requested. - See the operation documentation for the appropriate value for this field. - permissions (list[str]): The set of permissions to check for the ``resource``. Permissions - with wildcards (such as '*' or 'storage.*') are not allowed. For more - information see `IAM - Overview `__. + name (str): Required. Name of the notification config to delete. Its format is + "organizations/[organization_id]/notificationConfigs/[config_id]". retry (Optional[google.api_core.retry.Retry]): A retry object used to retry requests. If ``None`` is specified, requests will be retried using a default configuration. @@ -881,9 +575,6 @@ def test_iam_permissions( metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata that is provided to the method. - Returns: - A :class:`~google.cloud.securitycenter_v1.types.TestIamPermissionsResponse` instance. - Raises: google.api_core.exceptions.GoogleAPICallError: If the request failed for any reason. @@ -892,24 +583,24 @@ def test_iam_permissions( ValueError: If the parameters are invalid. """ # Wrap the transport method to add retry and timeout logic. - if "test_iam_permissions" not in self._inner_api_calls: + if "delete_notification_config" not in self._inner_api_calls: self._inner_api_calls[ - "test_iam_permissions" + "delete_notification_config" ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.test_iam_permissions, - default_retry=self._method_configs["TestIamPermissions"].retry, - default_timeout=self._method_configs["TestIamPermissions"].timeout, + self.transport.delete_notification_config, + default_retry=self._method_configs["DeleteNotificationConfig"].retry, + default_timeout=self._method_configs[ + "DeleteNotificationConfig" + ].timeout, client_info=self._client_info, ) - request = iam_policy_pb2.TestIamPermissionsRequest( - resource=resource, permissions=permissions, - ) + request = securitycenter_service_pb2.DeleteNotificationConfigRequest(name=name,) if metadata is None: metadata = [] metadata = list(metadata) try: - routing_header = [("resource", resource)] + routing_header = [("name", name)] except AttributeError: pass else: @@ -918,41 +609,39 @@ def test_iam_permissions( ) metadata.append(routing_metadata) - return self._inner_api_calls["test_iam_permissions"]( + self._inner_api_calls["delete_notification_config"]( request, retry=retry, timeout=timeout, metadata=metadata ) - def create_source( + def get_iam_policy( self, - parent, - source, + resource, + options_=None, retry=google.api_core.gapic_v1.method.DEFAULT, timeout=google.api_core.gapic_v1.method.DEFAULT, metadata=None, ): """ - Creates a source. + Gets the access control policy on the specified Source. Example: >>> from google.cloud import securitycenter_v1 >>> >>> client = securitycenter_v1.SecurityCenterClient() >>> - >>> parent = client.organization_path('[ORGANIZATION]') - >>> - >>> # TODO: Initialize `source`: - >>> source = {} + >>> # TODO: Initialize `resource`: + >>> resource = '' >>> - >>> response = client.create_source(parent, source) + >>> response = client.get_iam_policy(resource) Args: - parent (str): Required. Resource name of the new source's parent. Its format - should be "organizations/[organization_id]". - source (Union[dict, ~google.cloud.securitycenter_v1.types.Source]): Required. The Source being created, only the display_name and - description will be used. All other fields will be ignored. + resource (str): REQUIRED: The resource for which the policy is being requested. + See the operation documentation for the appropriate value for this field. + options_ (Union[dict, ~google.cloud.securitycenter_v1.types.GetPolicyOptions]): OPTIONAL: A ``GetPolicyOptions`` object for specifying options to + ``GetIamPolicy``. This field is only used by Cloud IAM. If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.securitycenter_v1.types.Source` + message :class:`~google.cloud.securitycenter_v1.types.GetPolicyOptions` retry (Optional[google.api_core.retry.Retry]): A retry object used to retry requests. If ``None`` is specified, requests will be retried using a default configuration. @@ -963,7 +652,7 @@ def create_source( that is provided to the method. Returns: - A :class:`~google.cloud.securitycenter_v1.types.Source` instance. + A :class:`~google.cloud.securitycenter_v1.types.Policy` instance. Raises: google.api_core.exceptions.GoogleAPICallError: If the request @@ -973,24 +662,24 @@ def create_source( ValueError: If the parameters are invalid. """ # Wrap the transport method to add retry and timeout logic. - if "create_source" not in self._inner_api_calls: + if "get_iam_policy" not in self._inner_api_calls: self._inner_api_calls[ - "create_source" + "get_iam_policy" ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.create_source, - default_retry=self._method_configs["CreateSource"].retry, - default_timeout=self._method_configs["CreateSource"].timeout, + self.transport.get_iam_policy, + default_retry=self._method_configs["GetIamPolicy"].retry, + default_timeout=self._method_configs["GetIamPolicy"].timeout, client_info=self._client_info, ) - request = securitycenter_service_pb2.CreateSourceRequest( - parent=parent, source=source, + request = iam_policy_pb2.GetIamPolicyRequest( + resource=resource, options=options_, ) if metadata is None: metadata = [] metadata = list(metadata) try: - routing_header = [("parent", parent)] + routing_header = [("resource", resource)] except AttributeError: pass else: @@ -999,49 +688,32 @@ def create_source( ) metadata.append(routing_metadata) - return self._inner_api_calls["create_source"]( + return self._inner_api_calls["get_iam_policy"]( request, retry=retry, timeout=timeout, metadata=metadata ) - def create_finding( + def get_notification_config( self, - parent, - finding_id, - finding, + name, retry=google.api_core.gapic_v1.method.DEFAULT, timeout=google.api_core.gapic_v1.method.DEFAULT, metadata=None, ): """ - Creates a finding. The corresponding source must exist for finding creation - to succeed. + Gets a notification config. Example: >>> from google.cloud import securitycenter_v1 >>> >>> client = securitycenter_v1.SecurityCenterClient() >>> - >>> parent = client.source_path('[ORGANIZATION]', '[SOURCE]') - >>> - >>> # TODO: Initialize `finding_id`: - >>> finding_id = '' - >>> - >>> # TODO: Initialize `finding`: - >>> finding = {} + >>> name = client.notification_config_path('[ORGANIZATION]', '[NOTIFICATION_CONFIG]') >>> - >>> response = client.create_finding(parent, finding_id, finding) + >>> response = client.get_notification_config(name) Args: - parent (str): Required. Resource name of the new finding's parent. Its format - should be "organizations/[organization_id]/sources/[source_id]". - finding_id (str): Required. Unique identifier provided by the client within the parent scope. - It must be alphanumeric and less than or equal to 32 characters and - greater than 0 characters in length. - finding (Union[dict, ~google.cloud.securitycenter_v1.types.Finding]): Required. The Finding being created. The name and security_marks - will be ignored as they are both output only fields on this resource. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.securitycenter_v1.types.Finding` + name (str): Required. Name of the notification config to get. Its format is + "organizations/[organization_id]/notificationConfigs/[config_id]". retry (Optional[google.api_core.retry.Retry]): A retry object used to retry requests. If ``None`` is specified, requests will be retried using a default configuration. @@ -1052,7 +724,7 @@ def create_finding( that is provided to the method. Returns: - A :class:`~google.cloud.securitycenter_v1.types.Finding` instance. + A :class:`~google.cloud.securitycenter_v1.types.NotificationConfig` instance. Raises: google.api_core.exceptions.GoogleAPICallError: If the request @@ -1062,24 +734,22 @@ def create_finding( ValueError: If the parameters are invalid. """ # Wrap the transport method to add retry and timeout logic. - if "create_finding" not in self._inner_api_calls: + if "get_notification_config" not in self._inner_api_calls: self._inner_api_calls[ - "create_finding" + "get_notification_config" ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.create_finding, - default_retry=self._method_configs["CreateFinding"].retry, - default_timeout=self._method_configs["CreateFinding"].timeout, + self.transport.get_notification_config, + default_retry=self._method_configs["GetNotificationConfig"].retry, + default_timeout=self._method_configs["GetNotificationConfig"].timeout, client_info=self._client_info, ) - request = securitycenter_service_pb2.CreateFindingRequest( - parent=parent, finding_id=finding_id, finding=finding, - ) + request = securitycenter_service_pb2.GetNotificationConfigRequest(name=name,) if metadata is None: metadata = [] metadata = list(metadata) try: - routing_header = [("parent", parent)] + routing_header = [("name", name)] except AttributeError: pass else: @@ -1088,50 +758,32 @@ def create_finding( ) metadata.append(routing_metadata) - return self._inner_api_calls["create_finding"]( + return self._inner_api_calls["get_notification_config"]( request, retry=retry, timeout=timeout, metadata=metadata ) - def create_notification_config( + def get_organization_settings( self, - parent, - config_id, - notification_config, + name, retry=google.api_core.gapic_v1.method.DEFAULT, timeout=google.api_core.gapic_v1.method.DEFAULT, metadata=None, ): """ - Creates a notification config. + Gets the settings for an organization. Example: >>> from google.cloud import securitycenter_v1 >>> >>> client = securitycenter_v1.SecurityCenterClient() >>> - >>> parent = client.organization_path('[ORGANIZATION]') - >>> - >>> # TODO: Initialize `config_id`: - >>> config_id = '' - >>> - >>> # TODO: Initialize `notification_config`: - >>> notification_config = {} + >>> name = client.organization_settings_path('[ORGANIZATION]') >>> - >>> response = client.create_notification_config(parent, config_id, notification_config) + >>> response = client.get_organization_settings(name) Args: - parent (str): Required. Resource name of the new notification config's parent. Its - format is "organizations/[organization_id]". - config_id (str): Required. - Unique identifier provided by the client within the parent scope. - It must be between 1 and 128 characters, and contains alphanumeric - characters, underscores or hyphens only. - notification_config (Union[dict, ~google.cloud.securitycenter_v1.types.NotificationConfig]): Required. The notification config being created. The name and the service - account will be ignored as they are both output only fields on this - resource. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.securitycenter_v1.types.NotificationConfig` + name (str): Required. Name of the organization to get organization settings for. + Its format is "organizations/[organization_id]/organizationSettings". retry (Optional[google.api_core.retry.Retry]): A retry object used to retry requests. If ``None`` is specified, requests will be retried using a default configuration. @@ -1142,7 +794,7 @@ def create_notification_config( that is provided to the method. Returns: - A :class:`~google.cloud.securitycenter_v1.types.NotificationConfig` instance. + A :class:`~google.cloud.securitycenter_v1.types.OrganizationSettings` instance. Raises: google.api_core.exceptions.GoogleAPICallError: If the request @@ -1152,26 +804,22 @@ def create_notification_config( ValueError: If the parameters are invalid. """ # Wrap the transport method to add retry and timeout logic. - if "create_notification_config" not in self._inner_api_calls: + if "get_organization_settings" not in self._inner_api_calls: self._inner_api_calls[ - "create_notification_config" + "get_organization_settings" ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.create_notification_config, - default_retry=self._method_configs["CreateNotificationConfig"].retry, - default_timeout=self._method_configs[ - "CreateNotificationConfig" - ].timeout, + self.transport.get_organization_settings, + default_retry=self._method_configs["GetOrganizationSettings"].retry, + default_timeout=self._method_configs["GetOrganizationSettings"].timeout, client_info=self._client_info, ) - request = securitycenter_service_pb2.CreateNotificationConfigRequest( - parent=parent, config_id=config_id, notification_config=notification_config, - ) + request = securitycenter_service_pb2.GetOrganizationSettingsRequest(name=name,) if metadata is None: metadata = [] metadata = list(metadata) try: - routing_header = [("parent", parent)] + routing_header = [("name", name)] except AttributeError: pass else: @@ -1180,11 +828,11 @@ def create_notification_config( ) metadata.append(routing_metadata) - return self._inner_api_calls["create_notification_config"]( + return self._inner_api_calls["get_organization_settings"]( request, retry=retry, timeout=timeout, metadata=metadata ) - def delete_notification_config( + def get_source( self, name, retry=google.api_core.gapic_v1.method.DEFAULT, @@ -1192,20 +840,20 @@ def delete_notification_config( metadata=None, ): """ - Deletes a notification config. + Gets a source. Example: >>> from google.cloud import securitycenter_v1 >>> >>> client = securitycenter_v1.SecurityCenterClient() >>> - >>> name = client.notification_config_path('[ORGANIZATION]', '[NOTIFICATION_CONFIG]') + >>> name = client.source_path('[ORGANIZATION]', '[SOURCE]') >>> - >>> client.delete_notification_config(name) + >>> response = client.get_source(name) Args: - name (str): Required. Name of the notification config to delete. Its format is - "organizations/[organization_id]/notificationConfigs/[config_id]". + name (str): Required. Relative resource name of the source. Its format is + "organizations/[organization_id]/source/[source_id]". retry (Optional[google.api_core.retry.Retry]): A retry object used to retry requests. If ``None`` is specified, requests will be retried using a default configuration. @@ -1215,6 +863,9 @@ def delete_notification_config( metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata that is provided to the method. + Returns: + A :class:`~google.cloud.securitycenter_v1.types.Source` instance. + Raises: google.api_core.exceptions.GoogleAPICallError: If the request failed for any reason. @@ -1223,19 +874,17 @@ def delete_notification_config( ValueError: If the parameters are invalid. """ # Wrap the transport method to add retry and timeout logic. - if "delete_notification_config" not in self._inner_api_calls: + if "get_source" not in self._inner_api_calls: self._inner_api_calls[ - "delete_notification_config" + "get_source" ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.delete_notification_config, - default_retry=self._method_configs["DeleteNotificationConfig"].retry, - default_timeout=self._method_configs[ - "DeleteNotificationConfig" - ].timeout, + self.transport.get_source, + default_retry=self._method_configs["GetSource"].retry, + default_timeout=self._method_configs["GetSource"].timeout, client_info=self._client_info, ) - request = securitycenter_service_pb2.DeleteNotificationConfigRequest(name=name,) + request = securitycenter_service_pb2.GetSourceRequest(name=name,) if metadata is None: metadata = [] metadata = list(metadata) @@ -1249,32 +898,186 @@ def delete_notification_config( ) metadata.append(routing_metadata) - self._inner_api_calls["delete_notification_config"]( + return self._inner_api_calls["get_source"]( request, retry=retry, timeout=timeout, metadata=metadata ) - def get_notification_config( + def group_assets( self, - name, + parent, + group_by, + filter_=None, + compare_duration=None, + read_time=None, + page_size=None, retry=google.api_core.gapic_v1.method.DEFAULT, timeout=google.api_core.gapic_v1.method.DEFAULT, metadata=None, ): """ - Gets a notification config. + Filters an organization's assets and groups them by their specified + properties. Example: >>> from google.cloud import securitycenter_v1 >>> >>> client = securitycenter_v1.SecurityCenterClient() >>> - >>> name = client.notification_config_path('[ORGANIZATION]', '[NOTIFICATION_CONFIG]') + >>> parent = client.organization_path('[ORGANIZATION]') >>> - >>> response = client.get_notification_config(name) + >>> # TODO: Initialize `group_by`: + >>> group_by = '' + >>> + >>> # Iterate over all results + >>> for element in client.group_assets(parent, group_by): + ... # process element + ... pass + >>> + >>> + >>> # Alternatively: + >>> + >>> # Iterate over results one page at a time + >>> for page in client.group_assets(parent, group_by).pages: + ... for element in page: + ... # process element + ... pass Args: - name (str): Required. Name of the notification config to get. Its format is - "organizations/[organization_id]/notificationConfigs/[config_id]". + parent (str): Required. Name of the organization to groupBy. Its format is + "organizations/[organization_id]". + group_by (str): Required. Expression that defines what assets fields to use for + grouping. The string value should follow SQL syntax: comma separated + list of fields. For example: + "security_center_properties.resource_project,security_center_properties.project". + + The following fields are supported when compare_duration is not set: + + - security_center_properties.resource_project + - security_center_properties.resource_project_display_name + - security_center_properties.resource_type + - security_center_properties.resource_parent + - security_center_properties.resource_parent_display_name + + The following fields are supported when compare_duration is set: + + - security_center_properties.resource_type + - security_center_properties.resource_project_display_name + - security_center_properties.resource_parent_display_name + filter_ (str): Expression that defines the filter to apply across assets. The + expression is a list of zero or more restrictions combined via logical + operators ``AND`` and ``OR``. Parentheses are supported, and ``OR`` has + higher precedence than ``AND``. + + Restrictions have the form `` `` and may have a + ``-`` character in front of them to indicate negation. The fields map to + those defined in the Asset resource. Examples include: + + - name + - security_center_properties.resource_name + - resource_properties.a_property + - security_marks.marks.marka + + The supported operators are: + + - ``=`` for all value types. + - ``>``, ``<``, ``>=``, ``<=`` for integer values. + - ``:``, meaning substring matching, for strings. + + The supported value types are: + + - string literals in quotes. + - integer literals without quotes. + - boolean literals ``true`` and ``false`` without quotes. + + The following field and operator combinations are supported: + + - name: ``=`` + + - update_time: ``=``, ``>``, ``<``, ``>=``, ``<=`` + + Usage: This should be milliseconds since epoch or an RFC3339 string. + Examples: ``update_time = "2019-06-10T16:07:18-07:00"`` + ``update_time = 1560208038000`` + + - create_time: ``=``, ``>``, ``<``, ``>=``, ``<=`` + + Usage: This should be milliseconds since epoch or an RFC3339 string. + Examples: ``create_time = "2019-06-10T16:07:18-07:00"`` + ``create_time = 1560208038000`` + + - iam_policy.policy_blob: ``=``, ``:`` + + - resource_properties: ``=``, ``:``, ``>``, ``<``, ``>=``, ``<=`` + + - security_marks.marks: ``=``, ``:`` + + - security_center_properties.resource_name: ``=``, ``:`` + + - security_center_properties.resource_display_name: ``=``, ``:`` + + - security_center_properties.resource_type: ``=``, ``:`` + + - security_center_properties.resource_parent: ``=``, ``:`` + + - security_center_properties.resource_parent_display_name: ``=``, ``:`` + + - security_center_properties.resource_project: ``=``, ``:`` + + - security_center_properties.resource_project_display_name: ``=``, + ``:`` + + - security_center_properties.resource_owners: ``=``, ``:`` + + For example, ``resource_properties.size = 100`` is a valid filter + string. + + Use a partial match on the empty string to filter based on a property + existing:\ ``resource_properties.my_property : ""`` + + Use a negated partial match on the empty string to filter based on a + property not existing: ``-resource_properties.my_property : ""`` + compare_duration (Union[dict, ~google.cloud.securitycenter_v1.types.Duration]): When compare_duration is set, the GroupResult's "state_change" + property is updated to indicate whether the asset was added, removed, or + remained present during the compare_duration period of time that + precedes the read_time. This is the time between (read_time - + compare_duration) and read_time. + + The state change value is derived based on the presence of the asset at + the two points in time. Intermediate state changes between the two times + don't affect the result. For example, the results aren't affected if the + asset is removed and re-created again. + + Possible "state_change" values when compare_duration is specified: + + - "ADDED": indicates that the asset was not present at the start of + compare_duration, but present at reference_time. + - "REMOVED": indicates that the asset was present at the start of + compare_duration, but not present at reference_time. + - "ACTIVE": indicates that the asset was present at both the start and + the end of the time period defined by compare_duration and + reference_time. + + If compare_duration is not specified, then the only possible + state_change is "UNUSED", which will be the state_change set for all + assets present at read_time. + + If this field is set then ``state_change`` must be a specified field in + ``group_by``. + + If a dict is provided, it must be of the same form as the protobuf + message :class:`~google.cloud.securitycenter_v1.types.Duration` + read_time (Union[dict, ~google.cloud.securitycenter_v1.types.Timestamp]): Time used as a reference point when filtering assets. The filter is limited + to assets existing at the supplied time and their values are those at that + specific time. Absence of this field will default to the API's version of + NOW. + + If a dict is provided, it must be of the same form as the protobuf + message :class:`~google.cloud.securitycenter_v1.types.Timestamp` + page_size (int): The maximum number of resources contained in the + underlying API response. If page streaming is performed per- + resource, this parameter does not affect the return value. If page + streaming is performed per-page, this determines the maximum number + of resources in a page. retry (Optional[google.api_core.retry.Retry]): A retry object used to retry requests. If ``None`` is specified, requests will be retried using a default configuration. @@ -1285,7 +1088,10 @@ def get_notification_config( that is provided to the method. Returns: - A :class:`~google.cloud.securitycenter_v1.types.NotificationConfig` instance. + A :class:`~google.api_core.page_iterator.PageIterator` instance. + An iterable of :class:`~google.cloud.securitycenter_v1.types.GroupResult` instances. + You can also iterate over the pages of the response + using its `pages` property. Raises: google.api_core.exceptions.GoogleAPICallError: If the request @@ -1295,22 +1101,29 @@ def get_notification_config( ValueError: If the parameters are invalid. """ # Wrap the transport method to add retry and timeout logic. - if "get_notification_config" not in self._inner_api_calls: + if "group_assets" not in self._inner_api_calls: self._inner_api_calls[ - "get_notification_config" + "group_assets" ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.get_notification_config, - default_retry=self._method_configs["GetNotificationConfig"].retry, - default_timeout=self._method_configs["GetNotificationConfig"].timeout, + self.transport.group_assets, + default_retry=self._method_configs["GroupAssets"].retry, + default_timeout=self._method_configs["GroupAssets"].timeout, client_info=self._client_info, ) - request = securitycenter_service_pb2.GetNotificationConfigRequest(name=name,) + request = securitycenter_service_pb2.GroupAssetsRequest( + parent=parent, + group_by=group_by, + filter=filter_, + compare_duration=compare_duration, + read_time=read_time, + page_size=page_size, + ) if metadata is None: metadata = [] metadata = list(metadata) try: - routing_header = [("name", name)] + routing_header = [("parent", parent)] except AttributeError: pass else: @@ -1319,102 +1132,187 @@ def get_notification_config( ) metadata.append(routing_metadata) - return self._inner_api_calls["get_notification_config"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) + iterator = google.api_core.page_iterator.GRPCIterator( + client=None, + method=functools.partial( + self._inner_api_calls["group_assets"], + retry=retry, + timeout=timeout, + metadata=metadata, + ), + request=request, + items_field="group_by_results", + request_token_field="page_token", + response_token_field="next_page_token", + ) + return iterator + + def group_findings( + self, + parent, + group_by, + filter_=None, + read_time=None, + compare_duration=None, + page_size=None, + retry=google.api_core.gapic_v1.method.DEFAULT, + timeout=google.api_core.gapic_v1.method.DEFAULT, + metadata=None, + ): + """ + Filters an organization or source's findings and groups them by + their specified properties. + + To group across all sources provide a ``-`` as the source id. Example: + /v1/organizations/{organization_id}/sources/-/findings + + Example: + >>> from google.cloud import securitycenter_v1 + >>> + >>> client = securitycenter_v1.SecurityCenterClient() + >>> + >>> parent = client.source_path('[ORGANIZATION]', '[SOURCE]') + >>> + >>> # TODO: Initialize `group_by`: + >>> group_by = '' + >>> + >>> # Iterate over all results + >>> for element in client.group_findings(parent, group_by): + ... # process element + ... pass + >>> + >>> + >>> # Alternatively: + >>> + >>> # Iterate over results one page at a time + >>> for page in client.group_findings(parent, group_by).pages: + ... for element in page: + ... # process element + ... pass + + Args: + parent (str): Required. Name of the source to groupBy. Its format is + "organizations/[organization_id]/sources/[source_id]". To groupBy across + all sources provide a source_id of ``-``. For example: + organizations/{organization_id}/sources/- + group_by (str): Required. Expression that defines what assets fields to use for + grouping (including ``state_change``). The string value should follow + SQL syntax: comma separated list of fields. For example: + "parent,resource_name". + + The following fields are supported: + + - resource_name + - category + - state + - parent + + The following fields are supported when compare_duration is set: + + - state_change + filter_ (str): Expression that defines the filter to apply across findings. The + expression is a list of one or more restrictions combined via logical + operators ``AND`` and ``OR``. Parentheses are supported, and ``OR`` has + higher precedence than ``AND``. + + Restrictions have the form `` `` and may have a + ``-`` character in front of them to indicate negation. Examples include: + + - name + - source_properties.a_property + - security_marks.marks.marka + + The supported operators are: + + - ``=`` for all value types. + - ``>``, ``<``, ``>=``, ``<=`` for integer values. + - ``:``, meaning substring matching, for strings. + + The supported value types are: + + - string literals in quotes. + - integer literals without quotes. + - boolean literals ``true`` and ``false`` without quotes. + + The following field and operator combinations are supported: + + - name: ``=`` + + - parent: ``=``, ``:`` + + - resource_name: ``=``, ``:`` + + - state: ``=``, ``:`` + + - category: ``=``, ``:`` + + - external_uri: ``=``, ``:`` + + - event_time: ``=``, ``>``, ``<``, ``>=``, ``<=`` + + Usage: This should be milliseconds since epoch or an RFC3339 string. + Examples: ``event_time = "2019-06-10T16:07:18-07:00"`` + ``event_time = 1560208038000`` + + - security_marks.marks: ``=``, ``:`` + + - source_properties: ``=``, ``:``, ``>``, ``<``, ``>=``, ``<=`` - def get_organization_settings( - self, - name, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Gets the settings for an organization. + For example, ``source_properties.size = 100`` is a valid filter string. - Example: - >>> from google.cloud import securitycenter_v1 - >>> - >>> client = securitycenter_v1.SecurityCenterClient() - >>> - >>> name = client.organization_settings_path('[ORGANIZATION]') - >>> - >>> response = client.get_organization_settings(name) + Use a partial match on the empty string to filter based on a property + existing: ``source_properties.my_property : ""`` - Args: - name (str): Required. Name of the organization to get organization settings for. - Its format is "organizations/[organization_id]/organizationSettings". - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. + Use a negated partial match on the empty string to filter based on a + property not existing: ``-source_properties.my_property : ""`` + read_time (Union[dict, ~google.cloud.securitycenter_v1.types.Timestamp]): Time used as a reference point when filtering findings. The filter is + limited to findings existing at the supplied time and their values are + those at that specific time. Absence of this field will default to the + API's version of NOW. - Returns: - A :class:`~google.cloud.securitycenter_v1.types.OrganizationSettings` instance. + If a dict is provided, it must be of the same form as the protobuf + message :class:`~google.cloud.securitycenter_v1.types.Timestamp` + compare_duration (Union[dict, ~google.cloud.securitycenter_v1.types.Duration]): When compare_duration is set, the GroupResult's "state_change" + attribute is updated to indicate whether the finding had its state + changed, the finding's state remained unchanged, or if the finding was + added during the compare_duration period of time that precedes the + read_time. This is the time between (read_time - compare_duration) and + read_time. - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "get_organization_settings" not in self._inner_api_calls: - self._inner_api_calls[ - "get_organization_settings" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.get_organization_settings, - default_retry=self._method_configs["GetOrganizationSettings"].retry, - default_timeout=self._method_configs["GetOrganizationSettings"].timeout, - client_info=self._client_info, - ) + The state_change value is derived based on the presence and state of the + finding at the two points in time. Intermediate state changes between + the two times don't affect the result. For example, the results aren't + affected if the finding is made inactive and then active again. - request = securitycenter_service_pb2.GetOrganizationSettingsRequest(name=name,) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) + Possible "state_change" values when compare_duration is specified: - return self._inner_api_calls["get_organization_settings"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) + - "CHANGED": indicates that the finding was present and matched the + given filter at the start of compare_duration, but changed its state + at read_time. + - "UNCHANGED": indicates that the finding was present and matched the + given filter at the start of compare_duration and did not change + state at read_time. + - "ADDED": indicates that the finding did not match the given filter or + was not present at the start of compare_duration, but was present at + read_time. + - "REMOVED": indicates that the finding was present and matched the + filter at the start of compare_duration, but did not match the filter + at read_time. - def get_source( - self, - name, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Gets a source. + If compare_duration is not specified, then the only possible + state_change is "UNUSED", which will be the state_change set for all + findings present at read_time. - Example: - >>> from google.cloud import securitycenter_v1 - >>> - >>> client = securitycenter_v1.SecurityCenterClient() - >>> - >>> name = client.source_path('[ORGANIZATION]', '[SOURCE]') - >>> - >>> response = client.get_source(name) + If this field is set then ``state_change`` must be a specified field in + ``group_by``. - Args: - name (str): Required. Relative resource name of the source. Its format is - "organizations/[organization_id]/source/[source_id]". + If a dict is provided, it must be of the same form as the protobuf + message :class:`~google.cloud.securitycenter_v1.types.Duration` + page_size (int): The maximum number of resources contained in the + underlying API response. If page streaming is performed per- + resource, this parameter does not affect the return value. If page + streaming is performed per-page, this determines the maximum number + of resources in a page. retry (Optional[google.api_core.retry.Retry]): A retry object used to retry requests. If ``None`` is specified, requests will be retried using a default configuration. @@ -1425,7 +1323,10 @@ def get_source( that is provided to the method. Returns: - A :class:`~google.cloud.securitycenter_v1.types.Source` instance. + A :class:`~google.api_core.page_iterator.PageIterator` instance. + An iterable of :class:`~google.cloud.securitycenter_v1.types.GroupResult` instances. + You can also iterate over the pages of the response + using its `pages` property. Raises: google.api_core.exceptions.GoogleAPICallError: If the request @@ -1435,22 +1336,29 @@ def get_source( ValueError: If the parameters are invalid. """ # Wrap the transport method to add retry and timeout logic. - if "get_source" not in self._inner_api_calls: + if "group_findings" not in self._inner_api_calls: self._inner_api_calls[ - "get_source" + "group_findings" ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.get_source, - default_retry=self._method_configs["GetSource"].retry, - default_timeout=self._method_configs["GetSource"].timeout, + self.transport.group_findings, + default_retry=self._method_configs["GroupFindings"].retry, + default_timeout=self._method_configs["GroupFindings"].timeout, client_info=self._client_info, ) - request = securitycenter_service_pb2.GetSourceRequest(name=name,) + request = securitycenter_service_pb2.GroupFindingsRequest( + parent=parent, + group_by=group_by, + filter=filter_, + read_time=read_time, + compare_duration=compare_duration, + page_size=page_size, + ) if metadata is None: metadata = [] metadata = list(metadata) try: - routing_header = [("name", name)] + routing_header = [("parent", parent)] except AttributeError: pass else: @@ -1459,9 +1367,20 @@ def get_source( ) metadata.append(routing_metadata) - return self._inner_api_calls["get_source"]( - request, retry=retry, timeout=timeout, metadata=metadata + iterator = google.api_core.page_iterator.GRPCIterator( + client=None, + method=functools.partial( + self._inner_api_calls["group_findings"], + retry=retry, + timeout=timeout, + metadata=metadata, + ), + request=request, + items_field="group_by_results", + request_token_field="page_token", + response_token_field="next_page_token", ) + return iterator def list_assets( self, @@ -2394,6 +2313,87 @@ def set_iam_policy( request, retry=retry, timeout=timeout, metadata=metadata ) + def test_iam_permissions( + self, + resource, + permissions, + retry=google.api_core.gapic_v1.method.DEFAULT, + timeout=google.api_core.gapic_v1.method.DEFAULT, + metadata=None, + ): + """ + Returns the permissions that a caller has on the specified source. + + Example: + >>> from google.cloud import securitycenter_v1 + >>> + >>> client = securitycenter_v1.SecurityCenterClient() + >>> + >>> # TODO: Initialize `resource`: + >>> resource = '' + >>> + >>> # TODO: Initialize `permissions`: + >>> permissions = [] + >>> + >>> response = client.test_iam_permissions(resource, permissions) + + Args: + resource (str): REQUIRED: The resource for which the policy detail is being requested. + See the operation documentation for the appropriate value for this field. + permissions (list[str]): The set of permissions to check for the ``resource``. Permissions + with wildcards (such as '*' or 'storage.*') are not allowed. For more + information see `IAM + Overview `__. + retry (Optional[google.api_core.retry.Retry]): A retry object used + to retry requests. If ``None`` is specified, requests will + be retried using a default configuration. + timeout (Optional[float]): The amount of time, in seconds, to wait + for the request to complete. Note that if ``retry`` is + specified, the timeout applies to each individual attempt. + metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata + that is provided to the method. + + Returns: + A :class:`~google.cloud.securitycenter_v1.types.TestIamPermissionsResponse` instance. + + Raises: + google.api_core.exceptions.GoogleAPICallError: If the request + failed for any reason. + google.api_core.exceptions.RetryError: If the request failed due + to a retryable error and retry attempts failed. + ValueError: If the parameters are invalid. + """ + # Wrap the transport method to add retry and timeout logic. + if "test_iam_permissions" not in self._inner_api_calls: + self._inner_api_calls[ + "test_iam_permissions" + ] = google.api_core.gapic_v1.method.wrap_method( + self.transport.test_iam_permissions, + default_retry=self._method_configs["TestIamPermissions"].retry, + default_timeout=self._method_configs["TestIamPermissions"].timeout, + client_info=self._client_info, + ) + + request = iam_policy_pb2.TestIamPermissionsRequest( + resource=resource, permissions=permissions, + ) + if metadata is None: + metadata = [] + metadata = list(metadata) + try: + routing_header = [("resource", resource)] + except AttributeError: + pass + else: + routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( + routing_header + ) + metadata.append(routing_metadata) + + return self._inner_api_calls["test_iam_permissions"]( + request, retry=retry, timeout=timeout, metadata=metadata + ) + def update_finding( self, finding, diff --git a/google/cloud/securitycenter_v1/gapic/security_center_client_config.py b/google/cloud/securitycenter_v1/gapic/security_center_client_config.py index 7bf5a897..111431ea 100644 --- a/google/cloud/securitycenter_v1/gapic/security_center_client_config.py +++ b/google/cloud/securitycenter_v1/gapic/security_center_client_config.py @@ -2,135 +2,174 @@ "interfaces": { "google.cloud.securitycenter.v1.SecurityCenter": { "retry_codes": { - "idempotent": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], - "non_idempotent": [], + "retry_policy_1_codes": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], + "no_retry_2_codes": [], + "no_retry_codes": [], + "retry_policy_2_codes": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], + "no_retry_1_codes": [], }, "retry_params": { - "default": { + "retry_policy_1_params": { + "initial_retry_delay_millis": 100, + "retry_delay_multiplier": 1.3, + "max_retry_delay_millis": 60000, + "initial_rpc_timeout_millis": 60000, + "rpc_timeout_multiplier": 1.0, + "max_rpc_timeout_millis": 60000, + "total_timeout_millis": 60000, + }, + "retry_policy_2_params": { "initial_retry_delay_millis": 100, "retry_delay_multiplier": 1.3, "max_retry_delay_millis": 60000, "initial_rpc_timeout_millis": 480000, "rpc_timeout_multiplier": 1.0, "max_rpc_timeout_millis": 480000, - "total_timeout_millis": 600000, - } - }, - "methods": { - "GetIamPolicy": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "total_timeout_millis": 480000, }, - "GroupAssets": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "GroupFindings": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "no_retry_params": { + "initial_retry_delay_millis": 0, + "retry_delay_multiplier": 0.0, + "max_retry_delay_millis": 0, + "initial_rpc_timeout_millis": 0, + "rpc_timeout_multiplier": 1.0, + "max_rpc_timeout_millis": 0, + "total_timeout_millis": 0, + }, + "no_retry_1_params": { + "initial_retry_delay_millis": 0, + "retry_delay_multiplier": 0.0, + "max_retry_delay_millis": 0, + "initial_rpc_timeout_millis": 60000, + "rpc_timeout_multiplier": 1.0, + "max_rpc_timeout_millis": 60000, + "total_timeout_millis": 60000, }, - "TestIamPermissions": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "no_retry_2_params": { + "initial_retry_delay_millis": 0, + "retry_delay_multiplier": 0.0, + "max_retry_delay_millis": 0, + "initial_rpc_timeout_millis": 480000, + "rpc_timeout_multiplier": 1.0, + "max_rpc_timeout_millis": 480000, + "total_timeout_millis": 480000, }, + }, + "methods": { "CreateSource": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "CreateFinding": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "CreateNotificationConfig": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "DeleteNotificationConfig": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", + }, + "GetIamPolicy": { + "timeout_millis": 60000, + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", }, "GetNotificationConfig": { "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", }, "GetOrganizationSettings": { "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", }, "GetSource": { "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", + }, + "GroupAssets": { + "timeout_millis": 480000, + "retry_codes_name": "retry_policy_2_codes", + "retry_params_name": "retry_policy_2_params", + }, + "GroupFindings": { + "timeout_millis": 480000, + "retry_codes_name": "retry_policy_2_codes", + "retry_params_name": "retry_policy_2_params", }, "ListAssets": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "timeout_millis": 480000, + "retry_codes_name": "retry_policy_2_codes", + "retry_params_name": "retry_policy_2_params", }, "ListFindings": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "timeout_millis": 480000, + "retry_codes_name": "retry_policy_2_codes", + "retry_params_name": "retry_policy_2_params", }, "ListNotificationConfigs": { "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", }, "ListSources": { "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", }, "RunAssetDiscovery": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "SetFindingState": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "SetIamPolicy": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", + }, + "TestIamPermissions": { + "timeout_millis": 60000, + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", }, "UpdateFinding": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "UpdateNotificationConfig": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "UpdateOrganizationSettings": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "UpdateSource": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "UpdateSecurityMarks": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "timeout_millis": 480000, + "retry_codes_name": "no_retry_2_codes", + "retry_params_name": "no_retry_2_params", }, }, } diff --git a/google/cloud/securitycenter_v1/gapic/transports/security_center_grpc_transport.py b/google/cloud/securitycenter_v1/gapic/transports/security_center_grpc_transport.py index 1d16b3f2..58249a17 100644 --- a/google/cloud/securitycenter_v1/gapic/transports/security_center_grpc_transport.py +++ b/google/cloud/securitycenter_v1/gapic/transports/security_center_grpc_transport.py @@ -120,63 +120,6 @@ def channel(self): """ return self._channel - @property - def get_iam_policy(self): - """Return the gRPC stub for :meth:`SecurityCenterClient.get_iam_policy`. - - Gets the access control policy on the specified Source. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["security_center_stub"].GetIamPolicy - - @property - def group_assets(self): - """Return the gRPC stub for :meth:`SecurityCenterClient.group_assets`. - - Filters an organization's assets and groups them by their specified - properties. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["security_center_stub"].GroupAssets - - @property - def group_findings(self): - """Return the gRPC stub for :meth:`SecurityCenterClient.group_findings`. - - Filters an organization or source's findings and groups them by - their specified properties. - - To group across all sources provide a ``-`` as the source id. Example: - /v1/organizations/{organization_id}/sources/-/findings - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["security_center_stub"].GroupFindings - - @property - def test_iam_permissions(self): - """Return the gRPC stub for :meth:`SecurityCenterClient.test_iam_permissions`. - - Returns the permissions that a caller has on the specified source. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["security_center_stub"].TestIamPermissions - @property def create_source(self): """Return the gRPC stub for :meth:`SecurityCenterClient.create_source`. @@ -230,6 +173,19 @@ def delete_notification_config(self): """ return self._stubs["security_center_stub"].DeleteNotificationConfig + @property + def get_iam_policy(self): + """Return the gRPC stub for :meth:`SecurityCenterClient.get_iam_policy`. + + Gets the access control policy on the specified Source. + + Returns: + Callable: A callable which accepts the appropriate + deserialized request object and returns a + deserialized response object. + """ + return self._stubs["security_center_stub"].GetIamPolicy + @property def get_notification_config(self): """Return the gRPC stub for :meth:`SecurityCenterClient.get_notification_config`. @@ -269,6 +225,37 @@ def get_source(self): """ return self._stubs["security_center_stub"].GetSource + @property + def group_assets(self): + """Return the gRPC stub for :meth:`SecurityCenterClient.group_assets`. + + Filters an organization's assets and groups them by their specified + properties. + + Returns: + Callable: A callable which accepts the appropriate + deserialized request object and returns a + deserialized response object. + """ + return self._stubs["security_center_stub"].GroupAssets + + @property + def group_findings(self): + """Return the gRPC stub for :meth:`SecurityCenterClient.group_findings`. + + Filters an organization or source's findings and groups them by + their specified properties. + + To group across all sources provide a ``-`` as the source id. Example: + /v1/organizations/{organization_id}/sources/-/findings + + Returns: + Callable: A callable which accepts the appropriate + deserialized request object and returns a + deserialized response object. + """ + return self._stubs["security_center_stub"].GroupFindings + @property def list_assets(self): """Return the gRPC stub for :meth:`SecurityCenterClient.list_assets`. @@ -368,6 +355,19 @@ def set_iam_policy(self): """ return self._stubs["security_center_stub"].SetIamPolicy + @property + def test_iam_permissions(self): + """Return the gRPC stub for :meth:`SecurityCenterClient.test_iam_permissions`. + + Returns the permissions that a caller has on the specified source. + + Returns: + Callable: A callable which accepts the appropriate + deserialized request object and returns a + deserialized response object. + """ + return self._stubs["security_center_stub"].TestIamPermissions + @property def update_finding(self): """Return the gRPC stub for :meth:`SecurityCenterClient.update_finding`. diff --git a/google/cloud/securitycenter_v1/proto/asset_pb2.py b/google/cloud/securitycenter_v1/proto/asset_pb2.py index 9f5e82a0..834f4147 100644 --- a/google/cloud/securitycenter_v1/proto/asset_pb2.py +++ b/google/cloud/securitycenter_v1/proto/asset_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/asset.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1/proto/finding.proto b/google/cloud/securitycenter_v1/proto/finding.proto index 4ccdc495..cf0873cf 100644 --- a/google/cloud/securitycenter_v1/proto/finding.proto +++ b/google/cloud/securitycenter_v1/proto/finding.proto @@ -101,9 +101,11 @@ message Finding { // to the finding. SecurityMarks security_marks = 8 [(google.api.field_behavior) = OUTPUT_ONLY]; - // The time at which the event took place. For example, if the finding - // represents an open firewall it would capture the time the detector believes - // the firewall became open. The accuracy is determined by the detector. + // The time at which the event took place, or when an update to the finding + // occurred. For example, if the finding represents an open firewall it would + // capture the time the detector believes the firewall became open. The + // accuracy is determined by the detector. If the finding were to be resolved + // afterward, this time would reflect when the finding was resolved. google.protobuf.Timestamp event_time = 9; // The time at which the finding was created in Security Command Center. diff --git a/google/cloud/securitycenter_v1/proto/finding_pb2.py b/google/cloud/securitycenter_v1/proto/finding_pb2.py index c88d7a09..1730357e 100644 --- a/google/cloud/securitycenter_v1/proto/finding_pb2.py +++ b/google/cloud/securitycenter_v1/proto/finding_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/finding.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection @@ -435,10 +435,12 @@ entirely managed by the user and come from the SecurityMarks resource that belongs to the finding. event_time: - The time at which the event took place. For example, if the - finding represents an open firewall it would capture the time - the detector believes the firewall became open. The accuracy - is determined by the detector. + The time at which the event took place, or when an update to + the finding occurred. For example, if the finding represents + an open firewall it would capture the time the detector + believes the firewall became open. The accuracy is determined + by the detector. If the finding were to be resolved afterward, + this time would reflect when the finding was resolved. create_time: The time at which the finding was created in Security Command Center. diff --git a/google/cloud/securitycenter_v1/proto/notification_config_pb2.py b/google/cloud/securitycenter_v1/proto/notification_config_pb2.py index bbd41547..5a318bba 100644 --- a/google/cloud/securitycenter_v1/proto/notification_config_pb2.py +++ b/google/cloud/securitycenter_v1/proto/notification_config_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/notification_config.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1/proto/notification_message_pb2.py b/google/cloud/securitycenter_v1/proto/notification_message_pb2.py index eeb4372c..a7bd5d51 100644 --- a/google/cloud/securitycenter_v1/proto/notification_message_pb2.py +++ b/google/cloud/securitycenter_v1/proto/notification_message_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/notification_message.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1/proto/organization_settings_pb2.py b/google/cloud/securitycenter_v1/proto/organization_settings_pb2.py index c8f94ad6..bd872c24 100644 --- a/google/cloud/securitycenter_v1/proto/organization_settings_pb2.py +++ b/google/cloud/securitycenter_v1/proto/organization_settings_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/organization_settings.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1/proto/resource_pb2.py b/google/cloud/securitycenter_v1/proto/resource_pb2.py index 87bfb51c..c9c16fef 100644 --- a/google/cloud/securitycenter_v1/proto/resource_pb2.py +++ b/google/cloud/securitycenter_v1/proto/resource_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/resource.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1/proto/run_asset_discovery_response_pb2.py b/google/cloud/securitycenter_v1/proto/run_asset_discovery_response_pb2.py index defd52f7..c4e2b2bd 100644 --- a/google/cloud/securitycenter_v1/proto/run_asset_discovery_response_pb2.py +++ b/google/cloud/securitycenter_v1/proto/run_asset_discovery_response_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/run_asset_discovery_response.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1/proto/security_marks_pb2.py b/google/cloud/securitycenter_v1/proto/security_marks_pb2.py index f455b093..c110683b 100644 --- a/google/cloud/securitycenter_v1/proto/security_marks_pb2.py +++ b/google/cloud/securitycenter_v1/proto/security_marks_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/security_marks.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1/proto/securitycenter_service_pb2.py b/google/cloud/securitycenter_v1/proto/securitycenter_service_pb2.py index 9cb7a6b1..4bb4b007 100644 --- a/google/cloud/securitycenter_v1/proto/securitycenter_service_pb2.py +++ b/google/cloud/securitycenter_v1/proto/securitycenter_service_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/securitycenter_service.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1/proto/source_pb2.py b/google/cloud/securitycenter_v1/proto/source_pb2.py index 8e44d1d7..4d5792d1 100644 --- a/google/cloud/securitycenter_v1/proto/source_pb2.py +++ b/google/cloud/securitycenter_v1/proto/source_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1/proto/source.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1beta1/gapic/security_center_client_config.py b/google/cloud/securitycenter_v1beta1/gapic/security_center_client_config.py index 9b5c01a9..6d6b421b 100644 --- a/google/cloud/securitycenter_v1beta1/gapic/security_center_client_config.py +++ b/google/cloud/securitycenter_v1beta1/gapic/security_center_client_config.py @@ -2,110 +2,149 @@ "interfaces": { "google.cloud.securitycenter.v1beta1.SecurityCenter": { "retry_codes": { - "idempotent": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], - "non_idempotent": [], + "retry_policy_1_codes": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], + "no_retry_2_codes": [], + "no_retry_codes": [], + "retry_policy_2_codes": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], + "no_retry_1_codes": [], }, "retry_params": { - "default": { + "retry_policy_1_params": { "initial_retry_delay_millis": 100, "retry_delay_multiplier": 1.3, "max_retry_delay_millis": 60000, - "initial_rpc_timeout_millis": 20000, + "initial_rpc_timeout_millis": 60000, "rpc_timeout_multiplier": 1.0, - "max_rpc_timeout_millis": 20000, - "total_timeout_millis": 600000, - } + "max_rpc_timeout_millis": 60000, + "total_timeout_millis": 60000, + }, + "retry_policy_2_params": { + "initial_retry_delay_millis": 100, + "retry_delay_multiplier": 1.3, + "max_retry_delay_millis": 60000, + "initial_rpc_timeout_millis": 480000, + "rpc_timeout_multiplier": 1.0, + "max_rpc_timeout_millis": 480000, + "total_timeout_millis": 480000, + }, + "no_retry_params": { + "initial_retry_delay_millis": 0, + "retry_delay_multiplier": 0.0, + "max_retry_delay_millis": 0, + "initial_rpc_timeout_millis": 0, + "rpc_timeout_multiplier": 1.0, + "max_rpc_timeout_millis": 0, + "total_timeout_millis": 0, + }, + "no_retry_1_params": { + "initial_retry_delay_millis": 0, + "retry_delay_multiplier": 0.0, + "max_retry_delay_millis": 0, + "initial_rpc_timeout_millis": 60000, + "rpc_timeout_multiplier": 1.0, + "max_rpc_timeout_millis": 60000, + "total_timeout_millis": 60000, + }, + "no_retry_2_params": { + "initial_retry_delay_millis": 0, + "retry_delay_multiplier": 0.0, + "max_retry_delay_millis": 0, + "initial_rpc_timeout_millis": 480000, + "rpc_timeout_multiplier": 1.0, + "max_rpc_timeout_millis": 480000, + "total_timeout_millis": 480000, + }, }, "methods": { "CreateSource": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "CreateFinding": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "GetIamPolicy": { "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", }, "GetOrganizationSettings": { "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", }, "GetSource": { "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", }, "GroupAssets": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "timeout_millis": 480000, + "retry_codes_name": "retry_policy_2_codes", + "retry_params_name": "retry_policy_2_params", }, "GroupFindings": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "timeout_millis": 480000, + "retry_codes_name": "retry_policy_2_codes", + "retry_params_name": "retry_policy_2_params", }, "ListAssets": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "timeout_millis": 480000, + "retry_codes_name": "retry_policy_2_codes", + "retry_params_name": "retry_policy_2_params", }, "ListFindings": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "timeout_millis": 480000, + "retry_codes_name": "retry_policy_2_codes", + "retry_params_name": "retry_policy_2_params", }, "ListSources": { "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", }, "RunAssetDiscovery": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "SetFindingState": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "SetIamPolicy": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "TestIamPermissions": { "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", }, "UpdateFinding": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "UpdateOrganizationSettings": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "UpdateSource": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "UpdateSecurityMarks": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "timeout_millis": 480000, + "retry_codes_name": "no_retry_2_codes", + "retry_params_name": "no_retry_2_params", }, }, } diff --git a/google/cloud/securitycenter_v1beta1/proto/asset.proto b/google/cloud/securitycenter_v1beta1/proto/asset.proto index 85d0e090..b73f7d5b 100644 --- a/google/cloud/securitycenter_v1beta1/proto/asset.proto +++ b/google/cloud/securitycenter_v1beta1/proto/asset.proto @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC. +// 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. @@ -11,13 +11,13 @@ // 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. -// syntax = "proto3"; package google.cloud.securitycenter.v1beta1; import "google/api/field_behavior.proto"; +import "google/api/resource.proto"; import "google/cloud/securitycenter/v1beta1/security_marks.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; @@ -27,25 +27,31 @@ option go_package = "google.golang.org/genproto/googleapis/cloud/securitycenter/ option java_multiple_files = true; option java_package = "com.google.cloud.securitycenter.v1beta1"; -// Cloud Security Command Center's (Cloud SCC) representation of a Google Cloud -// Platform (GCP) resource. +// Security Command Center representation of a Google Cloud +// resource. // -// The Asset is a Cloud SCC resource that captures information about a single -// GCP resource. All modifications to an Asset are only within the context of -// Cloud SCC and don't affect the referenced GCP resource. +// The Asset is a Security Command Center resource that captures information +// about a single Google Cloud resource. All modifications to an Asset are only +// within the context of Security Command Center and don't affect the referenced +// Google Cloud resource. message Asset { - // Cloud SCC managed properties. These properties are managed by Cloud SCC and - // cannot be modified by the user. + option (google.api.resource) = { + type: "securitycenter.googleapis.com/Asset" + pattern: "organizations/{organization}/assets/{asset}" + }; + + // Security Command Center managed properties. These properties are managed by + // Security Command Center and cannot be modified by the user. message SecurityCenterProperties { - // Immutable. The full resource name of the GCP resource this asset + // Immutable. The full resource name of the Google Cloud resource this asset // represents. This field is immutable after create time. See: // https://cloud.google.com/apis/design/resource_names#full_resource_name string resource_name = 1 [(google.api.field_behavior) = IMMUTABLE]; - // The type of the GCP resource. Examples include: APPLICATION, + // The type of the Google Cloud resource. Examples include: APPLICATION, // PROJECT, and ORGANIZATION. This is a case insensitive field defined by - // Cloud SCC and/or the producer of the resource and is immutable - // after create time. + // Security Command Center and/or the producer of the resource and is + // immutable after create time. string resource_type = 2; // The full resource name of the immediate parent of the resource. See: @@ -66,22 +72,22 @@ message Asset { // "organizations/{organization_id}/assets/{asset_id}". string name = 1; - // Cloud SCC managed properties. These properties are managed by - // Cloud SCC and cannot be modified by the user. + // Security Command Center managed properties. These properties are managed by + // Security Command Center and cannot be modified by the user. SecurityCenterProperties security_center_properties = 2; // Resource managed properties. These properties are managed and defined by - // the GCP resource and cannot be modified by the user. + // the Google Cloud resource and cannot be modified by the user. map resource_properties = 7; // User specified security marks. These marks are entirely managed by the user // and come from the SecurityMarks resource that belongs to the asset. SecurityMarks security_marks = 8; - // The time at which the asset was created in Cloud SCC. + // The time at which the asset was created in Security Command Center. google.protobuf.Timestamp create_time = 9; - // The time at which the asset was last updated, added, or deleted in Cloud - // SCC. + // The time at which the asset was last updated, added, or deleted in Security + // Command Center. google.protobuf.Timestamp update_time = 10; } diff --git a/google/cloud/securitycenter_v1beta1/proto/asset_pb2.py b/google/cloud/securitycenter_v1beta1/proto/asset_pb2.py index e1e488ee..ecef17ea 100644 --- a/google/cloud/securitycenter_v1beta1/proto/asset_pb2.py +++ b/google/cloud/securitycenter_v1beta1/proto/asset_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1beta1/proto/asset.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection @@ -13,6 +13,7 @@ from google.api import field_behavior_pb2 as google_dot_api_dot_field__behavior__pb2 +from google.api import resource_pb2 as google_dot_api_dot_resource__pb2 from google.cloud.securitycenter_v1beta1.proto import ( security_marks_pb2 as google_dot_cloud_dot_securitycenter__v1beta1_dot_proto_dot_security__marks__pb2, ) @@ -27,9 +28,10 @@ syntax="proto3", serialized_options=b"\n'com.google.cloud.securitycenter.v1beta1P\001ZQgoogle.golang.org/genproto/googleapis/cloud/securitycenter/v1beta1;securitycenter", create_key=_descriptor._internal_create_key, - serialized_pb=b"\n5google/cloud/securitycenter_v1beta1/proto/asset.proto\x12#google.cloud.securitycenter.v1beta1\x1a\x1fgoogle/api/field_behavior.proto\x1a>google/cloud/securitycenter_v1beta1/proto/security_marks.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1cgoogle/api/annotations.proto\"\xfc\x04\n\x05\x41sset\x12\x0c\n\x04name\x18\x01 \x01(\t\x12g\n\x1asecurity_center_properties\x18\x02 \x01(\x0b\x32\x43.google.cloud.securitycenter.v1beta1.Asset.SecurityCenterProperties\x12_\n\x13resource_properties\x18\x07 \x03(\x0b\x32\x42.google.cloud.securitycenter.v1beta1.Asset.ResourcePropertiesEntry\x12J\n\x0esecurity_marks\x18\x08 \x01(\x0b\x32\x32.google.cloud.securitycenter.v1beta1.SecurityMarks\x12/\n\x0b\x63reate_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0bupdate_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a\x99\x01\n\x18SecurityCenterProperties\x12\x1a\n\rresource_name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x15\n\rresource_type\x18\x02 \x01(\t\x12\x17\n\x0fresource_parent\x18\x03 \x01(\t\x12\x18\n\x10resource_project\x18\x04 \x01(\t\x12\x17\n\x0fresource_owners\x18\x05 \x03(\t\x1aQ\n\x17ResourcePropertiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value:\x02\x38\x01\x42~\n'com.google.cloud.securitycenter.v1beta1P\x01ZQgoogle.golang.org/genproto/googleapis/cloud/securitycenter/v1beta1;securitycenterb\x06proto3", + serialized_pb=b"\n5google/cloud/securitycenter_v1beta1/proto/asset.proto\x12#google.cloud.securitycenter.v1beta1\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a>google/cloud/securitycenter_v1beta1/proto/security_marks.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1cgoogle/api/annotations.proto\"\xd3\x05\n\x05\x41sset\x12\x0c\n\x04name\x18\x01 \x01(\t\x12g\n\x1asecurity_center_properties\x18\x02 \x01(\x0b\x32\x43.google.cloud.securitycenter.v1beta1.Asset.SecurityCenterProperties\x12_\n\x13resource_properties\x18\x07 \x03(\x0b\x32\x42.google.cloud.securitycenter.v1beta1.Asset.ResourcePropertiesEntry\x12J\n\x0esecurity_marks\x18\x08 \x01(\x0b\x32\x32.google.cloud.securitycenter.v1beta1.SecurityMarks\x12/\n\x0b\x63reate_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0bupdate_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a\x99\x01\n\x18SecurityCenterProperties\x12\x1a\n\rresource_name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x15\n\rresource_type\x18\x02 \x01(\t\x12\x17\n\x0fresource_parent\x18\x03 \x01(\t\x12\x18\n\x10resource_project\x18\x04 \x01(\t\x12\x17\n\x0fresource_owners\x18\x05 \x03(\t\x1aQ\n\x17ResourcePropertiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value:\x02\x38\x01:U\xea\x41R\n#securitycenter.googleapis.com/Asset\x12+organizations/{organization}/assets/{asset}B~\n'com.google.cloud.securitycenter.v1beta1P\x01ZQgoogle.golang.org/genproto/googleapis/cloud/securitycenter/v1beta1;securitycenterb\x06proto3", dependencies=[ google_dot_api_dot_field__behavior__pb2.DESCRIPTOR, + google_dot_api_dot_resource__pb2.DESCRIPTOR, google_dot_cloud_dot_securitycenter__v1beta1_dot_proto_dot_security__marks__pb2.DESCRIPTOR, google_dot_protobuf_dot_struct__pb2.DESCRIPTOR, google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR, @@ -150,8 +152,8 @@ syntax="proto3", extension_ranges=[], oneofs=[], - serialized_start=685, - serialized_end=838, + serialized_start=712, + serialized_end=865, ) _ASSET_RESOURCEPROPERTIESENTRY = _descriptor.Descriptor( @@ -209,8 +211,8 @@ syntax="proto3", extension_ranges=[], oneofs=[], - serialized_start=840, - serialized_end=921, + serialized_start=867, + serialized_end=948, ) _ASSET = _descriptor.Descriptor( @@ -339,13 +341,13 @@ extensions=[], nested_types=[_ASSET_SECURITYCENTERPROPERTIES, _ASSET_RESOURCEPROPERTIESENTRY,], enum_types=[], - serialized_options=None, + serialized_options=b"\352AR\n#securitycenter.googleapis.com/Asset\022+organizations/{organization}/assets/{asset}", is_extendable=False, syntax="proto3", extension_ranges=[], oneofs=[], - serialized_start=285, - serialized_end=921, + serialized_start=312, + serialized_end=1035, ) _ASSET_SECURITYCENTERPROPERTIES.containing_type = _ASSET @@ -383,20 +385,21 @@ { "DESCRIPTOR": _ASSET_SECURITYCENTERPROPERTIES, "__module__": "google.cloud.securitycenter_v1beta1.proto.asset_pb2", - "__doc__": """Cloud SCC managed properties. These properties are managed by Cloud - SCC and cannot be modified by the user. + "__doc__": """Security Command Center managed properties. These properties are + managed by Security Command Center and cannot be modified by the user. Attributes: resource_name: - Immutable. The full resource name of the GCP resource this - asset represents. This field is immutable after create time. - See: https://cloud.google.com/apis/design/resource_names#full_ - resource_name + Immutable. The full resource name of the Google Cloud resource + this asset represents. This field is immutable after create + time. See: https://cloud.google.com/apis/design/resource_names + #full_resource_name resource_type: - The type of the GCP resource. Examples include: APPLICATION, - PROJECT, and ORGANIZATION. This is a case insensitive field - defined by Cloud SCC and/or the producer of the resource and - is immutable after create time. + The type of the Google Cloud resource. Examples include: + APPLICATION, PROJECT, and ORGANIZATION. This is a case + insensitive field defined by Security Command Center and/or + the producer of the resource and is immutable after create + time. resource_parent: The full resource name of the immediate parent of the resource. See: https://cloud.google.com/apis/design/resource_n @@ -422,11 +425,11 @@ ), "DESCRIPTOR": _ASSET, "__module__": "google.cloud.securitycenter_v1beta1.proto.asset_pb2", - "__doc__": """Cloud Security Command Center’s (Cloud SCC) representation of a Google - Cloud Platform (GCP) resource. The Asset is a Cloud SCC resource that - captures information about a single GCP resource. All modifications to - an Asset are only within the context of Cloud SCC and don’t affect the - referenced GCP resource. + "__doc__": """Security Command Center representation of a Google Cloud resource. + The Asset is a Security Command Center resource that captures + information about a single Google Cloud resource. All modifications to + an Asset are only within the context of Security Command Center and + don’t affect the referenced Google Cloud resource. Attributes: name: @@ -434,21 +437,23 @@ oogle.com/apis/design/resource_names#relative_resource_name Example: “organizations/{organization_id}/assets/{asset_id}”. security_center_properties: - Cloud SCC managed properties. These properties are managed by - Cloud SCC and cannot be modified by the user. + Security Command Center managed properties. These properties + are managed by Security Command Center and cannot be modified + by the user. resource_properties: Resource managed properties. These properties are managed and - defined by the GCP resource and cannot be modified by the - user. + defined by the Google Cloud resource and cannot be modified by + the user. security_marks: User specified security marks. These marks are entirely managed by the user and come from the SecurityMarks resource that belongs to the asset. create_time: - The time at which the asset was created in Cloud SCC. + The time at which the asset was created in Security Command + Center. update_time: The time at which the asset was last updated, added, or - deleted in Cloud SCC. + deleted in Security Command Center. """, # @@protoc_insertion_point(class_scope:google.cloud.securitycenter.v1beta1.Asset) }, @@ -461,4 +466,5 @@ DESCRIPTOR._options = None _ASSET_SECURITYCENTERPROPERTIES.fields_by_name["resource_name"]._options = None _ASSET_RESOURCEPROPERTIESENTRY._options = None +_ASSET._options = None # @@protoc_insertion_point(module_scope) diff --git a/google/cloud/securitycenter_v1beta1/proto/finding.proto b/google/cloud/securitycenter_v1beta1/proto/finding.proto index e582e6de..647b3b43 100644 --- a/google/cloud/securitycenter_v1beta1/proto/finding.proto +++ b/google/cloud/securitycenter_v1beta1/proto/finding.proto @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC. +// 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. @@ -11,29 +11,28 @@ // 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. -// syntax = "proto3"; package google.cloud.securitycenter.v1beta1; +import "google/api/annotations.proto"; import "google/api/field_behavior.proto"; import "google/api/resource.proto"; import "google/cloud/securitycenter/v1beta1/security_marks.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; -import "google/api/annotations.proto"; option go_package = "google.golang.org/genproto/googleapis/cloud/securitycenter/v1beta1;securitycenter"; option java_multiple_files = true; option java_package = "com.google.cloud.securitycenter.v1beta1"; -// Cloud Security Command Center (Cloud SCC) finding. +// Security Command Center finding. // // A finding is a record of assessment data (security, risk, health or privacy) -// ingested into Cloud SCC for presentation, notification, analysis, -// policy testing, and enforcement. For example, an XSS vulnerability in an -// App Engine application is a finding. +// ingested into Security Command Center for presentation, notification, +// analysis, policy testing, and enforcement. For example, an XSS vulnerability +// in an App Engine application is a finding. message Finding { option (google.api.resource) = { type: "securitycenter.googleapis.com/Finding" @@ -59,19 +58,20 @@ message Finding { // "organizations/{organization_id}/sources/{source_id}/findings/{finding_id}" string name = 1; - // Immutable. The relative resource name of the source the finding belongs to. See: + // Immutable. The relative resource name of the source the finding belongs to. + // See: // https://cloud.google.com/apis/design/resource_names#relative_resource_name // This field is immutable after creation time. // For example: // "organizations/{organization_id}/sources/{source_id}" string parent = 2 [(google.api.field_behavior) = IMMUTABLE]; - // For findings on Google Cloud Platform (GCP) resources, the full resource - // name of the GCP resource this finding is for. See: + // For findings on Google Cloud resources, the full resource + // name of the Google Cloud resource this finding is for. See: // https://cloud.google.com/apis/design/resource_names#full_resource_name - // When the finding is for a non-GCP resource, the resourceName can be a - // customer or partner defined string. - // This field is immutable after creation time. + // When the finding is for a non-Google Cloud resource, the resourceName can + // be a customer or partner defined string. This field is immutable after + // creation time. string resource_name = 3; // The state of the finding. @@ -82,9 +82,9 @@ message Finding { // Example: "XSS_FLASH_INJECTION" string category = 5; - // The URI that, if available, points to a web page outside of Cloud SCC - // where additional information about the finding can be found. This field is - // guaranteed to be either empty or a well formed URL. + // The URI that, if available, points to a web page outside of Security + // Command Center where additional information about the finding can be found. + // This field is guaranteed to be either empty or a well formed URL. string external_uri = 6; // Source specific properties. These properties are managed by the source @@ -98,11 +98,13 @@ message Finding { // to the finding. SecurityMarks security_marks = 8 [(google.api.field_behavior) = OUTPUT_ONLY]; - // The time at which the event took place. For example, if the finding - // represents an open firewall it would capture the time the detector believes - // the firewall became open. The accuracy is determined by the detector. + // The time at which the event took place, or when an update to the finding + // occurred. For example, if the finding represents an open firewall it would + // capture the time the detector believes the firewall became open. The + // accuracy is determined by the detector. If the finding were to be resolved + // afterward, this time would reflect when the finding was resolved. google.protobuf.Timestamp event_time = 9; - // The time at which the finding was created in Cloud SCC. + // The time at which the finding was created in Security Command Center. google.protobuf.Timestamp create_time = 10; } diff --git a/google/cloud/securitycenter_v1beta1/proto/finding_pb2.py b/google/cloud/securitycenter_v1beta1/proto/finding_pb2.py index 0c7b8e81..b62cd8a8 100644 --- a/google/cloud/securitycenter_v1beta1/proto/finding_pb2.py +++ b/google/cloud/securitycenter_v1beta1/proto/finding_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1beta1/proto/finding.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection @@ -12,6 +12,7 @@ _sym_db = _symbol_database.Default() +from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 from google.api import field_behavior_pb2 as google_dot_api_dot_field__behavior__pb2 from google.api import resource_pb2 as google_dot_api_dot_resource__pb2 from google.cloud.securitycenter_v1beta1.proto import ( @@ -19,7 +20,6 @@ ) from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 -from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 DESCRIPTOR = _descriptor.FileDescriptor( @@ -28,14 +28,14 @@ syntax="proto3", serialized_options=b"\n'com.google.cloud.securitycenter.v1beta1P\001ZQgoogle.golang.org/genproto/googleapis/cloud/securitycenter/v1beta1;securitycenter", create_key=_descriptor._internal_create_key, - serialized_pb=b'\n7google/cloud/securitycenter_v1beta1/proto/finding.proto\x12#google.cloud.securitycenter.v1beta1\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a>google/cloud/securitycenter_v1beta1/proto/security_marks.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1cgoogle/api/annotations.proto"\xb8\x05\n\x07\x46inding\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x06parent\x18\x02 \x01(\tB\x03\xe0\x41\x05\x12\x15\n\rresource_name\x18\x03 \x01(\t\x12\x41\n\x05state\x18\x04 \x01(\x0e\x32\x32.google.cloud.securitycenter.v1beta1.Finding.State\x12\x10\n\x08\x63\x61tegory\x18\x05 \x01(\t\x12\x14\n\x0c\x65xternal_uri\x18\x06 \x01(\t\x12]\n\x11source_properties\x18\x07 \x03(\x0b\x32\x42.google.cloud.securitycenter.v1beta1.Finding.SourcePropertiesEntry\x12O\n\x0esecurity_marks\x18\x08 \x01(\x0b\x32\x32.google.cloud.securitycenter.v1beta1.SecurityMarksB\x03\xe0\x41\x03\x12.\n\nevent_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x63reate_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1aO\n\x15SourcePropertiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value:\x02\x38\x01"8\n\x05State\x12\x15\n\x11STATE_UNSPECIFIED\x10\x00\x12\n\n\x06\x41\x43TIVE\x10\x01\x12\x0c\n\x08INACTIVE\x10\x02:l\xea\x41i\n%securitycenter.googleapis.com/Finding\x12@organizations/{organization}/sources/{source}/findings/{finding}B~\n\'com.google.cloud.securitycenter.v1beta1P\x01ZQgoogle.golang.org/genproto/googleapis/cloud/securitycenter/v1beta1;securitycenterb\x06proto3', + serialized_pb=b'\n7google/cloud/securitycenter_v1beta1/proto/finding.proto\x12#google.cloud.securitycenter.v1beta1\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a>google/cloud/securitycenter_v1beta1/proto/security_marks.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\xb8\x05\n\x07\x46inding\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x06parent\x18\x02 \x01(\tB\x03\xe0\x41\x05\x12\x15\n\rresource_name\x18\x03 \x01(\t\x12\x41\n\x05state\x18\x04 \x01(\x0e\x32\x32.google.cloud.securitycenter.v1beta1.Finding.State\x12\x10\n\x08\x63\x61tegory\x18\x05 \x01(\t\x12\x14\n\x0c\x65xternal_uri\x18\x06 \x01(\t\x12]\n\x11source_properties\x18\x07 \x03(\x0b\x32\x42.google.cloud.securitycenter.v1beta1.Finding.SourcePropertiesEntry\x12O\n\x0esecurity_marks\x18\x08 \x01(\x0b\x32\x32.google.cloud.securitycenter.v1beta1.SecurityMarksB\x03\xe0\x41\x03\x12.\n\nevent_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x63reate_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1aO\n\x15SourcePropertiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value:\x02\x38\x01"8\n\x05State\x12\x15\n\x11STATE_UNSPECIFIED\x10\x00\x12\n\n\x06\x41\x43TIVE\x10\x01\x12\x0c\n\x08INACTIVE\x10\x02:l\xea\x41i\n%securitycenter.googleapis.com/Finding\x12@organizations/{organization}/sources/{source}/findings/{finding}B~\n\'com.google.cloud.securitycenter.v1beta1P\x01ZQgoogle.golang.org/genproto/googleapis/cloud/securitycenter/v1beta1;securitycenterb\x06proto3', dependencies=[ + google_dot_api_dot_annotations__pb2.DESCRIPTOR, google_dot_api_dot_field__behavior__pb2.DESCRIPTOR, google_dot_api_dot_resource__pb2.DESCRIPTOR, google_dot_cloud_dot_securitycenter__v1beta1_dot_proto_dot_security__marks__pb2.DESCRIPTOR, google_dot_protobuf_dot_struct__pb2.DESCRIPTOR, google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR, - google_dot_api_dot_annotations__pb2.DESCRIPTOR, ], ) @@ -388,9 +388,9 @@ ), "DESCRIPTOR": _FINDING, "__module__": "google.cloud.securitycenter_v1beta1.proto.finding_pb2", - "__doc__": """Cloud Security Command Center (Cloud SCC) finding. A finding is a - record of assessment data (security, risk, health or privacy) ingested - into Cloud SCC for presentation, notification, analysis, policy + "__doc__": """Security Command Center finding. A finding is a record of assessment + data (security, risk, health or privacy) ingested into Security + Command Center for presentation, notification, analysis, policy testing, and enforcement. For example, an XSS vulnerability in an App Engine application is a finding. @@ -407,10 +407,10 @@ after creation time. For example: “organizations/{organization_id}/sources/{source_id}” resource_name: - For findings on Google Cloud Platform (GCP) resources, the - full resource name of the GCP resource this finding is for. - See: https://cloud.google.com/apis/design/resource_names#full_ - resource_name When the finding is for a non-GCP resource, the + For findings on Google Cloud resources, the full resource name + of the Google Cloud resource this finding is for. See: https:/ + /cloud.google.com/apis/design/resource_names#full_resource_nam + e When the finding is for a non-Google Cloud resource, the resourceName can be a customer or partner defined string. This field is immutable after creation time. state: @@ -421,9 +421,9 @@ “XSS_FLASH_INJECTION” external_uri: The URI that, if available, points to a web page outside of - Cloud SCC where additional information about the finding can - be found. This field is guaranteed to be either empty or a - well formed URL. + Security Command Center where additional information about the + finding can be found. This field is guaranteed to be either + empty or a well formed URL. source_properties: Source specific properties. These properties are managed by the source that writes the finding. The key names in the @@ -435,12 +435,15 @@ entirely managed by the user and come from the SecurityMarks resource that belongs to the finding. event_time: - The time at which the event took place. For example, if the - finding represents an open firewall it would capture the time - the detector believes the firewall became open. The accuracy - is determined by the detector. + The time at which the event took place, or when an update to + the finding occurred. For example, if the finding represents + an open firewall it would capture the time the detector + believes the firewall became open. The accuracy is determined + by the detector. If the finding were to be resolved afterward, + this time would reflect when the finding was resolved. create_time: - The time at which the finding was created in Cloud SCC. + The time at which the finding was created in Security Command + Center. """, # @@protoc_insertion_point(class_scope:google.cloud.securitycenter.v1beta1.Finding) }, diff --git a/google/cloud/securitycenter_v1beta1/proto/organization_settings.proto b/google/cloud/securitycenter_v1beta1/proto/organization_settings.proto index 9f7f2b0e..88b2008a 100644 --- a/google/cloud/securitycenter_v1beta1/proto/organization_settings.proto +++ b/google/cloud/securitycenter_v1beta1/proto/organization_settings.proto @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC. +// 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. @@ -11,7 +11,6 @@ // 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. -// syntax = "proto3"; @@ -24,8 +23,8 @@ option go_package = "google.golang.org/genproto/googleapis/cloud/securitycenter/ option java_multiple_files = true; option java_package = "com.google.cloud.securitycenter.v1beta1"; -// User specified settings that are attached to the Cloud Security Command -// Center (Cloud SCC) organization. +// User specified settings that are attached to the Security Command +// Center organization. message OrganizationSettings { option (google.api.resource) = { type: "securitycenter.googleapis.com/OrganizationSettings" diff --git a/google/cloud/securitycenter_v1beta1/proto/organization_settings_pb2.py b/google/cloud/securitycenter_v1beta1/proto/organization_settings_pb2.py index 779190be..0482472a 100644 --- a/google/cloud/securitycenter_v1beta1/proto/organization_settings_pb2.py +++ b/google/cloud/securitycenter_v1beta1/proto/organization_settings_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1beta1/proto/organization_settings.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection @@ -243,8 +243,8 @@ ), "DESCRIPTOR": _ORGANIZATIONSETTINGS, "__module__": "google.cloud.securitycenter_v1beta1.proto.organization_settings_pb2", - "__doc__": """User specified settings that are attached to the Cloud Security - Command Center (Cloud SCC) organization. + "__doc__": """User specified settings that are attached to the Security Command + Center organization. Attributes: name: diff --git a/google/cloud/securitycenter_v1beta1/proto/run_asset_discovery_response.proto b/google/cloud/securitycenter_v1beta1/proto/run_asset_discovery_response.proto index 53ba02ef..20d3b25b 100644 --- a/google/cloud/securitycenter_v1beta1/proto/run_asset_discovery_response.proto +++ b/google/cloud/securitycenter_v1beta1/proto/run_asset_discovery_response.proto @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC. +// 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. @@ -11,7 +11,6 @@ // 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. -// syntax = "proto3"; diff --git a/google/cloud/securitycenter_v1beta1/proto/run_asset_discovery_response_pb2.py b/google/cloud/securitycenter_v1beta1/proto/run_asset_discovery_response_pb2.py index dc17572d..6084afdf 100644 --- a/google/cloud/securitycenter_v1beta1/proto/run_asset_discovery_response_pb2.py +++ b/google/cloud/securitycenter_v1beta1/proto/run_asset_discovery_response_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1beta1/proto/run_asset_discovery_response.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1beta1/proto/security_marks.proto b/google/cloud/securitycenter_v1beta1/proto/security_marks.proto index 97baf247..2547c306 100644 --- a/google/cloud/securitycenter_v1beta1/proto/security_marks.proto +++ b/google/cloud/securitycenter_v1beta1/proto/security_marks.proto @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC. +// 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. @@ -11,7 +11,6 @@ // 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. -// syntax = "proto3"; @@ -24,9 +23,9 @@ option go_package = "google.golang.org/genproto/googleapis/cloud/securitycenter/ option java_multiple_files = true; option java_package = "com.google.cloud.securitycenter.v1beta1"; -// User specified security marks that are attached to the parent Cloud Security -// Command Center (Cloud SCC) resource. Security marks are scoped within a Cloud -// SCC organization -- they can be modified and viewed by all users who have +// User specified security marks that are attached to the parent Security +// Command Center resource. Security marks are scoped within a Security Command +// Center organization -- they can be modified and viewed by all users who have // proper permissions on the organization. message SecurityMarks { option (google.api.resource) = { diff --git a/google/cloud/securitycenter_v1beta1/proto/security_marks_pb2.py b/google/cloud/securitycenter_v1beta1/proto/security_marks_pb2.py index a9cae49e..144c51d3 100644 --- a/google/cloud/securitycenter_v1beta1/proto/security_marks_pb2.py +++ b/google/cloud/securitycenter_v1beta1/proto/security_marks_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1beta1/proto/security_marks.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection @@ -168,10 +168,10 @@ ), "DESCRIPTOR": _SECURITYMARKS, "__module__": "google.cloud.securitycenter_v1beta1.proto.security_marks_pb2", - "__doc__": """User specified security marks that are attached to the parent Cloud - Security Command Center (Cloud SCC) resource. Security marks are - scoped within a Cloud SCC organization – they can be modified and - viewed by all users who have proper permissions on the organization. + "__doc__": """User specified security marks that are attached to the parent Security + Command Center resource. Security marks are scoped within a Security + Command Center organization – they can be modified and viewed by all + users who have proper permissions on the organization. Attributes: name: diff --git a/google/cloud/securitycenter_v1beta1/proto/securitycenter_service.proto b/google/cloud/securitycenter_v1beta1/proto/securitycenter_service.proto index ba2edf4e..351c1f4a 100644 --- a/google/cloud/securitycenter_v1beta1/proto/securitycenter_service.proto +++ b/google/cloud/securitycenter_v1beta1/proto/securitycenter_service.proto @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC. +// 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. @@ -11,7 +11,6 @@ // 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. -// syntax = "proto3"; diff --git a/google/cloud/securitycenter_v1beta1/proto/securitycenter_service_pb2.py b/google/cloud/securitycenter_v1beta1/proto/securitycenter_service_pb2.py index 98f66db7..8616e6cb 100644 --- a/google/cloud/securitycenter_v1beta1/proto/securitycenter_service_pb2.py +++ b/google/cloud/securitycenter_v1beta1/proto/securitycenter_service_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1beta1/proto/securitycenter_service.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1beta1/proto/source.proto b/google/cloud/securitycenter_v1beta1/proto/source.proto index 98025bca..fb1e6c6a 100644 --- a/google/cloud/securitycenter_v1beta1/proto/source.proto +++ b/google/cloud/securitycenter_v1beta1/proto/source.proto @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC. +// 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. @@ -11,7 +11,6 @@ // 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. -// syntax = "proto3"; @@ -24,7 +23,7 @@ option go_package = "google.golang.org/genproto/googleapis/cloud/securitycenter/ option java_multiple_files = true; option java_package = "com.google.cloud.securitycenter.v1beta1"; -// Cloud Security Command Center's (Cloud SCC) finding source. A finding source +// Security Command Center finding source. A finding source // is an entity or a mechanism that can produce a finding. A source is like a // container of findings that come from the same scanner, logger, monitor, etc. message Source { @@ -48,7 +47,7 @@ message Source { // The description of the source (max of 1024 characters). // Example: - // "Cloud Security Scanner is a web security scanner for common + // "Web Security Scanner is a web security scanner for common // vulnerabilities in App Engine applications. It can automatically // scan and detect four common vulnerabilities, including cross-site-scripting // (XSS), Flash injection, mixed content (HTTP in HTTPS), and diff --git a/google/cloud/securitycenter_v1beta1/proto/source_pb2.py b/google/cloud/securitycenter_v1beta1/proto/source_pb2.py index 835fccd5..012d09ce 100644 --- a/google/cloud/securitycenter_v1beta1/proto/source_pb2.py +++ b/google/cloud/securitycenter_v1beta1/proto/source_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1beta1/proto/source.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection @@ -117,10 +117,10 @@ { "DESCRIPTOR": _SOURCE, "__module__": "google.cloud.securitycenter_v1beta1.proto.source_pb2", - "__doc__": """Cloud Security Command Center’s (Cloud SCC) finding source. A finding - source is an entity or a mechanism that can produce a finding. A - source is like a container of findings that come from the same - scanner, logger, monitor, etc. + "__doc__": """Security Command Center finding source. A finding source is an entity + or a mechanism that can produce a finding. A source is like a + container of findings that come from the same scanner, logger, + monitor, etc. Attributes: name: @@ -135,7 +135,7 @@ (inclusive). description: The description of the source (max of 1024 characters). - Example: “Cloud Security Scanner is a web security scanner for + Example: “Web Security Scanner is a web security scanner for common vulnerabilities in App Engine applications. It can automatically scan and detect four common vulnerabilities, including cross-site-scripting (XSS), Flash injection, mixed diff --git a/google/cloud/securitycenter_v1p1beta1/gapic/enums.py b/google/cloud/securitycenter_v1p1beta1/gapic/enums.py index 9dc872dd..9a308dd5 100644 --- a/google/cloud/securitycenter_v1p1beta1/gapic/enums.py +++ b/google/cloud/securitycenter_v1p1beta1/gapic/enums.py @@ -34,6 +34,24 @@ class NullValue(enum.IntEnum): class Finding(object): + class Severity(enum.IntEnum): + """ + The severity of the finding. + + Attributes: + SEVERITY_UNSPECIFIED (int): No severity specified. The default value. + CRITICAL (int): Critical severity. + HIGH (int): High severity. + MEDIUM (int): Medium severity. + LOW (int): Low severity. + """ + + SEVERITY_UNSPECIFIED = 0 + CRITICAL = 1 + HIGH = 2 + MEDIUM = 3 + LOW = 4 + class State(enum.IntEnum): """ The state of the finding. diff --git a/google/cloud/securitycenter_v1p1beta1/gapic/security_center_client.py b/google/cloud/securitycenter_v1p1beta1/gapic/security_center_client.py index 6e667b1c..b236e9f0 100644 --- a/google/cloud/securitycenter_v1p1beta1/gapic/security_center_client.py +++ b/google/cloud/securitycenter_v1p1beta1/gapic/security_center_client.py @@ -376,8 +376,6 @@ def create_finding( parent (str): Required. Resource name of the new finding's parent. Its format should be "organizations/[organization_id]/sources/[source_id]". finding_id (str): Required. Unique identifier provided by the client within the parent scope. - It must be alphanumeric and less than or equal to 32 characters and - greater than 0 characters in length. finding (Union[dict, ~google.cloud.securitycenter_v1p1beta1.types.Finding]): Required. The Finding being created. The name and security_marks will be ignored as they are both output only fields on this resource. @@ -467,9 +465,8 @@ def create_notification_config( Unique identifier provided by the client within the parent scope. It must be between 1 and 128 characters, and contains alphanumeric characters, underscores or hyphens only. - notification_config (Union[dict, ~google.cloud.securitycenter_v1p1beta1.types.NotificationConfig]): Required. The notification config being created. The name and the service - account will be ignored as they are both output only fields on this - resource. + notification_config (Union[dict, ~google.cloud.securitycenter_v1p1beta1.types.NotificationConfig]): Required. The notification config being created. The name and the service account + will be ignored as they are both output only fields on this resource. If a dict is provided, it must be of the same form as the protobuf message :class:`~google.cloud.securitycenter_v1p1beta1.types.NotificationConfig` @@ -1526,8 +1523,7 @@ def list_assets( If a dict is provided, it must be of the same form as the protobuf message :class:`~google.cloud.securitycenter_v1p1beta1.types.Duration` - field_mask (Union[dict, ~google.cloud.securitycenter_v1p1beta1.types.FieldMask]): Optional. - A field mask to specify the ListAssetsResult fields to be listed in the + field_mask (Union[dict, ~google.cloud.securitycenter_v1p1beta1.types.FieldMask]): A field mask to specify the ListAssetsResult fields to be listed in the response. An empty field mask will list all fields. @@ -1748,8 +1744,7 @@ def list_findings( If a dict is provided, it must be of the same form as the protobuf message :class:`~google.cloud.securitycenter_v1p1beta1.types.Duration` - field_mask (Union[dict, ~google.cloud.securitycenter_v1p1beta1.types.FieldMask]): Optional. - A field mask to specify the Finding fields to be listed in the response. + field_mask (Union[dict, ~google.cloud.securitycenter_v1p1beta1.types.FieldMask]): A field mask to specify the Finding fields to be listed in the response. An empty field mask will list all fields. If a dict is provided, it must be of the same form as the protobuf diff --git a/google/cloud/securitycenter_v1p1beta1/gapic/security_center_client_config.py b/google/cloud/securitycenter_v1p1beta1/gapic/security_center_client_config.py index 975998d8..1f6297b6 100644 --- a/google/cloud/securitycenter_v1p1beta1/gapic/security_center_client_config.py +++ b/google/cloud/securitycenter_v1p1beta1/gapic/security_center_client_config.py @@ -2,135 +2,174 @@ "interfaces": { "google.cloud.securitycenter.v1p1beta1.SecurityCenter": { "retry_codes": { - "idempotent": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], - "non_idempotent": [], + "retry_policy_1_codes": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], + "no_retry_2_codes": [], + "no_retry_codes": [], + "retry_policy_2_codes": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], + "no_retry_1_codes": [], }, "retry_params": { - "default": { + "retry_policy_1_params": { "initial_retry_delay_millis": 100, "retry_delay_multiplier": 1.3, "max_retry_delay_millis": 60000, - "initial_rpc_timeout_millis": 20000, + "initial_rpc_timeout_millis": 60000, "rpc_timeout_multiplier": 1.0, - "max_rpc_timeout_millis": 20000, - "total_timeout_millis": 600000, - } + "max_rpc_timeout_millis": 60000, + "total_timeout_millis": 60000, + }, + "retry_policy_2_params": { + "initial_retry_delay_millis": 100, + "retry_delay_multiplier": 1.3, + "max_retry_delay_millis": 60000, + "initial_rpc_timeout_millis": 480000, + "rpc_timeout_multiplier": 1.0, + "max_rpc_timeout_millis": 480000, + "total_timeout_millis": 480000, + }, + "no_retry_params": { + "initial_retry_delay_millis": 0, + "retry_delay_multiplier": 0.0, + "max_retry_delay_millis": 0, + "initial_rpc_timeout_millis": 0, + "rpc_timeout_multiplier": 1.0, + "max_rpc_timeout_millis": 0, + "total_timeout_millis": 0, + }, + "no_retry_1_params": { + "initial_retry_delay_millis": 0, + "retry_delay_multiplier": 0.0, + "max_retry_delay_millis": 0, + "initial_rpc_timeout_millis": 60000, + "rpc_timeout_multiplier": 1.0, + "max_rpc_timeout_millis": 60000, + "total_timeout_millis": 60000, + }, + "no_retry_2_params": { + "initial_retry_delay_millis": 0, + "retry_delay_multiplier": 0.0, + "max_retry_delay_millis": 0, + "initial_rpc_timeout_millis": 480000, + "rpc_timeout_multiplier": 1.0, + "max_rpc_timeout_millis": 480000, + "total_timeout_millis": 480000, + }, }, "methods": { "CreateSource": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "CreateFinding": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "CreateNotificationConfig": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "DeleteNotificationConfig": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "GetIamPolicy": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", }, "GetNotificationConfig": { "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", }, "GetOrganizationSettings": { "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", }, "GetSource": { "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", }, "GroupAssets": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "timeout_millis": 480000, + "retry_codes_name": "retry_policy_2_codes", + "retry_params_name": "retry_policy_2_params", }, "GroupFindings": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "timeout_millis": 480000, + "retry_codes_name": "retry_policy_2_codes", + "retry_params_name": "retry_policy_2_params", }, "ListAssets": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "timeout_millis": 480000, + "retry_codes_name": "retry_policy_2_codes", + "retry_params_name": "retry_policy_2_params", }, "ListFindings": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "timeout_millis": 480000, + "retry_codes_name": "retry_policy_2_codes", + "retry_params_name": "retry_policy_2_params", }, "ListNotificationConfigs": { "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", }, "ListSources": { "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", }, "RunAssetDiscovery": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "SetFindingState": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "SetIamPolicy": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "TestIamPermissions": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "retry_policy_1_codes", + "retry_params_name": "retry_policy_1_params", }, "UpdateFinding": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "UpdateNotificationConfig": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "UpdateOrganizationSettings": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "UpdateSource": { "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "retry_codes_name": "no_retry_1_codes", + "retry_params_name": "no_retry_1_params", }, "UpdateSecurityMarks": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", + "timeout_millis": 480000, + "retry_codes_name": "no_retry_2_codes", + "retry_params_name": "no_retry_2_params", }, }, } diff --git a/google/cloud/securitycenter_v1p1beta1/proto/asset_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/asset_pb2.py index 17685d49..7279b30b 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/asset_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/asset_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/asset.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1p1beta1/proto/finding.proto b/google/cloud/securitycenter_v1p1beta1/proto/finding.proto index 21b65536..49f8159f 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/finding.proto +++ b/google/cloud/securitycenter_v1p1beta1/proto/finding.proto @@ -55,6 +55,24 @@ message Finding { INACTIVE = 2; } + // The severity of the finding. + enum Severity { + // No severity specified. The default value. + SEVERITY_UNSPECIFIED = 0; + + // Critical severity. + CRITICAL = 1; + + // High severity. + HIGH = 2; + + // Medium severity. + MEDIUM = 3; + + // Low severity. + LOW = 4; + } + // The relative resource name of this finding. See: // https://cloud.google.com/apis/design/resource_names#relative_resource_name // Example: @@ -100,11 +118,16 @@ message Finding { // to the finding. SecurityMarks security_marks = 8 [(google.api.field_behavior) = OUTPUT_ONLY]; - // The time at which the event took place. For example, if the finding - // represents an open firewall it would capture the time the detector believes - // the firewall became open. The accuracy is determined by the detector. + // The time at which the event took place, or when an update to the finding + // occurred. For example, if the finding represents an open firewall it would + // capture the time the detector believes the firewall became open. The + // accuracy is determined by the detector. If the finding were to be resolved + // afterward, this time would reflect when the finding was resolved. google.protobuf.Timestamp event_time = 9; // The time at which the finding was created in Security Command Center. google.protobuf.Timestamp create_time = 10; + + // The severity of the finding. + Severity severity = 13; } diff --git a/google/cloud/securitycenter_v1p1beta1/proto/finding_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/finding_pb2.py index 84acbbfe..97dc7485 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/finding_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/finding_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/finding.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection @@ -28,7 +28,7 @@ syntax="proto3", serialized_options=b"\n)com.google.cloud.securitycenter.v1p1beta1P\001ZSgoogle.golang.org/genproto/googleapis/cloud/securitycenter/v1p1beta1;securitycenter\252\002%Google.Cloud.SecurityCenter.V1P1Beta1\312\002%Google\\Cloud\\SecurityCenter\\V1p1beta1\352\002(Google::Cloud::SecurityCenter::V1p1beta1", create_key=_descriptor._internal_create_key, - serialized_pb=b'\n9google/cloud/securitycenter_v1p1beta1/proto/finding.proto\x12%google.cloud.securitycenter.v1p1beta1\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a@google/cloud/securitycenter_v1p1beta1/proto/security_marks.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\xb9\x05\n\x07\x46inding\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06parent\x18\x02 \x01(\t\x12\x15\n\rresource_name\x18\x03 \x01(\t\x12\x43\n\x05state\x18\x04 \x01(\x0e\x32\x34.google.cloud.securitycenter.v1p1beta1.Finding.State\x12\x10\n\x08\x63\x61tegory\x18\x05 \x01(\t\x12\x14\n\x0c\x65xternal_uri\x18\x06 \x01(\t\x12_\n\x11source_properties\x18\x07 \x03(\x0b\x32\x44.google.cloud.securitycenter.v1p1beta1.Finding.SourcePropertiesEntry\x12Q\n\x0esecurity_marks\x18\x08 \x01(\x0b\x32\x34.google.cloud.securitycenter.v1p1beta1.SecurityMarksB\x03\xe0\x41\x03\x12.\n\nevent_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x63reate_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1aO\n\x15SourcePropertiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value:\x02\x38\x01"8\n\x05State\x12\x15\n\x11STATE_UNSPECIFIED\x10\x00\x12\n\n\x06\x41\x43TIVE\x10\x01\x12\x0c\n\x08INACTIVE\x10\x02:l\xea\x41i\n%securitycenter.googleapis.com/Finding\x12@organizations/{organization}/sources/{source}/findings/{finding}B\xfd\x01\n)com.google.cloud.securitycenter.v1p1beta1P\x01ZSgoogle.golang.org/genproto/googleapis/cloud/securitycenter/v1p1beta1;securitycenter\xaa\x02%Google.Cloud.SecurityCenter.V1P1Beta1\xca\x02%Google\\Cloud\\SecurityCenter\\V1p1beta1\xea\x02(Google::Cloud::SecurityCenter::V1p1beta1b\x06proto3', + serialized_pb=b'\n9google/cloud/securitycenter_v1p1beta1/proto/finding.proto\x12%google.cloud.securitycenter.v1p1beta1\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a@google/cloud/securitycenter_v1p1beta1/proto/security_marks.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\xd7\x06\n\x07\x46inding\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06parent\x18\x02 \x01(\t\x12\x15\n\rresource_name\x18\x03 \x01(\t\x12\x43\n\x05state\x18\x04 \x01(\x0e\x32\x34.google.cloud.securitycenter.v1p1beta1.Finding.State\x12\x10\n\x08\x63\x61tegory\x18\x05 \x01(\t\x12\x14\n\x0c\x65xternal_uri\x18\x06 \x01(\t\x12_\n\x11source_properties\x18\x07 \x03(\x0b\x32\x44.google.cloud.securitycenter.v1p1beta1.Finding.SourcePropertiesEntry\x12Q\n\x0esecurity_marks\x18\x08 \x01(\x0b\x32\x34.google.cloud.securitycenter.v1p1beta1.SecurityMarksB\x03\xe0\x41\x03\x12.\n\nevent_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x63reate_time\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12I\n\x08severity\x18\r \x01(\x0e\x32\x37.google.cloud.securitycenter.v1p1beta1.Finding.Severity\x1aO\n\x15SourcePropertiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value:\x02\x38\x01"8\n\x05State\x12\x15\n\x11STATE_UNSPECIFIED\x10\x00\x12\n\n\x06\x41\x43TIVE\x10\x01\x12\x0c\n\x08INACTIVE\x10\x02"Q\n\x08Severity\x12\x18\n\x14SEVERITY_UNSPECIFIED\x10\x00\x12\x0c\n\x08\x43RITICAL\x10\x01\x12\x08\n\x04HIGH\x10\x02\x12\n\n\x06MEDIUM\x10\x03\x12\x07\n\x03LOW\x10\x04:l\xea\x41i\n%securitycenter.googleapis.com/Finding\x12@organizations/{organization}/sources/{source}/findings/{finding}B\xfd\x01\n)com.google.cloud.securitycenter.v1p1beta1P\x01ZSgoogle.golang.org/genproto/googleapis/cloud/securitycenter/v1p1beta1;securitycenter\xaa\x02%Google.Cloud.SecurityCenter.V1P1Beta1\xca\x02%Google\\Cloud\\SecurityCenter\\V1p1beta1\xea\x02(Google::Cloud::SecurityCenter::V1p1beta1b\x06proto3', dependencies=[ google_dot_api_dot_annotations__pb2.DESCRIPTOR, google_dot_api_dot_field__behavior__pb2.DESCRIPTOR, @@ -74,11 +74,66 @@ ], containing_type=None, serialized_options=None, - serialized_start=851, - serialized_end=907, + serialized_start=926, + serialized_end=982, ) _sym_db.RegisterEnumDescriptor(_FINDING_STATE) +_FINDING_SEVERITY = _descriptor.EnumDescriptor( + name="Severity", + full_name="google.cloud.securitycenter.v1p1beta1.Finding.Severity", + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name="SEVERITY_UNSPECIFIED", + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="CRITICAL", + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="HIGH", + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="MEDIUM", + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="LOW", + index=4, + number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=984, + serialized_end=1065, +) +_sym_db.RegisterEnumDescriptor(_FINDING_SEVERITY) + _FINDING_SOURCEPROPERTIESENTRY = _descriptor.Descriptor( name="SourcePropertiesEntry", @@ -135,8 +190,8 @@ syntax="proto3", extension_ranges=[], oneofs=[], - serialized_start=770, - serialized_end=849, + serialized_start=845, + serialized_end=924, ) _FINDING = _descriptor.Descriptor( @@ -337,17 +392,36 @@ file=DESCRIPTOR, create_key=_descriptor._internal_create_key, ), + _descriptor.FieldDescriptor( + name="severity", + full_name="google.cloud.securitycenter.v1p1beta1.Finding.severity", + index=10, + number=13, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), ], extensions=[], nested_types=[_FINDING_SOURCEPROPERTIESENTRY,], - enum_types=[_FINDING_STATE,], + enum_types=[_FINDING_STATE, _FINDING_SEVERITY,], serialized_options=b"\352Ai\n%securitycenter.googleapis.com/Finding\022@organizations/{organization}/sources/{source}/findings/{finding}", is_extendable=False, syntax="proto3", extension_ranges=[], oneofs=[], serialized_start=320, - serialized_end=1017, + serialized_end=1175, ) _FINDING_SOURCEPROPERTIESENTRY.fields_by_name[ @@ -369,7 +443,9 @@ _FINDING.fields_by_name[ "create_time" ].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP +_FINDING.fields_by_name["severity"].enum_type = _FINDING_SEVERITY _FINDING_STATE.containing_type = _FINDING +_FINDING_SEVERITY.containing_type = _FINDING DESCRIPTOR.message_types_by_name["Finding"] = _FINDING _sym_db.RegisterFileDescriptor(DESCRIPTOR) @@ -435,13 +511,17 @@ entirely managed by the user and come from the SecurityMarks resource that belongs to the finding. event_time: - The time at which the event took place. For example, if the - finding represents an open firewall it would capture the time - the detector believes the firewall became open. The accuracy - is determined by the detector. + The time at which the event took place, or when an update to + the finding occurred. For example, if the finding represents + an open firewall it would capture the time the detector + believes the firewall became open. The accuracy is determined + by the detector. If the finding were to be resolved afterward, + this time would reflect when the finding was resolved. create_time: The time at which the finding was created in Security Command Center. + severity: + The severity of the finding. """, # @@protoc_insertion_point(class_scope:google.cloud.securitycenter.v1p1beta1.Finding) }, diff --git a/google/cloud/securitycenter_v1p1beta1/proto/notification_config_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/notification_config_pb2.py index 9564eaaa..8bbd4f58 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/notification_config_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/notification_config_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/notification_config.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1p1beta1/proto/notification_message_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/notification_message_pb2.py index 3d43d832..ad130b54 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/notification_message_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/notification_message_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/notification_message.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1p1beta1/proto/organization_settings_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/organization_settings_pb2.py index 83e3bca4..544781d4 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/organization_settings_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/organization_settings_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/organization_settings.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1p1beta1/proto/resource_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/resource_pb2.py index b44b1fc9..8ed3294f 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/resource_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/resource_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/resource.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1p1beta1/proto/run_asset_discovery_response_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/run_asset_discovery_response_pb2.py index 33099e91..a2657770 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/run_asset_discovery_response_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/run_asset_discovery_response_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/run_asset_discovery_response.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1p1beta1/proto/security_marks_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/security_marks_pb2.py index d8d0db24..76a7c221 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/security_marks_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/security_marks_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/security_marks.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/google/cloud/securitycenter_v1p1beta1/proto/securitycenter_service.proto b/google/cloud/securitycenter_v1p1beta1/proto/securitycenter_service.proto index c4264a6a..69d864c6 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/securitycenter_service.proto +++ b/google/cloud/securitycenter_v1p1beta1/proto/securitycenter_service.proto @@ -17,7 +17,6 @@ syntax = "proto3"; package google.cloud.securitycenter.v1p1beta1; import public "google/cloud/securitycenter/v1p1beta1/run_asset_discovery_response.proto"; - import "google/api/annotations.proto"; import "google/api/client.proto"; import "google/api/field_behavior.proto"; @@ -47,8 +46,7 @@ option ruby_package = "Google::Cloud::SecurityCenter::V1p1beta1"; // V1p1Beta1 APIs for Security Center service. service SecurityCenter { option (google.api.default_host) = "securitycenter.googleapis.com"; - option (google.api.oauth_scopes) = - "https://www.googleapis.com/auth/cloud-platform"; + option (google.api.oauth_scopes) = "https://www.googleapis.com/auth/cloud-platform"; // Creates a source. rpc CreateSource(CreateSourceRequest) returns (Source) { @@ -59,7 +57,6 @@ service SecurityCenter { option (google.api.method_signature) = "parent,source"; } - // // Creates a finding. The corresponding source must exist for finding // creation to succeed. rpc CreateFinding(CreateFindingRequest) returns (Finding) { @@ -72,20 +69,17 @@ service SecurityCenter { } // Creates a notification config. - rpc CreateNotificationConfig(CreateNotificationConfigRequest) - returns (NotificationConfig) { + rpc CreateNotificationConfig(CreateNotificationConfigRequest) returns (NotificationConfig) { option (google.api.http) = { post: "/v1p1beta1/{parent=organizations/*}/notificationConfigs" body: "notification_config" }; - option (google.api.method_signature) = - "parent,config_id,notification_config"; + option (google.api.method_signature) = "parent,config_id,notification_config"; option (google.api.method_signature) = "parent,notification_config"; } // Deletes a notification config. - rpc DeleteNotificationConfig(DeleteNotificationConfigRequest) - returns (google.protobuf.Empty) { + rpc DeleteNotificationConfig(DeleteNotificationConfigRequest) returns (google.protobuf.Empty) { option (google.api.http) = { delete: "/v1p1beta1/{name=organizations/*/notificationConfigs/*}" }; @@ -93,8 +87,7 @@ service SecurityCenter { } // Gets the access control policy on the specified Source. - rpc GetIamPolicy(google.iam.v1.GetIamPolicyRequest) - returns (google.iam.v1.Policy) { + rpc GetIamPolicy(google.iam.v1.GetIamPolicyRequest) returns (google.iam.v1.Policy) { option (google.api.http) = { post: "/v1p1beta1/{resource=organizations/*/sources/*}:getIamPolicy" body: "*" @@ -103,8 +96,7 @@ service SecurityCenter { } // Gets a notification config. - rpc GetNotificationConfig(GetNotificationConfigRequest) - returns (NotificationConfig) { + rpc GetNotificationConfig(GetNotificationConfigRequest) returns (NotificationConfig) { option (google.api.http) = { get: "/v1p1beta1/{name=organizations/*/notificationConfigs/*}" }; @@ -112,8 +104,7 @@ service SecurityCenter { } // Gets the settings for an organization. - rpc GetOrganizationSettings(GetOrganizationSettingsRequest) - returns (OrganizationSettings) { + rpc GetOrganizationSettings(GetOrganizationSettingsRequest) returns (OrganizationSettings) { option (google.api.http) = { get: "/v1p1beta1/{name=organizations/*/organizationSettings}" }; @@ -170,8 +161,7 @@ service SecurityCenter { } // Lists notification configs. - rpc ListNotificationConfigs(ListNotificationConfigsRequest) - returns (ListNotificationConfigsResponse) { + rpc ListNotificationConfigs(ListNotificationConfigsRequest) returns (ListNotificationConfigsResponse) { option (google.api.http) = { get: "/v1p1beta1/{parent=organizations/*}/notificationConfigs" }; @@ -192,8 +182,7 @@ service SecurityCenter { // This API can only be called with limited frequency for an organization. If // it is called too frequently the caller will receive a TOO_MANY_REQUESTS // error. - rpc RunAssetDiscovery(RunAssetDiscoveryRequest) - returns (google.longrunning.Operation) { + rpc RunAssetDiscovery(RunAssetDiscoveryRequest) returns (google.longrunning.Operation) { option (google.api.http) = { post: "/v1p1beta1/{parent=organizations/*}/assets:runDiscovery" body: "*" @@ -205,7 +194,6 @@ service SecurityCenter { }; } - // // Updates the state of a finding. rpc SetFindingState(SetFindingStateRequest) returns (Finding) { option (google.api.http) = { @@ -216,8 +204,7 @@ service SecurityCenter { } // Sets the access control policy on the specified Source. - rpc SetIamPolicy(google.iam.v1.SetIamPolicyRequest) - returns (google.iam.v1.Policy) { + rpc SetIamPolicy(google.iam.v1.SetIamPolicyRequest) returns (google.iam.v1.Policy) { option (google.api.http) = { post: "/v1p1beta1/{resource=organizations/*/sources/*}:setIamPolicy" body: "*" @@ -226,8 +213,7 @@ service SecurityCenter { } // Returns the permissions that a caller has on the specified source. - rpc TestIamPermissions(google.iam.v1.TestIamPermissionsRequest) - returns (google.iam.v1.TestIamPermissionsResponse) { + rpc TestIamPermissions(google.iam.v1.TestIamPermissionsRequest) returns (google.iam.v1.TestIamPermissionsResponse) { option (google.api.http) = { post: "/v1p1beta1/{resource=organizations/*/sources/*}:testIamPermissions" body: "*" @@ -248,8 +234,7 @@ service SecurityCenter { // Updates a notification config. The following update // fields are allowed: description, pubsub_topic, streaming_config.filter - rpc UpdateNotificationConfig(UpdateNotificationConfigRequest) - returns (NotificationConfig) { + rpc UpdateNotificationConfig(UpdateNotificationConfigRequest) returns (NotificationConfig) { option (google.api.http) = { patch: "/v1p1beta1/{notification_config.name=organizations/*/notificationConfigs/*}" body: "notification_config" @@ -259,8 +244,7 @@ service SecurityCenter { } // Updates an organization's settings. - rpc UpdateOrganizationSettings(UpdateOrganizationSettingsRequest) - returns (OrganizationSettings) { + rpc UpdateOrganizationSettings(UpdateOrganizationSettingsRequest) returns (OrganizationSettings) { option (google.api.http) = { patch: "/v1p1beta1/{organization_settings.name=organizations/*/organizationSettings}" body: "organization_settings" @@ -305,19 +289,17 @@ message CreateFindingRequest { ]; // Required. Unique identifier provided by the client within the parent scope. - // It must be alphanumeric and less than or equal to 32 characters and - // greater than 0 characters in length. string finding_id = 2 [(google.api.field_behavior) = REQUIRED]; - // Required. The Finding being created. The name and security_marks will be - // ignored as they are both output only fields on this resource. + // Required. The Finding being created. The name and security_marks will be ignored as + // they are both output only fields on this resource. Finding finding = 3 [(google.api.field_behavior) = REQUIRED]; } // Request message for creating a notification config. message CreateNotificationConfigRequest { - // Required. Resource name of the new notification config's parent. Its format - // is "organizations/[organization_id]". + // Required. Resource name of the new notification config's parent. Its format is + // "organizations/[organization_id]". string parent = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { @@ -331,11 +313,9 @@ message CreateNotificationConfigRequest { // characters, underscores or hyphens only. string config_id = 2 [(google.api.field_behavior) = REQUIRED]; - // Required. The notification config being created. The name and the service - // account will be ignored as they are both output only fields on this - // resource. - NotificationConfig notification_config = 3 - [(google.api.field_behavior) = REQUIRED]; + // Required. The notification config being created. The name and the service account + // will be ignored as they are both output only fields on this resource. + NotificationConfig notification_config = 3 [(google.api.field_behavior) = REQUIRED]; } // Request message for creating a source. @@ -349,8 +329,8 @@ message CreateSourceRequest { } ]; - // Required. The Source being created, only the display_name and description - // will be used. All other fields will be ignored. + // Required. The Source being created, only the display_name and description will be + // used. All other fields will be ignored. Source source = 2 [(google.api.field_behavior) = REQUIRED]; } @@ -380,8 +360,8 @@ message GetNotificationConfigRequest { // Request message for getting organization settings. message GetOrganizationSettingsRequest { - // Required. Name of the organization to get organization settings for. Its - // format is "organizations/[organization_id]/organizationSettings". + // Required. Name of the organization to get organization settings for. Its format is + // "organizations/[organization_id]/organizationSettings". string name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { @@ -477,9 +457,9 @@ message GroupAssetsRequest { // property not existing: `-resource_properties.my_property : ""` string filter = 2; - // Required. Expression that defines what assets fields to use for grouping. - // The string value should follow SQL syntax: comma separated list of fields. - // For example: + // Required. Expression that defines what assets fields to use for grouping. The string + // value should follow SQL syntax: comma separated list of fields. For + // example: // "security_center_properties.resource_project,security_center_properties.project". // // The following fields are supported when compare_duration is not set: @@ -624,9 +604,9 @@ message GroupFindingsRequest { // property not existing: `-source_properties.my_property : ""` string filter = 2; - // Required. Expression that defines what assets fields to use for grouping - // (including `state_change`). The string value should follow SQL syntax: - // comma separated list of fields. For example: "parent,resource_name". + // Required. Expression that defines what assets fields to use for grouping (including + // `state_change`). The string value should follow SQL syntax: comma separated + // list of fields. For example: "parent,resource_name". // // The following fields are supported: // @@ -750,8 +730,8 @@ message ListNotificationConfigsResponse { // Request message for listing sources. message ListSourcesRequest { - // Required. Resource name of the parent of sources to list. Its format should - // be "organizations/[organization_id]". + // Required. Resource name of the parent of sources to list. Its format should be + // "organizations/[organization_id]". string parent = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { @@ -909,12 +889,10 @@ message ListAssetsRequest { // read_time. google.protobuf.Duration compare_duration = 5; - // Optional. // A field mask to specify the ListAssetsResult fields to be listed in the // response. // An empty field mask will list all fields. - google.protobuf.FieldMask field_mask = 7 - [(google.api.field_behavior) = OPTIONAL]; + google.protobuf.FieldMask field_mask = 7; // The value returned by the last `ListAssetsResponse`; indicates // that this is a continuation of a prior `ListAssets` call, and @@ -1093,11 +1071,9 @@ message ListFindingsRequest { // read_time. google.protobuf.Duration compare_duration = 5; - // Optional. // A field mask to specify the Finding fields to be listed in the response. // An empty field mask will list all fields. - google.protobuf.FieldMask field_mask = 7 - [(google.api.field_behavior) = OPTIONAL]; + google.protobuf.FieldMask field_mask = 7; // The value returned by the last `ListFindingsResponse`; indicates // that this is a continuation of a prior `ListFindings` call, and @@ -1168,7 +1144,7 @@ message ListFindingsResponse { StateChange state_change = 2; // Output only. Resource that is associated with this finding. - Resource resource = 3; + Resource resource = 3 [(google.api.field_behavior) = OUTPUT_ONLY]; } // Findings matching the list request. @@ -1202,14 +1178,13 @@ message SetFindingStateRequest { Finding.State state = 2 [(google.api.field_behavior) = REQUIRED]; // Required. The time at which the updated state takes effect. - google.protobuf.Timestamp start_time = 3 - [(google.api.field_behavior) = REQUIRED]; + google.protobuf.Timestamp start_time = 3 [(google.api.field_behavior) = REQUIRED]; } // Request message for running asset discovery for an organization. message RunAssetDiscoveryRequest { - // Required. Name of the organization to run asset discovery for. Its format - // is "organizations/[organization_id]". + // Required. Name of the organization to run asset discovery for. Its format is + // "organizations/[organization_id]". string parent = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { @@ -1220,8 +1195,8 @@ message RunAssetDiscoveryRequest { // Request message for updating or creating a finding. message UpdateFindingRequest { - // Required. The finding resource to update or create if it does not already - // exist. parent, security_marks, and update_time will be ignored. + // Required. The finding resource to update or create if it does not already exist. + // parent, security_marks, and update_time will be ignored. // // In the case of creation, the finding id portion of the name must be // alphanumeric and less than or equal to 32 characters and greater than 0 @@ -1241,8 +1216,7 @@ message UpdateFindingRequest { // Request message for updating a notification config. message UpdateNotificationConfigRequest { // Required. The notification config to update. - NotificationConfig notification_config = 1 - [(google.api.field_behavior) = REQUIRED]; + NotificationConfig notification_config = 1 [(google.api.field_behavior) = REQUIRED]; // The FieldMask to use when updating the notification config. // @@ -1253,8 +1227,7 @@ message UpdateNotificationConfigRequest { // Request message for updating an organization's settings. message UpdateOrganizationSettingsRequest { // Required. The organization settings resource to update. - OrganizationSettings organization_settings = 1 - [(google.api.field_behavior) = REQUIRED]; + OrganizationSettings organization_settings = 1 [(google.api.field_behavior) = REQUIRED]; // The FieldMask to use when updating the settings resource. // diff --git a/google/cloud/securitycenter_v1p1beta1/proto/securitycenter_service_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/securitycenter_service_pb2.py index 583e5d79..5a70da84 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/securitycenter_service_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/securitycenter_service_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/securitycenter_service.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection @@ -56,7 +56,7 @@ syntax="proto3", serialized_options=b"\n)com.google.cloud.securitycenter.v1p1beta1P\001ZSgoogle.golang.org/genproto/googleapis/cloud/securitycenter/v1p1beta1;securitycenter\252\002%Google.Cloud.SecurityCenter.V1P1Beta1\312\002%Google\\Cloud\\SecurityCenter\\V1p1beta1\352\002(Google::Cloud::SecurityCenter::V1p1beta1", create_key=_descriptor._internal_create_key, - serialized_pb=b'\nHgoogle/cloud/securitycenter_v1p1beta1/proto/securitycenter_service.proto\x12%google.cloud.securitycenter.v1p1beta1\x1aNgoogle/cloud/securitycenter_v1p1beta1/proto/run_asset_discovery_response.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x37google/cloud/securitycenter_v1p1beta1/proto/asset.proto\x1a\x39google/cloud/securitycenter_v1p1beta1/proto/finding.proto\x1a\x45google/cloud/securitycenter_v1p1beta1/proto/notification_config.proto\x1aGgoogle/cloud/securitycenter_v1p1beta1/proto/organization_settings.proto\x1a@google/cloud/securitycenter_v1p1beta1/proto/security_marks.proto\x1a\x38google/cloud/securitycenter_v1p1beta1/proto/source.proto\x1a\x1egoogle/iam/v1/iam_policy.proto\x1a\x1agoogle/iam/v1/policy.proto\x1a#google/longrunning/operations.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\xb3\x01\n\x14\x43reateFindingRequest\x12<\n\x06parent\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$securitycenter.googleapis.com/Source\x12\x17\n\nfinding_id\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x44\n\x07\x66inding\x18\x03 \x01(\x0b\x32..google.cloud.securitycenter.v1p1beta1.FindingB\x03\xe0\x41\x02"\xe0\x01\n\x1f\x43reateNotificationConfigRequest\x12H\n\x06parent\x18\x01 \x01(\tB8\xe0\x41\x02\xfa\x41\x32\n0cloudresourcemanager.googleapis.com/Organization\x12\x16\n\tconfig_id\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12[\n\x13notification_config\x18\x03 \x01(\x0b\x32\x39.google.cloud.securitycenter.v1p1beta1.NotificationConfigB\x03\xe0\x41\x02"\xa3\x01\n\x13\x43reateSourceRequest\x12H\n\x06parent\x18\x01 \x01(\tB8\xe0\x41\x02\xfa\x41\x32\n0cloudresourcemanager.googleapis.com/Organization\x12\x42\n\x06source\x18\x02 \x01(\x0b\x32-.google.cloud.securitycenter.v1p1beta1.SourceB\x03\xe0\x41\x02"i\n\x1f\x44\x65leteNotificationConfigRequest\x12\x46\n\x04name\x18\x01 \x01(\tB8\xe0\x41\x02\xfa\x41\x32\n0securitycenter.googleapis.com/NotificationConfig"f\n\x1cGetNotificationConfigRequest\x12\x46\n\x04name\x18\x01 \x01(\tB8\xe0\x41\x02\xfa\x41\x32\n0securitycenter.googleapis.com/NotificationConfig"j\n\x1eGetOrganizationSettingsRequest\x12H\n\x04name\x18\x01 \x01(\tB:\xe0\x41\x02\xfa\x41\x34\n2securitycenter.googleapis.com/OrganizationSettings"N\n\x10GetSourceRequest\x12:\n\x04name\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$securitycenter.googleapis.com/Source"\x90\x02\n\x12GroupAssetsRequest\x12H\n\x06parent\x18\x01 \x01(\tB8\xe0\x41\x02\xfa\x41\x32\n0cloudresourcemanager.googleapis.com/Organization\x12\x0e\n\x06\x66ilter\x18\x02 \x01(\t\x12\x15\n\x08group_by\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x33\n\x10\x63ompare_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12-\n\tread_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\npage_token\x18\x07 \x01(\t\x12\x11\n\tpage_size\x18\x08 \x01(\x05"\xbf\x01\n\x13GroupAssetsResponse\x12L\n\x10group_by_results\x18\x01 \x03(\x0b\x32\x32.google.cloud.securitycenter.v1p1beta1.GroupResult\x12-\n\tread_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\x12\x12\n\ntotal_size\x18\x04 \x01(\x05"\x86\x02\n\x14GroupFindingsRequest\x12<\n\x06parent\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$securitycenter.googleapis.com/Source\x12\x0e\n\x06\x66ilter\x18\x02 \x01(\t\x12\x15\n\x08group_by\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12-\n\tread_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x10\x63ompare_duration\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x12\n\npage_token\x18\x07 \x01(\t\x12\x11\n\tpage_size\x18\x08 \x01(\x05"\xc1\x01\n\x15GroupFindingsResponse\x12L\n\x10group_by_results\x18\x01 \x03(\x0b\x32\x32.google.cloud.securitycenter.v1p1beta1.GroupResult\x12-\n\tread_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\x12\x12\n\ntotal_size\x18\x04 \x01(\x05"\xbf\x01\n\x0bGroupResult\x12V\n\nproperties\x18\x01 \x03(\x0b\x32\x42.google.cloud.securitycenter.v1p1beta1.GroupResult.PropertiesEntry\x12\r\n\x05\x63ount\x18\x02 \x01(\x03\x1aI\n\x0fPropertiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value:\x02\x38\x01"\x91\x01\n\x1eListNotificationConfigsRequest\x12H\n\x06parent\x18\x01 \x01(\tB8\xe0\x41\x02\xfa\x41\x32\n0cloudresourcemanager.googleapis.com/Organization\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x11\n\tpage_size\x18\x03 \x01(\x05"\x93\x01\n\x1fListNotificationConfigsResponse\x12W\n\x14notification_configs\x18\x01 \x03(\x0b\x32\x39.google.cloud.securitycenter.v1p1beta1.NotificationConfig\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\x85\x01\n\x12ListSourcesRequest\x12H\n\x06parent\x18\x01 \x01(\tB8\xe0\x41\x02\xfa\x41\x32\n0cloudresourcemanager.googleapis.com/Organization\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x11\n\tpage_size\x18\x07 \x01(\x05"n\n\x13ListSourcesResponse\x12>\n\x07sources\x18\x01 \x03(\x0b\x32-.google.cloud.securitycenter.v1p1beta1.Source\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\xbf\x02\n\x11ListAssetsRequest\x12H\n\x06parent\x18\x01 \x01(\tB8\xe0\x41\x02\xfa\x41\x32\n0cloudresourcemanager.googleapis.com/Organization\x12\x0e\n\x06\x66ilter\x18\x02 \x01(\t\x12\x10\n\x08order_by\x18\x03 \x01(\t\x12-\n\tread_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x10\x63ompare_duration\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x33\n\nfield_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x01\x12\x12\n\npage_token\x18\x08 \x01(\t\x12\x11\n\tpage_size\x18\t \x01(\x05"\xd8\x03\n\x12ListAssetsResponse\x12g\n\x13list_assets_results\x18\x01 \x03(\x0b\x32J.google.cloud.securitycenter.v1p1beta1.ListAssetsResponse.ListAssetsResult\x12-\n\tread_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\x12\x12\n\ntotal_size\x18\x04 \x01(\x05\x1a\xfc\x01\n\x10ListAssetsResult\x12;\n\x05\x61sset\x18\x01 \x01(\x0b\x32,.google.cloud.securitycenter.v1p1beta1.Asset\x12l\n\x0cstate_change\x18\x02 \x01(\x0e\x32V.google.cloud.securitycenter.v1p1beta1.ListAssetsResponse.ListAssetsResult.StateChange"=\n\x0bStateChange\x12\n\n\x06UNUSED\x10\x00\x12\t\n\x05\x41\x44\x44\x45\x44\x10\x01\x12\x0b\n\x07REMOVED\x10\x02\x12\n\n\x06\x41\x43TIVE\x10\x03"\xb5\x02\n\x13ListFindingsRequest\x12<\n\x06parent\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$securitycenter.googleapis.com/Source\x12\x0e\n\x06\x66ilter\x18\x02 \x01(\t\x12\x10\n\x08order_by\x18\x03 \x01(\t\x12-\n\tread_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x10\x63ompare_duration\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x33\n\nfield_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x01\x12\x12\n\npage_token\x18\x08 \x01(\t\x12\x11\n\tpage_size\x18\t \x01(\x05"\xe5\x05\n\x14ListFindingsResponse\x12m\n\x15list_findings_results\x18\x01 \x03(\x0b\x32N.google.cloud.securitycenter.v1p1beta1.ListFindingsResponse.ListFindingsResult\x12-\n\tread_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\x12\x12\n\ntotal_size\x18\x04 \x01(\x05\x1a\x81\x04\n\x12ListFindingsResult\x12?\n\x07\x66inding\x18\x01 \x01(\x0b\x32..google.cloud.securitycenter.v1p1beta1.Finding\x12p\n\x0cstate_change\x18\x02 \x01(\x0e\x32Z.google.cloud.securitycenter.v1p1beta1.ListFindingsResponse.ListFindingsResult.StateChange\x12i\n\x08resource\x18\x03 \x01(\x0b\x32W.google.cloud.securitycenter.v1p1beta1.ListFindingsResponse.ListFindingsResult.Resource\x1a~\n\x08Resource\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x14\n\x0cproject_name\x18\x02 \x01(\t\x12\x1c\n\x14project_display_name\x18\x03 \x01(\t\x12\x13\n\x0bparent_name\x18\x04 \x01(\t\x12\x1b\n\x13parent_display_name\x18\x05 \x01(\t"M\n\x0bStateChange\x12\n\n\x06UNUSED\x10\x00\x12\x0b\n\x07\x43HANGED\x10\x01\x12\r\n\tUNCHANGED\x10\x02\x12\t\n\x05\x41\x44\x44\x45\x44\x10\x03\x12\x0b\n\x07REMOVED\x10\x04"\xd4\x01\n\x16SetFindingStateRequest\x12;\n\x04name\x18\x01 \x01(\tB-\xe0\x41\x02\xfa\x41\'\n%securitycenter.googleapis.com/Finding\x12H\n\x05state\x18\x02 \x01(\x0e\x32\x34.google.cloud.securitycenter.v1p1beta1.Finding.StateB\x03\xe0\x41\x02\x12\x33\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02"d\n\x18RunAssetDiscoveryRequest\x12H\n\x06parent\x18\x01 \x01(\tB8\xe0\x41\x02\xfa\x41\x32\n0cloudresourcemanager.googleapis.com/Organization"\x8d\x01\n\x14UpdateFindingRequest\x12\x44\n\x07\x66inding\x18\x01 \x01(\x0b\x32..google.cloud.securitycenter.v1p1beta1.FindingB\x03\xe0\x41\x02\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMask"\xaf\x01\n\x1fUpdateNotificationConfigRequest\x12[\n\x13notification_config\x18\x01 \x01(\x0b\x32\x39.google.cloud.securitycenter.v1p1beta1.NotificationConfigB\x03\xe0\x41\x02\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMask"\xb5\x01\n!UpdateOrganizationSettingsRequest\x12_\n\x15organization_settings\x18\x01 \x01(\x0b\x32;.google.cloud.securitycenter.v1p1beta1.OrganizationSettingsB\x03\xe0\x41\x02\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMask"\x8a\x01\n\x13UpdateSourceRequest\x12\x42\n\x06source\x18\x01 \x01(\x0b\x32-.google.cloud.securitycenter.v1p1beta1.SourceB\x03\xe0\x41\x02\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMask"\xd0\x01\n\x1aUpdateSecurityMarksRequest\x12Q\n\x0esecurity_marks\x18\x01 \x01(\x0b\x32\x34.google.cloud.securitycenter.v1p1beta1.SecurityMarksB\x03\xe0\x41\x02\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp2\x86+\n\x0eSecurityCenter\x12\xc6\x01\n\x0c\x43reateSource\x12:.google.cloud.securitycenter.v1p1beta1.CreateSourceRequest\x1a-.google.cloud.securitycenter.v1p1beta1.Source"K\x82\xd3\xe4\x93\x02\x35"+/v1p1beta1/{parent=organizations/*}/sources:\x06source\xda\x41\rparent,source\x12\xfd\x01\n\rCreateFinding\x12;.google.cloud.securitycenter.v1p1beta1.CreateFindingRequest\x1a..google.cloud.securitycenter.v1p1beta1.Finding"\x7f\x82\xd3\xe4\x93\x02\x41"6/v1p1beta1/{parent=organizations/*/sources/*}/findings:\x07\x66inding\xda\x41\x19parent,finding_id,finding\xda\x41\x19parent,finding,finding_id\x12\xb8\x02\n\x18\x43reateNotificationConfig\x12\x46.google.cloud.securitycenter.v1p1beta1.CreateNotificationConfigRequest\x1a\x39.google.cloud.securitycenter.v1p1beta1.NotificationConfig"\x98\x01\x82\xd3\xe4\x93\x02N"7/v1p1beta1/{parent=organizations/*}/notificationConfigs:\x13notification_config\xda\x41$parent,config_id,notification_config\xda\x41\x1aparent,notification_config\x12\xc2\x01\n\x18\x44\x65leteNotificationConfig\x12\x46.google.cloud.securitycenter.v1p1beta1.DeleteNotificationConfigRequest\x1a\x16.google.protobuf.Empty"F\x82\xd3\xe4\x93\x02\x39*7/v1p1beta1/{name=organizations/*/notificationConfigs/*}\xda\x41\x04name\x12\x9d\x01\n\x0cGetIamPolicy\x12".google.iam.v1.GetIamPolicyRequest\x1a\x15.google.iam.v1.Policy"R\x82\xd3\xe4\x93\x02\x41"/v1p1beta1/{finding.name=organizations/*/sources/*/findings/*}:\x07\x66inding\xda\x41\x07\x66inding\xda\x41\x13\x66inding,update_mask\x12\xc0\x02\n\x18UpdateNotificationConfig\x12\x46.google.cloud.securitycenter.v1p1beta1.UpdateNotificationConfigRequest\x1a\x39.google.cloud.securitycenter.v1p1beta1.NotificationConfig"\xa0\x01\x82\xd3\xe4\x93\x02\x62\x32K/v1p1beta1/{notification_config.name=organizations/*/notificationConfigs/*}:\x13notification_config\xda\x41\x13notification_config\xda\x41\x1fnotification_config,update_mask\x12\xa9\x02\n\x1aUpdateOrganizationSettings\x12H.google.cloud.securitycenter.v1p1beta1.UpdateOrganizationSettingsRequest\x1a;.google.cloud.securitycenter.v1p1beta1.OrganizationSettings"\x83\x01\x82\xd3\xe4\x93\x02\x65\x32L/v1p1beta1/{organization_settings.name=organizations/*/organizationSettings}:\x15organization_settings\xda\x41\x15organization_settings\x12\xdb\x01\n\x0cUpdateSource\x12:.google.cloud.securitycenter.v1p1beta1.UpdateSourceRequest\x1a-.google.cloud.securitycenter.v1p1beta1.Source"`\x82\xd3\xe4\x93\x02<22/v1p1beta1/{source.name=organizations/*/sources/*}:\x06source\xda\x41\x06source\xda\x41\x12source,update_mask\x12\x86\x03\n\x13UpdateSecurityMarks\x12\x41.google.cloud.securitycenter.v1p1beta1.UpdateSecurityMarksRequest\x1a\x34.google.cloud.securitycenter.v1p1beta1.SecurityMarks"\xf5\x01\x82\xd3\xe4\x93\x02\xc0\x01\x32G/v1p1beta1/{security_marks.name=organizations/*/assets/*/securityMarks}:\x0esecurity_marksZe2S/v1p1beta1/{security_marks.name=organizations/*/sources/*/findings/*/securityMarks}:\x0esecurity_marks\xda\x41\x0esecurity_marks\xda\x41\x1asecurity_marks,update_mask\x1aQ\xca\x41\x1dsecuritycenter.googleapis.com\xd2\x41.https://www.googleapis.com/auth/cloud-platformB\xfd\x01\n)com.google.cloud.securitycenter.v1p1beta1P\x01ZSgoogle.golang.org/genproto/googleapis/cloud/securitycenter/v1p1beta1;securitycenter\xaa\x02%Google.Cloud.SecurityCenter.V1P1Beta1\xca\x02%Google\\Cloud\\SecurityCenter\\V1p1beta1\xea\x02(Google::Cloud::SecurityCenter::V1p1beta1P\x00\x62\x06proto3', + serialized_pb=b'\nHgoogle/cloud/securitycenter_v1p1beta1/proto/securitycenter_service.proto\x12%google.cloud.securitycenter.v1p1beta1\x1aNgoogle/cloud/securitycenter_v1p1beta1/proto/run_asset_discovery_response.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x37google/cloud/securitycenter_v1p1beta1/proto/asset.proto\x1a\x39google/cloud/securitycenter_v1p1beta1/proto/finding.proto\x1a\x45google/cloud/securitycenter_v1p1beta1/proto/notification_config.proto\x1aGgoogle/cloud/securitycenter_v1p1beta1/proto/organization_settings.proto\x1a@google/cloud/securitycenter_v1p1beta1/proto/security_marks.proto\x1a\x38google/cloud/securitycenter_v1p1beta1/proto/source.proto\x1a\x1egoogle/iam/v1/iam_policy.proto\x1a\x1agoogle/iam/v1/policy.proto\x1a#google/longrunning/operations.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\xb3\x01\n\x14\x43reateFindingRequest\x12<\n\x06parent\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$securitycenter.googleapis.com/Source\x12\x17\n\nfinding_id\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x44\n\x07\x66inding\x18\x03 \x01(\x0b\x32..google.cloud.securitycenter.v1p1beta1.FindingB\x03\xe0\x41\x02"\xe0\x01\n\x1f\x43reateNotificationConfigRequest\x12H\n\x06parent\x18\x01 \x01(\tB8\xe0\x41\x02\xfa\x41\x32\n0cloudresourcemanager.googleapis.com/Organization\x12\x16\n\tconfig_id\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12[\n\x13notification_config\x18\x03 \x01(\x0b\x32\x39.google.cloud.securitycenter.v1p1beta1.NotificationConfigB\x03\xe0\x41\x02"\xa3\x01\n\x13\x43reateSourceRequest\x12H\n\x06parent\x18\x01 \x01(\tB8\xe0\x41\x02\xfa\x41\x32\n0cloudresourcemanager.googleapis.com/Organization\x12\x42\n\x06source\x18\x02 \x01(\x0b\x32-.google.cloud.securitycenter.v1p1beta1.SourceB\x03\xe0\x41\x02"i\n\x1f\x44\x65leteNotificationConfigRequest\x12\x46\n\x04name\x18\x01 \x01(\tB8\xe0\x41\x02\xfa\x41\x32\n0securitycenter.googleapis.com/NotificationConfig"f\n\x1cGetNotificationConfigRequest\x12\x46\n\x04name\x18\x01 \x01(\tB8\xe0\x41\x02\xfa\x41\x32\n0securitycenter.googleapis.com/NotificationConfig"j\n\x1eGetOrganizationSettingsRequest\x12H\n\x04name\x18\x01 \x01(\tB:\xe0\x41\x02\xfa\x41\x34\n2securitycenter.googleapis.com/OrganizationSettings"N\n\x10GetSourceRequest\x12:\n\x04name\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$securitycenter.googleapis.com/Source"\x90\x02\n\x12GroupAssetsRequest\x12H\n\x06parent\x18\x01 \x01(\tB8\xe0\x41\x02\xfa\x41\x32\n0cloudresourcemanager.googleapis.com/Organization\x12\x0e\n\x06\x66ilter\x18\x02 \x01(\t\x12\x15\n\x08group_by\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x33\n\x10\x63ompare_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12-\n\tread_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\npage_token\x18\x07 \x01(\t\x12\x11\n\tpage_size\x18\x08 \x01(\x05"\xbf\x01\n\x13GroupAssetsResponse\x12L\n\x10group_by_results\x18\x01 \x03(\x0b\x32\x32.google.cloud.securitycenter.v1p1beta1.GroupResult\x12-\n\tread_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\x12\x12\n\ntotal_size\x18\x04 \x01(\x05"\x86\x02\n\x14GroupFindingsRequest\x12<\n\x06parent\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$securitycenter.googleapis.com/Source\x12\x0e\n\x06\x66ilter\x18\x02 \x01(\t\x12\x15\n\x08group_by\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12-\n\tread_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x10\x63ompare_duration\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x12\n\npage_token\x18\x07 \x01(\t\x12\x11\n\tpage_size\x18\x08 \x01(\x05"\xc1\x01\n\x15GroupFindingsResponse\x12L\n\x10group_by_results\x18\x01 \x03(\x0b\x32\x32.google.cloud.securitycenter.v1p1beta1.GroupResult\x12-\n\tread_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\x12\x12\n\ntotal_size\x18\x04 \x01(\x05"\xbf\x01\n\x0bGroupResult\x12V\n\nproperties\x18\x01 \x03(\x0b\x32\x42.google.cloud.securitycenter.v1p1beta1.GroupResult.PropertiesEntry\x12\r\n\x05\x63ount\x18\x02 \x01(\x03\x1aI\n\x0fPropertiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value:\x02\x38\x01"\x91\x01\n\x1eListNotificationConfigsRequest\x12H\n\x06parent\x18\x01 \x01(\tB8\xe0\x41\x02\xfa\x41\x32\n0cloudresourcemanager.googleapis.com/Organization\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x11\n\tpage_size\x18\x03 \x01(\x05"\x93\x01\n\x1fListNotificationConfigsResponse\x12W\n\x14notification_configs\x18\x01 \x03(\x0b\x32\x39.google.cloud.securitycenter.v1p1beta1.NotificationConfig\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\x85\x01\n\x12ListSourcesRequest\x12H\n\x06parent\x18\x01 \x01(\tB8\xe0\x41\x02\xfa\x41\x32\n0cloudresourcemanager.googleapis.com/Organization\x12\x12\n\npage_token\x18\x02 \x01(\t\x12\x11\n\tpage_size\x18\x07 \x01(\x05"n\n\x13ListSourcesResponse\x12>\n\x07sources\x18\x01 \x03(\x0b\x32-.google.cloud.securitycenter.v1p1beta1.Source\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"\xba\x02\n\x11ListAssetsRequest\x12H\n\x06parent\x18\x01 \x01(\tB8\xe0\x41\x02\xfa\x41\x32\n0cloudresourcemanager.googleapis.com/Organization\x12\x0e\n\x06\x66ilter\x18\x02 \x01(\t\x12\x10\n\x08order_by\x18\x03 \x01(\t\x12-\n\tread_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x10\x63ompare_duration\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12.\n\nfield_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x12\n\npage_token\x18\x08 \x01(\t\x12\x11\n\tpage_size\x18\t \x01(\x05"\xd8\x03\n\x12ListAssetsResponse\x12g\n\x13list_assets_results\x18\x01 \x03(\x0b\x32J.google.cloud.securitycenter.v1p1beta1.ListAssetsResponse.ListAssetsResult\x12-\n\tread_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\x12\x12\n\ntotal_size\x18\x04 \x01(\x05\x1a\xfc\x01\n\x10ListAssetsResult\x12;\n\x05\x61sset\x18\x01 \x01(\x0b\x32,.google.cloud.securitycenter.v1p1beta1.Asset\x12l\n\x0cstate_change\x18\x02 \x01(\x0e\x32V.google.cloud.securitycenter.v1p1beta1.ListAssetsResponse.ListAssetsResult.StateChange"=\n\x0bStateChange\x12\n\n\x06UNUSED\x10\x00\x12\t\n\x05\x41\x44\x44\x45\x44\x10\x01\x12\x0b\n\x07REMOVED\x10\x02\x12\n\n\x06\x41\x43TIVE\x10\x03"\xb0\x02\n\x13ListFindingsRequest\x12<\n\x06parent\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$securitycenter.googleapis.com/Source\x12\x0e\n\x06\x66ilter\x18\x02 \x01(\t\x12\x10\n\x08order_by\x18\x03 \x01(\t\x12-\n\tread_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x33\n\x10\x63ompare_duration\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12.\n\nfield_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x12\n\npage_token\x18\x08 \x01(\t\x12\x11\n\tpage_size\x18\t \x01(\x05"\xea\x05\n\x14ListFindingsResponse\x12m\n\x15list_findings_results\x18\x01 \x03(\x0b\x32N.google.cloud.securitycenter.v1p1beta1.ListFindingsResponse.ListFindingsResult\x12-\n\tread_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\x12\x12\n\ntotal_size\x18\x04 \x01(\x05\x1a\x86\x04\n\x12ListFindingsResult\x12?\n\x07\x66inding\x18\x01 \x01(\x0b\x32..google.cloud.securitycenter.v1p1beta1.Finding\x12p\n\x0cstate_change\x18\x02 \x01(\x0e\x32Z.google.cloud.securitycenter.v1p1beta1.ListFindingsResponse.ListFindingsResult.StateChange\x12n\n\x08resource\x18\x03 \x01(\x0b\x32W.google.cloud.securitycenter.v1p1beta1.ListFindingsResponse.ListFindingsResult.ResourceB\x03\xe0\x41\x03\x1a~\n\x08Resource\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x14\n\x0cproject_name\x18\x02 \x01(\t\x12\x1c\n\x14project_display_name\x18\x03 \x01(\t\x12\x13\n\x0bparent_name\x18\x04 \x01(\t\x12\x1b\n\x13parent_display_name\x18\x05 \x01(\t"M\n\x0bStateChange\x12\n\n\x06UNUSED\x10\x00\x12\x0b\n\x07\x43HANGED\x10\x01\x12\r\n\tUNCHANGED\x10\x02\x12\t\n\x05\x41\x44\x44\x45\x44\x10\x03\x12\x0b\n\x07REMOVED\x10\x04"\xd4\x01\n\x16SetFindingStateRequest\x12;\n\x04name\x18\x01 \x01(\tB-\xe0\x41\x02\xfa\x41\'\n%securitycenter.googleapis.com/Finding\x12H\n\x05state\x18\x02 \x01(\x0e\x32\x34.google.cloud.securitycenter.v1p1beta1.Finding.StateB\x03\xe0\x41\x02\x12\x33\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02"d\n\x18RunAssetDiscoveryRequest\x12H\n\x06parent\x18\x01 \x01(\tB8\xe0\x41\x02\xfa\x41\x32\n0cloudresourcemanager.googleapis.com/Organization"\x8d\x01\n\x14UpdateFindingRequest\x12\x44\n\x07\x66inding\x18\x01 \x01(\x0b\x32..google.cloud.securitycenter.v1p1beta1.FindingB\x03\xe0\x41\x02\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMask"\xaf\x01\n\x1fUpdateNotificationConfigRequest\x12[\n\x13notification_config\x18\x01 \x01(\x0b\x32\x39.google.cloud.securitycenter.v1p1beta1.NotificationConfigB\x03\xe0\x41\x02\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMask"\xb5\x01\n!UpdateOrganizationSettingsRequest\x12_\n\x15organization_settings\x18\x01 \x01(\x0b\x32;.google.cloud.securitycenter.v1p1beta1.OrganizationSettingsB\x03\xe0\x41\x02\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMask"\x8a\x01\n\x13UpdateSourceRequest\x12\x42\n\x06source\x18\x01 \x01(\x0b\x32-.google.cloud.securitycenter.v1p1beta1.SourceB\x03\xe0\x41\x02\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMask"\xd0\x01\n\x1aUpdateSecurityMarksRequest\x12Q\n\x0esecurity_marks\x18\x01 \x01(\x0b\x32\x34.google.cloud.securitycenter.v1p1beta1.SecurityMarksB\x03\xe0\x41\x02\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp2\x86+\n\x0eSecurityCenter\x12\xc6\x01\n\x0c\x43reateSource\x12:.google.cloud.securitycenter.v1p1beta1.CreateSourceRequest\x1a-.google.cloud.securitycenter.v1p1beta1.Source"K\x82\xd3\xe4\x93\x02\x35"+/v1p1beta1/{parent=organizations/*}/sources:\x06source\xda\x41\rparent,source\x12\xfd\x01\n\rCreateFinding\x12;.google.cloud.securitycenter.v1p1beta1.CreateFindingRequest\x1a..google.cloud.securitycenter.v1p1beta1.Finding"\x7f\x82\xd3\xe4\x93\x02\x41"6/v1p1beta1/{parent=organizations/*/sources/*}/findings:\x07\x66inding\xda\x41\x19parent,finding_id,finding\xda\x41\x19parent,finding,finding_id\x12\xb8\x02\n\x18\x43reateNotificationConfig\x12\x46.google.cloud.securitycenter.v1p1beta1.CreateNotificationConfigRequest\x1a\x39.google.cloud.securitycenter.v1p1beta1.NotificationConfig"\x98\x01\x82\xd3\xe4\x93\x02N"7/v1p1beta1/{parent=organizations/*}/notificationConfigs:\x13notification_config\xda\x41$parent,config_id,notification_config\xda\x41\x1aparent,notification_config\x12\xc2\x01\n\x18\x44\x65leteNotificationConfig\x12\x46.google.cloud.securitycenter.v1p1beta1.DeleteNotificationConfigRequest\x1a\x16.google.protobuf.Empty"F\x82\xd3\xe4\x93\x02\x39*7/v1p1beta1/{name=organizations/*/notificationConfigs/*}\xda\x41\x04name\x12\x9d\x01\n\x0cGetIamPolicy\x12".google.iam.v1.GetIamPolicyRequest\x1a\x15.google.iam.v1.Policy"R\x82\xd3\xe4\x93\x02\x41"/v1p1beta1/{finding.name=organizations/*/sources/*/findings/*}:\x07\x66inding\xda\x41\x07\x66inding\xda\x41\x13\x66inding,update_mask\x12\xc0\x02\n\x18UpdateNotificationConfig\x12\x46.google.cloud.securitycenter.v1p1beta1.UpdateNotificationConfigRequest\x1a\x39.google.cloud.securitycenter.v1p1beta1.NotificationConfig"\xa0\x01\x82\xd3\xe4\x93\x02\x62\x32K/v1p1beta1/{notification_config.name=organizations/*/notificationConfigs/*}:\x13notification_config\xda\x41\x13notification_config\xda\x41\x1fnotification_config,update_mask\x12\xa9\x02\n\x1aUpdateOrganizationSettings\x12H.google.cloud.securitycenter.v1p1beta1.UpdateOrganizationSettingsRequest\x1a;.google.cloud.securitycenter.v1p1beta1.OrganizationSettings"\x83\x01\x82\xd3\xe4\x93\x02\x65\x32L/v1p1beta1/{organization_settings.name=organizations/*/organizationSettings}:\x15organization_settings\xda\x41\x15organization_settings\x12\xdb\x01\n\x0cUpdateSource\x12:.google.cloud.securitycenter.v1p1beta1.UpdateSourceRequest\x1a-.google.cloud.securitycenter.v1p1beta1.Source"`\x82\xd3\xe4\x93\x02<22/v1p1beta1/{source.name=organizations/*/sources/*}:\x06source\xda\x41\x06source\xda\x41\x12source,update_mask\x12\x86\x03\n\x13UpdateSecurityMarks\x12\x41.google.cloud.securitycenter.v1p1beta1.UpdateSecurityMarksRequest\x1a\x34.google.cloud.securitycenter.v1p1beta1.SecurityMarks"\xf5\x01\x82\xd3\xe4\x93\x02\xc0\x01\x32G/v1p1beta1/{security_marks.name=organizations/*/assets/*/securityMarks}:\x0esecurity_marksZe2S/v1p1beta1/{security_marks.name=organizations/*/sources/*/findings/*/securityMarks}:\x0esecurity_marks\xda\x41\x0esecurity_marks\xda\x41\x1asecurity_marks,update_mask\x1aQ\xca\x41\x1dsecuritycenter.googleapis.com\xd2\x41.https://www.googleapis.com/auth/cloud-platformB\xfd\x01\n)com.google.cloud.securitycenter.v1p1beta1P\x01ZSgoogle.golang.org/genproto/googleapis/cloud/securitycenter/v1p1beta1;securitycenter\xaa\x02%Google.Cloud.SecurityCenter.V1P1Beta1\xca\x02%Google\\Cloud\\SecurityCenter\\V1p1beta1\xea\x02(Google::Cloud::SecurityCenter::V1p1beta1P\x00\x62\x06proto3', dependencies=[ google_dot_cloud_dot_securitycenter__v1p1beta1_dot_proto_dot_run__asset__discovery__response__pb2.DESCRIPTOR, google_dot_api_dot_annotations__pb2.DESCRIPTOR, @@ -126,8 +126,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=4327, - serialized_end=4388, + serialized_start=4322, + serialized_end=4383, ) _sym_db.RegisterEnumDescriptor(_LISTASSETSRESPONSE_LISTASSETSRESULT_STATECHANGE) @@ -181,8 +181,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=5367, - serialized_end=5444, + serialized_start=5362, + serialized_end=5439, ) _sym_db.RegisterEnumDescriptor(_LISTFINDINGSRESPONSE_LISTFINDINGSRESULT_STATECHANGE) @@ -1590,7 +1590,7 @@ containing_type=None, is_extension=False, extension_scope=None, - serialized_options=b"\340A\001", + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key, ), @@ -1642,7 +1642,7 @@ extension_ranges=[], oneofs=[], serialized_start=3594, - serialized_end=3913, + serialized_end=3908, ) @@ -1701,8 +1701,8 @@ syntax="proto3", extension_ranges=[], oneofs=[], - serialized_start=4136, - serialized_end=4388, + serialized_start=4131, + serialized_end=4383, ) _LISTASSETSRESPONSE = _descriptor.Descriptor( @@ -1798,8 +1798,8 @@ syntax="proto3", extension_ranges=[], oneofs=[], - serialized_start=3916, - serialized_end=4388, + serialized_start=3911, + serialized_end=4383, ) @@ -1921,7 +1921,7 @@ containing_type=None, is_extension=False, extension_scope=None, - serialized_options=b"\340A\001", + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key, ), @@ -1972,8 +1972,8 @@ syntax="proto3", extension_ranges=[], oneofs=[], - serialized_start=4391, - serialized_end=4700, + serialized_start=4386, + serialized_end=4690, ) @@ -2089,8 +2089,8 @@ syntax="proto3", extension_ranges=[], oneofs=[], - serialized_start=5239, - serialized_end=5365, + serialized_start=5234, + serialized_end=5360, ) _LISTFINDINGSRESPONSE_LISTFINDINGSRESULT = _descriptor.Descriptor( @@ -2154,7 +2154,7 @@ containing_type=None, is_extension=False, extension_scope=None, - serialized_options=None, + serialized_options=b"\340A\003", file=DESCRIPTOR, create_key=_descriptor._internal_create_key, ), @@ -2167,8 +2167,8 @@ syntax="proto3", extension_ranges=[], oneofs=[], - serialized_start=4931, - serialized_end=5444, + serialized_start=4921, + serialized_end=5439, ) _LISTFINDINGSRESPONSE = _descriptor.Descriptor( @@ -2264,8 +2264,8 @@ syntax="proto3", extension_ranges=[], oneofs=[], - serialized_start=4703, - serialized_end=5444, + serialized_start=4693, + serialized_end=5439, ) @@ -2343,8 +2343,8 @@ syntax="proto3", extension_ranges=[], oneofs=[], - serialized_start=5447, - serialized_end=5659, + serialized_start=5442, + serialized_end=5654, ) @@ -2384,8 +2384,8 @@ syntax="proto3", extension_ranges=[], oneofs=[], - serialized_start=5661, - serialized_end=5761, + serialized_start=5656, + serialized_end=5756, ) @@ -2444,8 +2444,8 @@ syntax="proto3", extension_ranges=[], oneofs=[], - serialized_start=5764, - serialized_end=5905, + serialized_start=5759, + serialized_end=5900, ) @@ -2504,8 +2504,8 @@ syntax="proto3", extension_ranges=[], oneofs=[], - serialized_start=5908, - serialized_end=6083, + serialized_start=5903, + serialized_end=6078, ) @@ -2564,8 +2564,8 @@ syntax="proto3", extension_ranges=[], oneofs=[], - serialized_start=6086, - serialized_end=6267, + serialized_start=6081, + serialized_end=6262, ) @@ -2624,8 +2624,8 @@ syntax="proto3", extension_ranges=[], oneofs=[], - serialized_start=6270, - serialized_end=6408, + serialized_start=6265, + serialized_end=6403, ) @@ -2703,8 +2703,8 @@ syntax="proto3", extension_ranges=[], oneofs=[], - serialized_start=6411, - serialized_end=6619, + serialized_start=6406, + serialized_end=6614, ) _CREATEFINDINGREQUEST.fields_by_name[ @@ -2930,8 +2930,7 @@ “organizations/[organization_id]/sources/[source_id]”. finding_id: Required. Unique identifier provided by the client within the - parent scope. It must be alphanumeric and less than or equal - to 32 characters and greater than 0 characters in length. + parent scope. finding: Required. The Finding being created. The name and security_marks will be ignored as they are both output only @@ -3554,9 +3553,9 @@ only possible state_change is “UNUSED”, which will be the state_change set for all assets present at read_time. field_mask: - Optional. A field mask to specify the ListAssetsResult fields - to be listed in the response. An empty field mask will list - all fields. + A field mask to specify the ListAssetsResult fields to be + listed in the response. An empty field mask will list all + fields. page_token: The value returned by the last ``ListAssetsResponse``; indicates that this is a continuation of a prior @@ -3703,9 +3702,8 @@ which will be the state_change set for all findings present at read_time. field_mask: - Optional. A field mask to specify the Finding fields to be - listed in the response. An empty field mask will list all - fields. + A field mask to specify the Finding fields to be listed in the + response. An empty field mask will list all fields. page_token: The value returned by the last ``ListFindingsResponse``; indicates that this is a continuation of a prior @@ -3972,9 +3970,8 @@ _LISTNOTIFICATIONCONFIGSREQUEST.fields_by_name["parent"]._options = None _LISTSOURCESREQUEST.fields_by_name["parent"]._options = None _LISTASSETSREQUEST.fields_by_name["parent"]._options = None -_LISTASSETSREQUEST.fields_by_name["field_mask"]._options = None _LISTFINDINGSREQUEST.fields_by_name["parent"]._options = None -_LISTFINDINGSREQUEST.fields_by_name["field_mask"]._options = None +_LISTFINDINGSRESPONSE_LISTFINDINGSRESULT.fields_by_name["resource"]._options = None _SETFINDINGSTATEREQUEST.fields_by_name["name"]._options = None _SETFINDINGSTATEREQUEST.fields_by_name["state"]._options = None _SETFINDINGSTATEREQUEST.fields_by_name["start_time"]._options = None @@ -3994,8 +3991,8 @@ index=0, serialized_options=b"\312A\035securitycenter.googleapis.com\322A.https://www.googleapis.com/auth/cloud-platform", create_key=_descriptor._internal_create_key, - serialized_start=6622, - serialized_end=12132, + serialized_start=6617, + serialized_end=12127, methods=[ _descriptor.MethodDescriptor( name="CreateSource", diff --git a/google/cloud/securitycenter_v1p1beta1/proto/securitycenter_service_pb2_grpc.py b/google/cloud/securitycenter_v1p1beta1/proto/securitycenter_service_pb2_grpc.py index b1c98c2f..59b91c3f 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/securitycenter_service_pb2_grpc.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/securitycenter_service_pb2_grpc.py @@ -167,8 +167,7 @@ def CreateSource(self, request, context): raise NotImplementedError("Method not implemented!") def CreateFinding(self, request, context): - """ - Creates a finding. The corresponding source must exist for finding + """Creates a finding. The corresponding source must exist for finding creation to succeed. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) @@ -280,8 +279,7 @@ def RunAssetDiscovery(self, request, context): raise NotImplementedError("Method not implemented!") def SetFindingState(self, request, context): - """ - Updates the state of a finding. + """Updates the state of a finding. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details("Method not implemented!") diff --git a/google/cloud/securitycenter_v1p1beta1/proto/source_pb2.py b/google/cloud/securitycenter_v1p1beta1/proto/source_pb2.py index 33ac8a80..e50bfc53 100644 --- a/google/cloud/securitycenter_v1p1beta1/proto/source_pb2.py +++ b/google/cloud/securitycenter_v1p1beta1/proto/source_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: google/cloud/securitycenter_v1p1beta1/proto/source.proto - +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection diff --git a/noxfile.py b/noxfile.py index 758afabf..6775f51d 100644 --- a/noxfile.py +++ b/noxfile.py @@ -100,6 +100,10 @@ def system(session): """Run the system test suite.""" system_test_path = os.path.join("tests", "system.py") system_test_folder_path = os.path.join("tests", "system") + + # Check the value of `RUN_SYSTEM_TESTS` env var. It defaults to true. + if os.environ.get("RUN_SYSTEM_TESTS", "true") == "false": + session.skip("RUN_SYSTEM_TESTS is set to false, skipping") # Sanity check: Only run tests if the environment variable is set. if not os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", ""): session.skip("Credentials must be set via environment variable") @@ -160,3 +164,38 @@ def docs(session): os.path.join("docs", ""), os.path.join("docs", "_build", "html", ""), ) + + +@nox.session(python=DEFAULT_PYTHON_VERSION) +def docfx(session): + """Build the docfx yaml files for this library.""" + + session.install("-e", ".") + # sphinx-docfx-yaml supports up to sphinx version 1.5.5. + # https://github.com/docascode/sphinx-docfx-yaml/issues/97 + session.install("sphinx==1.5.5", "alabaster", "recommonmark", "sphinx-docfx-yaml") + + shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True) + session.run( + "sphinx-build", + "-T", # show full traceback on exception + "-N", # no colors + "-D", + ( + "extensions=sphinx.ext.autodoc," + "sphinx.ext.autosummary," + "docfx_yaml.extension," + "sphinx.ext.intersphinx," + "sphinx.ext.coverage," + "sphinx.ext.napoleon," + "sphinx.ext.todo," + "sphinx.ext.viewcode," + "recommonmark" + ), + "-b", + "html", + "-d", + os.path.join("docs", "_build", "doctrees", ""), + os.path.join("docs", ""), + os.path.join("docs", "_build", "html", ""), + ) diff --git a/samples/snippets/noxfile.py b/samples/snippets/noxfile.py index 5660f08b..ba55d7ce 100644 --- a/samples/snippets/noxfile.py +++ b/samples/snippets/noxfile.py @@ -37,22 +37,24 @@ TEST_CONFIG = { # You can opt out from the test for specific Python versions. - "ignored_versions": ["2.7"], + 'ignored_versions': ["2.7"], + # An envvar key for determining the project id to use. Change it # to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a # build specific Cloud project. You can also use your own string # to use your own Cloud project. - "gcloud_project_env": "GOOGLE_CLOUD_PROJECT", + 'gcloud_project_env': 'GOOGLE_CLOUD_PROJECT', # 'gcloud_project_env': 'BUILD_SPECIFIC_GCLOUD_PROJECT', + # A dictionary you want to inject into your test. Don't put any # secrets here. These values will override predefined values. - "envs": {}, + 'envs': {}, } try: # Ensure we can import noxfile_config in the project's directory. - sys.path.append(".") + sys.path.append('.') from noxfile_config import TEST_CONFIG_OVERRIDE except ImportError as e: print("No user noxfile_config found: detail: {}".format(e)) @@ -67,12 +69,12 @@ def get_pytest_env_vars(): ret = {} # Override the GCLOUD_PROJECT and the alias. - env_key = TEST_CONFIG["gcloud_project_env"] + env_key = TEST_CONFIG['gcloud_project_env'] # This should error out if not set. - ret["GOOGLE_CLOUD_PROJECT"] = os.environ[env_key] + ret['GOOGLE_CLOUD_PROJECT'] = os.environ[env_key] # Apply user supplied envs. - ret.update(TEST_CONFIG["envs"]) + ret.update(TEST_CONFIG['envs']) return ret @@ -81,7 +83,7 @@ def get_pytest_env_vars(): ALL_VERSIONS = ["2.7", "3.6", "3.7", "3.8"] # Any default versions that should be ignored. -IGNORED_VERSIONS = TEST_CONFIG["ignored_versions"] +IGNORED_VERSIONS = TEST_CONFIG['ignored_versions'] TESTED_VERSIONS = sorted([v for v in ALL_VERSIONS if v not in IGNORED_VERSIONS]) @@ -136,7 +138,7 @@ def lint(session): args = FLAKE8_COMMON_ARGS + [ "--application-import-names", ",".join(local_names), - ".", + "." ] session.run("flake8", *args) @@ -180,9 +182,9 @@ def py(session): if session.python in TESTED_VERSIONS: _session_tests(session) else: - session.skip( - "SKIPPED: {} tests are disabled for this sample.".format(session.python) - ) + session.skip("SKIPPED: {} tests are disabled for this sample.".format( + session.python + )) # diff --git a/scripts/decrypt-secrets.sh b/scripts/decrypt-secrets.sh index ff599eb2..21f6d2a2 100755 --- a/scripts/decrypt-secrets.sh +++ b/scripts/decrypt-secrets.sh @@ -20,14 +20,27 @@ ROOT=$( dirname "$DIR" ) # Work from the project root. cd $ROOT +# Prevent it from overriding files. +# We recommend that sample authors use their own service account files and cloud project. +# In that case, they are supposed to prepare these files by themselves. +if [[ -f "testing/test-env.sh" ]] || \ + [[ -f "testing/service-account.json" ]] || \ + [[ -f "testing/client-secrets.json" ]]; then + echo "One or more target files exist, aborting." + exit 1 +fi + # Use SECRET_MANAGER_PROJECT if set, fallback to cloud-devrel-kokoro-resources. PROJECT_ID="${SECRET_MANAGER_PROJECT:-cloud-devrel-kokoro-resources}" gcloud secrets versions access latest --secret="python-docs-samples-test-env" \ + --project="${PROJECT_ID}" \ > testing/test-env.sh gcloud secrets versions access latest \ --secret="python-docs-samples-service-account" \ + --project="${PROJECT_ID}" \ > testing/service-account.json gcloud secrets versions access latest \ --secret="python-docs-samples-client-secrets" \ - > testing/client-secrets.json \ No newline at end of file + --project="${PROJECT_ID}" \ + > testing/client-secrets.json diff --git a/synth.metadata b/synth.metadata index c9656a59..3d13c815 100644 --- a/synth.metadata +++ b/synth.metadata @@ -4,29 +4,21 @@ "git": { "name": ".", "remote": "git@github.com:googleapis/python-securitycenter.git", - "sha": "a30a996cafb8dd9fed3c86ef641d42ab959febe3" - } - }, - { - "git": { - "name": "googleapis", - "remote": "https://github.com/googleapis/googleapis.git", - "sha": "50ae1c72fd94a3ae4269394b09e4b7fbb9251146", - "internalRef": "320484049" + "sha": "1cc4d1ffb5d64301d891d4ee95e429e4be1e4cf4" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "799d8e6522c1ef7cb55a70d9ea0b15e045c3d00b" + "sha": "ffcee7952b74f647cbb3ef021d95422f10816fca" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "799d8e6522c1ef7cb55a70d9ea0b15e045c3d00b" + "sha": "ffcee7952b74f647cbb3ef021d95422f10816fca" } } ], diff --git a/tests/unit/gapic/v1/test_security_center_client_v1.py b/tests/unit/gapic/v1/test_security_center_client_v1.py index dbecf0c9..96cf1bd2 100644 --- a/tests/unit/gapic/v1/test_security_center_client_v1.py +++ b/tests/unit/gapic/v1/test_security_center_client_v1.py @@ -74,196 +74,6 @@ class CustomException(Exception): class TestSecurityCenterClient(object): - def test_get_iam_policy(self): - # Setup Expected Response - version = 351608024 - etag = b"21" - expected_response = {"version": version, "etag": etag} - expected_response = policy_pb2.Policy(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = securitycenter_v1.SecurityCenterClient() - - # Setup Request - resource = "resource-341064690" - - response = client.get_iam_policy(resource) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = iam_policy_pb2.GetIamPolicyRequest(resource=resource) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_get_iam_policy_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = securitycenter_v1.SecurityCenterClient() - - # Setup request - resource = "resource-341064690" - - with pytest.raises(CustomException): - client.get_iam_policy(resource) - - def test_group_assets(self): - # Setup Expected Response - next_page_token = "" - total_size = 705419236 - group_by_results_element = {} - group_by_results = [group_by_results_element] - expected_response = { - "next_page_token": next_page_token, - "total_size": total_size, - "group_by_results": group_by_results, - } - expected_response = securitycenter_service_pb2.GroupAssetsResponse( - **expected_response - ) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = securitycenter_v1.SecurityCenterClient() - - # Setup Request - parent = client.organization_path("[ORGANIZATION]") - group_by = "groupBy506361367" - - paged_list_response = client.group_assets(parent, group_by) - resources = list(paged_list_response) - assert len(resources) == 1 - - assert expected_response.group_by_results[0] == resources[0] - - assert len(channel.requests) == 1 - expected_request = securitycenter_service_pb2.GroupAssetsRequest( - parent=parent, group_by=group_by - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_group_assets_exception(self): - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = securitycenter_v1.SecurityCenterClient() - - # Setup request - parent = client.organization_path("[ORGANIZATION]") - group_by = "groupBy506361367" - - paged_list_response = client.group_assets(parent, group_by) - with pytest.raises(CustomException): - list(paged_list_response) - - def test_group_findings(self): - # Setup Expected Response - next_page_token = "" - total_size = 705419236 - group_by_results_element = {} - group_by_results = [group_by_results_element] - expected_response = { - "next_page_token": next_page_token, - "total_size": total_size, - "group_by_results": group_by_results, - } - expected_response = securitycenter_service_pb2.GroupFindingsResponse( - **expected_response - ) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = securitycenter_v1.SecurityCenterClient() - - # Setup Request - parent = client.source_path("[ORGANIZATION]", "[SOURCE]") - group_by = "groupBy506361367" - - paged_list_response = client.group_findings(parent, group_by) - resources = list(paged_list_response) - assert len(resources) == 1 - - assert expected_response.group_by_results[0] == resources[0] - - assert len(channel.requests) == 1 - expected_request = securitycenter_service_pb2.GroupFindingsRequest( - parent=parent, group_by=group_by - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_group_findings_exception(self): - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = securitycenter_v1.SecurityCenterClient() - - # Setup request - parent = client.source_path("[ORGANIZATION]", "[SOURCE]") - group_by = "groupBy506361367" - - paged_list_response = client.group_findings(parent, group_by) - with pytest.raises(CustomException): - list(paged_list_response) - - def test_test_iam_permissions(self): - # Setup Expected Response - expected_response = {} - expected_response = iam_policy_pb2.TestIamPermissionsResponse( - **expected_response - ) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = securitycenter_v1.SecurityCenterClient() - - # Setup Request - resource = "resource-341064690" - permissions = [] - - response = client.test_iam_permissions(resource, permissions) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = iam_policy_pb2.TestIamPermissionsRequest( - resource=resource, permissions=permissions - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_test_iam_permissions_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = securitycenter_v1.SecurityCenterClient() - - # Setup request - resource = "resource-341064690" - permissions = [] - - with pytest.raises(CustomException): - client.test_iam_permissions(resource, permissions) - def test_create_source(self): # Setup Expected Response name = "name3373707" @@ -459,6 +269,45 @@ def test_delete_notification_config_exception(self): with pytest.raises(CustomException): client.delete_notification_config(name) + def test_get_iam_policy(self): + # Setup Expected Response + version = 351608024 + etag = b"21" + expected_response = {"version": version, "etag": etag} + expected_response = policy_pb2.Policy(**expected_response) + + # Mock the API response + channel = ChannelStub(responses=[expected_response]) + patch = mock.patch("google.api_core.grpc_helpers.create_channel") + with patch as create_channel: + create_channel.return_value = channel + client = securitycenter_v1.SecurityCenterClient() + + # Setup Request + resource = "resource-341064690" + + response = client.get_iam_policy(resource) + assert expected_response == response + + assert len(channel.requests) == 1 + expected_request = iam_policy_pb2.GetIamPolicyRequest(resource=resource) + actual_request = channel.requests[0][1] + assert expected_request == actual_request + + def test_get_iam_policy_exception(self): + # Mock the API response + channel = ChannelStub(responses=[CustomException()]) + patch = mock.patch("google.api_core.grpc_helpers.create_channel") + with patch as create_channel: + create_channel.return_value = channel + client = securitycenter_v1.SecurityCenterClient() + + # Setup request + resource = "resource-341064690" + + with pytest.raises(CustomException): + client.get_iam_policy(resource) + def test_get_notification_config(self): # Setup Expected Response name_2 = "name2-1052831874" @@ -603,6 +452,114 @@ def test_get_source_exception(self): with pytest.raises(CustomException): client.get_source(name) + def test_group_assets(self): + # Setup Expected Response + next_page_token = "" + total_size = 705419236 + group_by_results_element = {} + group_by_results = [group_by_results_element] + expected_response = { + "next_page_token": next_page_token, + "total_size": total_size, + "group_by_results": group_by_results, + } + expected_response = securitycenter_service_pb2.GroupAssetsResponse( + **expected_response + ) + + # Mock the API response + channel = ChannelStub(responses=[expected_response]) + patch = mock.patch("google.api_core.grpc_helpers.create_channel") + with patch as create_channel: + create_channel.return_value = channel + client = securitycenter_v1.SecurityCenterClient() + + # Setup Request + parent = client.organization_path("[ORGANIZATION]") + group_by = "groupBy506361367" + + paged_list_response = client.group_assets(parent, group_by) + resources = list(paged_list_response) + assert len(resources) == 1 + + assert expected_response.group_by_results[0] == resources[0] + + assert len(channel.requests) == 1 + expected_request = securitycenter_service_pb2.GroupAssetsRequest( + parent=parent, group_by=group_by + ) + actual_request = channel.requests[0][1] + assert expected_request == actual_request + + def test_group_assets_exception(self): + channel = ChannelStub(responses=[CustomException()]) + patch = mock.patch("google.api_core.grpc_helpers.create_channel") + with patch as create_channel: + create_channel.return_value = channel + client = securitycenter_v1.SecurityCenterClient() + + # Setup request + parent = client.organization_path("[ORGANIZATION]") + group_by = "groupBy506361367" + + paged_list_response = client.group_assets(parent, group_by) + with pytest.raises(CustomException): + list(paged_list_response) + + def test_group_findings(self): + # Setup Expected Response + next_page_token = "" + total_size = 705419236 + group_by_results_element = {} + group_by_results = [group_by_results_element] + expected_response = { + "next_page_token": next_page_token, + "total_size": total_size, + "group_by_results": group_by_results, + } + expected_response = securitycenter_service_pb2.GroupFindingsResponse( + **expected_response + ) + + # Mock the API response + channel = ChannelStub(responses=[expected_response]) + patch = mock.patch("google.api_core.grpc_helpers.create_channel") + with patch as create_channel: + create_channel.return_value = channel + client = securitycenter_v1.SecurityCenterClient() + + # Setup Request + parent = client.source_path("[ORGANIZATION]", "[SOURCE]") + group_by = "groupBy506361367" + + paged_list_response = client.group_findings(parent, group_by) + resources = list(paged_list_response) + assert len(resources) == 1 + + assert expected_response.group_by_results[0] == resources[0] + + assert len(channel.requests) == 1 + expected_request = securitycenter_service_pb2.GroupFindingsRequest( + parent=parent, group_by=group_by + ) + actual_request = channel.requests[0][1] + assert expected_request == actual_request + + def test_group_findings_exception(self): + channel = ChannelStub(responses=[CustomException()]) + patch = mock.patch("google.api_core.grpc_helpers.create_channel") + with patch as create_channel: + create_channel.return_value = channel + client = securitycenter_v1.SecurityCenterClient() + + # Setup request + parent = client.source_path("[ORGANIZATION]", "[SOURCE]") + group_by = "groupBy506361367" + + paged_list_response = client.group_findings(parent, group_by) + with pytest.raises(CustomException): + list(paged_list_response) + def test_list_assets(self): # Setup Expected Response next_page_token = "" @@ -949,6 +906,49 @@ def test_set_iam_policy_exception(self): with pytest.raises(CustomException): client.set_iam_policy(resource, policy) + def test_test_iam_permissions(self): + # Setup Expected Response + expected_response = {} + expected_response = iam_policy_pb2.TestIamPermissionsResponse( + **expected_response + ) + + # Mock the API response + channel = ChannelStub(responses=[expected_response]) + patch = mock.patch("google.api_core.grpc_helpers.create_channel") + with patch as create_channel: + create_channel.return_value = channel + client = securitycenter_v1.SecurityCenterClient() + + # Setup Request + resource = "resource-341064690" + permissions = [] + + response = client.test_iam_permissions(resource, permissions) + assert expected_response == response + + assert len(channel.requests) == 1 + expected_request = iam_policy_pb2.TestIamPermissionsRequest( + resource=resource, permissions=permissions + ) + actual_request = channel.requests[0][1] + assert expected_request == actual_request + + def test_test_iam_permissions_exception(self): + # Mock the API response + channel = ChannelStub(responses=[CustomException()]) + patch = mock.patch("google.api_core.grpc_helpers.create_channel") + with patch as create_channel: + create_channel.return_value = channel + client = securitycenter_v1.SecurityCenterClient() + + # Setup request + resource = "resource-341064690" + permissions = [] + + with pytest.raises(CustomException): + client.test_iam_permissions(resource, permissions) + def test_update_finding(self): # Setup Expected Response name = "name3373707" diff --git a/tests/unit/gapic/v1beta1/test_security_center_client_v1beta1.py b/tests/unit/gapic/v1beta1/test_security_center_client_v1beta1.py index bab98fc9..3cc4f388 100644 --- a/tests/unit/gapic/v1beta1/test_security_center_client_v1beta1.py +++ b/tests/unit/gapic/v1beta1/test_security_center_client_v1beta1.py @@ -189,7 +189,7 @@ def test_get_iam_policy(self): client = securitycenter_v1beta1.SecurityCenterClient() # Setup Request - resource = client.source_path("[ORGANIZATION]", "[SOURCE]") + resource = "resource-341064690" response = client.get_iam_policy(resource) assert expected_response == response @@ -208,7 +208,7 @@ def test_get_iam_policy_exception(self): client = securitycenter_v1beta1.SecurityCenterClient() # Setup request - resource = client.source_path("[ORGANIZATION]", "[SOURCE]") + resource = "resource-341064690" with pytest.raises(CustomException): client.get_iam_policy(resource) @@ -673,7 +673,7 @@ def test_set_iam_policy(self): client = securitycenter_v1beta1.SecurityCenterClient() # Setup Request - resource = client.source_path("[ORGANIZATION]", "[SOURCE]") + resource = "resource-341064690" policy = {} response = client.set_iam_policy(resource, policy) @@ -695,7 +695,7 @@ def test_set_iam_policy_exception(self): client = securitycenter_v1beta1.SecurityCenterClient() # Setup request - resource = client.source_path("[ORGANIZATION]", "[SOURCE]") + resource = "resource-341064690" policy = {} with pytest.raises(CustomException): @@ -716,7 +716,7 @@ def test_test_iam_permissions(self): client = securitycenter_v1beta1.SecurityCenterClient() # Setup Request - resource = client.source_path("[ORGANIZATION]", "[SOURCE]") + resource = "resource-341064690" permissions = [] response = client.test_iam_permissions(resource, permissions) @@ -738,7 +738,7 @@ def test_test_iam_permissions_exception(self): client = securitycenter_v1beta1.SecurityCenterClient() # Setup request - resource = client.source_path("[ORGANIZATION]", "[SOURCE]") + resource = "resource-341064690" permissions = [] with pytest.raises(CustomException): From dbb9311676003f452295848c49cbe97cb22c47b5 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 10 Sep 2020 17:12:03 +0000 Subject: [PATCH 8/8] chore: release 0.7.0 (#56) :robot: I have created a release \*beep\* \*boop\* --- ## [0.7.0](https://www.github.com/googleapis/python-securitycenter/compare/v0.6.0...v0.7.0) (2020-09-10) ### Features * add field severity to findings; update retry configs ([#53](https://www.github.com/googleapis/python-securitycenter/issues/53)) ([80494a9](https://www.github.com/googleapis/python-securitycenter/commit/80494a915ca33d260862694be889b817869ff01a)) ### Documentation * Update Security Command Center UpdateNotificationConfig sample, adding filter to mutable field ([#39](https://www.github.com/googleapis/python-securitycenter/issues/39)) ([c70d790](https://www.github.com/googleapis/python-securitycenter/commit/c70d7904425ae5ac252ffa7317ec6d08234a6c27)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). --- CHANGELOG.md | 12 ++++++++++++ setup.py | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60717740..fdcba7b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,18 @@ [1]: https://pypi.org/project/google-cloud-securitycenter/#history +## [0.7.0](https://www.github.com/googleapis/python-securitycenter/compare/v0.6.0...v0.7.0) (2020-09-10) + + +### Features + +* add field severity to findings; update retry configs ([#53](https://www.github.com/googleapis/python-securitycenter/issues/53)) ([80494a9](https://www.github.com/googleapis/python-securitycenter/commit/80494a915ca33d260862694be889b817869ff01a)) + + +### Documentation + +* Update Security Command Center UpdateNotificationConfig sample, adding filter to mutable field ([#39](https://www.github.com/googleapis/python-securitycenter/issues/39)) ([c70d790](https://www.github.com/googleapis/python-securitycenter/commit/c70d7904425ae5ac252ffa7317ec6d08234a6c27)) + ## [0.6.0](https://www.github.com/googleapis/python-securitycenter/compare/v0.5.0...v0.6.0) (2020-07-01) diff --git a/setup.py b/setup.py index 5a2cf044..514937a6 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ name = "google-cloud-securitycenter" description = "Cloud Security Command Center API API client library" -version = "0.6.0" +version = "0.7.0" release_status = "Development Status :: 3 - Alpha" dependencies = [ "google-api-core[grpc] >= 1.14.0, < 2.0.0dev",