From 3d525b2dac6117d967ef317160f5bbf1b5b648ad Mon Sep 17 00:00:00 2001 From: Micah Kornfield Date: Mon, 1 Apr 2019 03:11:25 -0700 Subject: [PATCH 01/13] Update and add tests for missing docs --- securitycenter/docs/snippets_findings.py | 378 ++++++++++++++++++ securitycenter/docs/snippets_orgs.py | 63 +++ .../docs/snippets_security_marks.py | 258 ++++++++++++ 3 files changed, 699 insertions(+) create mode 100644 securitycenter/docs/snippets_findings.py create mode 100644 securitycenter/docs/snippets_orgs.py create mode 100644 securitycenter/docs/snippets_security_marks.py diff --git a/securitycenter/docs/snippets_findings.py b/securitycenter/docs/snippets_findings.py new file mode 100644 index 000000000000..ec723b24dafc --- /dev/null +++ b/securitycenter/docs/snippets_findings.py @@ -0,0 +1,378 @@ +#!/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.""" +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 as 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 as 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) + + client.create_source( + org_name, + { + "display_name": "Customized Display Name", + "description": "A new custom source that does X", + }, + ) + # [END create_source] + + +def test_list_source(organization_id): + """ Create a new findings source. """ + i = -1 + # [START list_sources] + from google.cloud import securitycenter as 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): + """Demonstrate listing and printing all assets.""" + # [START create_finding] + from google.cloud import securitycenter as 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 as 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 as 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": {"l_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 as 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 as 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 as 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) + for i, finding_result in enumerate(client.list_findings(all_sources)): + 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 as 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 as 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 diff --git a/securitycenter/docs/snippets_orgs.py b/securitycenter/docs/snippets_orgs.py new file mode 100644 index 000000000000..b07399a7dfd9 --- /dev/null +++ b/securitycenter/docs/snippets_orgs.py @@ -0,0 +1,63 @@ +#!/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 + + +ORGANIZATION_ID = os.environ["GCLOUD_ORGANIZATION"] + + +def test_get_settings(): + """Example showing how to retreive current organization settings.""" + # [START get_org_settings] + from google.cloud import securitycenter as securitycenter + + 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 + ) + + org_settings = client.get_organization_settings(org_settings_name) + print(org_settings) + # [END get_org_settings] + + +def test_update_asset_discovery_org_settings(): + """Example showing how to update the asset discovery configuration + for an organization.""" + # [START update_org_settings] + from google.cloud import securitycenter as 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/securitycenter/docs/snippets_security_marks.py b/securitycenter/docs/snippets_security_marks.py new file mode 100644 index 000000000000..54ffe60ce745 --- /dev/null +++ b/securitycenter/docs/snippets_security_marks.py @@ -0,0 +1,258 @@ +#!/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 as 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 as 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 a returns it name.""" + from google.cloud import securitycenter as 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/11232" + }, + ) + client.create_finding( + source_name, + "untouched", + { + "state": Finding.ACTIVE, + "category": "MEDIUM_RISK_ONE", + "event_time": now_proto, + }, + ) + + 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 as 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): + # Make sure they are there first + test_add_to_asset(asset_name) + # [START clear_marks_asset] + from google.cloud import securitycenter as 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): + # Make sure they are there first + test_add_to_asset(asset_name) + # [START delete_and_update_marks] + from google.cloud import securitycenter as securitycenter + from google.protobuf import field_mask_pb2 + + client = securitycenter.SecurityCenterClient() + 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): + # [START add_marks_to_finding] + from google.cloud import securitycenter as securitycenter + from google.protobuf import field_mask_pb2 + + client = securitycenter.SecurityCenterClient() + 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): + test_add_to_asset(asset_name) + # [START demo_list_assets_with_security_marks] + from google.cloud import securitycenter as 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): + # 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 as 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 2cc3c3b3346830a099c64e6d7170cd17ce1c5aa8 Mon Sep 17 00:00:00 2001 From: Micah Kornfield Date: Mon, 1 Apr 2019 03:29:55 -0700 Subject: [PATCH 02/13] Update list assets to better conform to rubrics and to v1 add other tests to noxfile --- securitycenter/docs/snippets_list_assets.py | 56 ++++++++++++--------- securitycenter/noxfile.py | 7 ++- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/securitycenter/docs/snippets_list_assets.py b/securitycenter/docs/snippets_list_assets.py index e75b5cfa9f86..fd912c7a64f6 100644 --- a/securitycenter/docs/snippets_list_assets.py +++ b/securitycenter/docs/snippets_list_assets.py @@ -17,20 +17,24 @@ """ Examples of listing assets in Cloud Security Command Center.""" import os from datetime import datetime, timedelta +import pytest -# The numeric identifier for the organization. -ORGANIZATION_ID = os.environ["GCLOUD_ORGANIZATION"] +@pytest.fixture(scope="module") +def organization_id(): + """Get Organization ID from the environment variable """ + return os.environ["GCLOUD_ORGANIZATION"] -def test_list_all_assets(): +def test_list_all_assets(organization_id): """Demonstrate listing and printing all assets.""" - from google.cloud import securitycenter_v1beta1 as securitycenter - # [START demo_list_all_assets] + from google.cloud import securitycenter as securitycenter + client = securitycenter.SecurityCenterClient() - # ORGANIZATION_ID is the numeric ID of the organization (e.g. 123213123121) - org_name = "organizations/{org_id}".format(org_id=ORGANIZATION_ID) + # 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) @@ -40,15 +44,16 @@ def test_list_all_assets(): assert i > 0 -def test_list_assets_with_filters(): +def test_list_assets_with_filters(organization_id): """Demonstrate listing assets with a filter.""" - from google.cloud import securitycenter_v1beta1 as securitycenter - # [START demo_list_assets_with_filter] + from google.cloud import securitycenter as securitycenter + client = securitycenter.SecurityCenterClient() - # ORGANIZATION_ID is the numeric ID of the organization (e.g. 123213123121) - org_name = "organizations/{org_id}".format(org_id=ORGANIZATION_ID) + # 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=" @@ -62,17 +67,20 @@ def test_list_assets_with_filters(): assert i > 0 -def test_list_assets_with_filters_and_read_time(): +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.cloud import securitycenter_v1beta1 as securitycenter + from google.protobuf.timestamp_pb2 import Timestamp - # [START demo_list_assets_with_filter_and_time] + from google.cloud import securitycenter as securitycenter + client = securitycenter.SecurityCenterClient() - # ORGANIZATION_ID is the numeric ID of the organization (e.g. 123213123121) - org_name = "organizations/{org_id}".format(org_id=ORGANIZATION_ID) + # 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=" @@ -94,17 +102,19 @@ def test_list_assets_with_filters_and_read_time(): assert i > 0 -def test_list_point_in_time_changes(): +def test_list_point_in_time_changes(organization_id): """Demonstrate listing assets along with their state changes.""" - from google.cloud import securitycenter_v1beta1 as securitycenter - from google.protobuf.duration_pb2 import Duration + # [START demo_list_assets_changes] from datetime import timedelta - # [START demo_list_assets_changes] + from google.protobuf.duration_pb2 import Duration + from google.cloud import securitycenter as securitycenter + client = securitycenter.SecurityCenterClient() - # ORGANIZATION_ID is the numeric ID of the organization (e.g. 123213123121) - org_name = "organizations/{org_id}".format(org_id=ORGANIZATION_ID) + # 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"' diff --git a/securitycenter/noxfile.py b/securitycenter/noxfile.py index ec2d908c3803..65135ccd4999 100644 --- a/securitycenter/noxfile.py +++ b/securitycenter/noxfile.py @@ -158,6 +158,11 @@ def snippets(session): 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'), + + *session.posargs ) From 391761f99fd231b71611eba32a13f31d3d1eea93 Mon Sep 17 00:00:00 2001 From: Micah Kornfield Date: Mon, 1 Apr 2019 23:08:18 -0700 Subject: [PATCH 03/13] add list assets back to nox file --- securitycenter/noxfile.py | 1 + 1 file changed, 1 insertion(+) diff --git a/securitycenter/noxfile.py b/securitycenter/noxfile.py index 65135ccd4999..3988c2ab352c 100644 --- a/securitycenter/noxfile.py +++ b/securitycenter/noxfile.py @@ -158,6 +158,7 @@ def snippets(session): 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'), From 9a6440ea76420590c14be2e4ef67d7e79dac956c Mon Sep 17 00:00:00 2001 From: Micah Kornfield Date: Wed, 3 Apr 2019 00:25:12 -0700 Subject: [PATCH 04/13] correct typo in update source properties --- securitycenter/docs/snippets_findings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/securitycenter/docs/snippets_findings.py b/securitycenter/docs/snippets_findings.py index ec723b24dafc..2f539815f463 100644 --- a/securitycenter/docs/snippets_findings.py +++ b/securitycenter/docs/snippets_findings.py @@ -208,7 +208,7 @@ def test_update_finding(source_name): updated_finding = client.update_finding( { "name": finding_name, - "source_properties": {"l_value": value}, + "source_properties": {"s_value": value}, "event_time": now_proto, }, update_mask=field_mask, From a287607b2027596dc195f546b3ac4493feb928d4 Mon Sep 17 00:00:00 2001 From: Micah Kornfield Date: Wed, 3 Apr 2019 12:05:36 -0700 Subject: [PATCH 05/13] blacken --- securitycenter/docs/snippets_security_marks.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/securitycenter/docs/snippets_security_marks.py b/securitycenter/docs/snippets_security_marks.py index 54ffe60ce745..33e23a553e92 100644 --- a/securitycenter/docs/snippets_security_marks.py +++ b/securitycenter/docs/snippets_security_marks.py @@ -71,7 +71,6 @@ def finding_name(source_name): from google.cloud.securitycenter_v1.proto.finding_pb2 import Finding from google.protobuf.timestamp_pb2 import Timestamp - client = securitycenter.SecurityCenterClient() now_proto = Timestamp() @@ -84,7 +83,7 @@ def finding_name(source_name): "state": Finding.ACTIVE, "category": "C1", "event_time": now_proto, - 'resource_name': "//cloudresourcemanager.googleapis.com/organizations/11232" + "resource_name": "//cloudresourcemanager.googleapis.com/organizations/11232", }, ) client.create_finding( From 8d20324b114b339a8ed3626c531ac398d6b76e1c Mon Sep 17 00:00:00 2001 From: Micah Kornfield Date: Thu, 4 Apr 2019 11:25:22 -0700 Subject: [PATCH 06/13] cleanup --- securitycenter/docs/snippets_findings.py | 81 +++++++++++++++++-- .../docs/snippets_security_marks.py | 14 ++++ 2 files changed, 90 insertions(+), 5 deletions(-) diff --git a/securitycenter/docs/snippets_findings.py b/securitycenter/docs/snippets_findings.py index 2f539815f463..7959f2b35dcf 100644 --- a/securitycenter/docs/snippets_findings.py +++ b/securitycenter/docs/snippets_findings.py @@ -14,7 +14,9 @@ # 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.""" +"""Examples of working with source and findings in Cloud Security Command Center.""" + +from itertools import chain import os import pytest @@ -43,7 +45,7 @@ def source_name(organization_id): def test_create_source(organization_id): - """ Create a new findings source. """ + """Create a new findings source. """ # [START create_source] from google.cloud import securitycenter as securitycenter @@ -52,18 +54,87 @@ def test_create_source(organization_id): # organization_id = "111122222444" org_name = "organizations/{org_id}".format(org_id=organization_id) - client.create_source( + 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_update_source(source_name): + "Updates a sources display name." + # [START update_source] + from google.cloud import securitycenter as 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 as 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): - """ Create a new findings source. """ + """Lists finding sources.""" i = -1 # [START list_sources] from google.cloud import securitycenter as securitycenter @@ -82,7 +153,7 @@ def test_list_source(organization_id): def test_create_finding(source_name): - """Demonstrate listing and printing all assets.""" + """Creates a new finding.""" # [START create_finding] from google.cloud import securitycenter as securitycenter from google.cloud.securitycenter_v1.proto.finding_pb2 import Finding diff --git a/securitycenter/docs/snippets_security_marks.py b/securitycenter/docs/snippets_security_marks.py index 33e23a553e92..32adb0f5c1cd 100644 --- a/securitycenter/docs/snippets_security_marks.py +++ b/securitycenter/docs/snippets_security_marks.py @@ -131,6 +131,7 @@ def test_add_to_asset(asset_name): 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] @@ -164,6 +165,7 @@ def test_clear_from_asset(asset_name): 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] @@ -171,6 +173,10 @@ def test_delete_and_update_marks(asset_name): 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"]) @@ -185,11 +191,17 @@ def test_delete_and_update_marks(asset_name): def test_add_to_finding(finding_name): + """Adds security marks to a finding. """ # [START add_marks_to_finding] from google.cloud import securitycenter as 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 @@ -208,6 +220,7 @@ def test_add_to_finding(finding_name): 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 as securitycenter @@ -231,6 +244,7 @@ def test_list_assets_with_query_marks(organization_id, asset_name): 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 From 74734a1554afff9ea02cf69a5548136c64f8e50f Mon Sep 17 00:00:00 2001 From: Micah Kornfield Date: Fri, 5 Apr 2019 17:44:40 -0700 Subject: [PATCH 07/13] add missing policy and source tests --- securitycenter/docs/snippets_findings.py | 43 +++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/securitycenter/docs/snippets_findings.py b/securitycenter/docs/snippets_findings.py index 7959f2b35dcf..508b33040ba3 100644 --- a/securitycenter/docs/snippets_findings.py +++ b/securitycenter/docs/snippets_findings.py @@ -65,8 +65,28 @@ def test_create_source(organization_id): # [END create_source] +def test_get_source(source_name): + """Gets an existing source.""" + # [START get_source] + from google.cloud import securitycenter as securitycenter + from google.protobuf import field_mask_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" + source = client.get_source(source_name) + + print("Source: {}".format(source)) + # [END get_source] + + def test_update_source(source_name): - "Updates a sources display name." + """Updates a source's display name.""" # [START update_source] from google.cloud import securitycenter as securitycenter from google.protobuf import field_mask_pb2 @@ -447,3 +467,24 @@ def test_list_findings_at_time(source_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 as 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] From abf572ff0034a9aa6234f8315b1d85b62e2c962b Mon Sep 17 00:00:00 2001 From: Micah Kornfield Date: Tue, 9 Apr 2019 13:46:45 -0700 Subject: [PATCH 08/13] Fixes from bugbash --- securitycenter/docs/snippets_findings.py | 3 ++- securitycenter/docs/snippets_orgs.py | 15 +++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/securitycenter/docs/snippets_findings.py b/securitycenter/docs/snippets_findings.py index 508b33040ba3..6b6649c4902b 100644 --- a/securitycenter/docs/snippets_findings.py +++ b/securitycenter/docs/snippets_findings.py @@ -394,7 +394,8 @@ def test_list_all_findings(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) - for i, finding_result in enumerate(client.list_findings(all_sources)): + 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 diff --git a/securitycenter/docs/snippets_orgs.py b/securitycenter/docs/snippets_orgs.py index b07399a7dfd9..8d1d9f99ad9b 100644 --- a/securitycenter/docs/snippets_orgs.py +++ b/securitycenter/docs/snippets_orgs.py @@ -15,12 +15,15 @@ # 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"] -ORGANIZATION_ID = os.environ["GCLOUD_ORGANIZATION"] - -def test_get_settings(): +def test_get_settings(organization_id): """Example showing how to retreive current organization settings.""" # [START get_org_settings] from google.cloud import securitycenter as securitycenter @@ -29,7 +32,7 @@ def test_get_settings(): # 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 + org_id=organization_id ) org_settings = client.get_organization_settings(org_settings_name) @@ -37,7 +40,7 @@ def test_get_settings(): # [END get_org_settings] -def test_update_asset_discovery_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] @@ -49,7 +52,7 @@ def test_update_asset_discovery_org_settings(): # 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 + org_id=organization_id ) # Only update the enable_asset_discovery_value (leave others untouched). field_mask = field_mask_pb2.FieldMask(paths=["enable_asset_discovery"]) From 0510ac8cdadbb71d64ed1ced19b3913c8ce1fcd2 Mon Sep 17 00:00:00 2001 From: Micah Kornfield Date: Wed, 10 Apr 2019 10:48:41 -0700 Subject: [PATCH 09/13] correct capitalization in comments --- securitycenter/docs/snippets_orgs.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/securitycenter/docs/snippets_orgs.py b/securitycenter/docs/snippets_orgs.py index 8d1d9f99ad9b..7202a3c16df8 100644 --- a/securitycenter/docs/snippets_orgs.py +++ b/securitycenter/docs/snippets_orgs.py @@ -29,8 +29,8 @@ def test_get_settings(organization_id): from google.cloud import securitycenter as securitycenter client = securitycenter.SecurityCenterClient() - # ORGANIZATION_ID is numeric ID for the organization. e.g. - # ORGANIZATION_ID = "111112223333" + # 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 ) @@ -49,8 +49,8 @@ def test_update_asset_discovery_org_settings(organization_id): # Create the client client = securitycenter.SecurityCenterClient() - # ORGANIZATION_ID is numeric ID for the organization. e.g. - # ORGANIZATION_ID = "111112223333" + # 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 ) From 6ed9043802082e4d6db2d28498d2bb7b230968b7 Mon Sep 17 00:00:00 2001 From: Micah Kornfield Date: Sun, 14 Apr 2019 22:25:20 -0700 Subject: [PATCH 10/13] add group by --- securitycenter/docs/snippets_findings.py | 114 +++++++++++++++++++- securitycenter/docs/snippets_list_assets.py | 81 +++++++++++++- securitycenter/docs/snippets_orgs.py | 1 + 3 files changed, 191 insertions(+), 5 deletions(-) diff --git a/securitycenter/docs/snippets_findings.py b/securitycenter/docs/snippets_findings.py index 6b6649c4902b..229292682e99 100644 --- a/securitycenter/docs/snippets_findings.py +++ b/securitycenter/docs/snippets_findings.py @@ -343,7 +343,7 @@ def test_update_finding_state(source_name): def test_trouble_shoot(source_name): - """Demonstrate calling test_iam_permissions to determine if the + """Demonstrate calling test_iam_permissions to determine if the service account has the correct permisions.""" # [START test_iam_permissions] from google.cloud import securitycenter as securitycenter @@ -489,3 +489,115 @@ def test_get_iam_policy(source_name): 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 as 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 as 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 as 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 as 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/securitycenter/docs/snippets_list_assets.py b/securitycenter/docs/snippets_list_assets.py index fd912c7a64f6..25478169c3ae 100644 --- a/securitycenter/docs/snippets_list_assets.py +++ b/securitycenter/docs/snippets_list_assets.py @@ -33,7 +33,7 @@ def test_list_all_assets(organization_id): client = securitycenter.SecurityCenterClient() # organization_id is the numeric ID of the organization. - # organization_id=1234567777 + # organization_id = "1234567777" org_name = "organizations/{org_id}".format(org_id=organization_id) # Call the API and print results. @@ -52,7 +52,7 @@ def test_list_assets_with_filters(organization_id): client = securitycenter.SecurityCenterClient() # organization_id is the numeric ID of the organization. - # organization_id=1234567777 + # organization_id = "1234567777" org_name = "organizations/{org_id}".format(org_id=organization_id) project_filter = ( @@ -79,7 +79,7 @@ def test_list_assets_with_filters_and_read_time(organization_id): client = securitycenter.SecurityCenterClient() # organization_id is the numeric ID of the organization. - # organization_id=1234567777 + # organization_id = "1234567777" org_name = "organizations/{org_id}".format(org_id=organization_id) project_filter = ( @@ -113,7 +113,7 @@ def test_list_point_in_time_changes(organization_id): client = securitycenter.SecurityCenterClient() # organization_id is the numeric ID of the organization. - # organization_id=1234567777 + # organization_id = "1234567777" org_name = "organizations/{org_id}".format(org_id=organization_id) project_filter = ( "security_center_properties.resource_type=" @@ -134,3 +134,76 @@ def test_list_point_in_time_changes(organization_id): # [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 as 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 as 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 as 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/securitycenter/docs/snippets_orgs.py b/securitycenter/docs/snippets_orgs.py index 7202a3c16df8..31d5f8a9ad17 100644 --- a/securitycenter/docs/snippets_orgs.py +++ b/securitycenter/docs/snippets_orgs.py @@ -17,6 +17,7 @@ import os import pytest + @pytest.fixture(scope="module") def organization_id(): """Get Organization ID from the environment variable """ From b67bdd3ada135d5380b84d4409965683dda38da5 Mon Sep 17 00:00:00 2001 From: Micah Kornfield Date: Tue, 21 May 2019 17:56:28 -0700 Subject: [PATCH 11/13] address review feedback --- securitycenter/docs/snippets_findings.py | 39 +++++++++---------- securitycenter/docs/snippets_list_assets.py | 14 +++---- securitycenter/docs/snippets_orgs.py | 4 +- .../docs/snippets_security_marks.py | 18 ++++----- 4 files changed, 37 insertions(+), 38 deletions(-) diff --git a/securitycenter/docs/snippets_findings.py b/securitycenter/docs/snippets_findings.py index 229292682e99..dbd9406c8ab1 100644 --- a/securitycenter/docs/snippets_findings.py +++ b/securitycenter/docs/snippets_findings.py @@ -29,7 +29,7 @@ def organization_id(): @pytest.fixture(scope="module") def source_name(organization_id): - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter client = securitycenter.SecurityCenterClient() org_name = "organizations/{org_id}".format(org_id=organization_id) @@ -47,7 +47,7 @@ def source_name(organization_id): def test_create_source(organization_id): """Create a new findings source. """ # [START create_source] - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter client = securitycenter.SecurityCenterClient() # organization_id is the numeric ID of the organization. e.g.: @@ -68,8 +68,7 @@ def test_create_source(organization_id): def test_get_source(source_name): """Gets an existing source.""" # [START get_source] - from google.cloud import securitycenter as securitycenter - from google.protobuf import field_mask_pb2 + from google.cloud import securitycenter client = securitycenter.SecurityCenterClient() @@ -88,7 +87,7 @@ def test_get_source(source_name): def test_update_source(source_name): """Updates a source's display name.""" # [START update_source] - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter from google.protobuf import field_mask_pb2 client = securitycenter.SecurityCenterClient() @@ -115,7 +114,7 @@ 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 as securitycenter + from google.cloud import securitycenter from google.iam.v1 import policy_pb2 client = securitycenter.SecurityCenterClient() @@ -157,7 +156,7 @@ def test_list_source(organization_id): """Lists finding sources.""" i = -1 # [START list_sources] - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter # Create a new client. client = securitycenter.SecurityCenterClient() @@ -175,7 +174,7 @@ def test_list_source(organization_id): def test_create_finding(source_name): """Creates a new finding.""" # [START create_finding] - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter from google.cloud.securitycenter_v1.proto.finding_pb2 import Finding from google.protobuf.timestamp_pb2 import Timestamp @@ -220,7 +219,7 @@ def test_create_finding(source_name): 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 as securitycenter + 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 @@ -270,7 +269,7 @@ def test_create_finding_with_source_properties(source_name): def test_update_finding(source_name): # [START update_finding] - from google.cloud import securitycenter as securitycenter + 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 @@ -316,7 +315,7 @@ def test_update_finding(source_name): def test_update_finding_state(source_name): """Demonstrate updating only a finding state.""" # [START update_finding_state] - from google.cloud import securitycenter as securitycenter + 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 @@ -346,7 +345,7 @@ 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 as securitycenter + from google.cloud import securitycenter # Create a client. client = securitycenter.SecurityCenterClient() @@ -383,7 +382,7 @@ def test_trouble_shoot(source_name): def test_list_all_findings(organization_id): # [START list_all_findings] - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter # Create a client. client = securitycenter.SecurityCenterClient() @@ -407,7 +406,7 @@ def test_list_all_findings(organization_id): def test_list_filtered_findings(source_name): # [START list_filtered_findings] - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter # Create a new client. client = securitycenter.SecurityCenterClient() @@ -437,7 +436,7 @@ def test_list_filtered_findings(source_name): def test_list_findings_at_time(source_name): # [START list_findings_at_a_time] - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter from google.protobuf.timestamp_pb2 import Timestamp from datetime import timedelta, datetime @@ -474,7 +473,7 @@ 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 as securitycenter + from google.cloud import securitycenter from google.iam.v1 import policy_pb2 client = securitycenter.SecurityCenterClient() @@ -494,7 +493,7 @@ def test_get_iam_policy(source_name): def test_group_all_findings(organization_id): """Demonstrates grouping all findings across an organization.""" # [START group_all_findings] - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter # Create a client. client = securitycenter.SecurityCenterClient() @@ -515,7 +514,7 @@ def test_group_all_findings(organization_id): def test_group_filtered_findings(source_name): """Demonstrates grouping all findings across an organization.""" # [START group_filtered_findings] - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter # Create a client. client = securitycenter.SecurityCenterClient() @@ -542,7 +541,7 @@ def test_group_findings_at_time(source_name): i = -1 # [START group_findings_at_time] from datetime import datetime, timedelta - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter from google.protobuf.timestamp_pb2 import Timestamp # Create a client. @@ -575,7 +574,7 @@ def test_group_findings_and_changes(source_name): # [START group_filtered_findings_with_changes] from datetime import timedelta - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter from google.protobuf.duration_pb2 import Duration # Create a client. diff --git a/securitycenter/docs/snippets_list_assets.py b/securitycenter/docs/snippets_list_assets.py index 25478169c3ae..ae50ff916495 100644 --- a/securitycenter/docs/snippets_list_assets.py +++ b/securitycenter/docs/snippets_list_assets.py @@ -29,7 +29,7 @@ def organization_id(): def test_list_all_assets(organization_id): """Demonstrate listing and printing all assets.""" # [START demo_list_all_assets] - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter client = securitycenter.SecurityCenterClient() # organization_id is the numeric ID of the organization. @@ -47,7 +47,7 @@ def test_list_all_assets(organization_id): 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 as securitycenter + from google.cloud import securitycenter client = securitycenter.SecurityCenterClient() @@ -74,7 +74,7 @@ def test_list_assets_with_filters_and_read_time(organization_id): from google.protobuf.timestamp_pb2 import Timestamp - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter client = securitycenter.SecurityCenterClient() @@ -108,7 +108,7 @@ def test_list_point_in_time_changes(organization_id): from datetime import timedelta from google.protobuf.duration_pb2 import Duration - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter client = securitycenter.SecurityCenterClient() @@ -139,7 +139,7 @@ def test_list_point_in_time_changes(organization_id): def test_group_assets(organization_id): """Demonstrates grouping all assets by type. """ # [START group_all_assets] - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter client = securitycenter.SecurityCenterClient() @@ -160,7 +160,7 @@ def test_group_assets(organization_id): def test_group_filtered_assets(organization_id): """Demonstrates grouping assets by type with a filter. """ # [START group_all_assets] - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter client = securitycenter.SecurityCenterClient() @@ -188,7 +188,7 @@ def test_group_assets_by_changes(organization_id): # [START group_all_assets_by_change] from datetime import timedelta - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter from google.protobuf.duration_pb2 import Duration client = securitycenter.SecurityCenterClient() diff --git a/securitycenter/docs/snippets_orgs.py b/securitycenter/docs/snippets_orgs.py index 31d5f8a9ad17..7ebe7e8bbb31 100644 --- a/securitycenter/docs/snippets_orgs.py +++ b/securitycenter/docs/snippets_orgs.py @@ -27,7 +27,7 @@ def organization_id(): def test_get_settings(organization_id): """Example showing how to retreive current organization settings.""" # [START get_org_settings] - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter client = securitycenter.SecurityCenterClient() # organization_id is numeric ID for the organization. e.g. @@ -45,7 +45,7 @@ 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 as securitycenter + from google.cloud import securitycenter from google.protobuf import field_mask_pb2 # Create the client diff --git a/securitycenter/docs/snippets_security_marks.py b/securitycenter/docs/snippets_security_marks.py index 32adb0f5c1cd..2b4fb3d37367 100644 --- a/securitycenter/docs/snippets_security_marks.py +++ b/securitycenter/docs/snippets_security_marks.py @@ -29,7 +29,7 @@ def organization_id(): @pytest.fixture(scope="module") def asset_name(organization_id): """Returns a random asset name from existing assets.""" - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter client = securitycenter.SecurityCenterClient() # organization_id is the numeric ID of the organization. @@ -50,7 +50,7 @@ def asset_name(organization_id): @pytest.fixture(scope="module") def source_name(organization_id): """Creates a new source in the organization.""" - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter client = securitycenter.SecurityCenterClient() org_name = "organizations/{org_id}".format(org_id=organization_id) @@ -67,7 +67,7 @@ def source_name(organization_id): @pytest.fixture(scope="module") def finding_name(source_name): """Creates a new finding a returns it name.""" - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter from google.cloud.securitycenter_v1.proto.finding_pb2 import Finding from google.protobuf.timestamp_pb2 import Timestamp @@ -102,7 +102,7 @@ def finding_name(source_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 as securitycenter + from google.cloud import securitycenter from google.protobuf import field_mask_pb2 # Create a new client. @@ -135,7 +135,7 @@ def test_clear_from_asset(asset_name): # Make sure they are there first test_add_to_asset(asset_name) # [START clear_marks_asset] - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter from google.protobuf import field_mask_pb2 # Create a new client. @@ -169,7 +169,7 @@ def test_delete_and_update_marks(asset_name): # Make sure they are there first test_add_to_asset(asset_name) # [START delete_and_update_marks] - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter from google.protobuf import field_mask_pb2 client = securitycenter.SecurityCenterClient() @@ -193,7 +193,7 @@ def test_delete_and_update_marks(asset_name): def test_add_to_finding(finding_name): """Adds security marks to a finding. """ # [START add_marks_to_finding] - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter from google.protobuf import field_mask_pb2 client = securitycenter.SecurityCenterClient() @@ -223,7 +223,7 @@ 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 as securitycenter + from google.cloud import securitycenter client = securitycenter.SecurityCenterClient() @@ -249,7 +249,7 @@ def test_list_findings_with_query_marks(source_name, finding_name): test_add_to_finding(finding_name) i = -1 # [START demo_list_findings_with_security_marks] - from google.cloud import securitycenter as securitycenter + from google.cloud import securitycenter client = securitycenter.SecurityCenterClient() From 6ab41916eec9654806a07714420a0ee5cd11efba Mon Sep 17 00:00:00 2001 From: Bu Sun Kim Date: Fri, 30 Aug 2019 13:15:19 -0700 Subject: [PATCH 12/13] Set GCLOUD_ORGANIZATION in noxfile. --- securitycenter/noxfile.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/securitycenter/noxfile.py b/securitycenter/noxfile.py index 3988c2ab352c..76444c928096 100644 --- a/securitycenter/noxfile.py +++ b/securitycenter/noxfile.py @@ -148,7 +148,10 @@ def snippets(session): if not os.environ.get('GOOGLE_APPLICATION_CREDENTIALS', ''): session.skip('Credentials must be set via environment variable.') if not os.environ.get('GCLOUD_ORGANIZATION', ''): - session.skip('Credentials must be set via environment variable.') + if 'KOKORO' in os.environ: + session.env['GCLOUD_ORGANIZATION'] = '1081635000895' + else: + session.skip('Credentials must be set via environment variable.') # Install all test dependencies, then install local packages in place. From c432a29730c093a95ae4ec456d990f3eac6f675a Mon Sep 17 00:00:00 2001 From: Bu Sun Kim Date: Fri, 30 Aug 2019 13:34:38 -0700 Subject: [PATCH 13/13] Look for KOKORO_GFILE_DIR instead. --- securitycenter/noxfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/securitycenter/noxfile.py b/securitycenter/noxfile.py index 76444c928096..4b838ce77c52 100644 --- a/securitycenter/noxfile.py +++ b/securitycenter/noxfile.py @@ -148,7 +148,7 @@ def snippets(session): 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' in os.environ: + if 'KOKORO_GFILE_DIR' in os.environ: session.env['GCLOUD_ORGANIZATION'] = '1081635000895' else: session.skip('Credentials must be set via environment variable.')