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

V6.0.12 dfci #1

Draft
wants to merge 52 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
b74b6c3
Initial v6.0.12-dfci branch creation
JREastonMarks Sep 13, 2024
bba1656
Importer Addition
JREastonMarks Sep 13, 2024
d0a12e3
Add Importer
JREastonMarks Sep 16, 2024
7556746
Fix ImportMapper.xml Mapping
JREastonMarks Sep 23, 2024
eea5547
Update ImportController.java
JREastonMarks Sep 24, 2024
bbdc2cc
Add show_profile_download_tab property and OpenAPI Config
JREastonMarks Sep 24, 2024
c7069df
6.0.12-dfci UI Update
JREastonMarks Sep 25, 2024
d5e7665
Update Dockerfile
JREastonMarks Sep 26, 2024
cb102c8
Update .gitignore
JREastonMarks Sep 26, 2024
5818d9b
Security Change to Support SAML Authorization
JREastonMarks Sep 30, 2024
56bb47b
Add importer to WebMVC Configuration
JREastonMarks Sep 30, 2024
85a59f8
Add Context Path to proxy
JREastonMarks Oct 11, 2024
bc8d0b2
Update proxy service
JREastonMarks Oct 16, 2024
31121d9
Handle Chunked Streaming
JREastonMarks Oct 17, 2024
c6c2d37
Parameter Passing
JREastonMarks Oct 18, 2024
f72daca
Update Frontend
JREastonMarks Oct 21, 2024
24369a0
Add Profile Latest tar.gz path
JREastonMarks Oct 21, 2024
21363c4
Update UI
JREastonMarks Nov 5, 2024
17bdbe4
Allow import to pass through
JREastonMarks Nov 6, 2024
51cc400
Fix Username being sent to SAML only
JREastonMarks Nov 6, 2024
3c12a53
Add logs to WebAppConfig
JREastonMarks Nov 6, 2024
6770d34
Fix missing comma
JREastonMarks Nov 6, 2024
2429cf0
Try a new config entry
JREastonMarks Nov 6, 2024
cb4674e
Update WebAppConfig.java
JREastonMarks Nov 6, 2024
62140bc
Update pom.xml
JREastonMarks Nov 7, 2024
a02d3b2
Allow for logout
JREastonMarks Nov 7, 2024
5dae3c2
Update Frontend Version to Remove SV
JREastonMarks Nov 8, 2024
bfa8fb2
Update frontend version
JREastonMarks Nov 11, 2024
931d3cb
Update version to test SV fix
JREastonMarks Nov 13, 2024
985e3a5
Update Jackson Max String Length
JREastonMarks Dec 2, 2024
9e15076
Fix Gene Panel Data when MolecularProfileIds is Empty
JREastonMarks Dec 11, 2024
af3ee9b
Filer Update
JREastonMarks Dec 11, 2024
edf8672
Fix for importer UI issue
JREastonMarks Dec 17, 2024
a03a16e
Add IP-IMAGES url route
JREastonMarks Dec 17, 2024
77490b0
Fix ip-images
JREastonMarks Dec 17, 2024
ab9cd99
Roll back GenePanelData
JREastonMarks Dec 18, 2024
c9467f2
Update Frontend Version
JREastonMarks Dec 18, 2024
bbe7195
Fix No Genomic Data Study Failure Issue
JREastonMarks Dec 19, 2024
7e9aab9
Move semantic CSS to not override cBio CSS
JREastonMarks Dec 19, 2024
f9a82f2
Fix imports in index template
JREastonMarks Dec 20, 2024
bbc5a83
Add BootStrap
JREastonMarks Dec 20, 2024
3c05690
Update Frontend Version
JREastonMarks Dec 20, 2024
9105965
Update frontend version
JREastonMarks Dec 26, 2024
6650f16
Update Frontend Version
JREastonMarks Dec 26, 2024
881431c
Revert Changes to Import Controller
JREastonMarks Dec 26, 2024
94b1639
Update ImportController User Header
JREastonMarks Dec 30, 2024
eb15331
Update Logout for OAuth2
JREastonMarks Jan 3, 2025
792f7f5
Fix image URI
JREastonMarks Jan 21, 2025
2a85767
Update login.html
JREastonMarks Jan 21, 2025
3740058
Fix Authentication Redirect Loop
JREastonMarks Jan 22, 2025
ce0de96
Clean up security, resources, and proxy
JREastonMarks Jan 28, 2025
5992ec7
Remove webapp folder
JREastonMarks Jan 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,4 @@ Dockerfile.local
security.properties
*.crt
*.key
*.pem
11 changes: 6 additions & 5 deletions docker/web-and-data/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,18 @@ RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*-exec.jar)
FROM eclipse-temurin:21

