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

SLS 12 - Spring Interceptor #29

Merged
merged 18 commits into from
Apr 19, 2023
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: 3 additions & 2 deletions .github/workflows/pr_scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,13 @@ jobs:
with:
sarif_file: ${{ steps.scan.outputs.sarif }}
- name: Run Sonar Scanner
run: ./gradlew build sonarqube --info
run: ./gradlew sonar --info
-Dsonar.organization=pagopa
-Dsonar.projectKey=${{ env.PROJECT_KEY }}
-Dsonar.coverage.jacoco.xmlReportPaths=test-coverage/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml
-Dsonar.coverage.jacoco.xmlReportPaths=test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml
-Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*"
-Dsonar.host.url=https://sonarcloud.io
-Dsonar.java.libraries="**/*.jar"
-Dsonar.login=${{ env.SONAR_TOKEN }}
-Dsonar.pullrequest.key=${{ github.event.pull_request.number }}
-Dsonar.pullrequest.branch=${{ github.head_ref }}
Expand Down
1 change: 0 additions & 1 deletion assertion-rest-client-native/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ plugins {
// Apply the java-library plugin for API and implementation separation.
id 'java-library'
id("io.freefair.lombok") version "8.0.0"
/*id("org.openapi.generator") version "6.5.0"*/
}

group 'it.pagopa.tech'
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

31 changes: 30 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ allprojects {
}


dependencies {
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.14.1'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.1'
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformats-text:2.14.1'
implementation 'com.fasterxml.jackson.module:jackson-modules-java8:2.14.1'
implementation 'com.fasterxml.jackson.module:jackson-module-parameter-names:2.14.1'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.14.1'
}

