GoogleCloudSCC
Security Command Center is a security and risk management platform for Google Cloud. Security Command Center enables you to understand your security and data attack surface by providing asset inventory and discovery, identifying vulnerabilities and threats, and helping you mitigate and remediate risks across an organization. This integration helps you to perform tasks related to findings and assets.
Data Enrichment & Threat Intelligence · Google Cloud SCC
Details
| ID | GoogleCloudSCC |
|---|---|
| Provider | |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 6.0.0 |
| Docker Image | demisto/google-api-py3:1.0.0.10182333 |
| Supported Modules | Agentix XSIAM |
README
Security Command Center is a security and risk management platform for Google Cloud. Security Command Center enables you to understand your security and data attack surface by providing asset inventory and discovery, identifying vulnerabilities and threats, and helping you mitigate and remediate risks across an organization. This integration helps you to perform tasks related to findings and assets.
This integration was integrated and tested with version v1 of GoogleCloudSCC.
Detailed Description
This integration uses Pub/Sub to fetch the incidents. This integration supports multiple organizations. In order to fetch data from multiple organizations, configure multiple instances for different organizations. To set up the initial parameters of Google SCC in Cortex XSOAR, please follow the below instructions. For more information, refer to this guide by Google SCC for configuring Cortex XSOAR Integration.
Scope
We need to provide the below mentioned OAuth scope to execute the commands: https://www.googleapis.com/auth/cloud-platform.
Create a Service Account
- Go to the Google documentation and follow the procedure mentioned in the Creating a Service Account section. After you create a service account, a Service Account Private Key file is downloaded. You will need this file when configuring an instance of the integration.
- Grant the Security Command Center admin permission to the Service Account to enable the Service Account to perform certain Google Cloud API commands.
- For additional information on the types of permissions that can be granted to Service Account, see the Permissions section below.
- In Cortex XSOAR, configure an instance of the Google Cloud Security Command Center integration. For the Service Account Private Key parameter, add the Service Account Private Key file contents (JSON).
Permissions
To set up Security Command Center or change the configuration of your organization, you need both of the following roles at the organization level:
- Organization Admin (roles/resourcemanager.organizationAdmin)
- Security Center Admin (roles/securitycenter.admin)
If a user doesn’t require edit permissions, consider granting them viewer roles. To view all assets and findings in Security Command Center, users need the Security Center Admin Viewer (roles/securitycenter.adminViewer) role at the organization level. Users who need to edit the findings need the Security Center Admin (roles/securitycenter.admin) role at the organization level.
To restrict access to individual folders and projects, don’t grant all roles at the organization level. Instead, grant the following roles at the folder or project level:
- Security Center Assets Viewer (roles/securitycenter.assetsViewer)
- Security Center Findings Viewer (roles/securitycenter.findingsViewer)
Refer to Google Documentation for further information on granting roles to persons and applications, as well as specific permissions.
Steps to configure workload identity federation
- Follow the steps to construct a workload identity pool and a workload identity pool provider to leverage workload identity federation.
- Navigate to the ‘Granting external identities permission to impersonate a service account’ section.
-
Follow the step-1 mentioned in the Google documentation to create a credential file for external identities. The contents of the downloaded file should be given into the ‘Service Account Configuration’ parameter.
Prerequisite for accessing Google services from AWS
Prerequisite for accessing Google services from Azure
- Create an Azure AD application and service principal.
- Set an Application ID URI for the application.
- Create a managed identity. Note the Object ID of the managed identity. You need it later when you configure impersonation.
- Assign the managed identity to a virtual machine or another resource that runs your application.
Getting your Organization ID
The Organization ID is a unique identifier for an organization and is automatically created when your organization resource is created.
- To get the Organization ID for your organization, follow the steps mentioned in Google documentation provided here.
- To get your Organization ID using the Cloud Console, Go to the Cloud Console and at the top of the page, click the project selection drop-down list and from the Select window that appears, click the organization drop-down list and select the organization you want.
- On the right side, click More, then click Settings. The Settings page displays your organization’s ID.
Getting your Project ID
When we create a new project or for an existing project, Project ID generates for that project. To get the Project ID and the Project number, you can follow the same instructions provided above for getting Organization ID. For more details, You can follow the instructions provided in Google documentation here.
Getting Subscription ID from Pub/Sub
To fetch incidents using Google Pub/Sub, we need to configure Pub/Sub first. This Google documentation will help setting up Pub/Sub prerequisites for creating a subscription.
- To add a subscription, we need to have a topic first. So after you create a topic, go to the menu for the topic and click on Create subscription and it will take you to the Add new subscription page.
- Type a name for the subscription and leave the delivery type as Pull.
- Set the Message retention duration to retain unacknowledged messages for a specified duration. If the checkbox of Retain acknowledged messages is enabled, acknowledged messages are retained for the same duration. It is recommended to keep maximum possible value for Message retention so messages can be retained inside subscription until they are pulled.
- Set the Acknowledgement deadline for pub/sub to wait for the subscriber to acknowledge receipt before resending the message. Minimum recommended value for Acknowledgement deadline is 300 seconds for this integration.
- Apply the other settings as required and click on the CREATE button.
- Once the subscription is created, it will take you to the Subscriptions page, where you can see the Subscription ID for the subscription you just created.
Setting up finding notifications
- Enable the Security Command Center API notifications feature. Notifications send information to a Pub/Sub topic to provide findings updates and new findings within minutes. Set up the notifications as per Google Documentation available and get SCC data in Cortex XSOAR.
- The basic parameters required for setting up pub/sub notifications are ORGANIZATION_ID, PUBSUB_TOPIC, DESCRIPTION and FILTER.
- Before creating a pub/sub notification, make sure to check the filter parameters using google-cloud-scc-finding-list command provided in this integration. The total size applicable for the filter provided can be checked using Total retrieved findings available inside the command results section. A maximum of 200 findings per minute is recommended.
Configure GoogleCloudSCC on Cortex XSOAR
- Navigate to Settings > Integrations > Servers & Services.
- Search for GoogleCloudSCC.
-
Click Add instance to create and configure a new integration instance.
Parameter Description Required Service Account Configuration If the application runs on cloud provider (AWS, Azure) use workload identity federation configuration setup file otherwise use service account credential file. True Organization ID Organization ID defines from which organization incidents need to be fetched. True Fetch incidents Enables fetch incident. False Project ID ID of the project to use for fetching incidents. If ID is not provided it will be taken from the provided service account JSON.
Only required if the XSOAR instance is running on AWS or Azure cloud solutions.False Subscription ID ID of subscription from which to fetch incidents. False Max Incidents The maximum number of incidents to fetch every time. False Incident type Type of incident. False Trust any certificate (not secure) Enables to trust on all certificates. False Use system proxy settings Enables system proxy settings. False - Click Test to validate configuration parameter.
Commands
You can execute these commands from the Cortex XSOAR CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
google-cloud-scc-asset-list
Lists an organization’s assets.
Base Command
google-cloud-scc-asset-list
Input
| Argument Name | Description | Required |
|---|---|---|
| filter | The filter 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.Examples include: 1) name 2) securityCenterProperties.resource_name 3) resourceProperties.name 4) securityMarks.marks.marka The supported operators are: 1) = for all value types. 2) >, <, >=, <= for integer values. 3) :, meaning substring matching, for strings. The following field and operator combinations are supported: 1) name: = 2) updateTime: =, >, <, >=, < Example: resourceProperties.displayName=”test.com” OR resourceProperties.projectNumber=”455757558851” Use a negated partial match on the empty string to filter based on a property not existing: “-resourceProperties.project=45”. |
Optional |
| orderBy | This parameter defines what fields and order to use for sorting. The string value should be a comma-separated list of fields. The default sorting order is ascending. To specify descending order for a field, a suffix “desc” should be appended to the field name. For example: “name desc,resourceProperties.owner”. The following fields are supported for orderBy: name, updateTime, resourceProperties, securityMarks.marks, securityCenterProperties.resource_name, securityCenterProperties.resource_display_name, securityCenterProperties.resource_parent, securityCenterProperties.resource_parent_display_name, securityCenterProperties.resource_project, securityCenterProperties.resource_project_display_name, securityCenterProperties.resource_type. |
Optional |
| readTime | Time is 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. If not provided, it will take current time. Format: YYYY-MM-ddTHH:mm:ss.sssZ Example: 2020-07-22T07:10:02.782Z. |
Optional |
| compareDuration | When compareDuration is set, the “stateChange” attribute is updated to indicate whether the asset was added, removed, or remained present during the compareDuration period of time that precedes the readTime. Possible “stateChange” values when compareDuration is specified: 1) ADDED 2) REMOVED 3) ACTIVE If compareDuration is not specified, then the only possible stateChange is “UNUSED”, Example value: 3.5s. |
Optional |
| fieldMask | A field mask is used to specify the specific response fields to be listed in the response. An empty field mask will list all fields. Comma-separated values are supported in this parameter. Example: “asset.resourceProperties.owner,asset.securityCenterProperties.resourceName”. |
Optional |
| pageToken | The value returned by the last response of the google-cloud-scc-asset-list command indicates that this is a continuation of prior assets.list call, and that the system should return the next page of data. | Optional |
| pageSize | The maximum number of results to return in a single response. The minimum value is 1 and maximum value is 1000. Default is 10. | Optional |
| resourceType | This parameter is used to filter assets by resource types by providing a single value or a comma-separated value of resource types. If any resource type is not provided, by default all resource types will be considered for listing assets.The value provided inside resourceType would be applied in the query as a filter parameter for filtering results. Example: cloudfunction, bucket. | Optional |
| project | This parameter is used to filter assets by the project by providing a single value or a comma-separated value of projects. If any project is not provided, by default all projects will be considered for listing assets. Value provided inside the project would be applied in the query as a filter parameter for filtering results. Example: Automeet, Backstory. | Optional |
| activeAssetsOnly | This parameter is used to filter assets by their lifeCycleState value by selecting an option from the dropdown. If ‘True’ is selected the assets having lifeCycleState as ‘ACTIVE’ will be fetched and if ‘False’ or no option selected from the dropdown, then assets with all states will be considered for listing assets. The value selected in activeAssetsOnly would be applied in the query as a filter parameter for filtering results. Possible values are: True, False. Default is False. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleCloudSCC.Asset.name | String | The relative resource name of the asset. |
| GoogleCloudSCC.Asset.securityCenterProperties.resourceName | String | The full resource name of the Google Cloud resource this asset represents. |
| GoogleCloudSCC.Asset.securityCenterProperties.resourceType | String | The type of the Google Cloud resource. |
| GoogleCloudSCC.Asset.securityCenterProperties.resourceParent | String | The full resource name of the immediate parent of the resource. |
| GoogleCloudSCC.Asset.securityCenterProperties.resourceProject | String | The full resource name of the project the resource belongs to. |
| GoogleCloudSCC.Asset.securityCenterProperties.resourceOwners | String | Owners of the Google Cloud resource. |
| GoogleCloudSCC.Asset.securityCenterProperties.resourceDisplayName | String | The user defined display name for this resource. |
| GoogleCloudSCC.Asset.securityCenterProperties.resourceParentDisplayName | String | The user defined display name for the parent of this resource. |
| GoogleCloudSCC.Asset.securityCenterProperties.resourceProjectDisplayName | String | The user defined display name for the project of this resource. |
| GoogleCloudSCC.Asset.securityCenterProperties.folders.resourceFolder | String | Full resource name of this folder. |
| GoogleCloudSCC.Asset.securityCenterProperties.folders.resourceFolderDisplayName | String | The user defined display name for this folder. |
| GoogleCloudSCC.Asset.resourceProperties | Unknown | Resource managed properties. These properties are managed and defined by the Google Cloud resource and cannot be modified by the user. Properties are varying from assets to assets. |
| GoogleCloudSCC.Asset.securityMarks.name | String | The relative resource name of the SecurityMarks. |
| GoogleCloudSCC.Asset.securityMarks.marks | String | Mutable user specified security marks belonging to the parent resource. |
| GoogleCloudSCC.Asset.createTime | String | The time at which the asset was created in the Security Command Center. |
| GoogleCloudSCC.Asset.updateTime | String | The time at which the asset was last updated, added, or deleted in Security Command Center. |
| GoogleCloudSCC.Asset.iamPolicy.policyBlob | String | Cloud IAM Policy information associated with the Google Cloud resource described by the Security Command Center asset. |
| GoogleCloudSCC.Asset.stateChange | String | State change of the asset between the points in time. |
| GoogleCloudSCC.Asset.readTime | String | Time used for executing the list request. |
| GoogleCloudSCC.Token.nextPageToken | String | Token to retrieve the next page of results, or empty if there are no more results. |
| GoogleCloudSCC.Token.name | String | Name of the command. |
Command Example
!google-cloud-scc-asset-list pageSize="3"
Context Example
{
"GoogleCloudSCC": {
"Asset": [
{
"createTime": "2020-07-22T07:10:02.782Z",
"iamPolicy": {
"policyBlob": "{\"bindings\":[{\"role\":\"roles/billing.admin\",\"members\":[\"group:gcp-billing-admins@test.com\",\"user:harsh.shah@test.com\",\"user:malhar@test.com\",\"user:shail.rabdu@test.com\"]},{\"role\":\"roles/billing.creator\",\"members\":[\"domain:test.com\",\"group:gcp-billing-admins@test.com\",\"user:harsh.shah@test.com\",\"user:malhar@test.com\",\"user:shail.rabdu@test.com\"]},{\"role\":\"roles/billing.user\",\"members\":[\"group:gcp-organization-admins@test.com\"]},{\"role\":\"roles/browser\",\"members\":[\"user:jignesh.patel@test.com\"]},{\"role\":\"roles/cloudfunctions.serviceAgent\",\"members\":[\"serviceAccount:service-org-595779152576@security-center-api.iam.gserviceaccount.com\"]},{\"role\":\"roles/cloudsql.admin\",\"members\":[\"serviceAccount:service-org-595779152576@security-center-api.iam.gserviceaccount.com\"]},{\"role\":\"roles/cloudsupport.admin\",\"members\":[\"group:gcp-organization-admins@test.com\"]},{\"role\":\"roles/compute.admin\",\"members\":[\"user:jignesh.patel@test.com\"]},{\"role\":\"roles/iam.organizationRoleAdmin\",\"members\":[\"group:gcp-organization-admins@test.com\"]},{\"role\":\"roles/iam.serviceAccountAdmin\",\"members\":[\"user:jignesh.patel@test.com\"]},{\"role\":\"roles/orgpolicy.policyAdmin\",\"members\":[\"group:gcp-organization-admins@test.com\"]},{\"role\":\"roles/owner\",\"members\":[\"user:harsh.shah@test.com\"]},{\"role\":\"roles/pubsub.editor\",\"members\":[\"serviceAccount:scc-test-sa-0908@gscc-demo-0908.iam.gserviceaccount.com\"]},{\"role\":\"roles/resourcemanager.folderAdmin\",\"members\":[\"group:gcp-organization-admins@test.com\"]},{\"role\":\"roles/resourcemanager.organizationAdmin\",\"members\":[\"group:gcp-organization-admins@test.com\",\"user:harsh.shah@test.com\",\"user:it.systems@test.com\",\"user:malhar@test.com\",\"user:shivang.patel@test.com\"]},{\"role\":\"roles/resourcemanager.organizationViewer\",\"members\":[\"group:gcp-billing-admins@test.com\",\"user:shivang.patel@test.com\"]},{\"role\":\"roles/resourcemanager.projectCreator\",\"members\":[\"group:gcp-organization-admins@test.com\",\"user:it.systems@test.com\"]},{\"role\":\"roles/securitycenter.admin\",\"members\":[\"domain:test.com\",\"group:gcp-organization-admins@test.com\",\"serviceAccount:scc-test-sa-0908@gscc-demo-0908.iam.gserviceaccount.com\",\"deleted:serviceAccount:scc-test-sa@gscc-demo.iam.gserviceaccount.com?uid\\u003d111170257821042589392\",\"serviceAccount:scc-test@calcium-vial-280707.iam.gserviceaccount.com\",\"user:jignesh.patel@test.com\",\"user:namrata.haridwari@test.com\",\"user:shivang.patel@test.com\"]},{\"role\":\"roles/securitycenter.serviceAgent\",\"members\":[\"serviceAccount:service-org-595779152576@security-center-api.iam.gserviceaccount.com\"]},{\"role\":\"roles/serviceusage.serviceUsageAdmin\",\"members\":[\"serviceAccount:service-org-595779152576@security-center-api.iam.gserviceaccount.com\"]},{\"role\":\"roles/viewer\",\"members\":[\"serviceAccount:scc-test-sa-0908@gscc-demo-0908.iam.gserviceaccount.com\",\"deleted:serviceAccount:scc-test-sa@gscc-demo.iam.gserviceaccount.com?uid\\u003d111170257821042589392\"]}]}"
},
"name": "organizations/595779152576/assets/7180457033309348544",
"readTime": "2021-02-11T13:51:59.620Z",
"resourceProperties": {
"creationTime": "2017-01-23T08:50:47.212Z",
"displayName": "test.com",
"lifecycleState": "ACTIVE",
"name": "organizations/595779152576",
"organizationId": "595779152576",
"owner": "{\"directoryCustomerId\":\"C02umwv6u\"}"
},
"securityCenterProperties": {
"resourceDisplayName": "test.com",
"resourceName": "//cloudresourcemanager.googleapis.com/organizations/595779152576",
"resourceType": "google.cloud.resourcemanager.Organization"
},
"securityMarks": {
"marks": {
"compressed": "SSH",
"LastSeen": "Yesterday"
},
"name": "organizations/595779152576/assets/7180457033309348544/securityMarks"
},
"updateTime": "2021-02-06T11:01:26.317Z"
},
{
"createTime": "2020-12-16T10:05:58.742Z",
"iamPolicy": {
"policyBlob": "{\"bindings\":[{\"role\":\"roles/owner\",\"members\":[\"user:milankumar.thummar@test.com\"]}]}"
},
"name": "organizations/595779152576/assets/2994068353411300094",
"readTime": "2021-02-11T13:51:59.620Z",
"resourceProperties": {
"createTime": "2020-12-16T10:05:54.696Z",
"lifecycleState": "ACTIVE",
"name": "Calender",
"parent": "{\"id\":\"595779152576\",\"type\":\"organization\"}",
"projectId": "calender-1608113154215",
"projectNumber": "455757558851"
},
"securityCenterProperties": {
"resourceDisplayName": "calender-1608113154215",
"resourceName": "//cloudresourcemanager.googleapis.com/projects/455757558851",
"resourceOwners": [
"user:milankumar.thummar@test.com"
],
"resourceParent": "//cloudresourcemanager.googleapis.com/organizations/595779152576",
"resourceParentDisplayName": "test.com",
"resourceProject": "//cloudresourcemanager.googleapis.com/projects/455757558851",
"resourceProjectDisplayName": "calender-1608113154215",
"resourceType": "google.cloud.resourcemanager.Project"
},
"securityMarks": {
"marks": {
"compressed": "SSH",
"LastSeen": "Yesterday"
},
"name": "organizations/595779152576/assets/2994068353411300094/securityMarks"
},
"updateTime": "2020-12-16T10:06:00.134Z"
},
{
"createTime": "2019-09-24T02:10:50.766Z",
"iamPolicy": {
"policyBlob": "{\"bindings\":[{\"role\":\"roles/owner\",\"members\":[\"user:heena.vaghela@test.com\"]}]}"
},
"name": "organizations/595779152576/assets/14656821127596596302",
"readTime": "2021-02-11T13:51:59.620Z",
"resourceProperties": {
"createTime": "2019-08-13T06:58:21.574Z",
"lifecycleState": "ACTIVE",
"name": "Test Proj",
"parent": "{\"id\":\"595779152576\",\"type\":\"organization\"}",
"projectId": "test-proj-249706",
"projectNumber": "265894444436"
},
"securityCenterProperties": {
"resourceDisplayName": "test-proj-249706",
"resourceName": "//cloudresourcemanager.googleapis.com/projects/265894444436",
"resourceOwners": [
"user:heena.vaghela@test.com"
],
"resourceParent": "//cloudresourcemanager.googleapis.com/organizations/595779152576",
"resourceParentDisplayName": "test.com",
"resourceProject": "//cloudresourcemanager.googleapis.com/projects/265894444436",
"resourceProjectDisplayName": "test-proj-249706",
"resourceType": "google.cloud.resourcemanager.Project"
},
"securityMarks": {
"name": "organizations/595779152576/assets/14656821127596596302/securityMarks"
},
"updateTime": "2020-04-16T06:09:38.488Z"
}
],
"Token": {
"name": "google-cloud-scc-asset-list",
"nextPageToken": "next-page-token"
}
}
}
Human Readable Output
Total retrieved asset(s): 3
| Organization ID |Name|Project|Resource Name|Resource Type|Resource Owners|Security Marks|
|—|—|—|—|—|—|—|
| 595779152576 | organizations/595779152576/assets/7180457033309348544 | organizations/595779152576 | //cloudresourcemanager.googleapis.com/organizations/595779152576 | google.cloud.resourcemanager.Organization | | compressed: SSH
LastSeen: Yesterday |
| 595779152576 | organizations/595779152576/assets/2994068353411300094 | Calender | //cloudresourcemanager.googleapis.com/projects/455757558851 | google.cloud.resourcemanager.Project | user:milankumar.thummar@test.com | compressed: SSH
LastSeen: Yesterday |
| 595779152576 | organizations/595779152576/assets/14656821127596596302 | Test Proj | //cloudresourcemanager.googleapis.com/projects/265894444436 | google.cloud.resourcemanager.Project | user:heena.vaghela@test.com | |
To fetch the next batch of results, execute the command with the page token as next-page-token
google-cloud-scc-finding-list
Lists an organization or source’s findings.
Base Command
google-cloud-scc-finding-list
Input
| Argument Name | Description | Required |
|---|---|---|
| severity | Filter findings by their severity (LOW, MEDIUM, HIGH, CRITICAL). Comma-separated values are supported and if any severity value is not provided, by default all the severities will be considered for listing of findings. Value provided inside severity would be applied in the query as a filter parameter for filtering results. | Optional |
| category | Filter findings by providing comma-separated values of categories or a single category. If any category value is not provided, by default all the categories will be considered for listing findings. Value provided inside the category would be applied in the query as a filter parameter for filtering results. For Example: anomaly,application. |
Optional |
| sourceTypeId | Filter findings by providing the value of a single source type. If any source type Id value is not provided, by default all source types will be considered for list findings. Default is -. | Optional |
| pageSize | The maximum number of results to return in a single response. The minimum value is 1 and maximum value is 1000. Default is 10. | Optional |
| state | Filter the findings by their state. Can be ‘ACTIVE’, ‘INACTIVE’. Comma-separated values are supported and if any state value is not provided, by default ‘ACTIVE’ state will be considered for listing of findings. Value provided inside the state would be applied in the query as a filter parameter for filtering results. Default is ACTIVE. | Optional |
| filter | The filter 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.Examples include: 1) name 2) sourceProperties.a_property 3) securityMarks.marks.marka The supported operators are: 1) = for all value types. 2) >, <, >=, <= for integer values. 3) :, meaning substring matching, for strings. The following field and operator combinations are supported: 1) name: = 2) parent: =, : 3) resourceName: =, : 4) state: =, : 5) category: =, : 6) externalUri: =, : 7) eventTime: =, >, <, >=, <= 8) severity: =, : 9) findingClass: = Examples: “sourceProperties.browser=”chrome” AND sourceProperties.event_type=”proximity”“ Use a negated partial match on the empty string to filter based on a property not existing: “-severity=LOW”. |
Optional |
| orderBy | This parameter defines what fields and order to use for sorting. The string value should be a comma separated list of fields. The default sorting order is ascending. To specify descending order for a field, a suffix “ desc” should be appended to the field name. For example: “name desc,sourceProperties.browser”. Supported fields: name, parent, state, category, resourceName, eventTime, sourceProperties, securityMarks.marks. |
Optional |
| compareDuration | When compareDuration is set, the “stateChange” attribute is updated to indicate whether the finding had its state changed, the finding’s state remained unchanged, or if the finding was added in any state during the compareDuration period of time that precedes the readTime. This is the time between (readTime - compareDuration) and readTime. The results aren’t affected if the finding is made inactive and then active again. Possible “stateChange” values when compareDuration is specified: 1) CHANGED 2) UNCHANGED 3) ADDED 4) REMOVED If compareDuration is not specified, then the only possible stateChange is “UNUSED”. Example value: “3.5s”. |
Optional |
| readTime | 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. If not provided, it will take current time. Format: YYYY-MM-ddTHH:mm:ss.sssZ Example: 2020-07-22T07:10:02.782Z. |
Optional |
| fieldMask | A field mask is used to specify the specific response fields to be listed in the response. An empty field mask will list all fields. Comma-separated values are supported in this parameter. Example: “user.displayName,sourceProperties.browser”. |
Optional |
| pageToken | The value returned by the last response of a google-cloud-scc-finding-list command indicates that this is a continuation of a prior findings.list call, and that the system should return the next page of data. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleCloudSCC.Finding.name | String | The relative resource name of this finding. |
| GoogleCloudSCC.Finding.parent | String | The relative resource name of the source the finding belongs to. |
| GoogleCloudSCC.Finding.resourceName | String | For findings on Google Cloud resources, the full resource name of the Google Cloud resource this finding is for. |
| GoogleCloudSCC.Finding.state | String | The state of the finding. |
| GoogleCloudSCC.Finding.category | String | The additional taxonomy group within findings from a given source. |
| GoogleCloudSCC.Finding.externalUri | String | The URI that, if available, points to a web page outside of Security Command Center where additional information about the finding can be found. |
| GoogleCloudSCC.Finding.createTime | String | The time at which the finding was created in Security Command Center. |
| GoogleCloudSCC.Finding.eventTime | String | The time at which the event took place, or when an update to the finding occurred. |
| GoogleCloudSCC.Finding.resource.name | String | The full resource name of the resource. |
| GoogleCloudSCC.Finding.resource.parentDisplayName | String | The human readable name of resource’s parent. |
| GoogleCloudSCC.Finding.resource.parentName | String | The full resource name of resource’s parent. |
| GoogleCloudSCC.Finding.resource.projectDisplayName | String | The human readable name of project that the resource belongs to. |
| GoogleCloudSCC.Finding.resource.projectName | String | The full resource name of the project that the resource belongs to. |
| GoogleCloudSCC.Finding.resource.folders.resourceFolder | String | Full resource name of this folder. |
| GoogleCloudSCC.Finding.resource.folders.resourceFolderDisplayName | String | The user defined display name for this folder. |
| GoogleCloudSCC.Finding.stateChange | String | State change of the finding between the points in time. |
| GoogleCloudSCC.Finding.sourceProperties | Unknown | Source specific properties. These properties are managed by the source that writes the finding. Properties are varying from finding to finding. |
| GoogleCloudSCC.Finding.severity | String | Severity of the finding. |
| GoogleCloudSCC.Finding.securityMarks.name | String | The relative resource name of the SecurityMarks. |
| GoogleCloudSCC.Finding.securityMarks.marks | String | Mutable user specified security marks belonging to the parent resource. |
| GoogleCloudSCC.Finding.readTime | String | Time used for executing the list request. |
| GoogleCloudSCC.Token.nextPageToken | String | Token to retrieve the next page of results, or empty if there are no more results. |
| GoogleCloudSCC.Token.name | String | Name of the command. |
Command Example
!google-cloud-scc-finding-list sourceTypeId="-" pageSize="3" state="ACTIVE"
Context Example
{
"GoogleCloudSCC": {
"Finding": [
{
"category": "page",
"createTime": "2020-05-15T05:57:46.641Z",
"eventTime": "2021-02-11T09:33:30.716Z",
"externalUri": "http://www.fake-url.com",
"name": "organizations/595779152576/sources/10134421585261057824/findings/00002906967111ea87141217baf6db4d",
"parent": "organizations/595779152576/sources/10134421585261057824",
"readTime": "2021-02-11T13:52:10.594Z",
"resource": {
"name": "//cloudresourcemanager.googleapis.com/projects/339295427573",
"parentDisplayName": "test.com",
"parentName": "//cloudresourcemanager.googleapis.com/organizations/595779152576",
"projectDisplayName": "gscc-demo-0908",
"projectName": "//cloudresourcemanager.googleapis.com/projects/339295427573"
},
"resourceName": "//cloudresourcemanager.googleapis.com/projects/339295427573",
"securityMarks": {
"name": "organizations/595779152576/sources/10134421585261057824/findings/00002906967111ea87141217baf6db4d/securityMarks"
},
"sourceProperties": {
"access_method": "IPSec",
"appcategory": "Technology",
"bypass_traffic": "yes",
"category": "Technology",
"ccl": "unknown",
"count": "1",
"domain": "www.fake-url.com",
"dst_country": "US",
"dst_geoip_src": "2",
"dst_latitude": 35.7319,
"dst_location": "Morganton",
"dst_longitude": -81.7091,
"dst_region": "North Carolina",
"dst_zipcode": "28655",
"dstip": "127.0.0.1",
"id": "fda1f2cb566f247dac4c4c77",
"insertion_epoch_timestamp": "1584069016",
"organization_unit": "None",
"page": "www.fake-url.com",
"page_id": "0",
"policy": "Domains",
"site": "apple",
"src_country": "US",
"src_geoip_src": "2",
"src_latitude": 37.4073,
"src_location": "San Jose",
"src_longitude": -121.939,
"src_region": "California",
"src_zipcode": "95134",
"srcip": "127.0.0.1",
"ssl_decrypt_policy": "no",
"tenant_name": "partners",
"timestamp": "1584069012",
"traffic_type": "Web",
"transaction_id": "0",
"type": "page",
"ur_normalized": "127.0.0.1",
"url": "www.fake-url.com",
"user": "127.0.0.1",
"user_generated": "yes",
"userip": "127.0.0.1"
},
"state": "ACTIVE"
},
{
"category": "page",
"createTime": "2020-05-30T15:19:49.539Z",
"eventTime": "2021-02-11T07:21:45.317Z",
"name": "organizations/595779152576/sources/10134421585261057824/findings/00002ccaa28911ea9d221217baf6db4d",
"parent": "organizations/595779152576/sources/10134421585261057824",
"readTime": "2021-02-11T13:52:10.594Z",
"resource": {
"name": "//cloudresourcemanager.googleapis.com/projects/339295427573",
"parentDisplayName": "test.com",
"parentName": "//cloudresourcemanager.googleapis.com/organizations/595779152576",
"projectDisplayName": "gscc-demo-0908",
"projectName": "//cloudresourcemanager.googleapis.com/projects/339295427573"
},
"resourceName": "//cloudresourcemanager.googleapis.com/projects/339295427573",
"securityMarks": {
"name": "organizations/595779152576/sources/10134421585261057824/findings/00002ccaa28911ea9d221217baf6db4d/securityMarks"
},
"state": "ACTIVE"
},
{
"category": "page",
"createTime": "2020-05-30T02:41:01.848Z",
"eventTime": "2020-03-16T01:38:52Z",
"externalUri": "http://www.fake-url.com",
"name": "organizations/595779152576/sources/10134421585261057824/findings/000031c6a21f11ea9d221217baf6db4d",
"parent": "organizations/595779152576/sources/10134421585261057824",
"readTime": "2021-02-11T13:52:10.594Z",
"resource": {
"name": "//cloudresourcemanager.googleapis.com/projects/339295427573",
"parentDisplayName": "test.com",
"parentName": "//cloudresourcemanager.googleapis.com/organizations/595779152576",
"projectDisplayName": "gscc-demo-0908",
"projectName": "//cloudresourcemanager.googleapis.com/projects/339295427573"
},
"resourceName": "//cloudresourcemanager.googleapis.com/projects/339295427573",
"securityMarks": {
"name": "organizations/595779152576/sources/10134421585261057824/findings/000031c6a21f11ea9d221217baf6db4d/securityMarks"
},
"sourceProperties": {
"access_method": "IPSec",
"app": "LinkedIn",
"appcategory": "Social",
"bypass_traffic": "yes",
"category": "Social",
"cci": "65",
"ccl": "medium",
"count": "1",
"domain": "www.fake-url.com",
"dst_country": "US",
"dst_geoip_src": "1",
"dst_latitude": 37.368889,
"dst_location": "Sunnyvale",
"dst_longitude": -122.035278,
"dst_region": "California",
"dst_timezone": "N/A",
"dst_zipcode": "N/A",
"dstip": "127.0.0.1",
"id": "567a33f799d411dab82da23e",
"insertion_epoch_timestamp": "1584322739",
"organization_unit": "None",
"page": "www.fake-url.com",
"page_id": "0",
"policy": "No_Decrypt",
"site": "Linkedin",
"src_country": "US",
"src_geoip_src": "2",
"src_latitude": 37.4073,
"src_location": "San Jose",
"src_longitude": -121.939,
"src_region": "California",
"src_zipcode": "95134",
"srcip": "127.0.0.1",
"ssl_decrypt_policy": "yes",
"tenant_name": "partners",
"timestamp": "1584322732",
"traffic_type": "CloudApp",
"transaction_id": "0",
"type": "page",
"ur_normalized": "127.0.0.1",
"url": "www.fake-url.com",
"user": "127.0.0.1",
"user_generated": "yes",
"userip": "127.0.0.1"
},
"state": "ACTIVE"
}
],
"Token": {
"name": "google-cloud-scc-finding-list",
"nextPageToken": "next-page-token"
}
}
}
Human Readable Output
Total retrieved finding(s): 3
| Organization ID |Name|Category|Resource Name|Finding Class|Event Time|Create Time|Security Marks|
|—|—|—|—|—|—|—|—|
| 595779152576 | organizations/595779152576/sources/10134421585261057824/findings/00002906967111ea87141217baf6db4d | page | //cloudresourcemanager.googleapis.com/projects/339295427573 | THREAT | February 11, 2021 at 09:33:30 AM | May 15, 2020 at 05:57:46 AM | { “name”: “wrench”, “count”: “3” } |
| 595779152576 | organizations/595779152576/sources/10134421585261057824/findings/00002ccaa28911ea9d221217baf6db4d | page | //cloudresourcemanager.googleapis.com/projects/339295427573 | THREAT | February 11, 2021 at 07:21:45 AM | May 30, 2020 at 03:19:49 PM | { “name”: “wrench”, “count”: “3” } |
| 595779152576 | organizations/595779152576/sources/10134421585261057824/findings/000031c6a21f11ea9d221217baf6db4d | page | //cloudresourcemanager.googleapis.com/projects/339295427573 | THREAT | March 16, 2020 at 01:38:52 AM | May 30, 2020 at 02:41:01 AM | { “name”: “wrench”, “count”: “3” } |
To fetch the next batch of results, execute the command with the page token as next-page-token
google-cloud-scc-finding-update
Update an organization’s or source’s finding.
Base Command
google-cloud-scc-finding-update
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The relative resource name of the finding. Format: organizations/{organization_id}/sources/{source_id}/finding/{findingId} Example: organizations/595779152576/sources/14801394649435054450/findings/bc5a86da657611ebb979005056a5924e. |
Required |
| eventTime | Time at which the event took place. By default UTC current time will be taken if no value is provided in eventTime. Format: YYYY-MM-ddTHH:mm:ss.sssZ Example: 2020-07-22T07:10:02.782Z, 2014-10-02T15:01:23.045123456Z. |
Optional |
| severity | Related severity of the finding. Possible values are: LOW, MEDIUM, HIGH, CRITICAL. | Optional |
| externalUri | URI that points to a web page outside of Cloud SCC (Security Command Center) where additional information about the finding can be found. | Optional |
| sourceProperties | Source specific properties. These properties are managed by the source that writes the finding. For example “key1=val1,key2=val2”. | Optional |
| updateMask | A updateMask argument supports single or comma-separated fields that need to be updated/deleted. A updateMask is automatically generated in the backend for the specific arguments provided in the command and only those values will be updated. To delete attributes/properties, add those keys in updateMask without specifying those fields individually in the command arguments. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleCloudSCC.Finding.name | String | The relative resource name of this finding. |
| GoogleCloudSCC.Finding.parent | String | The relative resource name of the source the finding belongs to. |
| GoogleCloudSCC.Finding.resourceName | String | For findings on Google Cloud resources, the full resource name of the Google Cloud resource this finding is for. |
| GoogleCloudSCC.Finding.state | String | The state of the finding. |
| GoogleCloudSCC.Finding.category | String | The additional taxonomy group within findings from a given source. |
| GoogleCloudSCC.Finding.externalUri | String | The URI that, if available, points to a web page outside of Security Command Center where additional information about the finding can be found. |
| GoogleCloudSCC.Finding.createTime | String | The time at which the finding was created in Security Command Center. |
| GoogleCloudSCC.Finding.eventTime | String | The time at which the event took place, or when an update to the finding occurred. |
| GoogleCloudSCC.Finding.sourceProperties | Unknown | Source specific properties. These properties are managed by the source that writes the finding. Properties are varying from finding to finding. |
| GoogleCloudSCC.Finding.severity | String | Severity of the finding. |
| GoogleCloudSCC.Finding.securityMarks.name | String | The relative resource name of the SecurityMarks. |
| GoogleCloudSCC.Finding.securityMarks.marks | String | Mutable user specified security marks belonging to the parent resource. |
Command Example
!google-cloud-scc-finding-update name="organizations/595779152576/sources/10134421585261057824/findings/00002906967111ea87141217baf6db4d"
Context Example
{
"GoogleCloudSCC": {
"Finding": {
"category": "page",
"createTime": "2020-05-15T05:57:46.641Z",
"eventTime": "2021-02-11T13:52:25.986162Z",
"externalUri": "http://www.fake-url.com",
"name": "organizations/595779152576/sources/10134421585261057824/findings/00002906967111ea87141217baf6db4d",
"parent": "organizations/595779152576/sources/10134421585261057824",
"resourceName": "//cloudresourcemanager.googleapis.com/projects/339295427573",
"securityMarks": {
"name": "organizations/595779152576/sources/10134421585261057824/findings/00002906967111ea87141217baf6db4d/securityMarks"
},
"sourceProperties": {
"access_method": "IPSec",
"appcategory": "Technology",
"bypass_traffic": "yes",
"category": "Technology",
"ccl": "unknown",
"count": "1",
"domain": "www.fake-url.com",
"dst_country": "US",
"dst_geoip_src": "2",
"dst_latitude": 35.7319,
"dst_location": "Morganton",
"dst_longitude": -81.7091,
"dst_region": "North Carolina",
"dst_zipcode": "28655",
"dstip": "127.0.0.1",
"id": "fda1f2cb566f247dac4c4c77",
"insertion_epoch_timestamp": "1584069016",
"organization_unit": "None",
"page": "www.fake-url.com",
"page_id": "0",
"policy": "Domains",
"site": "apple",
"src_country": "US",
"src_geoip_src": "2",
"src_latitude": 37.4073,
"src_location": "San Jose",
"src_longitude": -121.939,
"src_region": "California",
"src_zipcode": "95134",
"srcip": "127.0.0.1",
"ssl_decrypt_policy": "no",
"tenant_name": "partners",
"timestamp": "1584069012",
"traffic_type": "Web",
"transaction_id": "0",
"type": "page",
"ur_normalized": "127.0.0.1",
"url": "www.fake-url.com",
"user": "127.0.0.1",
"user_generated": "yes",
"userip": "127.0.0.1"
},
"state": "ACTIVE"
}
}
}
Human Readable Output
The finding has been updated successfully
Organization ID Name State Category Event Time Create Time External Uri Resource Name 595779152576 organizations/595779152576/sources/10134421585261057824/findings/00002906967111ea87141217baf6db4d ACTIVE page February 11, 2021 at 01:52:25 PM May 15, 2020 at 05:57:46 AM http://www.fake-url.com //cloudresourcemanager.googleapis.com/projects/339295427573
google-cloud-scc-asset-resource-list
Lists cloud asset’s resources.
Base Command
google-cloud-scc-asset-resource-list
Input
| Argument Name | Description | Required |
|---|---|---|
| parent | Name of the organization or project the assets belong to. Organization Id provided in the Integration Configuration will be taken by default, if no value is provided to the parent. Format: “organizations/[organization-number]” (such as “organizations/123”), “projects/[project-id]” (such as “projects/my-project-id”), or “projects/[project-number]” (such as “projects/12345”). |
Optional |
| assetTypes | This parameter is used to filter assets by asset types by providing a single value or a comma-separated value of asset types. For example: “compute.googleapis.com/Disk”. Regular expression is also supported. For example: 1) “compute.googleapis.com.” resources whose asset type starts with “compute.googleapis.com”. 2) “.Instance” resources whose asset type ends with “Instance”. 3) “.Instance.” resources whose asset type contains “Instance”. |
Optional |
| pageSize | The maximum number of results to return in a single response. The minimum value is 1 and maximum value is 1000. Default is 10. | Optional |
| pageToken | The nextPageToken returned from the previous scc-asset-resource-list command response, or unspecified for the first scc-asset-resource-list command. It is a continuation of a prior scc-asset-resource-list call, and the API should return the next page of assets. | Optional |
| readTime | Time used as a reference point when filtering assets. This can only be set to a timestamp between the current time and the current time minus 35 days (inclusive). If not provided, it will take current time. Format: (<number> <time unit>, e.g., “12 hours ago”, “7 days ago”, “1 week”, “1 month”) or (<date> <time>, e.g. “yyyy-mm-ddTHH-MM-SS”) or ( “YYYY-MM-ddTHH:mm:ss.sssZ”, e.g. 2020-07-22T07:10:02.782Z) or (<date>, e.g. “2020-07-22”). |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleCloudSCC.CloudAsset.Resource.name | String | The full name of the asset. |
| GoogleCloudSCC.CloudAsset.Resource.assetType | String | The type of the asset. |
| GoogleCloudSCC.CloudAsset.Resource.updateTime | String | The last update timestamp of an asset. The updateTime is updated when create/update/delete operation is performed. |
| GoogleCloudSCC.CloudAsset.Resource.readTime | String | Time used for executing the list request. |
| GoogleCloudSCC.CloudAsset.Resource.ancestors | Unknown | The ancestry path of an asset in Google Cloud resource hierarchy, represented as a list of relative resource names. An ancestry path starts with the closest ancestor in the hierarchy and ends at root. If the asset is a project, folder, or organization, the ancestry path starts from the asset itself. |
| GoogleCloudSCC.CloudAsset.Resource.resource.version | String | The API version. |
| GoogleCloudSCC.CloudAsset.Resource.resource.discoveryDocumentUri | String | The URL of the discovery document containing the resource’s JSON schema. This value is unspecified for resources that do not have an API based on a discovery document, such as Cloud Bigtable. |
| GoogleCloudSCC.CloudAsset.Resource.resource.discoveryName | String | The JSON schema name listed in the discovery document. This value is unspecified for resources that do not have an API based on a discovery document, such as Cloud Bigtable. |
| GoogleCloudSCC.CloudAsset.Resource.resource.resourceUrl | String | The REST URL for accessing the resource. An HTTP GET request using this URL returns the resource itself. |
| GoogleCloudSCC.CloudAsset.Resource.resource.parent | String | The full name of the immediate parent of this resource. For third-party assets, this field may be set differently. |
| GoogleCloudSCC.CloudAsset.Resource.resource.data | String | The content of the resource, in which some sensitive fields are removed and may not be present. |
| GoogleCloudSCC.CloudAsset.Resource.resource.location | String | The location of the resource in Google Cloud, such as its zone and region. |
| GoogleCloudSCC.Token.name | String | Name of the command. |
| GoogleCloudSCC.Token.nextPageToken | String | Token to retrieve the next page of results, or empty if there are no more results. |
Command Example
!google-cloud-scc-asset-resource-list pageSize=2
Context Example
{
"GoogleCloudSCC": {
"CloudAsset": {
"Resource": [
{
"ancestors": [
"organizations/123456789"
],
"assetType": "cloudbilling.googleapis.com/BillingAccount",
"name": "//cloudbilling.googleapis.com/billingAccounts/12345-6789",
"readTime": "2021-06-17T10:19:59.557941456Z",
"resource": {
"data": {
"displayName": "My Billing Account",
"name": "billingAccounts/12345-6789"
},
"discoveryDocumentUri": "https://cloudbilling.googleapis.com/$discovery/rest",
"discoveryName": "BillingAccount",
"location": "global",
"version": "v1"
},
"updateTime": "2020-08-21T09:05:39.425Z"
},
{
"ancestors": [
"organizations/123456789"
],
"assetType": "cloudbilling.googleapis.com/BillingAccount",
"name": "//cloudbilling.googleapis.com/billingAccounts/23456-7890",
"readTime": "2021-06-17T10:19:59.557941456Z",
"resource": {
"data": {
"displayName": "Our-Account",
"name": "billingAccounts/23456-7890"
},
"discoveryDocumentUri": "https://cloudbilling.googleapis.com/$discovery/rest",
"discoveryName": "BillingAccount",
"location": "global",
"version": "v1"
},
"updateTime": "2021-04-01T19:38:12.836197Z"
}
]
},
"Token": {
"name": "google-cloud-scc-asset-resource-list",
"nextPageToken": "next-page-token"
}
}
}
Human Readable Output
| Organization ID |Asset Name|Asset Type|Discovery Name|Ancestors|Update Time (In UTC)|
|—|—|—|—|—|—|
| 595779152576 | //cloudbilling.googleapis.com/billingAccounts/12345-6789 | cloudbilling.googleapis.com/BillingAccount | BillingAccount | organizations/123456789 | August 21, 2020 at 09:05:39 AM |
| 595779152576 | //cloudbilling.googleapis.com/billingAccounts/23456-7890 | cloudbilling.googleapis.com/BillingAccount | BillingAccount | organizations/123456789 | April 01, 2021 at 07:38:12 PM |
To fetch the next batch of results, execute the command with the page token as next-page-token
google-cloud-scc-asset-owner-get
Gets the owner information for the provided projects.
Base Command
google-cloud-scc-asset-owner-get
Input
| Argument Name | Description | Required |
|---|---|---|
| projectName | Name of the project. Supports comma separated values. Format: “projects/[project-number]” or for multiple projects “projects/[first-project-number], projects/[second-project-number]”. |
Required |
| maxIteration | Number of iterations to search the owner information. Each iteration retrieves 1000 records. The minimum value is 1 and maximum value is 10. Default is 2. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleCloudSCC.CloudAsset.IamPolicy.name | String | The full name of the asset. |
| GoogleCloudSCC.CloudAsset.IamPolicy.owners | Unknown | List of owners of the asset. |
| GoogleCloudSCC.CloudAsset.IamPolicy.assetType | String | The type of the asset. |
| GoogleCloudSCC.CloudAsset.IamPolicy.updateTime | String | The last update timestamp of an asset. The updateTime is updated when create/update/delete operation is performed. |
| GoogleCloudSCC.CloudAsset.IamPolicy.readTime | String | Time used for executing the list request. |
| GoogleCloudSCC.CloudAsset.IamPolicy.ancestors | Unknown | The ancestry path of an asset in Google Cloud resource hierarchy, represented as a list of relative resource names. An ancestry path starts with the closest ancestor in the hierarchy and ends at root. If the asset is a project, folder, or organization, the ancestry path starts from the asset itself. |
| GoogleCloudSCC.CloudAsset.IamPolicy.version | String | Specifies the format of the policy. |
| GoogleCloudSCC.CloudAsset.IamPolicy.etag | String | The etag is used for optimistic concurrency control as a way to help prevent simultaneous updates of a policy from overwriting each other. It is strongly suggested that systems make use of the etag in the read-modify-write cycle to perform policy updates in order to avoid race conditions: An etag is returned in the response to getIamPolicy, and systems are expected to put that etag in the request to setIamPolicy to ensure that their change will be applied to the same version of the policy. |
| GoogleCloudSCC.CloudAsset.IamPolicy.bindings.role | String | A role is a named collection of permissions that provide the ability to perform actions on Google Cloud resources. |
| GoogleCloudSCC.CloudAsset.IamPolicy.bindings.members | Unknown | A member, also known as an identity or principal, which can be a user account, service account, Google group, or domain. |
| GoogleCloudSCC.CloudAsset.IamPolicy.bindings.condition | String | A condition, which is an optional logic expression that further constrains the role binding based on attributes about the request, such as its origin, the target resource, and so on. Conditions are typically used to control whether access is granted based on the context for a request. |
| GoogleCloudSCC.CloudAsset.IamPolicy.auditConfigs.service | String | Specifies a service that will be enabled for audit logging. |
| GoogleCloudSCC.CloudAsset.IamPolicy.auditConfigs.auditLogConfigs.logType | String | The log type that this config enables. |
| GoogleCloudSCC.CloudAsset.IamPolicy.auditConfigs.auditLogConfigs.exemptedMembers | String | Specifies the identities that do not cause logging for this type of permission. |
Command Example
!google-cloud-scc-asset-owner-get projectName="projects/123456789"
Context Example
{
"GoogleCloudSCC": {
"CloudAsset": {
"IamPolicy": {
"ancestors": [
"projects/123456789",
"organizations/123456789"
],
"assetType": "cloudresourcemanager.googleapis.com/Project",
"iamPolicy": {
"bindings": [
{
"members": [
"serviceAccount:dummmyaccount@dummycom",
"user:dummmyuser1@dummycom"
],
"role": "roles/owner"
}
],
"etag": "BwV9ONRnkz4=",
"version": 1
},
"name": "//cloudresourcemanager.googleapis.com/projects/123456789",
"owners": [
"serviceAccount:dummmyaccount@dummycom",
"user:dummmyuser1@dummycom"
],
"readTime": "2021-06-17T10:20:43.762746137Z",
"updateTime": "2018-12-24T10:00:00Z"
}
}
}
}
Human Readable Output
Organization ID Project Name Project Owner Ancestors Update Time (In UTC) 595779152576 //cloudresourcemanager.googleapis.com/projects/123456789 serviceAccount:dummmyaccount@dummycom,
user:dummmyuser1@dummycomprojects/123456789,
organizations/123456789December 24, 2018 at 10:00:00 AM
google-cloud-scc-finding-state-update
Update the state of organization’s or source’s finding.
Base Command
google-cloud-scc-finding-state-update
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The relative resource name of the finding. Format: organizations/{organization_id}/sources/{source_id}/finding/{findingId} Example: organizations/595779152576/sources/14801394649435054450/findings/bc5a86da657611ebb979005056a5924e. |
Required |
| state | The desired state of the finding. Possible values are: ACTIVE, INACTIVE. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleCloudSCC.Finding.name | String | The relative resource name of this finding. |
| GoogleCloudSCC.Finding.parent | String | The relative resource name of the source the finding belongs to. |
| GoogleCloudSCC.Finding.resourceName | String | For findings on Google Cloud resources, the full resource name of the Google Cloud resource this finding is for. |
| GoogleCloudSCC.Finding.state | String | The state of the finding. |
| GoogleCloudSCC.Finding.category | String | The additional taxonomy group within findings from a given source. |
| GoogleCloudSCC.Finding.externalUri | String | The URI that, if available, points to a web page outside of Security Command Center where additional information about the finding can be found. |
| GoogleCloudSCC.Finding.createTime | String | The time at which the finding was created in Security Command Center. |
| GoogleCloudSCC.Finding.eventTime | String | The time at which the event took place, or when an update to the finding occurred. |
| GoogleCloudSCC.Finding.sourceProperties | Unknown | Source specific properties. These properties are managed by the source that writes the finding. Properties are varying from finding to finding. |
| GoogleCloudSCC.Finding.severity | String | Severity of the finding. |
| GoogleCloudSCC.Finding.securityMarks.name | String | The relative resource name of the SecurityMarks. |
| GoogleCloudSCC.Finding.securityMarks.marks | String | Mutable user specified security marks belonging to the parent resource. |
Command Example
!google-cloud-scc-finding-state-update name="organizations/595779152576/sources/10134421585261057824/findings/00002906967111ea87141217baf6db4d" state=ACTIVE"
Context Example
{
"GoogleCloudSCC": {
"Finding": {
"category": "page",
"createTime": "2020-05-15T05:57:46.641Z",
"eventTime": "2021-02-11T13:52:25.986162Z",
"externalUri": "http://www.fake-url.com",
"name": "organizations/595779152576/sources/10134421585261057824/findings/00002906967111ea87141217baf6db4d",
"parent": "organizations/595779152576/sources/10134421585261057824",
"resourceName": "//cloudresourcemanager.googleapis.com/projects/339295427573",
"securityMarks": {
"name": "organizations/595779152576/sources/10134421585261057824/findings/00002906967111ea87141217baf6db4d/securityMarks"
},
"sourceProperties": {
"access_method": "IPSec",
"appcategory": "Technology",
"bypass_traffic": "yes",
"category": "Technology",
"ccl": "unknown",
"count": "1",
"domain": "www.fake-url.com",
"dst_country": "US",
"dst_geoip_src": "2",
"dst_latitude": 35.7319,
"dst_location": "Morganton",
"dst_longitude": -81.7091,
"dst_region": "North Carolina",
"dst_zipcode": "28655",
"dstip": "127.0.0.1",
"id": "fda1f2cb566f247dac4c4c77",
"insertion_epoch_timestamp": "1584069016",
"organization_unit": "None",
"page": "www.fake-url.com",
"page_id": "0",
"policy": "Domains",
"site": "apple",
"src_country": "US",
"src_geoip_src": "2",
"src_latitude": 37.4073,
"src_location": "San Jose",
"src_longitude": -121.939,
"src_region": "California",
"src_zipcode": "95134",
"srcip": "127.0.0.1",
"ssl_decrypt_policy": "no",
"tenant_name": "partners",
"timestamp": "1584069012",
"traffic_type": "Web",
"transaction_id": "0",
"type": "page",
"ur_normalized": "127.0.0.1",
"url": "www.fake-url.com",
"user": "127.0.0.1",
"user_generated": "yes",
"userip": "127.0.0.1"
},
"state": "ACTIVE"
}
}
}
Human Readable Output
The finding has been updated successfully
Organization ID Name State Severity Category Event Time Create Time External Uri Resource Name 595779152576 organizations/595779152576/sources/10134421585261057824/findings/00002906967111ea87141217baf6db4d ACTIVE High page February 11, 2021 at 01:52:25 PM May 15, 2020 at 05:57:46 AM http://www.fake-url.com //cloudresourcemanager.googleapis.com/projects/339295427573
Known Limitations
This integration supports only secure connection hence disabling SSL(Trust any certificate) support is not provided.
Configuration parameters
service_account_json— Service Account Configuration (required)organization_id— Organization ID (required)isFetch— Fetch incidentsproject_id— Project IDsubscription_id— Subscription IDmax_fetch— Max IncidentsincidentType— Incident typeincidentFetchInterval— Incidents Fetch Intervalinsecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (6)
-
google-cloud-scc-asset-listDeprecatedLists an organization's assets.
-
google-cloud-scc-asset-owner-getGets the owner information for the provided projects.
-
google-cloud-scc-asset-resource-listLists cloud asset's resources.
-
google-cloud-scc-finding-listLists an organization or source's findings.
-
google-cloud-scc-finding-state-updateUpdate the state of organization's or source's finding.
-
google-cloud-scc-finding-updateUpdate an organization's or source's finding.
import json import os from unittest.mock import Mock, patch import pytest from GoogleCloudSCC import ( ERROR_MESSAGES, BaseGoogleClient, GoogleCloudAssetClient, GoogleNameParser, GooglePubSubClient, GoogleSccClient, ) with open("test_data/service_account_json.txt") as f: TEST_JSON = f.read() @pytest.fixture def client(): with patch.object(GoogleSccClient, "__init__", lambda x: None): mocked_client = GoogleSccClient() mocked_client.organization_id = "organization_id" mocked_client.service = Mock() mocked_client.execute_request = Mock() return mocked_client @pytest.fixture def pubsub_client(): with patch.object(GooglePubSubClient, "__init__", lambda x: None): mocked_client = GooglePubSubClient() mocked_client.project_id = "project_id" mocked_client.subscription_id = "subscription_id" mocked_client.service = Mock() mocked_client.execute_request = Mock() return mocked_client @pytest.fixture def cloud_asset_client(): with patch.object(GoogleCloudAssetClient, "__init__", lambda x: None): mocked_client = GoogleCloudAssetClient() mocked_client.organization_id = "organization_id" mocked_client.service = Mock() mocked_client.execute_request = Mock() return mocked_client @pytest.fixture def base_client(): with patch.object(BaseGoogleClient, "__init__", lambda x: None): mocked_client = BaseGoogleClient() mocked_client.service = "service" return mocked_client def test_safe_load_non_strict_json(): """ Scenario: Dictionary should be prepared from json string. Given: - json as string. When: - Preparing dictionary from string. Then: - Ensure valid json should be loaded successfully. """ from GoogleCloudSCC import safe_load_non_strict_json excepted_json = json.loads(TEST_JSON, strict=False) assert safe_load_non_strict_json(TEST_JSON) == excepted_json def test_safe_load_non_strict_json_parse_error(): """ Scenario: Failed to load json when invalid json string is given. Given: - Empty json string. When: - Preparing dictionary from string. Then: - Ensure Exception is raised with proper error message. """ from GoogleCloudSCC import safe_load_non_strict_json with pytest.raises(ValueError, match=ERROR_MESSAGES["JSON_PARSE_ERROR"].format("Service Account JSON")): safe_load_non_strict_json("Invalid json") def test_safe_load_non_strict_json_empty(): """ Scenario: Returns {}(blank) dictionary when empty json string is given. Given: - Invalid json as string. When: - Preparing dictionary from string. Then: - Ensure {}(blank) dictionary should be returned. """ from GoogleCloudSCC import safe_load_non_strict_json assert safe_load_non_strict_json("") == {} def test_get_source_path(mocker): """ Scenario: Return a fully-qualified source string. Given: - valid string parameters. When: - Preparing source string. Then: - Ensure a fully-qualified source string should be returned. """ from GoogleCloudSCC import GoogleNameParser, demisto mocker.patch.object(demisto, "params", return_value={"organization_id": "organization_id"}) assert GoogleNameParser.get_source_path("source_id") == "organizations/organization_id/sources/source_id" @patch("GoogleCloudSCC.init_google_scc_client") def test_validate_service_account_and_organization_name(mock1, client): """ Scenario:Validate organization by making "Organization settings" API call. Given: - Empty Dictionary. When: - Validating parameters. Then: - Ensure {}(blank) dictionary returns error. """ from GoogleCloudSCC import validate_service_account_and_organization_name mock1.return_value = client client.get_findings = Mock(return_value={}) validate_service_account_and_organization_name({"service_account_json": '{"test": "test"}'}) assert client.get_findings.call_count == 1 param = {"service_account_json": "123"} with pytest.raises(ValueError, match=ERROR_MESSAGES["INVALID_SERVICE_ACCOUNT"].format("Service Account JSON")): validate_service_account_and_organization_name(param) def test_prepare_markdown_fields_for_fetch_incidents(): """ Scenario:Prepares markdown fields for incident. Given: - Dictionary of fields received in response of fetch incident. When: - Validating parameters. Then: - Proper table format of given parameters. """ from GoogleCloudSCC import prepare_markdown_fields_for_fetch_incidents, tableToMarkdown data = {"finding": {"securityMarks": {"marks": {"A": 1, "B": 2}}, "sourceProperties": {"MfaDetails": {"C": 3, "D": 4}}}} actual_output = prepare_markdown_fields_for_fetch_incidents(data) expected_output = { "MfaDetails": tableToMarkdown("", {"C": 3, "D": 4}), "securityMarks": tableToMarkdown("", {"A": 1, "B": 2}), } assert actual_output == expected_output def test_create_filter_list_findings(): """ Scenario : Creating common filter query string for "list findings" API based on various filter parameter. Given: - List of filter parameters. When: - Preparing a filter query based on convention of API. Then: - A filter query with all parameters in proper format. """ from GoogleCloudSCC import create_filter_list_findings output = create_filter_list_findings("A, B ,C", "ABC = X", ["HIGH", "LOW"], ["ACTIVE"]) assert ( output == 'ABC = X AND (Severity="HIGH" OR Severity="LOW") AND (State="ACTIVE") AND ' '(Category="A" OR Category="B" OR Category="C")' ) output = create_filter_list_findings("A, B ,C", "", ["HIGH", "LOW"], ["ACTIVE"]) assert output == '(Severity="HIGH" OR Severity="LOW") AND (State="ACTIVE") AND (Category="A" OR Category="B" OR Category="C")' def test_fetch_incidents(pubsub_client): """ Scenario : Prepares incidents from past activity in Google Drive. Given: - List of parameters. When: - Preparing a incident according to given parameters. Then: - An incident made according to parameters and last_run is returned. """ from GoogleCloudSCC import fetch_incidents with open("test_data/fetch_incidents_data.json") as file: mock_data = json.load(file) pubsub_client.pull_messages = Mock(return_value=mock_data) pubsub_client.acknowledge_messages = Mock(return_value={}) param = {"organization_id": "123"} incidents = fetch_incidents(pubsub_client, param) assert len(incidents) == 4 def test_execute_request(base_client): """ Scenario : Execute the request and handle error scenario. Given: - Request object. When: - Handling error scenarios. Then: - Checks if correct Error message is there or not. """ from GoogleCloudSCC import HttpError, httplib2 from httplib2 import Response, socks mock_request = Mock() mock_request.execute = Mock( side_effect=[ HttpError(Response({"status": 404}), b"{}"), HttpError(Response({"status": 501}), b"{}"), socks.HTTPError("Proxy Error"), httplib2.ServerNotFoundError("Not Found."), ] ) errors = [ ERROR_MESSAGES["NOT_FOUND_ERROR"].format("Ok"), ERROR_MESSAGES["UNKNOWN_ERROR"].format(501, "Ok"), ERROR_MESSAGES["PROXY_ERROR"], ERROR_MESSAGES["TIMEOUT_ERROR"].format("Not Found."), ] for error in errors: with pytest.raises(ValueError, match=error): base_client.execute_request(mock_request) def test_google_name_parser(): """ Scenario: Validates static method of GoogleNameParser Given: - argument given Then: - Ensure static method should return proper outputs. """ from GoogleCloudSCC import GoogleNameParser assert GoogleNameParser.get_finding_path("-", "123") == "organizations//sources/-/findings/123" assert GoogleNameParser.get_project_path("123") == "projects/123" assert GoogleNameParser.get_subscription_path("123", "456") == "projects/123/subscriptions/456" def test_main(mocker, client): """ Scenario : Parse and validate integration params and commands. """ import GoogleCloudSCC from GoogleCloudSCC import demisto params = {"service_account_json": TEST_JSON, "organization_id": "organization_id"} mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "command", return_value="test-module") mocker.patch.object(GoogleCloudSCC, "init_google_scc_client") mocker.patch.object(GoogleCloudSCC, "init_google_pubsub_client") mocker.patch.object(GoogleCloudSCC, "test_module", return_value="ok") GoogleCloudSCC.main() assert GoogleCloudSCC.test_module.called mocker.patch.object(demisto, "command", return_value="fetch-incidents") mocker.patch.object(GoogleCloudSCC, "fetch_incidents", return_value=([], [])) GoogleCloudSCC.main() assert GoogleCloudSCC.fetch_incidents.called mocker.patch.object(GoogleCloudSCC, "fetch_incidents", side_effect=[Exception("test")]) with pytest.raises(Exception, match="Failed to execute {} command. Error: {}".format("fetch-incidents", "test")): GoogleCloudSCC.main() @patch("GoogleCloudSCC.init_google_scc_client") def test_test_module(mock1, client, mocker): """ Scenario : Test authentication using service json. """ from GoogleCloudSCC import demisto, test_module mocker.patch.object(demisto, "results") mock1.return_value = client client.get_findings = Mock(return_value={}) test_module({"organization_id": "organization_id", "service_account_json": '{"test": "test"}'}) assert demisto.results.called demisto.results.assert_called_with("ok") def test_validate_get_int_success(): """ Scenario: Validate and convert string max_results to integer. Given: - valid page size. When: - Validating max_results. Then: - Ensure if max_results is valid. """ from GoogleCloudSCC import validate_get_int max_results = "9" return_value = validate_get_int(max_results, ERROR_MESSAGES["MAX_INCIDENT_ERROR"]) assert return_value == 9 @pytest.mark.parametrize("string_input", ["invalid_int", "10000000", "-700"]) def test_validate_get_int_max_incident_error(string_input): """ Scenario: Validate and convert string max_results to integer. Given: - Invalid page size. When: - Validating max_results at a time of fetched incident Then: - Ensure if page_size is not in range it returns error. """ from GoogleCloudSCC import MAX_PAGE_SIZE, validate_get_int with pytest.raises(ValueError, match=ERROR_MESSAGES["MAX_INCIDENT_ERROR"]): validate_get_int(string_input, ERROR_MESSAGES["MAX_INCIDENT_ERROR"], MAX_PAGE_SIZE) def test_prepare_hr_and_ec_for_list_findings(): """ Scenario: Validates human readable and entry context for list findings Given: - finding response given Then: - Ensure finding HR and EC. """ from GoogleCloudSCC import prepare_hr_and_ec_for_list_findings with open("./test_data/list_finding_response.json") as f: finding_response = json.load(f) with open("./test_data/list_finding_ec.json") as f: finding_ec = json.load(f) _, context = prepare_hr_and_ec_for_list_findings(finding_response) assert context == finding_ec def test_prepare_hr_and_ec_for_list_findings_no_record(): """ Scenario: Validates human readable and entry context for list findings Given: - finding response given When: - Zero records found Then: - Ensure finding HR and EC. """ from GoogleCloudSCC import prepare_hr_and_ec_for_list_findings finding_response = {"listFindingsResults": []} hr, context = prepare_hr_and_ec_for_list_findings(finding_response) assert context == {} assert hr == ERROR_MESSAGES["NO_RECORDS_FOUND"].format("finding") def test_findings_list_command(client): """ Scenario: Validates command result for list-finding command. Given: - command arguments given for list finding command Then: - Ensure command should return proper outputs. """ from GoogleCloudSCC import finding_list_command with open("test_data/list_finding_response.json") as file: mock_data = json.load(file) with open("./test_data/list_finding_ec.json") as f: finding_ec = json.load(f) with open("test_data/list_finding_hr.md") as f: hr_output = f.read() GoogleNameParser.get_organization_id = Mock(return_value="123") client.get_findings = Mock(return_value=mock_data) arguments = {"category": "A, B", "status": "ACTIVE"} command_output = finding_list_command(client, arguments) assert command_output.outputs == finding_ec assert command_output.raw_response == mock_data assert command_output.readable_output == hr_output def test_create_filter_list_assets(): """ Scenario : Creating common filter query string for "list assets" API based on various filter parameter. Given: - List of filter parameters. When: - Preparing a filter query based on convention of API. Then: - A filter query with all parameters in proper format. """ from GoogleCloudSCC import create_filter_list_assets output = create_filter_list_assets("X, Y ,Z", "A, B, C", "ABC = XYZ", "true") assert ( output == 'ABC = XYZ AND (resourceProperties.name="A" OR resourceProperties.name="B" OR' ' resourceProperties.name="C") AND (securityCenterProperties.resourceType="X" OR ' 'securityCenterProperties.resourceType="Y" OR securityCenterProperties.resourceType="Z") AND ' '(resourceProperties.lifecycleState="ACTIVE")' ) output = create_filter_list_assets("X, Y ,Z", "A, B, C", "ABC = XYZ", "") assert ( output == 'ABC = XYZ AND (resourceProperties.name="A" OR resourceProperties.name="B" OR' ' resourceProperties.name="C") AND (securityCenterProperties.resourceType="X" OR ' 'securityCenterProperties.resourceType="Y" OR securityCenterProperties.resourceType="Z")' ) def test_prepare_hr_and_ec_for_list_assets(): """ Scenario: Validates human readable and entry context for list assets Given: - assets response given Then: - Ensure finding HR and EC. """ from GoogleCloudSCC import prepare_outputs_for_list_assets with open("./test_data/list_asset_response.json") as f: asset_response = json.load(f) with open("./test_data/list_asset_ec.json") as f: asset_ec = json.load(f) context, _ = prepare_outputs_for_list_assets(asset_response) assert context == asset_ec def test_prepare_hr_and_ec_for_list_assets_no_record(): """ Scenario: Validates human readable and entry context for list assets Given: - asset response given When: - Zero records found Then: - Ensure finding HR and EC. """ from GoogleCloudSCC import prepare_outputs_for_list_assets response = {"listAssetsResults": []} context, hr = prepare_outputs_for_list_assets(response) assert context == {} assert hr == ERROR_MESSAGES["NO_RECORDS_FOUND"].format("asset") def test_asset_list_command(client): """ Scenario: Validates command result for list-asset command. Given: - command arguments given for list asset command Then: - Ensure command should return proper outputs. """ from GoogleCloudSCC import asset_list_command with open("test_data/list_asset_response.json") as file: mock_data = json.load(file) with open("./test_data/list_asset_ec.json") as f: asset_ec = json.load(f) with open("test_data/list_asset_hr.md") as f: hr_output = f.read() GoogleNameParser.get_organization_id = Mock(return_value="123") client.get_assets = Mock(return_value=mock_data) arguments = {"resourceType": "A", "filter": "test"} command_output = asset_list_command(client, arguments) assert command_output.outputs == asset_ec assert command_output.raw_response == mock_data assert command_output.readable_output == hr_output def test_split(): """ Scenario: Validates that string should split properly. Given: - string which contains delimiter Then: - Ensure result should split by delimiter and not split by escaped delimeter """ from GoogleCloudSCC import split_and_escape assert split_and_escape(r"abc,ss,ssa,sc\,aa", ",") == ["abc", "ss", "ssa", "sc,aa"] assert split_and_escape(r"ab;cd ;xy\;ad", ";") == ["ab", "cd", "xy;ad"] def test_get_and_validate_args_finding_update(): """ Scenario: Get and validates argument of update finding command Given: - raw argument of update finding command Then: - Ensure all argument should be in valid format. """ from GoogleCloudSCC import get_and_validate_args_finding_update # Invalid severity args = {"severity": "INVALID"} with pytest.raises(ValueError, match=ERROR_MESSAGES["INVALID_SEVERITY_ERROR"]): get_and_validate_args_finding_update(args) args = {"sourceProperties": "A=B, C=D\\,X\\=Y"} assert get_and_validate_args_finding_update(args)[4] == {"A": "B", "C": "D,X=Y"} args = {"sourceProperties": "INVALID"} with pytest.raises(ValueError): get_and_validate_args_finding_update(args) args = {"severity": "HIGH", "updateMask": "A,B,C"} _, _, severity, _, _, update_mask = get_and_validate_args_finding_update(args) assert severity == "HIGH" assert update_mask == ["A", "B", "C"] def test_get_update_mask_for_update_finding(): """ Scenario: Validates updateMask field construct Properly Given: - update finding command arguments Then: - Ensure updateMask field construct properly """ from GoogleCloudSCC import get_update_mask_for_update_finding body = {"severity": "HIGH", "state": "ACTIVE", "eventTime": "REQUIRED", "sourceProperties": {"A": "1"}} update_mask = ["state", "severity"] assert get_update_mask_for_update_finding(body, update_mask).split(",") == [ "state", "severity", "eventTime", "sourceProperties.A", ] def test_prepare_hr_and_ec_for_update_finding(): """ Scenario: Validates human readable and entry context for update finding Given: - update finding response given Then: - Ensure finding HR is correct """ from GoogleCloudSCC import prepare_hr_and_ec_for_update_finding with open("./test_data/update_finding_response.json") as f: finding_response = json.load(f) hr, _ = prepare_hr_and_ec_for_update_finding(finding_response) assert "Name" in hr assert "State" in hr assert "Category" in hr assert "Severity" not in hr def test_prepare_hr_and_ec_for_cloud_assets_list(): """ Scenario: Validates human readable and entry context for cloud assets list Given: - asset list response given Then: - Ensure HR and entry context is correct """ from GoogleCloudSCC import prepare_hr_and_ec_for_cloud_asset_list with open("./test_data/cloud_assets_list_response.json") as f: cloud_assets_response = json.load(f) with open("./test_data/cloud_assets_list_ec.json") as f: cloud_assets_ec = json.load(f) hr, ec = prepare_hr_and_ec_for_cloud_asset_list(cloud_assets_response) assert cloud_assets_ec == ec assert "Asset Name" in hr assert "Asset Type" in hr assert "Parent" in hr assert "Discovery Name" in hr assert "Ancestors" in hr assert "Update Time (In UTC)" in hr def test_prepare_hr_and_ec_for_cloud_assets_list_no_record(): """ Scenario: Validates human readable and entry context for cloud assets list Given: - cloud asset response given When: - Zero records found Then: - Ensure finding HR and EC. """ from GoogleCloudSCC import prepare_hr_and_ec_for_cloud_asset_list response = {"assets": []} hr, context = prepare_hr_and_ec_for_cloud_asset_list(response) assert context == {} assert hr == ERROR_MESSAGES["NO_RECORDS_FOUND"].format("resource") def test_cloud_asset_list_command(cloud_asset_client): """ Scenario: Validates command result for cloud asset-resource-list command. Given: - command arguments given for cloud asset resource list command Then: - Ensure command should return proper outputs. """ from GoogleCloudSCC import cloud_asset_list_command with open("test_data/cloud_assets_list_response.json") as file: mock_data = json.load(file) with open("./test_data/cloud_assets_list_ec.json") as f: asset_ec = json.load(f) with open("test_data/cloud_assets_list_hr.md") as f: hr_output = f.read() GoogleNameParser.get_organization_id = Mock(return_value="123") cloud_asset_client.get_assets = Mock(return_value=mock_data) arguments = {"parent": "project/123456789000"} command_output = cloud_asset_list_command(cloud_asset_client, arguments) assert command_output.outputs == asset_ec assert command_output.raw_response == mock_data assert command_output.readable_output == hr_output @pytest.mark.parametrize( "test_case, project_names, max_iterations, call_count", [ ("one-iteration-one-found", "projects/123456789", 2, 1), ("two-iteration-two-found", "projects/123456789,projects/234567890", 2, 2), ("two-iteration-one-only-found-no-token", "projects/123456789,projects/234567890", 2, 1), ("two-iteration-one-only-found-max-iteration-reached", "projects/123456789,projects/234567890", 1, 1), ], ) def test_cloud_asset_owner_get_command(cloud_asset_client, test_case, project_names, max_iterations, call_count): """ Scenario: Validates command result for cloud asset-owner-get command. Given: - command arguments given for cloud asset owner get command Then: - Ensure command should call the API expected times and return appropriate outputs. """ from GoogleCloudSCC import cloud_asset_owner_get_command with open("test_data/cloud_assets_owners_get_response.json") as file: mock_data = json.load(file)["test-cases"][test_case] with open("test_data/cloud_assets_owners_get_hr.json") as file: hr_output = json.load(file)["test-cases"][test_case] GoogleNameParser.get_organization_id = Mock(return_value="123") cloud_asset_client.get_assets = Mock(side_effect=mock_data["responses"]) arguments = {"projectName": project_names, "maxIteration": max_iterations} command_output = cloud_asset_owner_get_command(cloud_asset_client, arguments) assert command_output.outputs == mock_data["outputs"] assert cloud_asset_client.get_assets.call_count == call_count assert command_output.raw_response == mock_data["outputs"] assert command_output.readable_output == hr_output def test_finding_update_command(client, mocker): """ Scenario: Validates command result for update-finding command. Given: - command arguments given for update finding command Then: - Ensure command should return proper outputs. """ from GoogleCloudSCC import demisto, finding_update_command with open("test_data/update_finding_response.json") as file: mock_data = json.load(file) with open("./test_data/update_finding_ec.json") as f: finding_ec = json.load(f) with open("./test_data/update_finding_hr.md") as f: hr_output = f.read() client.update_finding = Mock(return_value=mock_data) params = { "organization_id": "123", } mocker.patch.object(demisto, "params", return_value=params) arguments = {"status": "ACTIVE"} command_output = finding_update_command(client, arguments) assert command_output.outputs_key_field == "name" assert command_output.raw_response == mock_data assert command_output.to_context()["EntryContext"] == finding_ec assert command_output.readable_output == hr_output def test_prepare_hr_and_ec_for_cloud_asset_owners_get(): """ Scenario: Validates human readable and entry context for cloud assets owners get Given: - project asset response given Then: - Ensure HR and entry context is correct """ from GoogleCloudSCC import prepare_hr_and_ec_for_cloud_asset_owners_get with open("./test_data/cloud_assets_owners_get_assets.json") as f: cloud_assets_response = json.load(f) with open("./test_data/cloud_assets_owners_get_ec.json") as f: cloud_assets_ec = json.load(f) hr, ec = prepare_hr_and_ec_for_cloud_asset_owners_get(cloud_assets_response["assets"], cloud_assets_response["readTime"]) assert cloud_assets_ec == ec assert "Project Name" in hr assert "Project Owner" in hr assert "Ancestors" in hr assert "Update Time (In UTC)" in hr def test_prepare_hr_and_ec_for_cloud_asset_owners_get_no_record(): """ Scenario: Validates human readable and entry context for cloud assets owners get Given: - project asset response given When: - Zero records found Then: - Ensure finding HR and EC. """ from GoogleCloudSCC import prepare_hr_and_ec_for_cloud_asset_owners_get hr, context = prepare_hr_and_ec_for_cloud_asset_owners_get([], "") assert context == [] assert hr == ERROR_MESSAGES["NO_RECORDS_FOUND"].format("project") @patch("GoogleCloudSCC.init_google_pubsub_client") def test_validate_project_and_subscription_id(mock1, pubsub_client): """ Scenario: Validates project ID and subscription ID Given: - configuration parameter When: - correct argument provided Then: - Ensure command should return proper outputs. """ from GoogleCloudSCC import validate_project_and_subscription_id mock1.return_value = pubsub_client params = {"project_id": "project_id", "subscription_id": "subscription_id"} pubsub_client.pull_messages = Mock(return_value={}) validate_project_and_subscription_id(params) assert pubsub_client.pull_messages.call_count == 1 def test_get_http_client_with_proxy(mocker, client): """ Scenario: Validate that proxy is set in http object Given: - proxy insecure path to custom certificate When: - correct proxy, insecure and certificate path arguments provided Then: - Ensure command that proxy, insecure and certificate path should set in Http object """ mocker.patch("GoogleCloudSCC.handle_proxy", return_value={"https": "admin:password@127.0.0.1:3128"}) mocker.patch.dict(os.environ, {"REQUESTS_CA_BUNDLE": "path/to/cert"}) http_obj = client.get_http_client_with_proxy(True, True) assert http_obj.proxy_info.proxy_host == "127.0.0.1" assert http_obj.proxy_info.proxy_port == 3128 assert http_obj.proxy_info.proxy_user == "admin" assert http_obj.proxy_info.proxy_pass == "password" assert http_obj.disable_ssl_certificate_validation assert http_obj.ca_certs == "path/to/cert" def test_google_scc_class_wrapper_methods(client): """ Scenario: Validates helper method of GoogleSccClient Given: - configuration parameter Then: - Ensure wrapper method should return proper outputs. """ client.execute_request = Mock(return_value={"A": 123}) assert client.get_findings(parent="123") == {"A": 123} assert client.get_assets("parent", "duration", "mask", "filter", "order", "size", "token", "readtime") == {"A": 123} assert client.get_source("name") == {"A": 123} assert client.update_finding("name", "time", "severity", "url", None, []) == {"A": 123} def test_google_pubsub_wrapper_methods(pubsub_client): """ Scenario: Validates helper method of GooglePubSubClient Given: - configuration parameter Then: - Ensure wrapper method should return proper outputs. """ pubsub_client.execute_request = Mock(return_value={"B": 123}) assert pubsub_client.pull_messages("123") == {"B": 123} assert pubsub_client.acknowledge_messages(["123"]) == {"B": 123} def test_google_cloud_assets_class_wrapper_methods(cloud_asset_client): """ Scenario: Validates helper method of GoogleCloudAssetClient Given: - configuration parameter Then: - Ensure wrapper method should return proper outputs. """ cloud_asset_client.execute_request = Mock(return_value={"A": 123}) assert cloud_asset_client.get_assets("parent", "asset_types", "content_type", "10", "page_token", "read_time") == {"A": 123} def test_validate_state_and_severity_list(): """ Scenario: Validates state and severity. Given: - state and severity is given When: - incorrect state and severity given Then: - Ensure proper error message should raised. """ from GoogleCloudSCC import validate_state_and_severity_list with pytest.raises(ValueError, match=ERROR_MESSAGES["INVALID_STATE_ERROR"]): validate_state_and_severity_list(["INVALID"], []) with pytest.raises(ValueError, match=ERROR_MESSAGES["INVALID_SEVERITY_ERROR"]): validate_state_and_severity_list(["ACTIVE"], ["INVALID"]) def test_flatten_keys_to_root_negative(): """ Scenario: Validates dictionary Given: - nested dict given Then: - Ensure proper dict should returned. """ from GoogleCloudSCC import flatten_keys_to_root input_dict = {"A": {"AA": 1}, "B": ["C"]} flatten_keys_to_root(input_dict, ["C"], {}) assert input_dict == {"A": {"AA": 1}, "B": ["C"], "C": None} flatten_keys_to_root(input_dict, ["A"], {}) assert input_dict == {"AA": 1, "B": ["C"], "C": None} def test_find_asset_owners(): """ Scenario: Validates find_asset_owners function Given: - minimized cloud asset Then: - Ensure that owners list is returned. """ from GoogleCloudSCC import find_asset_owners input_asset = { "iamPolicy": { "bindings": [ {"members": ["serviceAccount:service-12345"], "role": "roles/cloudfunctions.serviceAgent"}, {"members": ["cloudservices.gserviceaccount.com", "serviceAccount.gserviceaccount.com"], "role": "roles/owner"}, {"members": ["serviceAccount:firebase-dummy-account"], "role": "roles/firebase.managementServiceAgent"}, ] } } expected_owners = ["cloudservices.gserviceaccount.com", "serviceAccount.gserviceaccount.com"] assert expected_owners == find_asset_owners(input_asset) def test_find_asset_owners_no_record(): """ Scenario: Validates find_asset_owners function Given: - minimized asset without owners - empty input Then: - Ensure that empty list is returned. """ from GoogleCloudSCC import find_asset_owners input_asset = { "iamPolicy": { "bindings": [ {"members": ["serviceAccount:service-12345"], "role": "roles/cloudfunctions.serviceAgent"}, {"members": ["serviceAccount:firebase-dummy-account"], "role": "roles/firebase.managementServiceAgent"}, ] } } assert find_asset_owners(input_asset) == [] assert find_asset_owners({}) == [] def test_validate_with_regex(): """ Scenario: Validates validate_with_regex function Given: - pattern - string - validation_message When: - pattern matches - pattern does not match Then: - Ensure ValueError with provided message is raised when pattern does not match. """ from GoogleCloudSCC import validate_with_regex validate_with_regex("validation error", r"^\d{1,4}$", "123") with pytest.raises(ValueError) as e: validate_with_regex("validation error", r"^\d{1,4}$", "12345") assert str(e.value) == "validation error" def test_finding_state_update_command(client): """ Scenario: Validates command result for update-finding command. Given: - command arguments given for update finding command Then: - Ensure command should return proper outputs. """ from GoogleCloudSCC import finding_state_update_command with open("test_data/update_finding_response.json") as file: mock_data = json.load(file) with open("./test_data/update_finding_ec.json") as f: finding_ec = json.load(f) with open("test_data/update_finding_hr.md") as f: hr_output = f.read() GoogleNameParser.get_organization_id = Mock(return_value="123") client.update_state = Mock(return_value=mock_data) arguments = {"state": "ACTIVE", "name": "name"} command_output = finding_state_update_command(client, arguments) assert command_output.outputs_key_field == "name" assert command_output.raw_response == mock_data assert command_output.to_context()["EntryContext"] == finding_ec assert command_output.readable_output == hr_output def test_finding_state_update_command_invalid_args(client): """ Scenario: Validates command result for update-finding command. Given: - command arguments given for update finding command Then: - Ensure command should return proper outputs. """ from GoogleCloudSCC import finding_state_update_command arguments = {"state": "dummy", "name": "name"} with pytest.raises(ValueError) as err: finding_state_update_command(client, arguments) assert str(err.value) == ERROR_MESSAGES["INVALID_STATE_ERROR"]