Skip to content
Snippets Groups Projects
Commit d8b51d16 authored by Ruben Backx's avatar Ruben Backx :coffee:
Browse files

Merge branch 'development' into 'master'

Dev to master

See merge request !27
parents 6bc77cad dad253ed
No related branches found
No related tags found
No related merge requests found
Pipeline #528281 passed
......@@ -202,7 +202,6 @@ include:
- template: Jobs/Code-Quality.gitlab-ci.yml
- template: Security/SAST.gitlab-ci.yml
- template: Security/DAST.gitlab-ci.yml
- template: Security/Container-Scanning.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml
- template: Security/License-Scanning.gitlab-ci.yml
- template: Security/Secret-Detection.gitlab-ci.yml
......@@ -257,25 +256,6 @@ dast:
variables:
DAST_VERSION: latest
# Run the container scanning security checks.
# Currently set to manual because we do not believe it adds anything to the current
# setup of Portal.
container_scanning:
extends:
- .build_cached
- .gitlab_reporter
rules:
- if: $CI_PIPELINE_SOURCE == "trigger" ||
$CI_MERGE_REQUEST_EVENT_TYPE == "merge_train"
when: never
- if: $CI_COMMIT_BRANCH == "master" ||
$CI_COMMIT_BRANCH == "development"
when: manual
stage: gitlab reports
before_script:
- export DOCKER_USER=$CI_REGISTRY_USER
- export DOCKER_PASSWORD=$CI_REGISTRY_PASSWORD
# License scanning reporter for checking the licenses of dependencies.
license_scanning:
extends:
......@@ -325,6 +305,7 @@ deploy:
- if: $CI_PIPELINE_SOURCE == "trigger" ||
$CI_MERGE_REQUEST_EVENT_TYPE == "merge_train"
when: never
- if: $CI_COMMIT_BRANCH == "master"
- if: $CI_COMMIT_BRANCH == "master" ||
$CI_COMMIT_BRANCH == "development" # TODO TEMP
when: manual
......@@ -8,15 +8,10 @@ version = "1.0.0"
val javaVersion = JavaVersion.VERSION_11
val labradoorVersion = "1.0.7-SNAPSHOT9"
val labradoorVersion = "1.0.8-SNAPSHOT3"
val libradorVersion = "1.0.3-SNAPSHOT7"
val springBootVersion: String = "2.5.2"
val hibernateVersion = "5.4.8.Final"
val lombokVersion = "1.18.20"
val springDocVersion = "1.2.32"
val jacksonVersion = "2.12.3"
val commonsVersion = "3.2.2"
val sentryVersion = "1.7.30"
val jaegerVersion = "3.1.2"
val openCSVVersion = "5.5"
// The repositories used to lookup dependencies.
......@@ -212,25 +207,26 @@ dependencies {
implementation("com.h2database:h2:1.4.200")
// Generic Spring Boot starter dependencies
implementation("org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion")
implementation("org.springframework.boot:spring-boot-starter-webflux:$springBootVersion")
implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
implementation("org.springframework.boot:spring-boot-starter-validation:$springBootVersion")
implementation("org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion")
compileOnly("org.springframework.boot:spring-boot-devtools:$springBootVersion")
implementation("org.springframework.boot:spring-boot-starter")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
compileOnly("org.springframework.boot:spring-boot-devtools")
// Explicitly declare spring-web version against vulnerabilities
implementation("org.springframework:spring-web:5.3.8")
implementation("org.springframework:spring-web")
// Spring Boot security dependencies
implementation("org.springframework.boot:spring-boot-starter-security:$springBootVersion")
implementation("org.thymeleaf.extras:thymeleaf-extras-springsecurity4:3.0.4.RELEASE")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.thymeleaf.extras:thymeleaf-extras-springsecurity5")
// Thymeleaf layout dialect
implementation("nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:2.5.3")
implementation("nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect")
// Webjars
implementation("org.webjars:webjars-locator-core:0.47")
implementation("org.webjars:webjars-locator-core")
implementation("org.webjars:jquery:3.6.0")
implementation("org.webjars:font-awesome:5.15.3")
......@@ -238,35 +234,40 @@ dependencies {
implementation("commons-collections:commons-collections:$commonsVersion")
// Jackson core specific version for dependency vulnerabilities check
implementation("com.fasterxml.jackson.core:jackson-core:$jacksonVersion")
implementation("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion")
implementation("com.fasterxml.jackson.core:jackson-core")
implementation("com.fasterxml.jackson.core:jackson-databind")
// Dependency for mapping one data class to another
implementation("org.modelmapper:modelmapper:2.3.9")
// Test dependencies
testImplementation("org.springframework.boot:spring-boot-starter-test:$springBootVersion") {
testImplementation("org.springframework.boot:spring-boot-starter-test") {
exclude("junit", "junit")
}
testImplementation("org.springframework.security:spring-security-test:5.5.1") {
testImplementation("org.springframework.security:spring-security-test") {
exclude("junit", "junit")
}
testImplementation("org.junit.jupiter:junit-jupiter:5.6.2")
testImplementation("org.junit.jupiter:junit-jupiter")
//runtimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.0-M1")
testImplementation("org.apache.httpcomponents:httpclient:4.5.13")
testImplementation("org.apache.httpcomponents:httpclient")
// Lombok for generation of builder pattern, getters, setters, constructors, etc.
compileOnly("org.projectlombok:lombok:$lombokVersion")
testCompileOnly("org.projectlombok:lombok:$lombokVersion")
annotationProcessor("org.projectlombok:lombok:$lombokVersion")
testAnnotationProcessor("org.projectlombok:lombok:$lombokVersion")
compileOnly("org.projectlombok:lombok")
testCompileOnly("org.projectlombok:lombok")
annotationProcessor("org.projectlombok:lombok")
testAnnotationProcessor("org.projectlombok:lombok")
// Sentry for writing error logs to a server for developer access
implementation("io.sentry:sentry-spring:$sentryVersion")
implementation("io.sentry:sentry-spring-boot-starter:5.0.1")
implementation("io.sentry:sentry-logback:5.0.1")
// open CSV
implementation("com.opencsv:opencsv:$openCSVVersion")
// Jaeger
implementation("io.opentracing.contrib:opentracing-spring-jaeger-starter:$jaegerVersion")
implementation("io.opentracing.contrib:opentracing-spring-jaeger-web-starter:$jaegerVersion")
}
......@@ -17,69 +17,58 @@
*/
package nl.tudelft.portal.config;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.reactive.function.client.ClientRequest;
import io.sentry.DefaultSentryClientFactory;
import io.sentry.SentryClient;
import io.sentry.dsn.Dsn;
import io.sentry.event.helper.ContextBuilderHelper;
import io.sentry.event.helper.ForwardedAddressResolver;
import io.sentry.event.helper.HttpEventBuilderHelper;
import io.sentry.spring.SentryExceptionResolver;
import io.sentry.spring.SentryServletContextInitializer;
import io.opentracing.Span;
import io.opentracing.contrib.spring.web.client.WebClientSpanDecorator;
import io.opentracing.contrib.web.servlet.filter.ServletFilterSpanDecorator;
@Configuration
@Profile("production")
public class SentryConfig {
public class JaegerConfig {
public static class CustomSentryClientFactory extends DefaultSentryClientFactory {
/**
* Enable the ForwardedAddressResolver so we can see actual IPs in Sentry for Portal, which is hosted
* behind a proxy.
*
* See: https://docs.sentry.io/clients/java/config/#custom-functionality
*
* @param dsn URI can be found in Sentry settings (given appropriate access)
* @return a new Sentry Client
*/
@Bean
public WebClientSpanDecorator customWebClientSpanDecorator() {
return new WebClientSpanDecorator.StandardTags() {
@Override
public SentryClient createSentryClient(final Dsn dsn) {
final SentryClient sentryClient = new SentryClient(createConnection(dsn), getContextManager(dsn));
// Create and use the ForwardedAddressResolver, which will use the
// X-FORWARDED-FOR header for the remote address if it exists
final ForwardedAddressResolver addressResolver = new ForwardedAddressResolver();
sentryClient.addBuilderHelper(new HttpEventBuilderHelper(addressResolver));
public void onRequest(ClientRequest clientRequest, Span span) {
super.onRequest(clientRequest, span);
sentryClient.addBuilderHelper(new ContextBuilderHelper(sentryClient));
return configureSentryClient(sentryClient, dsn);
span.setOperationName(
"OUT: " + clientRequest.method().name() + " " + clientRequest.url().getPath());
}
};
}
/**
* Register a HandlerExceptionResolver that sends all exceptions to Sentry and then defers all handling to
* the other HandlerExceptionResolvers.
*
* @return the Sentry Exception Resolver
*/
@Bean
public HandlerExceptionResolver sentryExceptionResolver() {
return new SentryExceptionResolver();
public List<ServletFilterSpanDecorator> customServletFilterSpanDecorator() {
return List.of(ServletFilterSpanDecorator.STANDARD_TAGS, new ServletFilterSpanDecorator() {
@Override
public void onRequest(HttpServletRequest httpServletRequest, Span span) {
span.setOperationName(
httpServletRequest.getMethod() + " " + httpServletRequest.getServletPath());
}
/**
* Register a ServletContextInitializer that installs the SentryServletRequestListener so that Sentry
* events contain HTTP request information.
*
* @return the SentryServletContextInitializer
*/
@Bean
public ServletContextInitializer sentryServletContextInitializer() {
return new SentryServletContextInitializer();
@Override
public void onResponse(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, Span span) {
}
@Override
public void onError(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, Throwable exception, Span span) {
}
@Override
public void onTimeout(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, long timeout, Span span) {
}
});
}
}
......@@ -23,6 +23,8 @@ import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import io.sentry.Sentry;
@ControllerAdvice
public class ErrorController {
......@@ -35,6 +37,7 @@ public class ErrorController {
@ExceptionHandler(Exception.class)
public String exception(Exception e) {
e.printStackTrace();
Sentry.captureException(e);
return "error/error";
}
......@@ -42,7 +45,6 @@ public class ErrorController {
/**
* Returns the error page with the "unauthorised" error message.
*
* @param model the model to load data into
* @return the link to the error page
*/
@ResponseStatus(HttpStatus.FORBIDDEN)
......
......@@ -21,4 +21,4 @@
environment=dev
servername=localhost
stacktrace.app.packages=nl.tudelft.portal
factory=nl.tudelft.portal.config.SentryConfig.CustomSentryClientFactory
#factory=nl.tudelft.portal.config.SentryConfig.CustomSentryClientFactory
......@@ -43,7 +43,7 @@
<span class="edition_course" th:text="${role.edition.name}"></span>
</div>
<span class="edition_role" th:text="${role.edition.isArchived} ? #{edition.archived} : #{|role.${#strings.toLowerCase(role.type.toString())}|}"></span>
<span class="edition_role" th:text="${role.edition.isArchived} ? #{edition.status.archived} : #{|role.${#strings.toLowerCase(role.type.toString())}|}"></span>
</a>
</div>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment