diff --git a/google-cloud-clients/google-cloud-websecurityscanner/pom.xml b/google-cloud-clients/google-cloud-websecurityscanner/pom.xml index 958787b6c8a9..9a8e22bf80ad 100644 --- a/google-cloud-clients/google-cloud-websecurityscanner/pom.xml +++ b/google-cloud-clients/google-cloud-websecurityscanner/pom.xml @@ -54,6 +54,13 @@ testlib test + + + joda-time + joda-time + 2.10.3 + test + diff --git a/google-cloud-clients/google-cloud-websecurityscanner/src/test/java/com/google/cloud/websecurityscanner/it/v1beta/VPCServiceControlNegativeTest.java b/google-cloud-clients/google-cloud-websecurityscanner/src/test/java/com/google/cloud/websecurityscanner/it/v1beta/VPCServiceControlNegativeTest.java new file mode 100644 index 000000000000..595c7cce06f0 --- /dev/null +++ b/google-cloud-clients/google-cloud-websecurityscanner/src/test/java/com/google/cloud/websecurityscanner/it/v1beta/VPCServiceControlNegativeTest.java @@ -0,0 +1,146 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.websecurityscanner.it.v1beta; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; + +import com.google.api.gax.core.FixedCredentialsProvider; +import com.google.api.gax.rpc.PermissionDeniedException; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.cloud.websecurityscanner.v1beta.CreateScanConfigRequest; +import com.google.cloud.websecurityscanner.v1beta.ListScanConfigsRequest; +import com.google.cloud.websecurityscanner.v1beta.ProjectName; +import com.google.cloud.websecurityscanner.v1beta.ScanConfig; +import com.google.cloud.websecurityscanner.v1beta.WebSecurityScannerClient; +import com.google.cloud.websecurityscanner.v1beta.WebSecurityScannerClient.ListScanConfigsPagedResponse; +import com.google.cloud.websecurityscanner.v1beta.WebSecurityScannerSettings; +import com.google.common.collect.Lists; +import java.io.FileInputStream; +import java.io.IOException; +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Negative Integration tests for VPC-SC. */ +@RunWith(JUnit4.class) +public class VPCServiceControlNegativeTest { + + private static final String IN_VPCSC_GOOGLE_CLOUD_TEST_ENV = "GOOGLE_CLOUD_TESTS_IN_VPCSC"; + private static final String OUT_VPCSC_PROJECT_ENV = + "GOOGLE_CLOUD_TESTS_VPCSC_OUTSIDE_PERIMETER_PROJECT"; + private static final String OUT_VPCSC_HOSTNAME_ENV = + "GOOGLE_CLOUD_WEBSECURITYSCANNER_OUTSIDE_HOSTNAME"; + private static final String GOOGLE_CREDENTIAL_DEFAULT_ENV = "GOOGLE_APPLICATION_CREDENTIALS"; + private static final String GOOGLE_API_CLOUD_PLATFORM_LINK = + "https://www.googleapis.com/auth/cloud-platform"; + + private static final String IN_VPCSC_TEST = System.getenv(IN_VPCSC_GOOGLE_CLOUD_TEST_ENV); + private static final String OUT_VPCSC_PROJECT = System.getenv(OUT_VPCSC_PROJECT_ENV); + private static final String OUT_VPCSC_HOSTNAME = System.getenv(OUT_VPCSC_HOSTNAME_ENV); + private static final String OUT_VPCSC_GOOGLE_CREDENTIAL = + System.getenv(GOOGLE_CREDENTIAL_DEFAULT_ENV); + + private String testScanConfigCreationDisplayName; + + private static boolean isNotEmpty(String value) { + return value != null && value.length() != 0; + } + + @BeforeClass + public static void setUpClass() { + assumeTrue( + "To run tests, GOOGLE_CLOUD_TESTS_IN_VPCSC environment variable needs to be set to true", + IN_VPCSC_TEST != null && IN_VPCSC_TEST.equalsIgnoreCase("true")); + + assertTrue( + OUT_VPCSC_PROJECT_ENV + + " environment variable needs to be set to a GCP " + + "project that is out of the VPC perimeter", + isNotEmpty(OUT_VPCSC_PROJECT)); + + assertTrue( + OUT_VPCSC_HOSTNAME_ENV + " must be set to a webapp that resides in " + OUT_VPCSC_PROJECT, + isNotEmpty(OUT_VPCSC_HOSTNAME)); + + assertTrue( + GOOGLE_CREDENTIAL_DEFAULT_ENV + + " must be set to google application credentials " + + "that is outside VPCSC perimeter", + isNotEmpty(OUT_VPCSC_GOOGLE_CREDENTIAL)); + } + + @Before + public void setup() { + DateTimeFormatter formatter = + ISODateTimeFormat.basicDateTime().withZone(DateTimeZone.forID("America/Los_Angeles")); + String currentTime = formatter.print(DateTime.now(DateTimeZone.forID("America/Los_Angeles"))); + testScanConfigCreationDisplayName = "vpcsc-neg-test" + currentTime + "-0"; + } + + private WebSecurityScannerSettings getWssSettingWithCredentials() throws IOException { + GoogleCredentials credentials = + GoogleCredentials.fromStream(new FileInputStream(OUT_VPCSC_GOOGLE_CREDENTIAL)) + .createScoped(Lists.newArrayList(GOOGLE_API_CLOUD_PLATFORM_LINK)); + return WebSecurityScannerSettings.newBuilder() + .setCredentialsProvider(FixedCredentialsProvider.create(credentials)) + .build(); + } + + @Test + public void testScanConfigCreation() throws IOException { + WebSecurityScannerSettings wssSetting = getWssSettingWithCredentials(); + final String formattedParent = ProjectName.format(OUT_VPCSC_PROJECT); + try (WebSecurityScannerClient wssClient = WebSecurityScannerClient.create(wssSetting)) { + ScanConfig scanConfig = + ScanConfig.newBuilder() + .addAllStartingUrls(Lists.newArrayList(OUT_VPCSC_HOSTNAME)) + .setDisplayName(testScanConfigCreationDisplayName) + .build(); + CreateScanConfigRequest request = + CreateScanConfigRequest.newBuilder() + .setParent(formattedParent) + .setScanConfig(scanConfig) + .build(); + + ScanConfig responseScanConfig = wssClient.createScanConfig(request); + fail("Exception must occur for non-accessible project"); + } catch (PermissionDeniedException expected) { + } + } + + @Test + public void testScanConfigList() throws IOException { + // try to get the list of scan configs - it must fail + WebSecurityScannerSettings wssSetting = getWssSettingWithCredentials(); + final String formattedParent = ProjectName.format(OUT_VPCSC_PROJECT); + try (WebSecurityScannerClient wssClient = WebSecurityScannerClient.create(wssSetting)) { + ListScanConfigsRequest lscRequest = + ListScanConfigsRequest.newBuilder().setParent(formattedParent).build(); + ListScanConfigsPagedResponse scanConfigsList = wssClient.listScanConfigs(lscRequest); + fail("Exception must occur for non-acceessible project scan-configs"); + } catch (PermissionDeniedException expected) { + } + } +} diff --git a/google-cloud-clients/google-cloud-websecurityscanner/src/test/java/com/google/cloud/websecurityscanner/it/v1beta/VPCServiceControlPositiveTest.java b/google-cloud-clients/google-cloud-websecurityscanner/src/test/java/com/google/cloud/websecurityscanner/it/v1beta/VPCServiceControlPositiveTest.java new file mode 100644 index 000000000000..363e6367163c --- /dev/null +++ b/google-cloud-clients/google-cloud-websecurityscanner/src/test/java/com/google/cloud/websecurityscanner/it/v1beta/VPCServiceControlPositiveTest.java @@ -0,0 +1,270 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.websecurityscanner.it.v1beta; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; + +import com.google.api.gax.core.FixedCredentialsProvider; +import com.google.api.gax.rpc.NotFoundException; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.cloud.websecurityscanner.v1beta.CreateScanConfigRequest; +import com.google.cloud.websecurityscanner.v1beta.DeleteScanConfigRequest; +import com.google.cloud.websecurityscanner.v1beta.GetScanConfigRequest; +import com.google.cloud.websecurityscanner.v1beta.ListScanConfigsRequest; +import com.google.cloud.websecurityscanner.v1beta.ProjectName; +import com.google.cloud.websecurityscanner.v1beta.ScanConfig; +import com.google.cloud.websecurityscanner.v1beta.ScanRun; +import com.google.cloud.websecurityscanner.v1beta.ScanRun.ResultState; +import com.google.cloud.websecurityscanner.v1beta.StartScanRunRequest; +import com.google.cloud.websecurityscanner.v1beta.StopScanRunRequest; +import com.google.cloud.websecurityscanner.v1beta.WebSecurityScannerClient; +import com.google.cloud.websecurityscanner.v1beta.WebSecurityScannerSettings; +import com.google.common.collect.Lists; +import java.io.FileInputStream; +import java.io.IOException; +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Positive Integration Tests for VPC-SC */ +@RunWith(JUnit4.class) +public class VPCServiceControlPositiveTest { + private static final String IN_VPCSC_GOOGLE_CLOUD_TEST_ENV = "GOOGLE_CLOUD_TESTS_IN_VPCSC"; + private static final String IN_VPCSC_PROJECT_ENV = + "GOOGLE_CLOUD_TESTS_VPCSC_INSIDE_PERIMETER_PROJECT"; + private static final String IN_VPCSC_HOSTNAME_ENV = "GOOGLE_CLOUD_WEBSECURITYSCANNER_HOSTNAME"; + private static final String GOOGLE_CREDENTIAL_DEFAULT_ENV = "GOOGLE_APPLICATION_CREDENTIALS"; + private static final String GOOGLE_API_CLOUD_PLATFORM_LINK = + "https://www.googleapis.com/auth/cloud-platform"; + + private static final String IN_VPCSC_TEST = System.getenv(IN_VPCSC_GOOGLE_CLOUD_TEST_ENV); + private static final String IN_VPCSC_PROJECT = System.getenv(IN_VPCSC_PROJECT_ENV); + private static final String IN_VPCSC_HOSTNAME = System.getenv(IN_VPCSC_HOSTNAME_ENV); + private static final String IN_VPCSC_GOOGLE_CREDENTIAL = + System.getenv(GOOGLE_CREDENTIAL_DEFAULT_ENV); + + private String test0DisplayName; + private String test1DisplayName; + + private static boolean isNotEmpty(String value) { + return value != null && value.length() != 0; + } + + @BeforeClass + public static void setUpClass() { + assumeTrue( + "To run tests, GOOGLE_CLOUD_TESTS_IN_VPCSC environment variable needs to be set to true", + IN_VPCSC_TEST != null && IN_VPCSC_TEST.equalsIgnoreCase("true")); + + assertTrue( + IN_VPCSC_PROJECT_ENV + + " environment variable needs to be set to a GCP " + + "project that is inside the VPC perimeter", + isNotEmpty(IN_VPCSC_PROJECT)); + + assertTrue( + IN_VPCSC_HOSTNAME_ENV + + " environment variable needs to be set to a web " + + "application that resides inside " + + IN_VPCSC_PROJECT, + isNotEmpty(IN_VPCSC_HOSTNAME)); + + assertTrue( + GOOGLE_CREDENTIAL_DEFAULT_ENV + + " environment variable needs to be set to " + + "google application credentials that resides inside VPCSC", + isNotEmpty(IN_VPCSC_GOOGLE_CREDENTIAL)); + } + + @Before + public void setUp() { + DateTimeFormatter formatter = + ISODateTimeFormat.basicDateTime().withZone(DateTimeZone.forID("America/Los_Angeles")); + String currentTime = formatter.print(DateTime.now(DateTimeZone.forID("America/Los_Angeles"))); + test0DisplayName = "vpcsctest-" + currentTime + "-0"; + test1DisplayName = "vpcsctest-" + currentTime + "-1"; + } + + private WebSecurityScannerSettings getWssSettingWithCredentials() throws IOException { + GoogleCredentials credentials = + GoogleCredentials.fromStream(new FileInputStream(IN_VPCSC_GOOGLE_CREDENTIAL)) + .createScoped(Lists.newArrayList(GOOGLE_API_CLOUD_PLATFORM_LINK)); + return WebSecurityScannerSettings.newBuilder() + .setCredentialsProvider(FixedCredentialsProvider.create(credentials)) + .build(); + } + + private WebSecurityScannerSettings getWssSettingWithDefaultCredentials() throws IOException { + // If google-credentials is not passed explicitly then google apis uses the authentication + // credentials provided in environment variable GOOGLE_APPLICATION_CREDENTIALS is used + return WebSecurityScannerSettings.newBuilder().build(); + } + + @Test + public void testWithDefaultCredentials() throws IOException { + try (WebSecurityScannerClient wssClient = + WebSecurityScannerClient.create(getWssSettingWithDefaultCredentials())) { + test(wssClient, test0DisplayName); + } + } + + @Test + public void testWithCredentials() throws IOException { + try (WebSecurityScannerClient wssClient = + WebSecurityScannerClient.create(getWssSettingWithCredentials())) { + test(wssClient, test1DisplayName); + } + } + + private void test(final WebSecurityScannerClient wssClient, final String displayName) { + // This test performs following steps: + // 0. Create scan-config + // 1. Make sure that created scan-config is present + // 2. Start scan run on created scan-config + // 3. Make sure that created scan-run is present. + // 5. Stop the scan-run + // 6. Make sure that scan-run is stopped + // 7. Delete scan-config + // 8. Make sure that deleted scan-config is not present. + + final String formattedParent = ProjectName.format(IN_VPCSC_PROJECT); + + class TestResource implements AutoCloseable { + private WebSecurityScannerClient wssClient; + private final String displayName; + private ScanConfig createdScanConfig; + private ScanRun startedScanRun; + + TestResource(WebSecurityScannerClient wssClient, String displayName) { + this.wssClient = wssClient; + this.displayName = displayName; + } + + ScanConfig createScanConfig() { + ScanConfig scanConfig = + ScanConfig.newBuilder() + .addAllStartingUrls(Lists.newArrayList(IN_VPCSC_HOSTNAME)) + .setDisplayName(displayName) + .build(); + CreateScanConfigRequest request = + CreateScanConfigRequest.newBuilder() + .setParent(formattedParent) + .setScanConfig(scanConfig) + .build(); + createdScanConfig = wssClient.createScanConfig(request); + return createdScanConfig; + } + + void deleteScanConfig() { + DeleteScanConfigRequest deleteScanConfigRequest = + DeleteScanConfigRequest.newBuilder().setName(createdScanConfig.getName()).build(); + wssClient.deleteScanConfig(deleteScanConfigRequest); + createdScanConfig = null; + } + + ScanRun startScanRun() { + StartScanRunRequest startScanRunRequest = + StartScanRunRequest.newBuilder().setName(createdScanConfig.getName()).build(); + startedScanRun = wssClient.startScanRun(startScanRunRequest); + return startedScanRun; + } + + ScanRun stopScanRun() { + StopScanRunRequest stopScanRunRequest = + StopScanRunRequest.newBuilder().setName(startedScanRun.getName()).build(); + ScanRun stoppedScanRun = wssClient.stopScanRun(stopScanRunRequest); + startedScanRun = null; + return stoppedScanRun; + } + + @Override + public void close() { + if (startedScanRun != null) { + stopScanRun(); + startedScanRun = null; + } + + if (createdScanConfig != null) { + deleteScanConfig(); + createdScanConfig = null; + } + } + } + + try (TestResource testResource = new TestResource(wssClient, displayName)) { + + ScanConfig responseScanConfig = testResource.createScanConfig(); + assertEquals( + "Display name is response must be equal to display name in request", + displayName, + responseScanConfig.getDisplayName()); + + // Make sure that created scan config is present + GetScanConfigRequest scanConfigRequest = + GetScanConfigRequest.newBuilder().setName(responseScanConfig.getName()).build(); + ScanConfig obtainedScanConfig = wssClient.getScanConfig(scanConfigRequest); + assertEquals( + "Scan-Config name must be equal", + responseScanConfig.getName(), + obtainedScanConfig.getName()); + + ListScanConfigsRequest lscRequest = + ListScanConfigsRequest.newBuilder().setParent(formattedParent).build(); + boolean oneDisplayNameMatches = false; + for (ScanConfig sc : wssClient.listScanConfigs(lscRequest).iterateAll()) { + // since display name is never null so object equality can be used + if (displayName.equals(sc.getDisplayName())) { + oneDisplayNameMatches = true; + break; + } + } + assertTrue("One scan-config with " + displayName + " must be present", oneDisplayNameMatches); + + ScanRun scanRunResponse = testResource.startScanRun(); + assertTrue("Scan-run name must not be empty", isNotEmpty(scanRunResponse.getName())); + + assertNotEquals( + "Scan-run state must not be KILLED", + ResultState.KILLED, + scanRunResponse.getResultState()); + + ScanRun stoppedScanRun = testResource.stopScanRun(); + assertEquals( + "Result state must be killed", ResultState.KILLED, stoppedScanRun.getResultState()); + testResource.deleteScanConfig(); + + // make sure that deleted scan-config do not exist + GetScanConfigRequest getScanConfigRequest = + GetScanConfigRequest.newBuilder().setName(responseScanConfig.getName()).build(); + try { + ScanConfig deletedScanConfig = wssClient.getScanConfig(getScanConfigRequest); + fail("NotFoundException must be throw as scan-config must already be deleted"); + } catch (NotFoundException expected) { + } + } + } +}