-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Snippets for working with Assets in Cloud Security Command Center. #4690
Changes from 1 commit
0de725a
d1d7faa
870f100
1f2106c
c88e4cd
70eed96
4cac433
d100761
dc01b85
6703809
ca3af5c
4096ed2
4bd510c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Format: //devtools/kokoro/config/proto/build.proto | ||
|
||
# Configure the docker image for kokoro-trampoline. | ||
env_vars: { | ||
key: "TRAMPOLINE_IMAGE" | ||
value: "gcr.io/cloud-devrel-kokoro-resources/java8" | ||
} | ||
|
||
env_vars: { | ||
key: "INTEGRATION_TEST_ARGS" | ||
value: "google-cloud-clients/google-cloud-pubsub" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Old, code, I've removed all configuration. |
||
} | ||
|
||
env_vars: { | ||
key: "JOB_TYPE" | ||
value: "integration" | ||
} | ||
|
||
env_vars: { | ||
key: "GCLOUD_ORGANIZATION" | ||
value: "1081635000895" | ||
} | ||
|
||
env_vars: { | ||
key: "GOOGLE_APPLICATION_CREDENTIALS" | ||
value: "keystore/73713_cscc_it_service_account" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
package com.google.cloud.examples.securitycenter.snippets; | ||
emkornfield marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
import static com.google.cloud.ServiceOptions.getDefaultProjectId; | ||
|
||
import com.google.cloud.securitycenter.v1beta1.ListAssetsRequest; | ||
import com.google.cloud.securitycenter.v1beta1.ListAssetsResponse.ListAssetsResult; | ||
import com.google.cloud.securitycenter.v1beta1.OrganizationName; | ||
import com.google.cloud.securitycenter.v1beta1.SecurityCenterClient; | ||
import com.google.cloud.securitycenter.v1beta1.SecurityCenterClient.ListAssetsPagedResponse; | ||
import com.google.common.base.Preconditions; | ||
import com.google.common.collect.ImmutableList; | ||
import java.io.IOException; | ||
import org.threeten.bp.Duration; | ||
import org.threeten.bp.Instant; | ||
import org.threeten.bp.LocalDateTime; | ||
import org.threeten.bp.ZoneId; | ||
import org.threeten.bp.temporal.ChronoUnit; | ||
|
||
/** | ||
* Snippets for how to work with Assets in Cloud Security Command Center. | ||
*/ | ||
public class AssetSnippets { | ||
|
||
private final SecurityCenterClient securityCenterClient; | ||
private final OrganizationName organizationName; | ||
|
||
/** | ||
* Filter that returns all projects in the organization | ||
*/ | ||
// [START asset_resource_project_filter] | ||
emkornfield marked this conversation as resolved.
Show resolved
Hide resolved
|
||
public static final String PROJECT_ASSET_FILTERS = | ||
"security_center_properties.resource_type=\"google.cloud.resourcemanager.Project\""; | ||
// [END asset_resource_project_filter] | ||
|
||
|
||
/** | ||
* Create a new AssetSnippets object. | ||
* | ||
* @param client The client to use for contacting the service. | ||
* @param organizationId The organization ID (this should be a numeric value, not the display name | ||
* of the organization). | ||
*/ | ||
public AssetSnippets(SecurityCenterClient client, String organizationId) { | ||
this.securityCenterClient = client; | ||
// [START name_from_id] | ||
this.organizationName = OrganizationName.of(organizationId); | ||
// [END name_from_id] | ||
} | ||
|
||
/** | ||
* Lists assets for an organization given meeting <code>filter</code> as of a specific instant in | ||
* time. | ||
* | ||
* @param filter The filter that assets must meet (e.g. {@link #PROJECT_ASSET_FILTERS}). If null, | ||
* all assets in the organization are returned. | ||
* @param asOf The instant in time to query for. If null, current time is assumed | ||
*/ | ||
|
||
// [TARGET list_assets | ||
emkornfield marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// [VARIABLE "filter"] | ||
// [VARIABLE "as_of"] | ||
// [START list_assets ] | ||
emkornfield marked this conversation as resolved.
Show resolved
Hide resolved
|
||
public ImmutableList<ListAssetsResult> listAssets(String filter, | ||
Instant asOf) { | ||
ListAssetsRequest.Builder request = | ||
ListAssetsRequest.newBuilder().setParent(organizationName.toString()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add commented variables with a small description of what it's for? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I documented what you asked for |
||
// | ||
emkornfield marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (filter != null) { | ||
request.setFilter(filter); | ||
} | ||
// Limits assets returned to a particular point in time. | ||
if (asOf != null) { | ||
request.getReadTimeBuilder().setSeconds(asOf.getEpochSecond()).setNanos(asOf.getNano()); | ||
} | ||
ListAssetsPagedResponse response = securityCenterClient.listAssets(request.build()); | ||
|
||
// This creates one list for all assets. If your organization has a large number of assets | ||
// this can cause out of memory issues. You can process them batches by returning | ||
// the Iterable returned response.iterateAll() directly. | ||
return ImmutableList.copyOf(response.iterateAll()); | ||
} | ||
// [END list_assets ] | ||
|
||
/** | ||
* Run and print results from common queries. | ||
*/ | ||
void demoListAssets() { | ||
// [ START demo_list_assets ] ] | ||
emkornfield marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// This takes care of formatting the resource name appropriately from the id.. | ||
|
||
// Query for all currently existing assets | ||
System.out.println("All Assets: " + listAssets(null, null)); | ||
// Query for all firewall rules with open HTTP ports as of now. | ||
System.out.println("Project Assets (now): " + listAssets( | ||
PROJECT_ASSET_FILTERS, null)); | ||
// Query for all firewall rules with open HTTP open HTTP ports as of a day ago. | ||
System.out.println("Open HTTP Firewall Rules (1 day ago): " + listAssets( | ||
PROJECT_ASSET_FILTERS, | ||
Instant.now().minus(Duration.ofDays(1)))); | ||
// [ END demo_list_assets ] ] | ||
} | ||
|
||
/** | ||
* Returns Assets and metadata about assets activity (e.g. added, removed, no change) between | ||
* between | ||
* <code>asOf.minus(timespan)</code> and <code>asOf</code>. | ||
* | ||
* @param timeSpan The time-range to compare assets over. | ||
* @param filter The filter that assets must meet (e.g. {@link #PROJECT_ASSET_FILTERS}). If null, | ||
* all assets in the organization are returned. | ||
* @param asOf The instant in time to query for. If null, current time is assumed. | ||
*/ | ||
public ImmutableList<ListAssetsResult> listAssetAndStatusChanges(Duration timeSpan, String filter, | ||
Instant asOf) { | ||
// [ START list_asset_changes ] ] | ||
ListAssetsRequest.Builder request = | ||
ListAssetsRequest.newBuilder().setParent(organizationName.toString()); | ||
request.getCompareDurationBuilder().setSeconds(timeSpan.getSeconds()) | ||
.setNanos(timeSpan.getNano()); | ||
// | ||
if (filter != null) { | ||
request.setFilter(filter); | ||
} | ||
// Limits assets returned to a particular point in time. | ||
if (asOf != null) { | ||
request.getReadTimeBuilder().setSeconds(asOf.getEpochSecond()).setNanos(asOf.getNano()); | ||
} | ||
|
||
ListAssetsPagedResponse response = securityCenterClient.listAssets(request.build()); | ||
|
||
// This creates one list for all assets. If your organization has a large number of assets | ||
// this can cause out of memory issues. You can process them batches by returning | ||
// the Iterable returned response.iterateAll() directly. | ||
return ImmutableList.copyOf(response.iterateAll()); | ||
// [ END list_asset_changes ] ] | ||
} | ||
|
||
/** | ||
* Run and print demo outputs of different parameters for {@link #listAssetAndStatusChanges(Duration, | ||
* String, Instant)}. | ||
*/ | ||
void demoListAssetAndStatusChanges() { | ||
// [ START demo_list_asset_changes ] ] | ||
// List assets that are GCP Projects and their changes over the last day. | ||
System.out.println(listAssetAndStatusChanges(Duration.ofDays(1), PROJECT_ASSET_FILTERS, null)); | ||
|
||
final LocalDateTime jan1 = LocalDateTime.of(2019, 1, 1, 0, 0); | ||
final LocalDateTime dec1 = LocalDateTime.of(2018, 12, 1, 0, 0); | ||
final Duration lastMonth = Duration.ofDays(ChronoUnit.DAYS.between(dec1, jan1)); | ||
// Query for GCE instances with the name including "Debia" and there changes over between Dec 1, 2019 and Jan 1, 2019 . | ||
System.out.println( | ||
"Project Changes between (between Dec 2019 and Jan 2019): " + listAssetAndStatusChanges( | ||
lastMonth, /* filter (no filter applied) = */null, | ||
jan1.atZone(ZoneId.of("Europe/Paris")).toInstant())); | ||
// [ END demo_list_asset_changes ] ] | ||
} | ||
|
||
public static void main(String... args) throws IOException { | ||
try (SecurityCenterClient client = SecurityCenterClient.create()) { | ||
String org_id = System.getenv("ORGANIZATION_ID"); | ||
if (args.length > 0) { | ||
org_id = args[0]; | ||
} | ||
if (org_id == null) { | ||
Preconditions.checkNotNull(org_id, | ||
"Organization ID must either be set in the environment variable \"ORGANIZATION_ID\" or passed" | ||
+ " as the first parameter to the program."); | ||
} | ||
AssetSnippets snippets = new AssetSnippets(client, org_id); | ||
System.out.println("Project Assets:" + snippets.listAssets(PROJECT_ASSET_FILTERS, null)); | ||
System.out.println("Project Assets (changes as of a day ago): " + snippets | ||
.listAssetAndStatusChanges(Duration.ofDays(1), | ||
PROJECT_ASSET_FILTERS, null)); | ||
} | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package com.google.cloud.examples.securitycenter.snippets; | ||
emkornfield marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
import static com.google.cloud.ServiceOptions.getDefaultProjectId; | ||
import static junit.framework.TestCase.assertEquals; | ||
import static junit.framework.TestCase.assertTrue; | ||
import static org.hamcrest.MatcherAssert.assertThat; | ||
|
||
|
||
import com.google.cloud.securitycenter.v1beta1.ListAssetsResponse.ListAssetsResult; | ||
import com.google.cloud.securitycenter.v1beta1.SecurityCenterClient; | ||
import com.google.common.collect.ImmutableList; | ||
import java.io.IOException; | ||
import org.junit.AfterClass; | ||
import org.junit.BeforeClass; | ||
import org.junit.Test; | ||
import org.threeten.bp.Duration; | ||
import org.threeten.bp.Instant; | ||
import org.threeten.bp.LocalDateTime; | ||
import org.threeten.bp.ZoneOffset; | ||
|
||
/** Smoke tests for {@link com.google.cloud.examples.securitycenter.snippets.AssetSnippets} */ | ||
public class ITAssetSnippets { | ||
|
||
static SecurityCenterClient client; | ||
static AssetSnippets snippets; | ||
|
||
public static final Instant NOTHING_INSTANCE = LocalDateTime.of(2019, 1, 1, 0, 0).toInstant(ZoneOffset.UTC); | ||
public static final Instant SOMETHING_INSTANCE = LocalDateTime.of(2019, 3, 14, 8, 0).toInstant(ZoneOffset.ofHours((-8))); | ||
|
||
@BeforeClass | ||
public static void beforeClass() throws IOException { | ||
client = SecurityCenterClient.create(); | ||
snippets = new AssetSnippets(client, getOrganizationId()); | ||
} | ||
|
||
@Test | ||
public void mainRuns() throws IOException { | ||
AssetSnippets.main(getOrganizationId()); | ||
} | ||
|
||
@Test | ||
public void demosRun() throws IOException { | ||
snippets.demoListAssets(); | ||
snippets.demoListAssetAndStatusChanges(); | ||
} | ||
|
||
@Test | ||
public void testAllAssetsReturned() { | ||
assertTrue(0 < snippets.listAssets(null, null).size() ); | ||
} | ||
|
||
@Test | ||
public void testBeforeDateNoAssetsReturned() { | ||
assertTrue( | ||
snippets.listAssets(null, NOTHING_INSTANCE) | ||
.isEmpty()); | ||
} | ||
|
||
@Test | ||
public void testListAssetsNoFilterOrDate() { | ||
assertTrue(59 >= snippets.listAssets(null, null).size()); | ||
} | ||
|
||
@Test | ||
public void testListAssetsWithFilterAndInstance() { | ||
assertTrue(3 >= snippets.listAssets(AssetSnippets.PROJECT_ASSET_FILTERS, SOMETHING_INSTANCE).size()); | ||
} | ||
|
||
@Test | ||
public void testChangesReturnsValues() { | ||
ImmutableList<ListAssetsResult> result = snippets.listAssetAndStatusChanges(Duration.ofDays(3), AssetSnippets.PROJECT_ASSET_FILTERS, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line seems a bit long. Also, it has extra white space. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Old code? |
||
SOMETHING_INSTANCE); | ||
assertTrue("Result: " + result.toString(), result.toString().contains("ADDED")); | ||
assertTrue(3 >= result.size()); | ||
} | ||
|
||
@AfterClass | ||
public static void tearDown() { | ||
client.close(); | ||
} | ||
|
||
private static String getOrganizationId() { | ||
return System.getenv("GCLOUD_ORGANIZATION"); | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please remove the extra white space. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Old code? |
||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is to configure running integration tests found in the google-cloud-clients directory. Is that the intent here, or is this just for samples?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was intending this to be for samples, is there a mechanism to do that, or is it just best effort?