Skip to content
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

Update Security Integration test to remove selenium container #10615

Merged
merged 5 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading