Skip to content

Commit

Permalink
Update Security Integration test to remove selenium container (#10615)
Browse files Browse the repository at this point in the history
* Update Security Integration test to remove selenium container

* Fix yml file

* Add DirtiesContext annotation

* Remove internal.test.host

* Add mongo and session service
  • Loading branch information
haynescd authored Feb 15, 2024
1 parent 5d95f35 commit accee3b
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 171 deletions.
5 changes: 2 additions & 3 deletions .github/workflows/security-integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ jobs:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: 'Add host.testcontainers.internal to /etc/hosts'
run: |
echo "127.0.0.1 host.testcontainers.internal" | sudo tee -a /etc/hosts
- name: 'Download Chrome'
uses: browser-actions/setup-chrome@latest
- name: 'Copy Application.Properties'
working-directory: ./cbioportal
run: |
Expand Down
4 changes: 3 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
<!-- Unknown -->
<io.swagger.version>1.6.3</io.swagger.version>
<mybatis.starter.version>3.0.2</mybatis.starter.version>
<testcontainers.version>1.19.3</testcontainers.version>
<testcontainers.version>1.19.4</testcontainers.version>
<mockserver.version>5.15.0</mockserver.version>
<opensaml.version>4.1.1</opensaml.version>

Expand All @@ -96,6 +96,7 @@
<mysql_driver.version>5.1.48</mysql_driver.version>
<dasniko-testcontainer-keycloak.version>3.2.0</dasniko-testcontainer-keycloak.version>
<selenium_chrome_driver.version>3.14.0</selenium_chrome_driver.version>
<selenium.version>4.17.0</selenium.version>
<sentry.version>7.1.0</sentry.version>


Expand Down Expand Up @@ -277,6 +278,7 @@
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>${selenium.version}</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public void initializeImpl(ConfigurableApplicationContext configurableApplicatio
try {

String keycloakUrlForCBioportal = keycloakContainer.getAuthServerUrl();
String keycloakUrlForBrowser = String.format("http://host.testcontainers.internal:%s", keycloakContainer.getHttpPort());
String keycloakUrlForBrowser = String.format("http://localhost:%s", keycloakContainer.getHttpPort());

TestPropertyValues values = TestPropertyValues.of(

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package org.cbioportal.test.integration.security;

import dasniko.testcontainers.keycloak.KeycloakContainer;
import org.cbioportal.test.integration.OAuth2ResourceServerKeycloakInitializer;
import org.cbioportal.test.integration.MysqlInitializer;
import org.cbioportal.test.integration.OAuth2KeycloakInitializer;
import org.cbioportal.test.integration.OAuth2ResourceServerKeycloakInitializer;
import org.cbioportal.test.integration.SamlKeycloakInitializer;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.boot.web.context.WebServerInitializedEvent;
Expand All @@ -13,70 +14,62 @@
import org.springframework.context.ConfigurableApplicationContext;
import org.testcontainers.Testcontainers;
import org.testcontainers.containers.BindMode;
import org.testcontainers.containers.BrowserWebDriverContainer;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.shaded.com.google.common.collect.ImmutableList;
import org.testcontainers.utility.DockerImageName;

import java.io.File;
import java.io.IOException;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

import static org.cbioportal.test.integration.security.util.Util.isHostMappingPresent;
import static org.testcontainers.containers.BrowserWebDriverContainer.VncRecordingMode.RECORD_ALL;

public class ContainerConfig {

public final static int CBIO_PORT = 8080;
public final static int SESSION_SERVICE_PORT = 5000;
public final static int MONGO_PORT = 27017;
public final static int MYSQL_PORT = 3306;

public final static String MONGO_NETWORK = "mongo-network";
public final static int MOCKSERVER_PORT = 8085;
public final static String DOWNLOAD_FOLDER = "/tmp/browser_downloads";

private static final String SESSION_IMAGE_VERSION = "docker.io/cbioportal/session-service:0.6.1";
private static final String MONGO_IMAGE_VERSION = "docker.io/mongo:3.7.9";
private static final String KEYCLOAK_IMAGE_VERSION = "quay.io/keycloak/keycloak:22.0.5";
private static final String MYSQL_IMAGE_VERSION = "mysql:5.7";
private static final String MOCKSERVER_IMAGE_VERSION = "docker.io/mockserver/mockserver:5.15.0";

static final GenericContainer sessionServiceContainer;
static final GenericContainer mongoContainer;
static final MySQLContainer mysqlContainer;
static final GenericContainer mockServerContainer;
static final KeycloakContainer keycloakContainer;
static final BrowserWebDriverContainer chromedriverContainer;
static final ChromeDriver chromeDriver;

static {
static final GenericContainer sessionServiceContainer;
static final GenericContainer mongoContainer;

String hostToCheck = "host.testcontainers.internal";
String ipAddressToCheck = "127.0.0.1";
try {
if (!isHostMappingPresent(hostToCheck, ipAddressToCheck)) {
throw new IllegalStateException(hostToCheck + " is not mapped to " + ipAddressToCheck + " in /etc/hosts. Please add this mapping.");
}
} catch (IOException e) {
throw new RuntimeException("Unable to read /etc/hosts file.", e);
}
static {

Network mongoNetwork = Network.newNetwork();
mongoContainer = new GenericContainer(DockerImageName.parse(MONGO_IMAGE_VERSION))
.withNetwork(mongoNetwork)
.withNetworkAliases(MONGO_NETWORK)
.withAccessToHost(true)
.withEnv("MONGO_INITDB_DATABASE", "session_service");

String mongoConnectionString = String.format("-Dspring.data.mongodb.uri=mongodb://%s:%s/session-service",MONGO_NETWORK, MONGO_PORT);
sessionServiceContainer = new GenericContainer(DockerImageName.parse(SESSION_IMAGE_VERSION))
.withNetwork(mongoNetwork)
.withAccessToHost(true)
.withEnv("SERVER_PORT", "5000")
.withEnv("JAVA_OPTS", "-Dspring.data.mongodb.uri=mongodb://host.testcontainers.internal:27017/session-service");
.withEnv("JAVA_OPTS", mongoConnectionString);
sessionServiceContainer.setPortBindings(ImmutableList.of(String.format("%s:5000", SESSION_SERVICE_PORT)));

mongoContainer = new GenericContainer(DockerImageName.parse(MONGO_IMAGE_VERSION))
.withEnv("MONGO_INITDB_DATABASE", "session_service");
mongoContainer.setPortBindings(ImmutableList.of(String.format("%s:27017", MONGO_PORT, MONGO_PORT)));

keycloakContainer = new KeycloakContainer(KEYCLOAK_IMAGE_VERSION)
.withRealmImportFile("security/keycloak-configuration-generated.json")
.withAdminUsername("admin")
.withAdminPassword("admin")
.withEnv("KC_HOSTNAME", "host.testcontainers.internal")
.withEnv("KC_HOSTNAME", "localhost")
.withEnv("KC_HOSTNAME_ADMIN", "localhost");

mockServerContainer = new GenericContainer(MOCKSERVER_IMAGE_VERSION)
Expand All @@ -89,25 +82,22 @@ public class ContainerConfig {
.withStartupTimeout(Duration.ofMinutes(10));

ChromeOptions options = new ChromeOptions();
options.addArguments("--no-sandbox");
options.addArguments("--disable-dev-shm-usage");
options.addArguments("--headless");
Map<String, Object> prefs = new HashMap<>();
prefs.put("download.default_directory", DOWNLOAD_FOLDER);
prefs.put("profile.default_content_settings.popups", 0);
prefs.put("download.prompt_for_download", "false");
prefs.put("download.directory_upgrade", "true");
options.setExperimentalOption("prefs", prefs);
chromeDriver = new ChromeDriver(options);

chromedriverContainer = new BrowserWebDriverContainer<>()
.withCapabilities(options)
// activate this to record movies of the tests (great for debugging)
.withRecordingMode(RECORD_ALL, new File("/home/pnp300/"))
.withAccessToHost(true);

mysqlContainer.start();
sessionServiceContainer.start();
mongoContainer.start();
sessionServiceContainer.start();
mysqlContainer.start();
mockServerContainer.start();
keycloakContainer.start();
chromedriverContainer.start();
}

// Update application properties with connection info on Keycloak container
Expand Down Expand Up @@ -158,8 +148,7 @@ public void initialize(ConfigurableApplicationContext applicationContext) {
values.applyTo(applicationContext);
applicationContext.addApplicationListener(
(ApplicationListener<WebServerInitializedEvent>) event -> {
Testcontainers.exposeHostPorts(CBIO_PORT, keycloakContainer.getHttpPort(), MONGO_PORT);
keycloakContainer.setPortBindings(ImmutableList.of(String.format("%s:8080", keycloakContainer.getHttpPort())));
Testcontainers.exposeHostPorts(CBIO_PORT, MONGO_PORT);
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@

import org.cbioportal.PortalApplication;
import org.cbioportal.test.integration.security.util.Util;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
Expand Down Expand Up @@ -41,7 +39,7 @@
"dat.oauth2.clientId=cbioportal_oauth2",
"dat.oauth2.clientSecret=client_secret",
// Redirect URL to cBiopPortal application from perspective of browser
"dat.oauth2.redirectUri=http://host.testcontainers.internal:8080/api/data-access-token/oauth2",
"dat.oauth2.redirectUri=http://localhost:8080/api/data-access-token/oauth2",
"dat.oauth2.jwtRolesPath=resource_access::cbioportal::roles",
"session.service.url=http://localhost:5000/api/sessions/my_portal/",
"filter_groups_by_appname=false"
Expand All @@ -53,31 +51,30 @@
MyOAuth2KeycloakInitializer.class,
PortInitializer.class
})
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@DirtiesContext // needed to reuse port 8080 for multiple tests
@DirtiesContext
public class OAuth2AuthIntegrationTest extends ContainerConfig {

public final static String CBIO_URL_FROM_BROWSER =
String.format("http://host.testcontainers.internal:%d", CBIO_PORT);
String.format("http://localhost:%d", CBIO_PORT);

@Test
public void a_loginSuccess() {
Util.testLogin(CBIO_URL_FROM_BROWSER, chromedriverContainer);
Util.testLogin(CBIO_URL_FROM_BROWSER, chromeDriver);
}

@Test
public void b_downloadOfflineToken() throws Exception {
Util.testDownloadOfflineToken(CBIO_URL_FROM_BROWSER, chromedriverContainer);
Util.testDownloadOfflineToken(CBIO_URL_FROM_BROWSER, chromeDriver);
}

@Test
public void c_logoutSuccess() {
Util.testLogout(CBIO_URL_FROM_BROWSER, chromedriverContainer);
Util.testOAuthLogout(CBIO_URL_FROM_BROWSER, chromeDriver);
}

@Test
public void d_loginAgainSuccess() {
Util.testLoginAgain(CBIO_URL_FROM_BROWSER, chromedriverContainer);
Util.testLoginAgain(CBIO_URL_FROM_BROWSER, chromeDriver);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
package org.cbioportal.test.integration.security;


import org.cbioportal.PortalApplication;
import org.cbioportal.test.integration.security.util.HttpHelper;
import org.json.JSONArray;
import org.json.JSONException;
Expand Down Expand Up @@ -55,8 +54,7 @@
*/
@RunWith(SpringRunner.class)
@SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT,
classes = {PortalApplication.class}
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT
)
@TestPropertySource(
properties = {
Expand All @@ -71,10 +69,10 @@
"spring.security.saml2.relyingparty.registration.keycloak.signing.credentials[0].private-key-location=classpath:dev/security/signing-key.pem",
"dat.oauth2.clientId=client_id",
"dat.oauth2.clientSecret=client_secret",
"dat.oauth2.redirectUri=http://host.testcontainers.internal:8080/api/data-access-token/oauth2",
"dat.oauth2.redirectUri=http://localhost:8080/api/data-access-token/oauth2",
// host is the mock server that fakes the oidc idp
"dat.oauth2.accessTokenUri=http://host.testcontainers.internal:8085/realms/cbio/protocol/openid-connect/token",
"dat.oauth2.userAuthorizationUri=http://host.testcontainers.internal:8085/realms/cbio/protocol/openid-connect/auth",
"dat.oauth2.accessTokenUri=http://localhost:8085/realms/cbio/protocol/openid-connect/token",
"dat.oauth2.userAuthorizationUri=http://localhost:8085/realms/cbio/protocol/openid-connect/auth",
"dat.oauth2.jwtRolesPath=resource_access::cbioportal::roles",
"filter_groups_by_appname=false"
}
Expand All @@ -83,11 +81,12 @@
MyMysqlInitializer.class,
MyOAuth2ResourceServerKeycloakInitializer.class
})
@DirtiesContext // needed to reuse port 8080 for multiple tests
@DirtiesContext
public class OAuth2ResourceServerIntegrationTest extends ContainerConfig {

public final static String CBIO_URL_FROM_BROWSER =
String.format("http://localhost:%d", CBIO_PORT);

private final static String tokenUriPath = "/realms/cbio/protocol/openid-connect/token";

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package org.cbioportal.test.integration.security;

import org.cbioportal.PortalApplication;
import org.cbioportal.test.integration.security.util.Util;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
Expand All @@ -18,8 +15,7 @@

@RunWith(SpringRunner.class)
@SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT,
classes = {PortalApplication.class}
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT
)
@TestPropertySource(
properties = {
Expand Down Expand Up @@ -51,26 +47,25 @@
MySamlKeycloakInitializer.class,
PortInitializer.class
})
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@DirtiesContext // needed to reuse port 8080 for multiple tests
@DirtiesContext
public class SamlAuthIntegrationTest extends ContainerConfig {

public final static String CBIO_URL_FROM_BROWSER =
String.format("http://host.testcontainers.internal:%d", CBIO_PORT);
String.format("http://localhost:%d", CBIO_PORT);

@Test
public void a_loginSuccess() {
Util.testLogin(CBIO_URL_FROM_BROWSER, chromedriverContainer);
Util.testLogin(CBIO_URL_FROM_BROWSER, chromeDriver);
}

@Test
public void b_testAuthorizedStudy() {
Util.testLoginAndVerifyStudyNotPresent(CBIO_URL_FROM_BROWSER,chromedriverContainer );
Util.testLoginAndVerifyStudyNotPresent(CBIO_URL_FROM_BROWSER,chromeDriver );
}

@Test
public void c_logoutSuccess() {
Util.testLogout(CBIO_URL_FROM_BROWSER, chromedriverContainer);
Util.testSamlLogout(CBIO_URL_FROM_BROWSER, chromeDriver);
}

}
Loading

0 comments on commit accee3b

Please sign in to comment.