# download system dependencies first to take advantage of docker caching
RUN apt-get update; apt-get install -y --no-install-recommends \
RUN apt-get update;
RUN apt-get install -y --no-install-recommends \
build-essential \
default-mysql-client \
default-libmysqlclient-dev \
python3 \
python3-setuptools \
python3-dev \
python3-pip \
unzip \
&& rm -rf /var/lib/apt/lists/* \
&& pip3 install wheel
unzip
RUN rm -rf /var/lib/apt/lists/*
RUN pip3 install wheel --break-system-packages

# copy over core files and data-related scripts
RUN mkdir -p /cbioportal
Expand All @@ -52,7 +53,7 @@ COPY --from=build /cbioportal/src/main/resources/db-scripts /cbioportal/db-scrip

# install build and runtime dependencies
# ignore update failure980[1298[01 w2308s
RUN pip3 install -r /core/requirements.txt
RUN pip3 install -r /core/requirements.txt --break-system-packages

# add importer scripts to PATH for easy running in containers
RUN find /core/scripts/ -type f -executable \! -name '*.pl' -print0 | xargs -0 -- ln -st /usr/local/bin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ In its simplest terms, SAML boils down to four terms:

## Why is SAML Relevant to cBioPortal?

The cBioPortal code has no means of storing user name and passwords and no means of directly authenticating users. If you want to restrict access to your instance of cBioPortal, you therefore have to consider an external authentication service. SAML is one means of doing so, and your larger institution may already provide SAML support. For example, at Sloan Kettering and Dana-Farber, users of the internal cBioPortal instances login with their regular credentials via SAML. This greatly simplifies user management.
cBioPortal has no means of directly authenticating users. If you want to restrict access to your instance of cBioPortal, you therefore have to consider an external authentication service. SAML is one means of doing so, and your larger institution may already provide SAML support. For example, at Sloan Kettering and Dana-Farber, users of the internal cBioPortal instances login with their regular credentials via SAML. This greatly simplifies user management.

# Setting up an Identity Provider

Expand Down Expand Up @@ -49,7 +49,7 @@ To get started:
* ACS (Consumer) URL*: http://localhost:8080/saml/SSO

![](/images/previews/onelogin-config.png)

Note: These URLs presume that cBioPortal is operating at the root level and no context window is set.

* Add at least the parameters:
* Email (Attribute)
Expand Down Expand Up @@ -79,7 +79,7 @@ To get started:

then, move this XML file to:

portal/src/main/resources/
src/main/resources/

You should now be all set with OneLogin.com. Next, you need to configure your instance of cBioPortal.

Expand Down Expand Up @@ -127,44 +127,21 @@ Within application.properties, make sure that:

Then, modify the section labeled `authentication`. See SAML parameters shown in example below:

saml.sp.metadata.entityid=cbioportal
saml.sp.metadata.wantassertionsigned=true
saml.idp.metadata.location=classpath:/onelogin_metadata_620035.xml
saml.idp.metadata.entityid=https://app.onelogin.com/saml/metadata/620035
saml.keystore.location=classpath:/samlKeystore.jks
saml.keystore.password=apollo1
saml.keystore.private-key.key=secure-key
saml.keystore.private-key.password=apollo2
saml.keystore.default-key=secure-key
saml.idp.comm.binding.settings=defaultBinding
saml.idp.comm.binding.type=
saml.idp.metadata.attribute.email=User.email
saml.idp.metadata.attribute.userName=User.name
saml.custom.userservice.class=org.cbioportal.security.spring.authentication.saml.SAMLUserDetailsServiceImpl
# global logout (as opposed to local logout):
saml.logout.local=false
saml.logout.url=/
```
spring.security.saml2.relyingparty.registration.cbio-idp.assertingparty.metadata-uri=https://ksg.dfci.harvard.edu/keycloak/realms/partners/protocol/saml/descriptor
spring.security.saml2.relyingparty.registration.cbio-idp.entity-id=cbioportal
spring.security.saml2.relyingparty.registration.cbio-idp.signing.credentials[0].certificate-location=classpath:/samlCertificate.crt
spring.security.saml2.relyingparty.registration.cbio-idp.signing.credentials[0].private-key-location=classpath:/samlPrivateKey-pkcs8.pem
saml.logout.local=false
saml.logout.url=/
```

Please note that you will have to modify all the above to match your own settings. `saml.idp.comm.binding.type` can be left empty if `saml.idp.comm.binding.settings=defaultBinding`. The `saml.logout.*` settings above reflect the settings of an IDP that supports Single Logout (hopefully the default in most cases - more details in section below).

In the case that you are running cBioPortal behind a reverse proxy that handles the SSL certificates (such as nginx or traefik), you will have to also specify `saml.sp.metadata.entitybaseurl`. This should point to `https://host.example.come:443`. This setting is required such that cBioPortal uses the Spring SAML library appropriately for creating redirects back into cBioPortal.

In addition there is a known bug where redirect from the cBioPortal instance always goes over http instead of https (https://github.com/cBioPortal/cbioportal/issues/6342). To get around this issue you can pass the full URL including https to the `webapp-runnner.jar` command with e.g. `--proxy-base-url https://mycbioportalinstance.org`.
In the case that you are running cBioPortal behind a reverse proxy that handles the SSL certificates (such as nginx or traefik), you will have to also specify `server.forward-headers-strategy=FRAMEWORK` and `server.use-forward-headers=true`

### Custom scenarios

:information_source: Some settings may need to be adjusted to non-default values, depending on your IDP. For example, if your
IDP required HTTP-GET requests instead of HTTP-POST, you need to set these properties as such:

saml.idp.comm.binding.settings=specificBinding
saml.idp.comm.binding.type=bindings:HTTP-Redirect

If you need a very different parsing of the SAML tokens than what is done at `org.cbioportal.security.spring.authentication.saml.SAMLUserDetailsServiceImpl`, you can point the `saml.custom.userservice.class` to your own implementation:

saml.custom.userservice.class=<your_package.your_class_name>

:warning: The properties `saml.idp.metadata.attribute.email`, and `saml.idp.metadata.attribute.userName` can also vary per IDP. It is important to set these correctly since these are a required field by the cBioPortal SAML parser (that is, if `org.cbioportal.security.spring.authentication.saml.SAMLUserDetailsServiceImpl` is chosen for property `saml.custom.userservice.class`).

:warning: Some IDPs like to provide their own logout page (e.g. when they don't support the custom SAML Single Logout protocol). For this you can adjust the
`saml.logout.url` property to a custom URL provided by the IDP. Also set the `saml.logout.local=true` property in this case to indicate that global logout (or Single Logout) is not supported by IDP:

Expand All @@ -173,23 +150,6 @@ If you need a very different parsing of the SAML tokens than what is done at `or
saml.logout.url=<idp specific logout URL, e.g. https://idp.logoutpage.com >


:warning: Some IDPs (e.g. Azure Active Directory) cache user data for more than 2 hours causing cbioportal to complain that the authentication statement is too old to be used. You can fix this problem by setting `forceAuthN` to true. Below is an example how you can do this with the properties. You can choose any binding type you like. `bindings:HTTP-Redirect` is given just as an example.

```
saml.idp.comm.binding.settings=specificBinding
saml.idp.comm.binding.type=bindings:HTTP-Redirect
saml.idp.comm.binding.force-auth-n=true
```

## More customizations

If your IDP does not have the flexibility of sending the specific credential fields expected by our
default "user details parsers" implementation (i.e. `security/security-spring/src/main/java/org/cbioportal/security/spring/authentication/saml/SAMLUserDetailsServiceImpl.java`
expects field `mail` to be present in the SAML credential), then please let us know via a [new
issue at our issue tracking system](https://github.com/cBioPortal/cbioportal/issues/new), so we can
evaluate whether this is a scenario we would like to support in the default code. You can also consider
adding your own version of the `SAMLUserDetailsService` class.

## Authorizing Users

Next, please read the Wiki page on [User Authorization](User-Authorization.md), and add user rights for a single user.
Expand All @@ -201,22 +161,14 @@ The login page is configurable via the `application.properties` properties `skin
For example in `skin.authorization_message` you can be set to something like this:

```
skin.authorization_message= Welcome to this portal. Access to this portal is available to authorized test users at YOUR ORG. [<a href="https://thehyve.nl/">Request Access</a>].
skin.authorization_message= Welcome to this portal. Access to this portal is available to authorized test users at YOUR ORG. [<a href="https://youorg.com/">Request Access</a>].
```

and `skin.login.saml.registration_htm` can be set to:

```
skin.login.saml.registration_htm=Sign in via XXXX
```

You can also set a standard text in `skin.login.contact_html` that will appear in case of problems:

```
skin.login.contact_html=If you think you have received this message in error, please contact us at <a style="color:#FF0000" href="mailto:cbioportal-access@your.org">cbioportal-access@your.org</a>
```


## Doing a Test Run

You are now ready to go.
Expand Down Expand Up @@ -257,7 +209,7 @@ your best bet is to turn on all DEBUG logging. This can be done via `src/main/r
</logger>
```

Then, rebuild the WAR, redeploy, and try to authenticate again. Your log file will then include hundreds of SAML-specific messages, even the full XML of each SAML message, and this should help you debug the error.
Your log file will then include hundreds of SAML-specific messages, even the full XML of each SAML message, and this should help you debug the error.

### Seeing the SAML messages

Expand Down
22 changes: 13 additions & 9 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<groupId>org.cbioportal</groupId>
<artifactId>cbioportal</artifactId>
<version>6.0.12</version>
<version>6.0.12-dfci</version>

<description>cBioPortal for Cancer Genomics</description>

Expand All @@ -26,8 +26,8 @@
<timestamp>${maven.build.timestamp}</timestamp>
<!-- TODO replace with version of cbioportal frontend with compatible
login url-->
<frontend.groupId>com.github.cbioportal</frontend.groupId>
<frontend.version>v6.0.12</frontend.version>
<frontend.groupId>com.github.dfci</frontend.groupId>
<frontend.version>37c32295</frontend.version>

<!-- THIS SHOULD BE KEPT IN SYNC TO VERSION IN CGDS.SQL -->
<db.version>2.13.1</db.version>
Expand Down Expand Up @@ -107,6 +107,16 @@
</properties>

<dependencies>
<!--BEGIN TEST AREA -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway-mvc</artifactId>
<version>4.1.5</version>
</dependency>


<!-- END TEST AREA -->

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
Expand Down Expand Up @@ -310,12 +320,6 @@
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!-- JitPack Publishing -->
<dependency>
<groupId>com.github.jitpack</groupId>
<artifactId>maven-simple</artifactId>
<version>0.1</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/org/cbioportal/WebAppConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/images/**").addResourceLocations("classpath:/webapp/images/");
registry.addResourceHandler("/reactapp/**").addResourceLocations("classpath:/reactapp/");
registry.addResourceHandler("/js/**").addResourceLocations("classpath:/js/");
registry.addResourceHandler("/profile_latest.tar.gz").addResourceLocations("classpath:/profile_latest.tar.gz");
registry.addResourceHandler("/ip-images/**").addResourceLocations("classpath:/ip-images/");
}

@Override
Expand Down Expand Up @@ -58,10 +60,15 @@ public void addViewControllers(ViewControllerRegistry registry) {
"/oncoprinter**",
"/encodedRedirect",
"/datasets**",
"/import/*",
"/importer**",
"/logs/**",
"/ln**",
"/webAPI**",
"/news**",
"/visualize**"
"/visualize**",
"/test**",
"/DownloadProfileData"
);

endpoints.forEach( route -> registry.addViewController(route).setViewName(SINGLE_PAGE_APP_ROOT));
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/org/cbioportal/model/StudyAndSampleIds.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.cbioportal.model;

import java.io.Serializable;
import java.util.Set;

public class StudyAndSampleIds implements Serializable {
private String studyId;
private String studyName;
private Set<String> sampleIds;

public String getStudyId() {
return studyId;
}

public void setStudyId(String studyId) {
this.studyId = studyId;
}

public Set<String> getSampleIds() {
return sampleIds;
}

public void setSampleIds(Set<String> sampleIds) {
this.sampleIds = sampleIds;
}

public String getStudyName() {
return studyName;
}

public void setStudyName(String studyName) {
this.studyName = studyName;
}
}
41 changes: 41 additions & 0 deletions src/main/java/org/cbioportal/model/StudyOverlap.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.cbioportal.model;

import java.util.LinkedHashSet;

public class StudyOverlap {
private String studyId;
private LinkedHashSet<String> overlappingStudyIds;
private LinkedHashSet<String> overlappingStudyNames;

public StudyOverlap(){}

public StudyOverlap(String studyId) {
this.studyId = studyId;
overlappingStudyIds = new LinkedHashSet<>();
overlappingStudyNames = new LinkedHashSet<>();
}

public String getStudyId() {
return studyId;
}

public void setStudyId(String studyId) {
this.studyId = studyId;
}

public LinkedHashSet<String> getOverlappingStudyIds() {
return overlappingStudyIds;
}

public void setOverlappingStudyIds(LinkedHashSet<String> overlappingStudyIds) {
this.overlappingStudyIds = overlappingStudyIds;
}

public LinkedHashSet<String> getOverlappingStudyNames() {
return overlappingStudyNames;
}

public void setOverlappingStudyNames(LinkedHashSet<String> overlappingStudyNames) {
this.overlappingStudyNames = overlappingStudyNames;
}
}
Loading