// Settings for allowing reproducible build
tasks.withType(AbstractArchiveTask).configureEach {
preserveFileTimestamps = false
Expand Down Expand Up @@ -144,7 +153,8 @@ subprojects {

sonar {
properties {
property "sonar.sources", "src/main"
property "sonar.sources", "src/main/java"
property "sonar.tests", "src/test/java"
}
}

Expand All @@ -153,6 +163,7 @@ subprojects {
finalizedBy jacocoTestReport // report is always generated after tests run
jacoco {
excludes = ["**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*"]

}
}
jacocoTestReport {
Expand All @@ -163,6 +174,24 @@ subprojects {

}

project(":test-coverage") {
sonar {
skipProject = true
}
sonarqube {
skipProject = true
}
}

project(":redis-storage") {
sonar {
skipProject = true
}
sonarqube {
skipProject = true
}
}

graalvmNative {
binaries {
main {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
package it.pagopa.tech.lollipop.consumer.command;

import it.pagopa.tech.lollipop.consumer.model.CommandResult;
import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest;

/** Interface for the command executing the lollipop request consumption */
public interface LollipopConsumerCommand {
Expand All @@ -11,8 +10,7 @@ public interface LollipopConsumerCommand {
* Command that execute all necessary method for validating a Lollipop request: HTTP message
* verification and Saml assertion verification
*
* @param request LolliPop request
* @return {@link CommandResult} object with result code and message of request verification
*/
CommandResult doExecute(LollipopConsumerRequest request);
CommandResult doExecute();
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* (C)2023 */
package it.pagopa.tech.lollipop.consumer.command;

import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest;

/** Builder class for creating command instance */
public interface LollipopConsumerCommandBuilder {

Expand All @@ -9,5 +11,5 @@ public interface LollipopConsumerCommandBuilder {
*
* @return an instance of {@link LollipopConsumerCommand}
*/
LollipopConsumerCommand createCommand();
LollipopConsumerCommand createCommand(LollipopConsumerRequest lollipopConsumerRequest);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand;
import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder;
import it.pagopa.tech.lollipop.consumer.helper.LollipopConsumerFactoryHelper;
import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest;
import javax.inject.Inject;

/**
Expand All @@ -25,10 +26,11 @@ public LollipopConsumerCommandBuilderImpl(LollipopConsumerFactoryHelper factoryH
* @return an instance of {@link LollipopConsumerCommand}
*/
@Override
public LollipopConsumerCommand createCommand() {
public LollipopConsumerCommand createCommand(LollipopConsumerRequest lollipopConsumerRequest) {
return new LollipopConsumerCommandImpl(
factoryHelper.getHttpMessageVerifierService(),
factoryHelper.getAssertionVerifierService(),
factoryHelper.getRequestValidationService());
factoryHelper.getRequestValidationService(),
lollipopConsumerRequest);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public class LollipopConsumerCommandImpl implements LollipopConsumerCommand {
private final AssertionVerifierService assertionVerifierService;
private final LollipopConsumerRequestValidationService requestValidationService;

private final LollipopConsumerRequest request;

public static final String VERIFICATION_SUCCESS_CODE = "SUCCESS";
public static final String REQUEST_PARAMS_VALIDATION_FAILED =
"REQUEST PARAMS VALIDATION FAILED";
Expand All @@ -28,21 +30,22 @@ public class LollipopConsumerCommandImpl implements LollipopConsumerCommand {
public LollipopConsumerCommandImpl(
HttpMessageVerifierService messageVerifierService,
AssertionVerifierService assertionVerifierService,
LollipopConsumerRequestValidationService requestValidationService) {
LollipopConsumerRequestValidationService requestValidationService,
LollipopConsumerRequest lollipopConsumerRequest) {
this.messageVerifierService = messageVerifierService;
this.assertionVerifierService = assertionVerifierService;
this.requestValidationService = requestValidationService;
this.request = lollipopConsumerRequest;
}

/**
* Command that execute all necessary method for validating a Lollipop request: HTTP message
* verification and Saml assertion verification
*
* @param request LolliPop request
* @return {@link CommandResult} object with result code and message of request verification
*/
@Override
public CommandResult doExecute(LollipopConsumerRequest request) {
public CommandResult doExecute() {

try {
requestValidationService.validateLollipopRequest(request);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
/* (C)2023 */
package it.pagopa.tech.lollipop.consumer.config;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class LollipopConsumerRequestConfig {

@Builder.Default private boolean strictDigestVerify = false;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,43 @@
/* (C)2023 */
package it.pagopa.tech.lollipop.consumer.helper;

import it.pagopa.tech.lollipop.consumer.assertion.AssertionService;
import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory;
import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig;
import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory;
import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider;
import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory;
import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService;
import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService;
import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService;
import it.pagopa.tech.lollipop.consumer.service.impl.AssertionVerifierServiceImpl;
import it.pagopa.tech.lollipop.consumer.service.impl.HttpMessageVerifierServiceImpl;
import it.pagopa.tech.lollipop.consumer.service.impl.LollipopConsumerRequestValidationServiceImpl;
import javax.inject.Inject;

/** Helper class for retrieving instances */
public class LollipopConsumerFactoryHelper {

private final HttpMessageVerifierFactory httpMessageVerifierFactory;
private final IdpCertProviderFactory idpCertProviderFactory;
private final LollipopConsumerRequestValidationService lollipopConsumerRequestValidationService;
private final AssertionServiceFactory assertionServiceFactory;
private IdpCertProvider idpCertProvider;
private AssertionService assertionService;

private HttpMessageVerifierService httpMessageVerifierService;
private AssertionVerifierService assertionVerifierService;
private LollipopConsumerRequestConfig lollipopConsumerRequestConfig;

@Inject
public LollipopConsumerFactoryHelper(
HttpMessageVerifierFactory httpMessageVerifierFactory,
IdpCertProviderFactory idpCertProviderFactory,
AssertionServiceFactory assertionServiceFactory) {
AssertionServiceFactory assertionServiceFactory,
LollipopConsumerRequestValidationService lollipopConsumerRequestValidationService) {
this.httpMessageVerifierFactory = httpMessageVerifierFactory;
this.idpCertProviderFactory = idpCertProviderFactory;
this.assertionServiceFactory = assertionServiceFactory;
this.lollipopConsumerRequestValidationService = lollipopConsumerRequestValidationService;
}

/**
Expand All @@ -36,8 +46,11 @@ public LollipopConsumerFactoryHelper(
* @return an instance of {@link HttpMessageVerifierService}
*/
public HttpMessageVerifierService getHttpMessageVerifierService() {
return new HttpMessageVerifierServiceImpl(
getHttpMessageVerifierFactory().create(), getLollipopConsumerRequestConfig());
return this.httpMessageVerifierService != null
? this.httpMessageVerifierService
: new HttpMessageVerifierServiceImpl(
getHttpMessageVerifierFactory().create(),
getLollipopConsumerRequestConfig());
}

/**
Expand All @@ -46,10 +59,13 @@ public HttpMessageVerifierService getHttpMessageVerifierService() {
* @return an instance of {@link AssertionVerifierService}
*/
public AssertionVerifierService getAssertionVerifierService() {
return new AssertionVerifierServiceImpl(
getIdpCertProviderFactory().create(),
getAssertionServiceFactory().create(),
getLollipopConsumerRequestConfig());

return this.assertionVerifierService != null
? this.assertionVerifierService
: new AssertionVerifierServiceImpl(
createIdpCertProvider(),
createAssertionService(),
getLollipopConsumerRequestConfig());
}

public HttpMessageVerifierFactory getHttpMessageVerifierFactory() {
Expand All @@ -65,10 +81,39 @@ public AssertionServiceFactory getAssertionServiceFactory() {
}

public LollipopConsumerRequestConfig getLollipopConsumerRequestConfig() {
return LollipopConsumerRequestConfig.builder().build();
return lollipopConsumerRequestConfig != null
? lollipopConsumerRequestConfig
: createDefaultConfig();
}

private synchronized LollipopConsumerRequestConfig createDefaultConfig() {

if (this.lollipopConsumerRequestConfig == null) {
this.lollipopConsumerRequestConfig = LollipopConsumerRequestConfig.builder().build();
}

return this.lollipopConsumerRequestConfig;
}

private synchronized IdpCertProvider createIdpCertProvider() {

if (this.idpCertProvider == null) {
this.idpCertProvider = getIdpCertProviderFactory().create();
}

return this.idpCertProvider;
}

private synchronized AssertionService createAssertionService() {

if (this.assertionService == null) {
this.assertionService = getAssertionServiceFactory().create();
}

return this.assertionService;
}

public LollipopConsumerRequestValidationService getRequestValidationService() {
return new LollipopConsumerRequestValidationServiceImpl(getLollipopConsumerRequestConfig());
return lollipopConsumerRequestValidationService;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,23 @@
import java.io.StringReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import javax.inject.Inject;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import lombok.extern.java.Log;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

@Log
/** Standard implementation of {@link AssertionVerifierService} */
public class AssertionVerifierServiceImpl implements AssertionVerifierService {

Expand Down Expand Up @@ -269,6 +273,11 @@ private String calculateThumbprint(String inResponseToAlgorithm, String publicKe
throws AssertionThumbprintException {
Base64URL thumbprint;
try {
try {
publicKey = new String(Base64.getDecoder().decode(publicKey));
} catch (Exception e) {
log.log(Level.FINE, "Key not in Base64");
}
thumbprint = ThumbprintUtils.compute(inResponseToAlgorithm, JWK.parse(publicKey));
} catch (JOSEException | ParseException e) {
String errMsg = String.format("Can not calculate JwkThumbprint: %S", e.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest;
import it.pagopa.tech.lollipop.consumer.model.RSAPublicKey;
import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService;
import java.util.Base64;
import java.util.Map;
import java.util.regex.Pattern;

Expand All @@ -30,7 +31,6 @@ public void validateLollipopRequest(LollipopConsumerRequest request)
Map<String, String> headerParams = request.getHeaderParams();

validatePublicKey(headerParams.get(this.config.getPublicKeyHeader()));

validateAssertionRefHeader(headerParams.get(this.config.getAssertionRefHeader()));
validateAssertionTypeHeader(headerParams.get(this.config.getAssertionTypeHeader()));
validateUserIdHeader(headerParams.get(this.config.getUserIdHeader()));
Expand All @@ -49,6 +49,12 @@ private void validatePublicKey(String publicKey)
"Missing Public Key Header");
}

try {
publicKey = new String(Base64.getDecoder().decode(publicKey.getBytes()));
} catch (Exception e) {
//
}

if (isNotValidPublicKey(publicKey, ECPublicKey.class)
&& isNotValidPublicKey(publicKey, RSAPublicKey.class)) {
throw new LollipopRequestContentValidationException(
Expand Down
Loading