From 7b8efc4bf5db65805b880dd863142580888b2a6f Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Mon, 3 Apr 2023 10:07:32 +0200 Subject: [PATCH 001/403] [SLS-4] Created gradle project skeleton --- .gitattributes | 9 + .gitignore | 11 + assertion-rest-client-native/build.gradle | 32 +++ build.gradle | 36 +++ core/build.gradle | 31 +++ gradlew | 234 ++++++++++++++++++ gradlew.bat | 89 +++++++ http-verifier/build.gradle | 32 +++ .../build.gradle | 32 +++ redis-storage/build.gradle | 32 +++ settings.gradle | 18 ++ 11 files changed, 556 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 assertion-rest-client-native/build.gradle create mode 100644 build.gradle create mode 100644 core/build.gradle create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 http-verifier/build.gradle create mode 100644 identity-service-rest-client-native/build.gradle create mode 100644 redis-storage/build.gradle create mode 100644 settings.gradle diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..097f9f98 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,9 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# Linux start script should use lf +/gradlew text eol=lf + +# These are Windows script files and should use crlf +*.bat text eol=crlf + diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..7b524df4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore IntelliJ +.idea + +# Ignore Gradle +gradle + +# Ignore Gradle build output directory +build diff --git a/assertion-rest-client-native/build.gradle b/assertion-rest-client-native/build.gradle new file mode 100644 index 00000000..41547144 --- /dev/null +++ b/assertion-rest-client-native/build.gradle @@ -0,0 +1,32 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Java library project to get you started. + * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle + * User Manual available at https://docs.gradle.org/8.0.2/userguide/building_java_projects.html + */ + + +plugins { + // Apply the java-library plugin for API and implementation separation. + id 'java-library' + id("io.freefair.lombok") version "8.0.0-rc4" +} + +group 'it.pagopa.commons' + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + implementation project(path: ':core') + // Use JUnit Jupiter for testing. + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' +} + +tasks.named('test') { + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..b291b677 --- /dev/null +++ b/build.gradle @@ -0,0 +1,36 @@ +plugins { + id 'java' +} + +repositories { + mavenCentral() + gradlePluginPortal() +} + +allprojects { + version = "1.0.0-SNAPSHOT" + group = 'it.pagopa' +} + +subprojects { + + apply plugin: 'java' + apply plugin: 'maven-publish' + + java { + withSourcesJar() + withJavadocJar() + } + + publishing { + publications { + maven(MavenPublication) { + groupId project.group + artifactId project.name + version project.version + from components.java + } + } + } + +} \ No newline at end of file diff --git a/core/build.gradle b/core/build.gradle new file mode 100644 index 00000000..aa993003 --- /dev/null +++ b/core/build.gradle @@ -0,0 +1,31 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Java library project to get you started. + * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle + * User Manual available at https://docs.gradle.org/8.0.2/userguide/building_java_projects.html + */ + + +plugins { + // Apply the java-library plugin for API and implementation separation. + id 'java-library' + id("io.freefair.lombok") version "8.0.0-rc4" +} + +group 'it.pagopa.commons' + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + // Use JUnit Jupiter for testing. + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' +} + +tasks.named('test') { + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} \ No newline at end of file diff --git a/gradlew b/gradlew new file mode 100644 index 00000000..1b6c7873 --- /dev/null +++ b/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..107acd32 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle new file mode 100644 index 00000000..41547144 --- /dev/null +++ b/http-verifier/build.gradle @@ -0,0 +1,32 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Java library project to get you started. + * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle + * User Manual available at https://docs.gradle.org/8.0.2/userguide/building_java_projects.html + */ + + +plugins { + // Apply the java-library plugin for API and implementation separation. + id 'java-library' + id("io.freefair.lombok") version "8.0.0-rc4" +} + +group 'it.pagopa.commons' + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + implementation project(path: ':core') + // Use JUnit Jupiter for testing. + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' +} + +tasks.named('test') { + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} \ No newline at end of file diff --git a/identity-service-rest-client-native/build.gradle b/identity-service-rest-client-native/build.gradle new file mode 100644 index 00000000..41547144 --- /dev/null +++ b/identity-service-rest-client-native/build.gradle @@ -0,0 +1,32 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Java library project to get you started. + * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle + * User Manual available at https://docs.gradle.org/8.0.2/userguide/building_java_projects.html + */ + + +plugins { + // Apply the java-library plugin for API and implementation separation. + id 'java-library' + id("io.freefair.lombok") version "8.0.0-rc4" +} + +group 'it.pagopa.commons' + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + implementation project(path: ':core') + // Use JUnit Jupiter for testing. + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' +} + +tasks.named('test') { + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} \ No newline at end of file diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle new file mode 100644 index 00000000..41547144 --- /dev/null +++ b/redis-storage/build.gradle @@ -0,0 +1,32 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Java library project to get you started. + * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle + * User Manual available at https://docs.gradle.org/8.0.2/userguide/building_java_projects.html + */ + + +plugins { + // Apply the java-library plugin for API and implementation separation. + id 'java-library' + id("io.freefair.lombok") version "8.0.0-rc4" +} + +group 'it.pagopa.commons' + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + implementation project(path: ':core') + // Use JUnit Jupiter for testing. + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' +} + +tasks.named('test') { + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..2faad5f6 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,18 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user manual at https://docs.gradle.org/8.0.2/userguide/multi_project_builds.html + */ + +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } +} + +rootProject.name = 'eng-lollipop-consumer-java-sdk' +include 'core', 'assertion-rest-client-native', 'http-verifier', 'identity-service-rest-client-native', 'redis-storage' \ No newline at end of file From 2dd910d332f01bb635e8586ec962ec2df6ca2469 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Mon, 3 Apr 2023 10:55:32 +0200 Subject: [PATCH 002/403] [SLS-4] Introduced .dummy for package visibility --- assertion-rest-client-native/src/main/java/.dummy | 0 assertion-rest-client-native/src/main/resources/.dummy | 0 assertion-rest-client-native/src/test/java/.dummy | 0 assertion-rest-client-native/src/test/resources/.dummy | 0 core/src/main/java/.dummy | 0 core/src/main/resources/.dummy | 0 core/src/test/java/.dummy | 0 core/src/test/resources/.dummy | 0 http-verifier/src/main/java/.dummy | 0 http-verifier/src/main/resources/.dummy | 0 http-verifier/src/test/java/.dummy | 0 http-verifier/src/test/resources/.dummy | 0 identity-service-rest-client-native/src/main/java/.dummy | 0 identity-service-rest-client-native/src/main/resources/.dummy | 0 identity-service-rest-client-native/src/test/java/.dummy | 0 identity-service-rest-client-native/src/test/resources/.dummy | 0 redis-storage/src/main/java/.dummy | 0 redis-storage/src/main/resources/.dummy | 0 redis-storage/src/test/java/.dummy | 0 redis-storage/src/test/resources/.dummy | 0 20 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 assertion-rest-client-native/src/main/java/.dummy create mode 100644 assertion-rest-client-native/src/main/resources/.dummy create mode 100644 assertion-rest-client-native/src/test/java/.dummy create mode 100644 assertion-rest-client-native/src/test/resources/.dummy create mode 100644 core/src/main/java/.dummy create mode 100644 core/src/main/resources/.dummy create mode 100644 core/src/test/java/.dummy create mode 100644 core/src/test/resources/.dummy create mode 100644 http-verifier/src/main/java/.dummy create mode 100644 http-verifier/src/main/resources/.dummy create mode 100644 http-verifier/src/test/java/.dummy create mode 100644 http-verifier/src/test/resources/.dummy create mode 100644 identity-service-rest-client-native/src/main/java/.dummy create mode 100644 identity-service-rest-client-native/src/main/resources/.dummy create mode 100644 identity-service-rest-client-native/src/test/java/.dummy create mode 100644 identity-service-rest-client-native/src/test/resources/.dummy create mode 100644 redis-storage/src/main/java/.dummy create mode 100644 redis-storage/src/main/resources/.dummy create mode 100644 redis-storage/src/test/java/.dummy create mode 100644 redis-storage/src/test/resources/.dummy diff --git a/assertion-rest-client-native/src/main/java/.dummy b/assertion-rest-client-native/src/main/java/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/assertion-rest-client-native/src/main/resources/.dummy b/assertion-rest-client-native/src/main/resources/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/assertion-rest-client-native/src/test/java/.dummy b/assertion-rest-client-native/src/test/java/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/assertion-rest-client-native/src/test/resources/.dummy b/assertion-rest-client-native/src/test/resources/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/core/src/main/java/.dummy b/core/src/main/java/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/core/src/main/resources/.dummy b/core/src/main/resources/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/core/src/test/java/.dummy b/core/src/test/java/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/core/src/test/resources/.dummy b/core/src/test/resources/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/http-verifier/src/main/java/.dummy b/http-verifier/src/main/java/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/http-verifier/src/main/resources/.dummy b/http-verifier/src/main/resources/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/http-verifier/src/test/java/.dummy b/http-verifier/src/test/java/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/http-verifier/src/test/resources/.dummy b/http-verifier/src/test/resources/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/identity-service-rest-client-native/src/main/java/.dummy b/identity-service-rest-client-native/src/main/java/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/identity-service-rest-client-native/src/main/resources/.dummy b/identity-service-rest-client-native/src/main/resources/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/identity-service-rest-client-native/src/test/java/.dummy b/identity-service-rest-client-native/src/test/java/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/identity-service-rest-client-native/src/test/resources/.dummy b/identity-service-rest-client-native/src/test/resources/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/redis-storage/src/main/java/.dummy b/redis-storage/src/main/java/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/redis-storage/src/main/resources/.dummy b/redis-storage/src/main/resources/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/redis-storage/src/test/java/.dummy b/redis-storage/src/test/java/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/redis-storage/src/test/resources/.dummy b/redis-storage/src/test/resources/.dummy new file mode 100644 index 00000000..e69de29b From f09116365b0636bccd5a2b99c4cd797ca346f412 Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 3 Apr 2023 11:51:33 +0200 Subject: [PATCH 003/403] [SLS-5] Add Gradle reproducible build settings. Removed dummy files --- assertion-rest-client-native/src/main/java/.dummy | 0 assertion-rest-client-native/src/main/resources/.dummy | 0 assertion-rest-client-native/src/test/java/.dummy | 0 assertion-rest-client-native/src/test/resources/.dummy | 0 build.gradle | 5 +++++ core/src/main/java/.dummy | 0 core/src/main/resources/.dummy | 0 core/src/test/java/.dummy | 0 core/src/test/resources/.dummy | 0 http-verifier/src/main/java/.dummy | 0 http-verifier/src/main/resources/.dummy | 0 http-verifier/src/test/java/.dummy | 0 http-verifier/src/test/resources/.dummy | 0 identity-service-rest-client-native/src/main/java/.dummy | 0 .../src/main/resources/.dummy | 0 identity-service-rest-client-native/src/test/java/.dummy | 0 .../src/test/resources/.dummy | 0 redis-storage/src/main/java/.dummy | 0 redis-storage/src/main/resources/.dummy | 0 19 files changed, 5 insertions(+) delete mode 100644 assertion-rest-client-native/src/main/java/.dummy delete mode 100644 assertion-rest-client-native/src/main/resources/.dummy delete mode 100644 assertion-rest-client-native/src/test/java/.dummy delete mode 100644 assertion-rest-client-native/src/test/resources/.dummy delete mode 100644 core/src/main/java/.dummy delete mode 100644 core/src/main/resources/.dummy delete mode 100644 core/src/test/java/.dummy delete mode 100644 core/src/test/resources/.dummy delete mode 100644 http-verifier/src/main/java/.dummy delete mode 100644 http-verifier/src/main/resources/.dummy delete mode 100644 http-verifier/src/test/java/.dummy delete mode 100644 http-verifier/src/test/resources/.dummy delete mode 100644 identity-service-rest-client-native/src/main/java/.dummy delete mode 100644 identity-service-rest-client-native/src/main/resources/.dummy delete mode 100644 identity-service-rest-client-native/src/test/java/.dummy delete mode 100644 identity-service-rest-client-native/src/test/resources/.dummy delete mode 100644 redis-storage/src/main/java/.dummy delete mode 100644 redis-storage/src/main/resources/.dummy diff --git a/assertion-rest-client-native/src/main/java/.dummy b/assertion-rest-client-native/src/main/java/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/assertion-rest-client-native/src/main/resources/.dummy b/assertion-rest-client-native/src/main/resources/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/assertion-rest-client-native/src/test/java/.dummy b/assertion-rest-client-native/src/test/java/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/assertion-rest-client-native/src/test/resources/.dummy b/assertion-rest-client-native/src/test/resources/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/build.gradle b/build.gradle index b291b677..00c3b096 100644 --- a/build.gradle +++ b/build.gradle @@ -12,6 +12,11 @@ allprojects { group = 'it.pagopa' } +tasks.withType(AbstractArchiveTask).configureEach { + preserveFileTimestamps = false + reproducibleFileOrder = true +} + subprojects { apply plugin: 'java' diff --git a/core/src/main/java/.dummy b/core/src/main/java/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/core/src/main/resources/.dummy b/core/src/main/resources/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/core/src/test/java/.dummy b/core/src/test/java/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/core/src/test/resources/.dummy b/core/src/test/resources/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/http-verifier/src/main/java/.dummy b/http-verifier/src/main/java/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/http-verifier/src/main/resources/.dummy b/http-verifier/src/main/resources/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/http-verifier/src/test/java/.dummy b/http-verifier/src/test/java/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/http-verifier/src/test/resources/.dummy b/http-verifier/src/test/resources/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/identity-service-rest-client-native/src/main/java/.dummy b/identity-service-rest-client-native/src/main/java/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/identity-service-rest-client-native/src/main/resources/.dummy b/identity-service-rest-client-native/src/main/resources/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/identity-service-rest-client-native/src/test/java/.dummy b/identity-service-rest-client-native/src/test/java/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/identity-service-rest-client-native/src/test/resources/.dummy b/identity-service-rest-client-native/src/test/resources/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/redis-storage/src/main/java/.dummy b/redis-storage/src/main/java/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/redis-storage/src/main/resources/.dummy b/redis-storage/src/main/resources/.dummy deleted file mode 100644 index e69de29b..00000000 From bbd00665ca8598d4aa549faa20494c496460569d Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 3 Apr 2023 13:24:56 +0200 Subject: [PATCH 004/403] [SLS-5] Added checksum generation for jar file, extraction for all available plugins and added reproducible build settings for subprojects --- build.gradle | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/build.gradle b/build.gradle index 00c3b096..17effb85 100644 --- a/build.gradle +++ b/build.gradle @@ -12,11 +12,24 @@ allprojects { group = 'it.pagopa' } +// Settings for allowing reproducible build tasks.withType(AbstractArchiveTask).configureEach { preserveFileTimestamps = false reproducibleFileOrder = true } +// Generate MD5 checksum on eng-lollipop-consumer-java-sdk jar file +jar.doLast { task -> + ant.checksum file: task.archivePath +} + +// Print all available plugins +task showPlugins { + project.plugins.each { + println it.getClass().name + } +} + subprojects { apply plugin: 'java' @@ -27,6 +40,12 @@ subprojects { withJavadocJar() } + // Settings for allowing reproducible build + tasks.withType(AbstractArchiveTask).configureEach { + preserveFileTimestamps = false + reproducibleFileOrder = true + } + publishing { publications { maven(MavenPublication) { From c54f10315fbfca3e47ad5a00c96040df9433bafa Mon Sep 17 00:00:00 2001 From: svariant Date: Mon, 3 Apr 2023 14:23:14 +0200 Subject: [PATCH 005/403] [SLS-6] Configured build.gradle for native build with GraavLM --- build.gradle | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 00c3b096..97c38c54 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,6 @@ plugins { id 'java' + id 'org.graalvm.buildtools.native' version '0.9.20' } repositories { @@ -21,6 +22,7 @@ subprojects { apply plugin: 'java' apply plugin: 'maven-publish' + apply plugin: 'org.graalvm.buildtools.native' java { withSourcesJar() @@ -38,4 +40,15 @@ subprojects { } } -} \ No newline at end of file +} + +graalvmNative { + binaries { + main { + sharedLibrary=true + } + } +} + + + From 8e2c267bd335664383a2c266f13f8a0c086ffece Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Mon, 3 Apr 2023 14:41:09 +0200 Subject: [PATCH 006/403] [SLS-30] Introducing spotless plugin for style evaluation --- build.gradle | 86 +++++++++++++++++++++++++++++++++---------------- settings.gradle | 10 +++--- 2 files changed, 64 insertions(+), 32 deletions(-) diff --git a/build.gradle b/build.gradle index 00c3b096..617f20c1 100644 --- a/build.gradle +++ b/build.gradle @@ -1,41 +1,73 @@ plugins { - id 'java' + id 'java' + id("com.diffplug.spotless") version "6.17.0" } repositories { - mavenCentral() - gradlePluginPortal() + mavenCentral() + gradlePluginPortal() } allprojects { - version = "1.0.0-SNAPSHOT" - group = 'it.pagopa' + version = "1.0.0-SNAPSHOT" + group = 'it.pagopa' } tasks.withType(AbstractArchiveTask).configureEach { - preserveFileTimestamps = false - reproducibleFileOrder = true + preserveFileTimestamps = false + reproducibleFileOrder = true +} + +tasks.withType(JavaCompile) { + options.compilerArgs.add('-Xlint:all') +} + +spotless { + // optional: limit format enforcement to just the files changed by this feature branch + ratchetFrom 'origin/main' + + format 'misc', { + // define the files to apply `misc` to + target '*.gradle', '*.md', '.gitignore' + + // define the steps to apply to those files + trimTrailingWhitespace() + indentWithTabs() // or spaces. Takes an integer argument if you don't like 4 + endWithNewline() + } + java { + // don't need to set target, it is inferred from java + + // apply a specific flavor of google-java-format + googleJavaFormat('1.11.0').aosp().reflowLongStrings() + // fix formatting of type annotations + formatAnnotations() + // make sure every file has the following copyright header. + // optionally, Spotless can set copyright years by digging + // through git history (see "license" section below) + licenseHeader '/* (C)$YEAR */' + } } subprojects { - apply plugin: 'java' - apply plugin: 'maven-publish' - - java { - withSourcesJar() - withJavadocJar() - } - - publishing { - publications { - maven(MavenPublication) { - groupId project.group - artifactId project.name - version project.version - from components.java - } - } - } - -} \ No newline at end of file + apply plugin: 'java' + apply plugin: 'maven-publish' + + java { + withSourcesJar() + withJavadocJar() + } + + publishing { + publications { + maven(MavenPublication) { + groupId project.group + artifactId project.name + version project.version + from components.java + } + } + } + +} diff --git a/settings.gradle b/settings.gradle index 2faad5f6..231c70d5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,11 +8,11 @@ */ pluginManagement { - repositories { - mavenCentral() - gradlePluginPortal() - } + repositories { + mavenCentral() + gradlePluginPortal() + } } rootProject.name = 'eng-lollipop-consumer-java-sdk' -include 'core', 'assertion-rest-client-native', 'http-verifier', 'identity-service-rest-client-native', 'redis-storage' \ No newline at end of file +include 'core', 'assertion-rest-client-native', 'http-verifier', 'identity-service-rest-client-native', 'redis-storage' From ac9e4dd63822910f00a5002ee17a7e595b432ad4 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Mon, 3 Apr 2023 14:41:09 +0200 Subject: [PATCH 007/403] [SLS-30] Introducing spotless plugin for style evaluation --- build.gradle | 76 +++++++++++++++++++++++++++++++++++-------------- settings.gradle | 10 +++---- 2 files changed, 59 insertions(+), 27 deletions(-) diff --git a/build.gradle b/build.gradle index 97c38c54..2624fb26 100644 --- a/build.gradle +++ b/build.gradle @@ -1,44 +1,76 @@ plugins { id 'java' id 'org.graalvm.buildtools.native' version '0.9.20' + id("com.diffplug.spotless") version "6.17.0" } repositories { - mavenCentral() - gradlePluginPortal() + mavenCentral() + gradlePluginPortal() } allprojects { - version = "1.0.0-SNAPSHOT" - group = 'it.pagopa' + version = "1.0.0-SNAPSHOT" + group = 'it.pagopa' } tasks.withType(AbstractArchiveTask).configureEach { - preserveFileTimestamps = false - reproducibleFileOrder = true + preserveFileTimestamps = false + reproducibleFileOrder = true +} + +tasks.withType(JavaCompile) { + options.compilerArgs.add('-Xlint:all') +} + +spotless { + // optional: limit format enforcement to just the files changed by this feature branch + ratchetFrom 'origin/main' + + format 'misc', { + // define the files to apply `misc` to + target '*.gradle', '*.md', '.gitignore' + + // define the steps to apply to those files + trimTrailingWhitespace() + indentWithTabs() // or spaces. Takes an integer argument if you don't like 4 + endWithNewline() + } + java { + // don't need to set target, it is inferred from java + + // apply a specific flavor of google-java-format + googleJavaFormat('1.11.0').aosp().reflowLongStrings() + // fix formatting of type annotations + formatAnnotations() + // make sure every file has the following copyright header. + // optionally, Spotless can set copyright years by digging + // through git history (see "license" section below) + licenseHeader '/* (C)$YEAR */' + } } subprojects { - apply plugin: 'java' - apply plugin: 'maven-publish' + apply plugin: 'java' + apply plugin: 'maven-publish' apply plugin: 'org.graalvm.buildtools.native' - java { - withSourcesJar() - withJavadocJar() - } + java { + withSourcesJar() + withJavadocJar() + } - publishing { - publications { - maven(MavenPublication) { - groupId project.group - artifactId project.name - version project.version - from components.java - } - } - } + publishing { + publications { + maven(MavenPublication) { + groupId project.group + artifactId project.name + version project.version + from components.java + } + } + } } diff --git a/settings.gradle b/settings.gradle index 2faad5f6..231c70d5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,11 +8,11 @@ */ pluginManagement { - repositories { - mavenCentral() - gradlePluginPortal() - } + repositories { + mavenCentral() + gradlePluginPortal() + } } rootProject.name = 'eng-lollipop-consumer-java-sdk' -include 'core', 'assertion-rest-client-native', 'http-verifier', 'identity-service-rest-client-native', 'redis-storage' \ No newline at end of file +include 'core', 'assertion-rest-client-native', 'http-verifier', 'identity-service-rest-client-native', 'redis-storage' From d94aeef8ff4a427ac9dedf9c1aab06cec04d8e38 Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 3 Apr 2023 15:06:13 +0200 Subject: [PATCH 008/403] [SLS-5] configured artifact sharing between subproject in order to allow reproducible builds. --- assertion-rest-client-native/build.gradle | 23 +++++++++++++++++++ core/build.gradle | 14 +++++++++++ http-verifier/build.gradle | 23 +++++++++++++++++++ .../build.gradle | 23 +++++++++++++++++++ redis-storage/build.gradle | 23 +++++++++++++++++++ 5 files changed, 106 insertions(+) diff --git a/assertion-rest-client-native/build.gradle b/assertion-rest-client-native/build.gradle index 41547144..bb4d99f8 100644 --- a/assertion-rest-client-native/build.gradle +++ b/assertion-rest-client-native/build.gradle @@ -20,7 +20,30 @@ repositories { mavenCentral() } +configurations { + implementation { + attributes { + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, 'instrumented-core-jar')) + } + } +} + +abstract class InstrumentedJarsRule implements AttributeCompatibilityRule { + + @Override + void execute(CompatibilityCheckDetails details) { + if (details.consumerValue.name == 'instrumented-core-jar' && details.producerValue.name == 'jar') { + details.compatible() + } + } +} + dependencies { + attributesSchema { + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE) { + compatibilityRules.add(InstrumentedJarsRule) + } + } implementation project(path: ':core') // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' diff --git a/core/build.gradle b/core/build.gradle index aa993003..88334cd9 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -20,6 +20,20 @@ repositories { mavenCentral() } +configurations { + instrumentedJars { + canBeConsumed = true + canBeResolved = false + attributes { + attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.LIBRARY)) + attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME)) + attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, Bundling.EXTERNAL)) + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, JavaVersion.current().majorVersion.toInteger()) + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, 'instrumented-core-jar')) + } + } +} + dependencies { // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index 41547144..bb4d99f8 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -20,7 +20,30 @@ repositories { mavenCentral() } +configurations { + implementation { + attributes { + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, 'instrumented-core-jar')) + } + } +} + +abstract class InstrumentedJarsRule implements AttributeCompatibilityRule { + + @Override + void execute(CompatibilityCheckDetails details) { + if (details.consumerValue.name == 'instrumented-core-jar' && details.producerValue.name == 'jar') { + details.compatible() + } + } +} + dependencies { + attributesSchema { + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE) { + compatibilityRules.add(InstrumentedJarsRule) + } + } implementation project(path: ':core') // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' diff --git a/identity-service-rest-client-native/build.gradle b/identity-service-rest-client-native/build.gradle index 41547144..bb4d99f8 100644 --- a/identity-service-rest-client-native/build.gradle +++ b/identity-service-rest-client-native/build.gradle @@ -20,7 +20,30 @@ repositories { mavenCentral() } +configurations { + implementation { + attributes { + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, 'instrumented-core-jar')) + } + } +} + +abstract class InstrumentedJarsRule implements AttributeCompatibilityRule { + + @Override + void execute(CompatibilityCheckDetails details) { + if (details.consumerValue.name == 'instrumented-core-jar' && details.producerValue.name == 'jar') { + details.compatible() + } + } +} + dependencies { + attributesSchema { + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE) { + compatibilityRules.add(InstrumentedJarsRule) + } + } implementation project(path: ':core') // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle index 41547144..bb4d99f8 100644 --- a/redis-storage/build.gradle +++ b/redis-storage/build.gradle @@ -20,7 +20,30 @@ repositories { mavenCentral() } +configurations { + implementation { + attributes { + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, 'instrumented-core-jar')) + } + } +} + +abstract class InstrumentedJarsRule implements AttributeCompatibilityRule { + + @Override + void execute(CompatibilityCheckDetails details) { + if (details.consumerValue.name == 'instrumented-core-jar' && details.producerValue.name == 'jar') { + details.compatible() + } + } +} + dependencies { + attributesSchema { + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE) { + compatibilityRules.add(InstrumentedJarsRule) + } + } implementation project(path: ':core') // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' From 7d5aa9983d4f03373d83ef11342dae256827f3a0 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Mon, 3 Apr 2023 15:48:46 +0200 Subject: [PATCH 009/403] [SLS-30] Upgraded spotless config and subprojects apply. Defined javac compiler -Xlint config. --- build.gradle | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/build.gradle b/build.gradle index 2624fb26..9402f4c1 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,8 @@ plugins { - id 'java' - id 'org.graalvm.buildtools.native' version '0.9.20' + id 'java' + id 'org.graalvm.buildtools.native' version '0.9.20' id("com.diffplug.spotless") version "6.17.0" + id("nebula.lint") version "18.0.3" } repositories { @@ -12,6 +13,9 @@ repositories { allprojects { version = "1.0.0-SNAPSHOT" group = 'it.pagopa' + apply plugin: 'com.diffplug.spotless' + apply plugin: 'nebula.lint' + gradleLint.rules = ['all-dependency'] } tasks.withType(AbstractArchiveTask).configureEach { @@ -54,7 +58,8 @@ subprojects { apply plugin: 'java' apply plugin: 'maven-publish' - apply plugin: 'org.graalvm.buildtools.native' + apply plugin: 'org.graalvm.buildtools.native' + java { withSourcesJar() @@ -75,12 +80,9 @@ subprojects { } graalvmNative { - binaries { - main { - sharedLibrary=true - } - } + binaries { + main { + sharedLibrary=true + } + } } - - - From 46be394a484bf2bcb030af4f9e2b494e0a75ec4e Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Mon, 3 Apr 2023 16:01:03 +0200 Subject: [PATCH 010/403] [SLS-5] Upgraded rep-build config to determine fixed java version --- build.gradle | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index 17effb85..e2232130 100644 --- a/build.gradle +++ b/build.gradle @@ -10,6 +10,8 @@ repositories { allprojects { version = "1.0.0-SNAPSHOT" group = 'it.pagopa' + sourceCompatibility = '11' + targetCompatibility = '11' } // Settings for allowing reproducible build @@ -18,18 +20,6 @@ tasks.withType(AbstractArchiveTask).configureEach { reproducibleFileOrder = true } -// Generate MD5 checksum on eng-lollipop-consumer-java-sdk jar file -jar.doLast { task -> - ant.checksum file: task.archivePath -} - -// Print all available plugins -task showPlugins { - project.plugins.each { - println it.getClass().name - } -} - subprojects { apply plugin: 'java' @@ -46,6 +36,12 @@ subprojects { reproducibleFileOrder = true } + + // Generate MD5 checksum on eng-lollipop-consumer-java-sdk jar file + jar.doLast { task -> + ant.checksum file: task.archivePath + } + publishing { publications { maven(MavenPublication) { From c1991235aec517e69c0061977b0a6a013666b918 Mon Sep 17 00:00:00 2001 From: svariant Date: Mon, 3 Apr 2023 17:26:14 +0200 Subject: [PATCH 011/403] [SLS-7] Defined core package skeleton and relative interfaces --- .../common/lc/assertion/AssertionService.java | 8 ++++++ .../lc/assertion/AssertionServiceFactory.java | 6 +++++ .../lc/assertion/client/AssertionClient.java | 8 ++++++ .../client/AssertionClientProvider.java | 6 +++++ .../impl/AssertionServiceFactoryImplStub.java | 15 +++++++++++ .../impl/AssertionServiceImplStub.java | 16 ++++++++++++ .../assertion/storage/AssertionStorage.java | 10 +++++++ .../storage/AssertionStorageProvider.java | 8 ++++++ .../lc/command/LollipopConsumerCommand.java | 9 +++++++ .../LollipopConsumerCommandBuilder.java | 6 +++++ ...ollipopConsumerCommandBuilderImplStub.java | 12 +++++++++ .../impl/LollipopConsumerCommandImplStub.java | 12 +++++++++ .../LollipopConsumerFactoryHelperStub.java | 26 +++++++++++++++++++ .../lc/http_verifier/HttpMessageVerifier.java | 10 +++++++ .../HttpMessageVerifierFactory.java | 6 +++++ .../spid/common/lc/idp/IdpCertProvider.java | 7 +++++ .../common/lc/idp/IdpCertProviderFactory.java | 6 +++++ .../common/lc/idp/client/IdpCertClient.java | 8 ++++++ .../lc/idp/client/IdpCertClientProvider.java | 6 +++++ .../impl/IdpCertProviderFactoryImplStub.java | 16 ++++++++++++ .../lc/idp/impl/IdpCertProviderImplStub.java | 15 +++++++++++ .../common/lc/idp/storage/IdpCertStorage.java | 13 ++++++++++ .../idp/storage/IdpCertStorageProvider.java | 7 +++++ .../spid/common/lc/model/CommandResult.java | 12 +++++++++ .../spid/common/lc/model/IdpCertData.java | 14 ++++++++++ .../lc/model/LollipopConsumerRequest.java | 14 ++++++++++ .../spid/common/lc/model/SamlAssertion.java | 13 ++++++++++ .../lc/service/AssertionVerifierService.java | 8 ++++++ .../service/HttpMessageVerifierService.java | 8 ++++++ .../AssertionVerifierServiceImplStub.java | 26 +++++++++++++++++++ .../HttpMessageVerifierServiceImplStub.java | 15 +++++++++++ 31 files changed, 346 insertions(+) create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/assertion/AssertionService.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/assertion/AssertionServiceFactory.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/assertion/client/AssertionClient.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/assertion/client/AssertionClientProvider.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/assertion/impl/AssertionServiceFactoryImplStub.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/assertion/impl/AssertionServiceImplStub.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/assertion/storage/AssertionStorage.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/assertion/storage/AssertionStorageProvider.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/command/LollipopConsumerCommand.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/command/LollipopConsumerCommandBuilder.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/command/impl/LollipopConsumerCommandBuilderImplStub.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/command/impl/LollipopConsumerCommandImplStub.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/helper/LollipopConsumerFactoryHelperStub.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/http_verifier/HttpMessageVerifier.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/http_verifier/HttpMessageVerifierFactory.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/idp/IdpCertProvider.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/idp/IdpCertProviderFactory.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/idp/client/IdpCertClient.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/idp/client/IdpCertClientProvider.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/idp/impl/IdpCertProviderFactoryImplStub.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/idp/impl/IdpCertProviderImplStub.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/idp/storage/IdpCertStorage.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/idp/storage/IdpCertStorageProvider.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/model/CommandResult.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/model/IdpCertData.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/model/LollipopConsumerRequest.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/model/SamlAssertion.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/service/AssertionVerifierService.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/service/HttpMessageVerifierService.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/service/impl/AssertionVerifierServiceImplStub.java create mode 100644 core/src/main/java/it/pagopa/spid/common/lc/service/impl/HttpMessageVerifierServiceImplStub.java diff --git a/core/src/main/java/it/pagopa/spid/common/lc/assertion/AssertionService.java b/core/src/main/java/it/pagopa/spid/common/lc/assertion/AssertionService.java new file mode 100644 index 00000000..bab1a0e9 --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/assertion/AssertionService.java @@ -0,0 +1,8 @@ +package it.pagopa.spid.common.lc.assertion; + +import it.pagopa.spid.common.lc.model.SamlAssertion; + +public interface AssertionService { + + SamlAssertion getAssertion(String jwt, String assertionRef); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/assertion/AssertionServiceFactory.java b/core/src/main/java/it/pagopa/spid/common/lc/assertion/AssertionServiceFactory.java new file mode 100644 index 00000000..63d5aeb8 --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/assertion/AssertionServiceFactory.java @@ -0,0 +1,6 @@ +package it.pagopa.spid.common.lc.assertion; + +public interface AssertionServiceFactory { + + AssertionService create(); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/assertion/client/AssertionClient.java b/core/src/main/java/it/pagopa/spid/common/lc/assertion/client/AssertionClient.java new file mode 100644 index 00000000..78110537 --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/assertion/client/AssertionClient.java @@ -0,0 +1,8 @@ +package it.pagopa.spid.common.lc.assertion.client; + +import it.pagopa.spid.common.lc.model.SamlAssertion; + +public interface AssertionClient { + + SamlAssertion getAssertion(String jwt, String assertionRef); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/assertion/client/AssertionClientProvider.java b/core/src/main/java/it/pagopa/spid/common/lc/assertion/client/AssertionClientProvider.java new file mode 100644 index 00000000..01a2e46a --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/assertion/client/AssertionClientProvider.java @@ -0,0 +1,6 @@ +package it.pagopa.spid.common.lc.assertion.client; + +public interface AssertionClientProvider { + + AssertionClient provideClient(); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/assertion/impl/AssertionServiceFactoryImplStub.java b/core/src/main/java/it/pagopa/spid/common/lc/assertion/impl/AssertionServiceFactoryImplStub.java new file mode 100644 index 00000000..c55a2f6f --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/assertion/impl/AssertionServiceFactoryImplStub.java @@ -0,0 +1,15 @@ +package it.pagopa.spid.common.lc.assertion.impl; + +import it.pagopa.spid.common.lc.assertion.AssertionService; +import it.pagopa.spid.common.lc.assertion.AssertionServiceFactory; +import it.pagopa.spid.common.lc.assertion.client.AssertionClientProvider; +import it.pagopa.spid.common.lc.assertion.storage.AssertionStorageProvider; + +public class AssertionServiceFactoryImplStub implements AssertionServiceFactory { + private AssertionStorageProvider assertionStorageProvider; + private AssertionClientProvider assertionClientProvider; + @Override + public AssertionService create() { + return null; + } +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/assertion/impl/AssertionServiceImplStub.java b/core/src/main/java/it/pagopa/spid/common/lc/assertion/impl/AssertionServiceImplStub.java new file mode 100644 index 00000000..e072f6c8 --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/assertion/impl/AssertionServiceImplStub.java @@ -0,0 +1,16 @@ +package it.pagopa.spid.common.lc.assertion.impl; + +import it.pagopa.spid.common.lc.assertion.AssertionService; +import it.pagopa.spid.common.lc.assertion.client.AssertionClient; +import it.pagopa.spid.common.lc.assertion.storage.AssertionStorage; +import it.pagopa.spid.common.lc.model.SamlAssertion; + +public class AssertionServiceImplStub implements AssertionService { + + private AssertionStorage assertionStorage; + private AssertionClient assertionClient; + @Override + public SamlAssertion getAssertion(String jwt, String assertionRef) { + return null; + } +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/assertion/storage/AssertionStorage.java b/core/src/main/java/it/pagopa/spid/common/lc/assertion/storage/AssertionStorage.java new file mode 100644 index 00000000..19d5d4a1 --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/assertion/storage/AssertionStorage.java @@ -0,0 +1,10 @@ +package it.pagopa.spid.common.lc.assertion.storage; + +import it.pagopa.spid.common.lc.model.SamlAssertion; + +public interface AssertionStorage { + + SamlAssertion getAssertion(String assertionRef); + void saveAssertion(SamlAssertion assertion); + +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/assertion/storage/AssertionStorageProvider.java b/core/src/main/java/it/pagopa/spid/common/lc/assertion/storage/AssertionStorageProvider.java new file mode 100644 index 00000000..1c653c1d --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/assertion/storage/AssertionStorageProvider.java @@ -0,0 +1,8 @@ +package it.pagopa.spid.common.lc.assertion.storage; + +import it.pagopa.spid.common.lc.assertion.AssertionService; + +public interface AssertionStorageProvider { + + AssertionStorage provideStorage(); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/command/LollipopConsumerCommand.java b/core/src/main/java/it/pagopa/spid/common/lc/command/LollipopConsumerCommand.java new file mode 100644 index 00000000..bdc554ea --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/command/LollipopConsumerCommand.java @@ -0,0 +1,9 @@ +package it.pagopa.spid.common.lc.command; + +import it.pagopa.spid.common.lc.model.CommandResult; +import it.pagopa.spid.common.lc.model.LollipopConsumerRequest; + +public interface LollipopConsumerCommand { + + CommandResult doExecute(LollipopConsumerRequest request); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/command/LollipopConsumerCommandBuilder.java b/core/src/main/java/it/pagopa/spid/common/lc/command/LollipopConsumerCommandBuilder.java new file mode 100644 index 00000000..97ccdd30 --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/command/LollipopConsumerCommandBuilder.java @@ -0,0 +1,6 @@ +package it.pagopa.spid.common.lc.command; + +public interface LollipopConsumerCommandBuilder { + + LollipopConsumerCommand createCommand(); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/command/impl/LollipopConsumerCommandBuilderImplStub.java b/core/src/main/java/it/pagopa/spid/common/lc/command/impl/LollipopConsumerCommandBuilderImplStub.java new file mode 100644 index 00000000..2b6819cf --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/command/impl/LollipopConsumerCommandBuilderImplStub.java @@ -0,0 +1,12 @@ +package it.pagopa.spid.common.lc.command.impl; + +import it.pagopa.spid.common.lc.command.LollipopConsumerCommand; +import it.pagopa.spid.common.lc.command.LollipopConsumerCommandBuilder; + +public class LollipopConsumerCommandBuilderImplStub implements LollipopConsumerCommandBuilder { + + @Override + public LollipopConsumerCommand createCommand() { + return null; + } +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/command/impl/LollipopConsumerCommandImplStub.java b/core/src/main/java/it/pagopa/spid/common/lc/command/impl/LollipopConsumerCommandImplStub.java new file mode 100644 index 00000000..c3848bf3 --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/command/impl/LollipopConsumerCommandImplStub.java @@ -0,0 +1,12 @@ +package it.pagopa.spid.common.lc.command.impl; + +import it.pagopa.spid.common.lc.command.LollipopConsumerCommand; +import it.pagopa.spid.common.lc.model.CommandResult; +import it.pagopa.spid.common.lc.model.LollipopConsumerRequest; + +public class LollipopConsumerCommandImplStub implements LollipopConsumerCommand { + @Override + public CommandResult doExecute(LollipopConsumerRequest request) { + return null; + } +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/helper/LollipopConsumerFactoryHelperStub.java b/core/src/main/java/it/pagopa/spid/common/lc/helper/LollipopConsumerFactoryHelperStub.java new file mode 100644 index 00000000..32e05034 --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/helper/LollipopConsumerFactoryHelperStub.java @@ -0,0 +1,26 @@ +package it.pagopa.spid.common.lc.helper; + +import it.pagopa.spid.common.lc.http_verifier.HttpMessageVerifierFactory; +import it.pagopa.spid.common.lc.idp.IdpCertProviderFactory; +import it.pagopa.spid.common.lc.service.AssertionVerifierService; +import it.pagopa.spid.common.lc.service.HttpMessageVerifierService; + +public class LollipopConsumerFactoryHelperStub { + + public HttpMessageVerifierService getHttpMessageVerifierService(){ + return null; + } + + public AssertionVerifierService getAssertionVerifierService(){ + return null; + } + + public HttpMessageVerifierFactory getHttpMessageVerifierFactory(){ + return null; + } + + public IdpCertProviderFactory getIdpCertProviderFactory(){ + return null; + } + +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/http_verifier/HttpMessageVerifier.java b/core/src/main/java/it/pagopa/spid/common/lc/http_verifier/HttpMessageVerifier.java new file mode 100644 index 00000000..8b258b29 --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/http_verifier/HttpMessageVerifier.java @@ -0,0 +1,10 @@ +package it.pagopa.spid.common.lc.http_verifier; + +import java.util.Map; + +public interface HttpMessageVerifier { + + boolean verifyDigest(String digest, String requestBody); + boolean verifyHttpSignature(String signature, String signatureInput, Map parameters); + +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/http_verifier/HttpMessageVerifierFactory.java b/core/src/main/java/it/pagopa/spid/common/lc/http_verifier/HttpMessageVerifierFactory.java new file mode 100644 index 00000000..7ff69636 --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/http_verifier/HttpMessageVerifierFactory.java @@ -0,0 +1,6 @@ +package it.pagopa.spid.common.lc.http_verifier; + +public interface HttpMessageVerifierFactory { + + HttpMessageVerifier create(); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/idp/IdpCertProvider.java b/core/src/main/java/it/pagopa/spid/common/lc/idp/IdpCertProvider.java new file mode 100644 index 00000000..44bd9f3a --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/idp/IdpCertProvider.java @@ -0,0 +1,7 @@ +package it.pagopa.spid.common.lc.idp; + +public interface IdpCertProvider { + + boolean getIdpCertData(String assertionInstant, String entityId); + +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/idp/IdpCertProviderFactory.java b/core/src/main/java/it/pagopa/spid/common/lc/idp/IdpCertProviderFactory.java new file mode 100644 index 00000000..9e6f6579 --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/idp/IdpCertProviderFactory.java @@ -0,0 +1,6 @@ +package it.pagopa.spid.common.lc.idp; + +public interface IdpCertProviderFactory { + + IdpCertProvider create(); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/idp/client/IdpCertClient.java b/core/src/main/java/it/pagopa/spid/common/lc/idp/client/IdpCertClient.java new file mode 100644 index 00000000..fc2af0ba --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/idp/client/IdpCertClient.java @@ -0,0 +1,8 @@ +package it.pagopa.spid.common.lc.idp.client; + +import it.pagopa.spid.common.lc.model.IdpCertData; + +public interface IdpCertClient { + + IdpCertData getCertData(String entityId, String instant); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/idp/client/IdpCertClientProvider.java b/core/src/main/java/it/pagopa/spid/common/lc/idp/client/IdpCertClientProvider.java new file mode 100644 index 00000000..982b341d --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/idp/client/IdpCertClientProvider.java @@ -0,0 +1,6 @@ +package it.pagopa.spid.common.lc.idp.client; + +public interface IdpCertClientProvider { + + IdpCertClient provideClient(); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/idp/impl/IdpCertProviderFactoryImplStub.java b/core/src/main/java/it/pagopa/spid/common/lc/idp/impl/IdpCertProviderFactoryImplStub.java new file mode 100644 index 00000000..e287dc31 --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/idp/impl/IdpCertProviderFactoryImplStub.java @@ -0,0 +1,16 @@ +package it.pagopa.spid.common.lc.idp.impl; + +import it.pagopa.spid.common.lc.idp.IdpCertProvider; +import it.pagopa.spid.common.lc.idp.IdpCertProviderFactory; +import it.pagopa.spid.common.lc.idp.client.IdpCertClientProvider; +import it.pagopa.spid.common.lc.idp.storage.IdpCertStorageProvider; + +public class IdpCertProviderFactoryImplStub implements IdpCertProviderFactory { + + private IdpCertClientProvider idpCertClientProvider; + private IdpCertStorageProvider idpCertStorageProvider; + @Override + public IdpCertProvider create() { + return null; + } +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/idp/impl/IdpCertProviderImplStub.java b/core/src/main/java/it/pagopa/spid/common/lc/idp/impl/IdpCertProviderImplStub.java new file mode 100644 index 00000000..4027df7b --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/idp/impl/IdpCertProviderImplStub.java @@ -0,0 +1,15 @@ +package it.pagopa.spid.common.lc.idp.impl; + +import it.pagopa.spid.common.lc.idp.IdpCertProvider; +import it.pagopa.spid.common.lc.idp.client.IdpCertClient; +import it.pagopa.spid.common.lc.idp.storage.IdpCertStorage; + +public class IdpCertProviderImplStub implements IdpCertProvider { + + private IdpCertClient idpCertClient; + private IdpCertStorage idpCertStorage; + @Override + public boolean getIdpCertData(String assertionInstant, String entityId) { + return false; + } +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/idp/storage/IdpCertStorage.java b/core/src/main/java/it/pagopa/spid/common/lc/idp/storage/IdpCertStorage.java new file mode 100644 index 00000000..91f57434 --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/idp/storage/IdpCertStorage.java @@ -0,0 +1,13 @@ +package it.pagopa.spid.common.lc.idp.storage; + +import it.pagopa.spid.common.lc.model.IdpCertData; + +import java.util.List; + +public interface IdpCertStorage { + + List getTagList(); + void saveTagList(List tagList); + IdpCertData getIdpCertData(String tag); + void saveIdpCertData(String tag); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/idp/storage/IdpCertStorageProvider.java b/core/src/main/java/it/pagopa/spid/common/lc/idp/storage/IdpCertStorageProvider.java new file mode 100644 index 00000000..447404c6 --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/idp/storage/IdpCertStorageProvider.java @@ -0,0 +1,7 @@ +package it.pagopa.spid.common.lc.idp.storage; + + +public interface IdpCertStorageProvider { + + IdpCertStorage provideStorage(); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/model/CommandResult.java b/core/src/main/java/it/pagopa/spid/common/lc/model/CommandResult.java new file mode 100644 index 00000000..c9aa2c8e --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/model/CommandResult.java @@ -0,0 +1,12 @@ +package it.pagopa.spid.common.lc.model; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class CommandResult { + + private String resultCode; + private String resultMessage; +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/model/IdpCertData.java b/core/src/main/java/it/pagopa/spid/common/lc/model/IdpCertData.java new file mode 100644 index 00000000..0a45875c --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/model/IdpCertData.java @@ -0,0 +1,14 @@ +package it.pagopa.spid.common.lc.model; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class IdpCertData { + + private String entityId; + private String tag; + private String certData; + +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/model/LollipopConsumerRequest.java b/core/src/main/java/it/pagopa/spid/common/lc/model/LollipopConsumerRequest.java new file mode 100644 index 00000000..bb48477b --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/model/LollipopConsumerRequest.java @@ -0,0 +1,14 @@ +package it.pagopa.spid.common.lc.model; + +import lombok.Getter; +import lombok.Setter; + +import java.util.Map; + +@Getter +@Setter +public class LollipopConsumerRequest { + private String requestBody; + private Map requestParams; + private Map headerParams; +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/model/SamlAssertion.java b/core/src/main/java/it/pagopa/spid/common/lc/model/SamlAssertion.java new file mode 100644 index 00000000..3d761f0f --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/model/SamlAssertion.java @@ -0,0 +1,13 @@ +package it.pagopa.spid.common.lc.model; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class SamlAssertion { + + private String assertionRef; + private String inResponseTo; + private Long notBefore; +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/spid/common/lc/service/AssertionVerifierService.java new file mode 100644 index 00000000..63a61130 --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/service/AssertionVerifierService.java @@ -0,0 +1,8 @@ +package it.pagopa.spid.common.lc.service; + +import it.pagopa.spid.common.lc.model.LollipopConsumerRequest; + +public interface AssertionVerifierService { + + boolean validateLollipop(LollipopConsumerRequest request); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/service/HttpMessageVerifierService.java b/core/src/main/java/it/pagopa/spid/common/lc/service/HttpMessageVerifierService.java new file mode 100644 index 00000000..205a8754 --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/service/HttpMessageVerifierService.java @@ -0,0 +1,8 @@ +package it.pagopa.spid.common.lc.service; + +import it.pagopa.spid.common.lc.model.LollipopConsumerRequest; + +public interface HttpMessageVerifierService { + + boolean verifyHttpMessage(LollipopConsumerRequest request); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/service/impl/AssertionVerifierServiceImplStub.java b/core/src/main/java/it/pagopa/spid/common/lc/service/impl/AssertionVerifierServiceImplStub.java new file mode 100644 index 00000000..c1d72b6d --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/service/impl/AssertionVerifierServiceImplStub.java @@ -0,0 +1,26 @@ +package it.pagopa.spid.common.lc.service.impl; + +import it.pagopa.spid.common.lc.assertion.AssertionService; +import it.pagopa.spid.common.lc.idp.IdpCertProvider; +import it.pagopa.spid.common.lc.model.IdpCertData; +import it.pagopa.spid.common.lc.model.LollipopConsumerRequest; +import it.pagopa.spid.common.lc.model.SamlAssertion; +import it.pagopa.spid.common.lc.service.AssertionVerifierService; + +public class AssertionVerifierServiceImplStub implements AssertionVerifierService { + + private IdpCertProvider idpCertProvider; + private AssertionService assertion; + @Override + public boolean validateLollipop(LollipopConsumerRequest request) { + return false; + } + + private SamlAssertion getAssertion(String jwt, String assertionRef) { return null; } + private boolean validateAssertionPeriod(String notBefore) { return false; } + private boolean validateThumbprint(LollipopConsumerRequest request, SamlAssertion assertion) { return false; } + private boolean validateInResponseTo(LollipopConsumerRequest request, SamlAssertion assertion) { return false; } + private IdpCertData getIdpCertData(SamlAssertion assertion) { return null; } + private boolean validateSignature(SamlAssertion assertion, IdpCertData idpCertData) { return false; } + +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/service/impl/HttpMessageVerifierServiceImplStub.java b/core/src/main/java/it/pagopa/spid/common/lc/service/impl/HttpMessageVerifierServiceImplStub.java new file mode 100644 index 00000000..5b691b86 --- /dev/null +++ b/core/src/main/java/it/pagopa/spid/common/lc/service/impl/HttpMessageVerifierServiceImplStub.java @@ -0,0 +1,15 @@ +package it.pagopa.spid.common.lc.service.impl; + +import it.pagopa.spid.common.lc.http_verifier.HttpMessageVerifier; +import it.pagopa.spid.common.lc.model.LollipopConsumerRequest; +import it.pagopa.spid.common.lc.service.HttpMessageVerifierService; + +public class HttpMessageVerifierServiceImplStub implements HttpMessageVerifierService { + + private HttpMessageVerifier httpMessageVerifier; + + @Override + public boolean verifyHttpMessage(LollipopConsumerRequest request) { + return false; + } +} From 6858c889e2dd4f7f27b2bcdb1374cd887f3e0dfd Mon Sep 17 00:00:00 2001 From: svariant Date: Mon, 3 Apr 2023 17:26:50 +0200 Subject: [PATCH 012/403] [SLS-7] Added typesafe & mokito dependencies to core module --- core/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/build.gradle b/core/build.gradle index aa993003..560967b8 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -21,8 +21,11 @@ repositories { } dependencies { + implementation 'com.typesafe:config:1.4.2' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + testImplementation 'org.mockito:mockito-core:5.2.0' + testImplementation 'org.mockito:mockito-junit-jupiter:5.2.0' } tasks.named('test') { From af6196476b472498382ff2e16c7af8a33e00457c Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Mon, 3 Apr 2023 19:11:52 +0200 Subject: [PATCH 013/403] [SLS-8] Upgraded rep-build config to determine fixed java version --- .../consumer/assertion/AssertionService.java | 8 ++ .../assertion/AssertionServiceFactory.java | 2 +- .../assertion/client/AssertionClient.java | 8 ++ .../client/AssertionClientProvider.java | 2 +- .../impl/AssertionServiceFactoryImplStub.java | 15 ++ .../impl/AssertionServiceImplStub.java | 16 +++ .../assertion/storage/AssertionStorage.java | 4 +- .../storage/AssertionStorageProvider.java | 6 + .../command/LollipopConsumerCommand.java | 9 ++ .../LollipopConsumerCommandBuilder.java | 2 +- ...ollipopConsumerCommandBuilderImplStub.java | 12 ++ .../impl/LollipopConsumerCommandImplStub.java | 12 ++ .../exception/LollipopDigestException.java | 67 +++++++++ .../LollipopConsumerFactoryHelperStub.java | 10 +- .../http_verifier/HttpMessageVerifier.java | 13 ++ .../HttpMessageVerifierFactory.java | 2 +- .../consumer}/idp/IdpCertProvider.java | 2 +- .../consumer}/idp/IdpCertProviderFactory.java | 2 +- .../consumer/idp/client/IdpCertClient.java | 8 ++ .../idp/client/IdpCertClientProvider.java | 2 +- .../impl/IdpCertProviderFactoryImplStub.java | 16 +++ .../idp/impl/IdpCertProviderImplStub.java | 8 +- .../consumer}/idp/storage/IdpCertStorage.java | 4 +- .../idp/storage/IdpCertStorageProvider.java | 2 +- .../consumer}/model/CommandResult.java | 2 +- .../lollipop/consumer}/model/IdpCertData.java | 2 +- .../model/LollipopConsumerRequest.java | 2 +- .../consumer}/model/SamlAssertion.java | 2 +- .../service/AssertionVerifierService.java | 8 ++ .../service/HttpMessageVerifierService.java | 8 ++ .../AssertionVerifierServiceImplStub.java | 14 +- .../HttpMessageVerifierServiceImplStub.java | 15 ++ .../common/lc/assertion/AssertionService.java | 8 -- .../lc/assertion/client/AssertionClient.java | 8 -- .../impl/AssertionServiceFactoryImplStub.java | 15 -- .../impl/AssertionServiceImplStub.java | 16 --- .../storage/AssertionStorageProvider.java | 8 -- .../lc/command/LollipopConsumerCommand.java | 9 -- ...ollipopConsumerCommandBuilderImplStub.java | 12 -- .../impl/LollipopConsumerCommandImplStub.java | 12 -- .../lc/http_verifier/HttpMessageVerifier.java | 10 -- .../common/lc/idp/client/IdpCertClient.java | 8 -- .../impl/IdpCertProviderFactoryImplStub.java | 16 --- .../lc/service/AssertionVerifierService.java | 8 -- .../service/HttpMessageVerifierService.java | 8 -- .../HttpMessageVerifierServiceImplStub.java | 15 -- http-verifier/build.gradle | 2 + .../verifier/visma/ErrorCodeConverter.java | 24 ++++ .../visma/VismaHttpMessageVerifier.java | 53 +++++++ .../visma/VismaHttpMessageVerifierTest.java | 134 ++++++++++++++++++ redis-storage/src/test/java/.dummy | 0 redis-storage/src/test/resources/.dummy | 0 52 files changed, 466 insertions(+), 185 deletions(-) create mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/AssertionService.java rename core/src/main/java/it/pagopa/{spid/common/lc => common/lollipop/consumer}/assertion/AssertionServiceFactory.java (59%) create mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/client/AssertionClient.java rename core/src/main/java/it/pagopa/{spid/common/lc => common/lollipop/consumer}/assertion/client/AssertionClientProvider.java (57%) create mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java create mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java rename core/src/main/java/it/pagopa/{spid/common/lc => common/lollipop/consumer}/assertion/storage/AssertionStorage.java (53%) create mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/storage/AssertionStorageProvider.java create mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/command/LollipopConsumerCommand.java rename core/src/main/java/it/pagopa/{spid/common/lc => common/lollipop/consumer}/command/LollipopConsumerCommandBuilder.java (65%) create mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplStub.java create mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/command/impl/LollipopConsumerCommandImplStub.java create mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/exception/LollipopDigestException.java rename core/src/main/java/it/pagopa/{spid/common/lc => common/lollipop/consumer}/helper/LollipopConsumerFactoryHelperStub.java (54%) create mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/http_verifier/HttpMessageVerifier.java rename core/src/main/java/it/pagopa/{spid/common/lc => common/lollipop/consumer}/http_verifier/HttpMessageVerifierFactory.java (59%) rename core/src/main/java/it/pagopa/{spid/common/lc => common/lollipop/consumer}/idp/IdpCertProvider.java (69%) rename core/src/main/java/it/pagopa/{spid/common/lc => common/lollipop/consumer}/idp/IdpCertProviderFactory.java (61%) create mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/idp/client/IdpCertClient.java rename core/src/main/java/it/pagopa/{spid/common/lc => common/lollipop/consumer}/idp/client/IdpCertClientProvider.java (59%) create mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java rename core/src/main/java/it/pagopa/{spid/common/lc => common/lollipop/consumer}/idp/impl/IdpCertProviderImplStub.java (51%) rename core/src/main/java/it/pagopa/{spid/common/lc => common/lollipop/consumer}/idp/storage/IdpCertStorage.java (65%) rename core/src/main/java/it/pagopa/{spid/common/lc => common/lollipop/consumer}/idp/storage/IdpCertStorageProvider.java (60%) rename core/src/main/java/it/pagopa/{spid/common/lc => common/lollipop/consumer}/model/CommandResult.java (76%) rename core/src/main/java/it/pagopa/{spid/common/lc => common/lollipop/consumer}/model/IdpCertData.java (77%) rename core/src/main/java/it/pagopa/{spid/common/lc => common/lollipop/consumer}/model/LollipopConsumerRequest.java (83%) rename core/src/main/java/it/pagopa/{spid/common/lc => common/lollipop/consumer}/model/SamlAssertion.java (78%) create mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/service/AssertionVerifierService.java create mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/service/HttpMessageVerifierService.java rename core/src/main/java/it/pagopa/{spid/common/lc => common/lollipop/consumer}/service/impl/AssertionVerifierServiceImplStub.java (65%) create mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java delete mode 100644 core/src/main/java/it/pagopa/spid/common/lc/assertion/AssertionService.java delete mode 100644 core/src/main/java/it/pagopa/spid/common/lc/assertion/client/AssertionClient.java delete mode 100644 core/src/main/java/it/pagopa/spid/common/lc/assertion/impl/AssertionServiceFactoryImplStub.java delete mode 100644 core/src/main/java/it/pagopa/spid/common/lc/assertion/impl/AssertionServiceImplStub.java delete mode 100644 core/src/main/java/it/pagopa/spid/common/lc/assertion/storage/AssertionStorageProvider.java delete mode 100644 core/src/main/java/it/pagopa/spid/common/lc/command/LollipopConsumerCommand.java delete mode 100644 core/src/main/java/it/pagopa/spid/common/lc/command/impl/LollipopConsumerCommandBuilderImplStub.java delete mode 100644 core/src/main/java/it/pagopa/spid/common/lc/command/impl/LollipopConsumerCommandImplStub.java delete mode 100644 core/src/main/java/it/pagopa/spid/common/lc/http_verifier/HttpMessageVerifier.java delete mode 100644 core/src/main/java/it/pagopa/spid/common/lc/idp/client/IdpCertClient.java delete mode 100644 core/src/main/java/it/pagopa/spid/common/lc/idp/impl/IdpCertProviderFactoryImplStub.java delete mode 100644 core/src/main/java/it/pagopa/spid/common/lc/service/AssertionVerifierService.java delete mode 100644 core/src/main/java/it/pagopa/spid/common/lc/service/HttpMessageVerifierService.java delete mode 100644 core/src/main/java/it/pagopa/spid/common/lc/service/impl/HttpMessageVerifierServiceImplStub.java create mode 100644 http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java create mode 100644 http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java create mode 100644 http-verifier/src/test/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java delete mode 100644 redis-storage/src/test/java/.dummy delete mode 100644 redis-storage/src/test/resources/.dummy diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/AssertionService.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/AssertionService.java new file mode 100644 index 00000000..c559d067 --- /dev/null +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/AssertionService.java @@ -0,0 +1,8 @@ +package it.pagopa.common.lollipop.consumer.assertion; + +import it.pagopa.common.lollipop.consumer.model.SamlAssertion; + +public interface AssertionService { + + SamlAssertion getAssertion(String jwt, String assertionRef); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/assertion/AssertionServiceFactory.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/AssertionServiceFactory.java similarity index 59% rename from core/src/main/java/it/pagopa/spid/common/lc/assertion/AssertionServiceFactory.java rename to core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/AssertionServiceFactory.java index 63d5aeb8..0c6da4fc 100644 --- a/core/src/main/java/it/pagopa/spid/common/lc/assertion/AssertionServiceFactory.java +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/AssertionServiceFactory.java @@ -1,4 +1,4 @@ -package it.pagopa.spid.common.lc.assertion; +package it.pagopa.common.lollipop.consumer.assertion; public interface AssertionServiceFactory { diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/client/AssertionClient.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/client/AssertionClient.java new file mode 100644 index 00000000..b50c4be4 --- /dev/null +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/client/AssertionClient.java @@ -0,0 +1,8 @@ +package it.pagopa.common.lollipop.consumer.assertion.client; + +import it.pagopa.common.lollipop.consumer.model.SamlAssertion; + +public interface AssertionClient { + + SamlAssertion getAssertion(String jwt, String assertionRef); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/assertion/client/AssertionClientProvider.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/client/AssertionClientProvider.java similarity index 57% rename from core/src/main/java/it/pagopa/spid/common/lc/assertion/client/AssertionClientProvider.java rename to core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/client/AssertionClientProvider.java index 01a2e46a..3b2dfe79 100644 --- a/core/src/main/java/it/pagopa/spid/common/lc/assertion/client/AssertionClientProvider.java +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/client/AssertionClientProvider.java @@ -1,4 +1,4 @@ -package it.pagopa.spid.common.lc.assertion.client; +package it.pagopa.common.lollipop.consumer.assertion.client; public interface AssertionClientProvider { diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java new file mode 100644 index 00000000..995698f8 --- /dev/null +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java @@ -0,0 +1,15 @@ +package it.pagopa.common.lollipop.consumer.assertion.impl; + +import it.pagopa.common.lollipop.consumer.assertion.AssertionService; +import it.pagopa.common.lollipop.consumer.assertion.AssertionServiceFactory; +import it.pagopa.common.lollipop.consumer.assertion.storage.AssertionStorageProvider; +import it.pagopa.common.lollipop.consumer.assertion.client.AssertionClientProvider; + +public class AssertionServiceFactoryImplStub implements AssertionServiceFactory { + private AssertionStorageProvider assertionStorageProvider; + private AssertionClientProvider assertionClientProvider; + @Override + public AssertionService create() { + return null; + } +} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java new file mode 100644 index 00000000..b619bb7d --- /dev/null +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java @@ -0,0 +1,16 @@ +package it.pagopa.common.lollipop.consumer.assertion.impl; + +import it.pagopa.common.lollipop.consumer.assertion.AssertionService; +import it.pagopa.common.lollipop.consumer.assertion.storage.AssertionStorage; +import it.pagopa.common.lollipop.consumer.assertion.client.AssertionClient; +import it.pagopa.common.lollipop.consumer.model.SamlAssertion; + +public class AssertionServiceImplStub implements AssertionService { + + private AssertionStorage assertionStorage; + private AssertionClient assertionClient; + @Override + public SamlAssertion getAssertion(String jwt, String assertionRef) { + return null; + } +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/assertion/storage/AssertionStorage.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/storage/AssertionStorage.java similarity index 53% rename from core/src/main/java/it/pagopa/spid/common/lc/assertion/storage/AssertionStorage.java rename to core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/storage/AssertionStorage.java index 19d5d4a1..0b544107 100644 --- a/core/src/main/java/it/pagopa/spid/common/lc/assertion/storage/AssertionStorage.java +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/storage/AssertionStorage.java @@ -1,6 +1,6 @@ -package it.pagopa.spid.common.lc.assertion.storage; +package it.pagopa.common.lollipop.consumer.assertion.storage; -import it.pagopa.spid.common.lc.model.SamlAssertion; +import it.pagopa.common.lollipop.consumer.model.SamlAssertion; public interface AssertionStorage { diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/storage/AssertionStorageProvider.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/storage/AssertionStorageProvider.java new file mode 100644 index 00000000..30cc318c --- /dev/null +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/storage/AssertionStorageProvider.java @@ -0,0 +1,6 @@ +package it.pagopa.common.lollipop.consumer.assertion.storage; + +public interface AssertionStorageProvider { + + AssertionStorage provideStorage(); +} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/command/LollipopConsumerCommand.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/command/LollipopConsumerCommand.java new file mode 100644 index 00000000..edf2c1da --- /dev/null +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/command/LollipopConsumerCommand.java @@ -0,0 +1,9 @@ +package it.pagopa.common.lollipop.consumer.command; + +import it.pagopa.common.lollipop.consumer.model.CommandResult; +import it.pagopa.common.lollipop.consumer.model.LollipopConsumerRequest; + +public interface LollipopConsumerCommand { + + CommandResult doExecute(LollipopConsumerRequest request); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/command/LollipopConsumerCommandBuilder.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/command/LollipopConsumerCommandBuilder.java similarity index 65% rename from core/src/main/java/it/pagopa/spid/common/lc/command/LollipopConsumerCommandBuilder.java rename to core/src/main/java/it/pagopa/common/lollipop/consumer/command/LollipopConsumerCommandBuilder.java index 97ccdd30..450df727 100644 --- a/core/src/main/java/it/pagopa/spid/common/lc/command/LollipopConsumerCommandBuilder.java +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/command/LollipopConsumerCommandBuilder.java @@ -1,4 +1,4 @@ -package it.pagopa.spid.common.lc.command; +package it.pagopa.common.lollipop.consumer.command; public interface LollipopConsumerCommandBuilder { diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplStub.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplStub.java new file mode 100644 index 00000000..b6ceeb77 --- /dev/null +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplStub.java @@ -0,0 +1,12 @@ +package it.pagopa.common.lollipop.consumer.command.impl; + +import it.pagopa.common.lollipop.consumer.command.LollipopConsumerCommand; +import it.pagopa.common.lollipop.consumer.command.LollipopConsumerCommandBuilder; + +public class LollipopConsumerCommandBuilderImplStub implements LollipopConsumerCommandBuilder { + + @Override + public LollipopConsumerCommand createCommand() { + return null; + } +} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/command/impl/LollipopConsumerCommandImplStub.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/command/impl/LollipopConsumerCommandImplStub.java new file mode 100644 index 00000000..5ba4ab9f --- /dev/null +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/command/impl/LollipopConsumerCommandImplStub.java @@ -0,0 +1,12 @@ +package it.pagopa.common.lollipop.consumer.command.impl; + +import it.pagopa.common.lollipop.consumer.command.LollipopConsumerCommand; +import it.pagopa.common.lollipop.consumer.model.CommandResult; +import it.pagopa.common.lollipop.consumer.model.LollipopConsumerRequest; + +public class LollipopConsumerCommandImplStub implements LollipopConsumerCommand { + @Override + public CommandResult doExecute(LollipopConsumerRequest request) { + return null; + } +} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/exception/LollipopDigestException.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/exception/LollipopDigestException.java new file mode 100644 index 00000000..b0624c00 --- /dev/null +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/exception/LollipopDigestException.java @@ -0,0 +1,67 @@ +package it.pagopa.common.lollipop.consumer.exception; + +import java.util.Objects; + +/** + * Thrown in case of problems when computing or verifying digest, or when verified digest is incorrect + */ +public class LollipopDigestException extends Exception { + + /** + * Error code of this exception + */ + private final ErrorCode errorCode; + + /** + * Constructs new exception with provided error code and message + * + * @param errorCode Error code + * @param message Detail message + */ + public LollipopDigestException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Constructs new exception with provided error code, message and cause + * + * @param errorCode Error code + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public LollipopDigestException(ErrorCode errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Returns error code + * + * @return Error code of this exception + */ + public ErrorCode getErrorCode() { + return errorCode; + } + + /** + * Error codes to classify Digest Exceptions + */ + public enum ErrorCode { + /** + * No supported hash algorithms detected when verifying or processing Want-...-Digest headers. + */ + UNSUPPORTED_ALGORITHM, + + /** + * When verifying, provided digest is different from the computed one + */ + INCORRECT_DIGEST, + + /** + * Parsed ...-Digest or Want-...-Digest header is not syntactically correct + */ + INVALID_HEADER, + } + +} \ No newline at end of file diff --git a/core/src/main/java/it/pagopa/spid/common/lc/helper/LollipopConsumerFactoryHelperStub.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/helper/LollipopConsumerFactoryHelperStub.java similarity index 54% rename from core/src/main/java/it/pagopa/spid/common/lc/helper/LollipopConsumerFactoryHelperStub.java rename to core/src/main/java/it/pagopa/common/lollipop/consumer/helper/LollipopConsumerFactoryHelperStub.java index 32e05034..3050e527 100644 --- a/core/src/main/java/it/pagopa/spid/common/lc/helper/LollipopConsumerFactoryHelperStub.java +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/helper/LollipopConsumerFactoryHelperStub.java @@ -1,9 +1,9 @@ -package it.pagopa.spid.common.lc.helper; +package it.pagopa.common.lollipop.consumer.helper; -import it.pagopa.spid.common.lc.http_verifier.HttpMessageVerifierFactory; -import it.pagopa.spid.common.lc.idp.IdpCertProviderFactory; -import it.pagopa.spid.common.lc.service.AssertionVerifierService; -import it.pagopa.spid.common.lc.service.HttpMessageVerifierService; +import it.pagopa.common.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; +import it.pagopa.common.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.common.lollipop.consumer.service.AssertionVerifierService; +import it.pagopa.common.lollipop.consumer.service.HttpMessageVerifierService; public class LollipopConsumerFactoryHelperStub { diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/http_verifier/HttpMessageVerifier.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/http_verifier/HttpMessageVerifier.java new file mode 100644 index 00000000..699649ae --- /dev/null +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/http_verifier/HttpMessageVerifier.java @@ -0,0 +1,13 @@ +package it.pagopa.common.lollipop.consumer.http_verifier; + +import it.pagopa.common.lollipop.consumer.exception.LollipopDigestException; + +import java.io.UnsupportedEncodingException; +import java.util.Map; + +public interface HttpMessageVerifier { + + boolean verifyDigest(String digest, String requestBody, String encoding) throws LollipopDigestException, UnsupportedEncodingException; + boolean verifyHttpSignature(String signature, String signatureInput, Map parameters); + +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/http_verifier/HttpMessageVerifierFactory.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java similarity index 59% rename from core/src/main/java/it/pagopa/spid/common/lc/http_verifier/HttpMessageVerifierFactory.java rename to core/src/main/java/it/pagopa/common/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java index 7ff69636..ffe2c1bf 100644 --- a/core/src/main/java/it/pagopa/spid/common/lc/http_verifier/HttpMessageVerifierFactory.java +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java @@ -1,4 +1,4 @@ -package it.pagopa.spid.common.lc.http_verifier; +package it.pagopa.common.lollipop.consumer.http_verifier; public interface HttpMessageVerifierFactory { diff --git a/core/src/main/java/it/pagopa/spid/common/lc/idp/IdpCertProvider.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/IdpCertProvider.java similarity index 69% rename from core/src/main/java/it/pagopa/spid/common/lc/idp/IdpCertProvider.java rename to core/src/main/java/it/pagopa/common/lollipop/consumer/idp/IdpCertProvider.java index 44bd9f3a..5b508f5f 100644 --- a/core/src/main/java/it/pagopa/spid/common/lc/idp/IdpCertProvider.java +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/IdpCertProvider.java @@ -1,4 +1,4 @@ -package it.pagopa.spid.common.lc.idp; +package it.pagopa.common.lollipop.consumer.idp; public interface IdpCertProvider { diff --git a/core/src/main/java/it/pagopa/spid/common/lc/idp/IdpCertProviderFactory.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/IdpCertProviderFactory.java similarity index 61% rename from core/src/main/java/it/pagopa/spid/common/lc/idp/IdpCertProviderFactory.java rename to core/src/main/java/it/pagopa/common/lollipop/consumer/idp/IdpCertProviderFactory.java index 9e6f6579..4111563e 100644 --- a/core/src/main/java/it/pagopa/spid/common/lc/idp/IdpCertProviderFactory.java +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/IdpCertProviderFactory.java @@ -1,4 +1,4 @@ -package it.pagopa.spid.common.lc.idp; +package it.pagopa.common.lollipop.consumer.idp; public interface IdpCertProviderFactory { diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/client/IdpCertClient.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/client/IdpCertClient.java new file mode 100644 index 00000000..1f7e88ff --- /dev/null +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/client/IdpCertClient.java @@ -0,0 +1,8 @@ +package it.pagopa.common.lollipop.consumer.idp.client; + +import it.pagopa.common.lollipop.consumer.model.IdpCertData; + +public interface IdpCertClient { + + IdpCertData getCertData(String entityId, String instant); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/idp/client/IdpCertClientProvider.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/client/IdpCertClientProvider.java similarity index 59% rename from core/src/main/java/it/pagopa/spid/common/lc/idp/client/IdpCertClientProvider.java rename to core/src/main/java/it/pagopa/common/lollipop/consumer/idp/client/IdpCertClientProvider.java index 982b341d..41a36f61 100644 --- a/core/src/main/java/it/pagopa/spid/common/lc/idp/client/IdpCertClientProvider.java +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/client/IdpCertClientProvider.java @@ -1,4 +1,4 @@ -package it.pagopa.spid.common.lc.idp.client; +package it.pagopa.common.lollipop.consumer.idp.client; public interface IdpCertClientProvider { diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java new file mode 100644 index 00000000..0dbe5f1e --- /dev/null +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java @@ -0,0 +1,16 @@ +package it.pagopa.common.lollipop.consumer.idp.impl; + +import it.pagopa.common.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.common.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.common.lollipop.consumer.idp.client.IdpCertClientProvider; +import it.pagopa.common.lollipop.consumer.idp.storage.IdpCertStorageProvider; + +public class IdpCertProviderFactoryImplStub implements IdpCertProviderFactory { + + private IdpCertClientProvider idpCertClientProvider; + private IdpCertStorageProvider idpCertStorageProvider; + @Override + public IdpCertProvider create() { + return null; + } +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/idp/impl/IdpCertProviderImplStub.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java similarity index 51% rename from core/src/main/java/it/pagopa/spid/common/lc/idp/impl/IdpCertProviderImplStub.java rename to core/src/main/java/it/pagopa/common/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java index 4027df7b..3f17c4c2 100644 --- a/core/src/main/java/it/pagopa/spid/common/lc/idp/impl/IdpCertProviderImplStub.java +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java @@ -1,8 +1,8 @@ -package it.pagopa.spid.common.lc.idp.impl; +package it.pagopa.common.lollipop.consumer.idp.impl; -import it.pagopa.spid.common.lc.idp.IdpCertProvider; -import it.pagopa.spid.common.lc.idp.client.IdpCertClient; -import it.pagopa.spid.common.lc.idp.storage.IdpCertStorage; +import it.pagopa.common.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.common.lollipop.consumer.idp.client.IdpCertClient; +import it.pagopa.common.lollipop.consumer.idp.storage.IdpCertStorage; public class IdpCertProviderImplStub implements IdpCertProvider { diff --git a/core/src/main/java/it/pagopa/spid/common/lc/idp/storage/IdpCertStorage.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/storage/IdpCertStorage.java similarity index 65% rename from core/src/main/java/it/pagopa/spid/common/lc/idp/storage/IdpCertStorage.java rename to core/src/main/java/it/pagopa/common/lollipop/consumer/idp/storage/IdpCertStorage.java index 91f57434..7d0ae284 100644 --- a/core/src/main/java/it/pagopa/spid/common/lc/idp/storage/IdpCertStorage.java +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/storage/IdpCertStorage.java @@ -1,6 +1,6 @@ -package it.pagopa.spid.common.lc.idp.storage; +package it.pagopa.common.lollipop.consumer.idp.storage; -import it.pagopa.spid.common.lc.model.IdpCertData; +import it.pagopa.common.lollipop.consumer.model.IdpCertData; import java.util.List; diff --git a/core/src/main/java/it/pagopa/spid/common/lc/idp/storage/IdpCertStorageProvider.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/storage/IdpCertStorageProvider.java similarity index 60% rename from core/src/main/java/it/pagopa/spid/common/lc/idp/storage/IdpCertStorageProvider.java rename to core/src/main/java/it/pagopa/common/lollipop/consumer/idp/storage/IdpCertStorageProvider.java index 447404c6..c42ac568 100644 --- a/core/src/main/java/it/pagopa/spid/common/lc/idp/storage/IdpCertStorageProvider.java +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/storage/IdpCertStorageProvider.java @@ -1,4 +1,4 @@ -package it.pagopa.spid.common.lc.idp.storage; +package it.pagopa.common.lollipop.consumer.idp.storage; public interface IdpCertStorageProvider { diff --git a/core/src/main/java/it/pagopa/spid/common/lc/model/CommandResult.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/model/CommandResult.java similarity index 76% rename from core/src/main/java/it/pagopa/spid/common/lc/model/CommandResult.java rename to core/src/main/java/it/pagopa/common/lollipop/consumer/model/CommandResult.java index c9aa2c8e..919d09de 100644 --- a/core/src/main/java/it/pagopa/spid/common/lc/model/CommandResult.java +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/model/CommandResult.java @@ -1,4 +1,4 @@ -package it.pagopa.spid.common.lc.model; +package it.pagopa.common.lollipop.consumer.model; import lombok.Getter; import lombok.Setter; diff --git a/core/src/main/java/it/pagopa/spid/common/lc/model/IdpCertData.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/model/IdpCertData.java similarity index 77% rename from core/src/main/java/it/pagopa/spid/common/lc/model/IdpCertData.java rename to core/src/main/java/it/pagopa/common/lollipop/consumer/model/IdpCertData.java index 0a45875c..07a43aa4 100644 --- a/core/src/main/java/it/pagopa/spid/common/lc/model/IdpCertData.java +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/model/IdpCertData.java @@ -1,4 +1,4 @@ -package it.pagopa.spid.common.lc.model; +package it.pagopa.common.lollipop.consumer.model; import lombok.Getter; import lombok.Setter; diff --git a/core/src/main/java/it/pagopa/spid/common/lc/model/LollipopConsumerRequest.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/model/LollipopConsumerRequest.java similarity index 83% rename from core/src/main/java/it/pagopa/spid/common/lc/model/LollipopConsumerRequest.java rename to core/src/main/java/it/pagopa/common/lollipop/consumer/model/LollipopConsumerRequest.java index bb48477b..02d385e0 100644 --- a/core/src/main/java/it/pagopa/spid/common/lc/model/LollipopConsumerRequest.java +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/model/LollipopConsumerRequest.java @@ -1,4 +1,4 @@ -package it.pagopa.spid.common.lc.model; +package it.pagopa.common.lollipop.consumer.model; import lombok.Getter; import lombok.Setter; diff --git a/core/src/main/java/it/pagopa/spid/common/lc/model/SamlAssertion.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/model/SamlAssertion.java similarity index 78% rename from core/src/main/java/it/pagopa/spid/common/lc/model/SamlAssertion.java rename to core/src/main/java/it/pagopa/common/lollipop/consumer/model/SamlAssertion.java index 3d761f0f..c3b3cdfa 100644 --- a/core/src/main/java/it/pagopa/spid/common/lc/model/SamlAssertion.java +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/model/SamlAssertion.java @@ -1,4 +1,4 @@ -package it.pagopa.spid.common.lc.model; +package it.pagopa.common.lollipop.consumer.model; import lombok.Getter; import lombok.Setter; diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/service/AssertionVerifierService.java new file mode 100644 index 00000000..a688417f --- /dev/null +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/service/AssertionVerifierService.java @@ -0,0 +1,8 @@ +package it.pagopa.common.lollipop.consumer.service; + +import it.pagopa.common.lollipop.consumer.model.LollipopConsumerRequest; + +public interface AssertionVerifierService { + + boolean validateLollipop(LollipopConsumerRequest request); +} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/service/HttpMessageVerifierService.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/service/HttpMessageVerifierService.java new file mode 100644 index 00000000..e3940e46 --- /dev/null +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/service/HttpMessageVerifierService.java @@ -0,0 +1,8 @@ +package it.pagopa.common.lollipop.consumer.service; + +import it.pagopa.common.lollipop.consumer.model.LollipopConsumerRequest; + +public interface HttpMessageVerifierService { + + boolean verifyHttpMessage(LollipopConsumerRequest request); +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/service/impl/AssertionVerifierServiceImplStub.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java similarity index 65% rename from core/src/main/java/it/pagopa/spid/common/lc/service/impl/AssertionVerifierServiceImplStub.java rename to core/src/main/java/it/pagopa/common/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java index c1d72b6d..619c9185 100644 --- a/core/src/main/java/it/pagopa/spid/common/lc/service/impl/AssertionVerifierServiceImplStub.java +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java @@ -1,11 +1,11 @@ -package it.pagopa.spid.common.lc.service.impl; +package it.pagopa.common.lollipop.consumer.service.impl; -import it.pagopa.spid.common.lc.assertion.AssertionService; -import it.pagopa.spid.common.lc.idp.IdpCertProvider; -import it.pagopa.spid.common.lc.model.IdpCertData; -import it.pagopa.spid.common.lc.model.LollipopConsumerRequest; -import it.pagopa.spid.common.lc.model.SamlAssertion; -import it.pagopa.spid.common.lc.service.AssertionVerifierService; +import it.pagopa.common.lollipop.consumer.assertion.AssertionService; +import it.pagopa.common.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.common.lollipop.consumer.model.IdpCertData; +import it.pagopa.common.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.common.lollipop.consumer.model.SamlAssertion; +import it.pagopa.common.lollipop.consumer.service.AssertionVerifierService; public class AssertionVerifierServiceImplStub implements AssertionVerifierService { diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java new file mode 100644 index 00000000..1a35b859 --- /dev/null +++ b/core/src/main/java/it/pagopa/common/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java @@ -0,0 +1,15 @@ +package it.pagopa.common.lollipop.consumer.service.impl; + +import it.pagopa.common.lollipop.consumer.http_verifier.HttpMessageVerifier; +import it.pagopa.common.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.common.lollipop.consumer.service.HttpMessageVerifierService; + +public class HttpMessageVerifierServiceImplStub implements HttpMessageVerifierService { + + private HttpMessageVerifier httpMessageVerifier; + + @Override + public boolean verifyHttpMessage(LollipopConsumerRequest request) { + return false; + } +} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/assertion/AssertionService.java b/core/src/main/java/it/pagopa/spid/common/lc/assertion/AssertionService.java deleted file mode 100644 index bab1a0e9..00000000 --- a/core/src/main/java/it/pagopa/spid/common/lc/assertion/AssertionService.java +++ /dev/null @@ -1,8 +0,0 @@ -package it.pagopa.spid.common.lc.assertion; - -import it.pagopa.spid.common.lc.model.SamlAssertion; - -public interface AssertionService { - - SamlAssertion getAssertion(String jwt, String assertionRef); -} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/assertion/client/AssertionClient.java b/core/src/main/java/it/pagopa/spid/common/lc/assertion/client/AssertionClient.java deleted file mode 100644 index 78110537..00000000 --- a/core/src/main/java/it/pagopa/spid/common/lc/assertion/client/AssertionClient.java +++ /dev/null @@ -1,8 +0,0 @@ -package it.pagopa.spid.common.lc.assertion.client; - -import it.pagopa.spid.common.lc.model.SamlAssertion; - -public interface AssertionClient { - - SamlAssertion getAssertion(String jwt, String assertionRef); -} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/assertion/impl/AssertionServiceFactoryImplStub.java b/core/src/main/java/it/pagopa/spid/common/lc/assertion/impl/AssertionServiceFactoryImplStub.java deleted file mode 100644 index c55a2f6f..00000000 --- a/core/src/main/java/it/pagopa/spid/common/lc/assertion/impl/AssertionServiceFactoryImplStub.java +++ /dev/null @@ -1,15 +0,0 @@ -package it.pagopa.spid.common.lc.assertion.impl; - -import it.pagopa.spid.common.lc.assertion.AssertionService; -import it.pagopa.spid.common.lc.assertion.AssertionServiceFactory; -import it.pagopa.spid.common.lc.assertion.client.AssertionClientProvider; -import it.pagopa.spid.common.lc.assertion.storage.AssertionStorageProvider; - -public class AssertionServiceFactoryImplStub implements AssertionServiceFactory { - private AssertionStorageProvider assertionStorageProvider; - private AssertionClientProvider assertionClientProvider; - @Override - public AssertionService create() { - return null; - } -} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/assertion/impl/AssertionServiceImplStub.java b/core/src/main/java/it/pagopa/spid/common/lc/assertion/impl/AssertionServiceImplStub.java deleted file mode 100644 index e072f6c8..00000000 --- a/core/src/main/java/it/pagopa/spid/common/lc/assertion/impl/AssertionServiceImplStub.java +++ /dev/null @@ -1,16 +0,0 @@ -package it.pagopa.spid.common.lc.assertion.impl; - -import it.pagopa.spid.common.lc.assertion.AssertionService; -import it.pagopa.spid.common.lc.assertion.client.AssertionClient; -import it.pagopa.spid.common.lc.assertion.storage.AssertionStorage; -import it.pagopa.spid.common.lc.model.SamlAssertion; - -public class AssertionServiceImplStub implements AssertionService { - - private AssertionStorage assertionStorage; - private AssertionClient assertionClient; - @Override - public SamlAssertion getAssertion(String jwt, String assertionRef) { - return null; - } -} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/assertion/storage/AssertionStorageProvider.java b/core/src/main/java/it/pagopa/spid/common/lc/assertion/storage/AssertionStorageProvider.java deleted file mode 100644 index 1c653c1d..00000000 --- a/core/src/main/java/it/pagopa/spid/common/lc/assertion/storage/AssertionStorageProvider.java +++ /dev/null @@ -1,8 +0,0 @@ -package it.pagopa.spid.common.lc.assertion.storage; - -import it.pagopa.spid.common.lc.assertion.AssertionService; - -public interface AssertionStorageProvider { - - AssertionStorage provideStorage(); -} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/command/LollipopConsumerCommand.java b/core/src/main/java/it/pagopa/spid/common/lc/command/LollipopConsumerCommand.java deleted file mode 100644 index bdc554ea..00000000 --- a/core/src/main/java/it/pagopa/spid/common/lc/command/LollipopConsumerCommand.java +++ /dev/null @@ -1,9 +0,0 @@ -package it.pagopa.spid.common.lc.command; - -import it.pagopa.spid.common.lc.model.CommandResult; -import it.pagopa.spid.common.lc.model.LollipopConsumerRequest; - -public interface LollipopConsumerCommand { - - CommandResult doExecute(LollipopConsumerRequest request); -} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/command/impl/LollipopConsumerCommandBuilderImplStub.java b/core/src/main/java/it/pagopa/spid/common/lc/command/impl/LollipopConsumerCommandBuilderImplStub.java deleted file mode 100644 index 2b6819cf..00000000 --- a/core/src/main/java/it/pagopa/spid/common/lc/command/impl/LollipopConsumerCommandBuilderImplStub.java +++ /dev/null @@ -1,12 +0,0 @@ -package it.pagopa.spid.common.lc.command.impl; - -import it.pagopa.spid.common.lc.command.LollipopConsumerCommand; -import it.pagopa.spid.common.lc.command.LollipopConsumerCommandBuilder; - -public class LollipopConsumerCommandBuilderImplStub implements LollipopConsumerCommandBuilder { - - @Override - public LollipopConsumerCommand createCommand() { - return null; - } -} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/command/impl/LollipopConsumerCommandImplStub.java b/core/src/main/java/it/pagopa/spid/common/lc/command/impl/LollipopConsumerCommandImplStub.java deleted file mode 100644 index c3848bf3..00000000 --- a/core/src/main/java/it/pagopa/spid/common/lc/command/impl/LollipopConsumerCommandImplStub.java +++ /dev/null @@ -1,12 +0,0 @@ -package it.pagopa.spid.common.lc.command.impl; - -import it.pagopa.spid.common.lc.command.LollipopConsumerCommand; -import it.pagopa.spid.common.lc.model.CommandResult; -import it.pagopa.spid.common.lc.model.LollipopConsumerRequest; - -public class LollipopConsumerCommandImplStub implements LollipopConsumerCommand { - @Override - public CommandResult doExecute(LollipopConsumerRequest request) { - return null; - } -} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/http_verifier/HttpMessageVerifier.java b/core/src/main/java/it/pagopa/spid/common/lc/http_verifier/HttpMessageVerifier.java deleted file mode 100644 index 8b258b29..00000000 --- a/core/src/main/java/it/pagopa/spid/common/lc/http_verifier/HttpMessageVerifier.java +++ /dev/null @@ -1,10 +0,0 @@ -package it.pagopa.spid.common.lc.http_verifier; - -import java.util.Map; - -public interface HttpMessageVerifier { - - boolean verifyDigest(String digest, String requestBody); - boolean verifyHttpSignature(String signature, String signatureInput, Map parameters); - -} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/idp/client/IdpCertClient.java b/core/src/main/java/it/pagopa/spid/common/lc/idp/client/IdpCertClient.java deleted file mode 100644 index fc2af0ba..00000000 --- a/core/src/main/java/it/pagopa/spid/common/lc/idp/client/IdpCertClient.java +++ /dev/null @@ -1,8 +0,0 @@ -package it.pagopa.spid.common.lc.idp.client; - -import it.pagopa.spid.common.lc.model.IdpCertData; - -public interface IdpCertClient { - - IdpCertData getCertData(String entityId, String instant); -} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/idp/impl/IdpCertProviderFactoryImplStub.java b/core/src/main/java/it/pagopa/spid/common/lc/idp/impl/IdpCertProviderFactoryImplStub.java deleted file mode 100644 index e287dc31..00000000 --- a/core/src/main/java/it/pagopa/spid/common/lc/idp/impl/IdpCertProviderFactoryImplStub.java +++ /dev/null @@ -1,16 +0,0 @@ -package it.pagopa.spid.common.lc.idp.impl; - -import it.pagopa.spid.common.lc.idp.IdpCertProvider; -import it.pagopa.spid.common.lc.idp.IdpCertProviderFactory; -import it.pagopa.spid.common.lc.idp.client.IdpCertClientProvider; -import it.pagopa.spid.common.lc.idp.storage.IdpCertStorageProvider; - -public class IdpCertProviderFactoryImplStub implements IdpCertProviderFactory { - - private IdpCertClientProvider idpCertClientProvider; - private IdpCertStorageProvider idpCertStorageProvider; - @Override - public IdpCertProvider create() { - return null; - } -} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/spid/common/lc/service/AssertionVerifierService.java deleted file mode 100644 index 63a61130..00000000 --- a/core/src/main/java/it/pagopa/spid/common/lc/service/AssertionVerifierService.java +++ /dev/null @@ -1,8 +0,0 @@ -package it.pagopa.spid.common.lc.service; - -import it.pagopa.spid.common.lc.model.LollipopConsumerRequest; - -public interface AssertionVerifierService { - - boolean validateLollipop(LollipopConsumerRequest request); -} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/service/HttpMessageVerifierService.java b/core/src/main/java/it/pagopa/spid/common/lc/service/HttpMessageVerifierService.java deleted file mode 100644 index 205a8754..00000000 --- a/core/src/main/java/it/pagopa/spid/common/lc/service/HttpMessageVerifierService.java +++ /dev/null @@ -1,8 +0,0 @@ -package it.pagopa.spid.common.lc.service; - -import it.pagopa.spid.common.lc.model.LollipopConsumerRequest; - -public interface HttpMessageVerifierService { - - boolean verifyHttpMessage(LollipopConsumerRequest request); -} diff --git a/core/src/main/java/it/pagopa/spid/common/lc/service/impl/HttpMessageVerifierServiceImplStub.java b/core/src/main/java/it/pagopa/spid/common/lc/service/impl/HttpMessageVerifierServiceImplStub.java deleted file mode 100644 index 5b691b86..00000000 --- a/core/src/main/java/it/pagopa/spid/common/lc/service/impl/HttpMessageVerifierServiceImplStub.java +++ /dev/null @@ -1,15 +0,0 @@ -package it.pagopa.spid.common.lc.service.impl; - -import it.pagopa.spid.common.lc.http_verifier.HttpMessageVerifier; -import it.pagopa.spid.common.lc.model.LollipopConsumerRequest; -import it.pagopa.spid.common.lc.service.HttpMessageVerifierService; - -public class HttpMessageVerifierServiceImplStub implements HttpMessageVerifierService { - - private HttpMessageVerifier httpMessageVerifier; - - @Override - public boolean verifyHttpMessage(LollipopConsumerRequest request) { - return false; - } -} diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index 41547144..80ee0b8f 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -22,8 +22,10 @@ repositories { dependencies { implementation project(path: ':core') + implementation 'net.visma.autopay:http-signatures:1.1.0' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + testImplementation 'org.assertj:assertj-core:3.24.2' } tasks.named('test') { diff --git a/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java b/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java new file mode 100644 index 00000000..9579355b --- /dev/null +++ b/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java @@ -0,0 +1,24 @@ +package it.pagopa.lollipop.consumer.http.verifier.visma; + +import it.pagopa.common.lollipop.consumer.exception.LollipopDigestException; +import net.visma.autopay.http.digest.DigestException; + +public class ErrorCodeConverter { + + public static LollipopDigestException.ErrorCode convertErrorCode(DigestException.ErrorCode errorCode) { + + if (errorCode != null) { + switch (errorCode) { + case INVALID_HEADER: + return LollipopDigestException.ErrorCode.INVALID_HEADER; + case INCORRECT_DIGEST: + return LollipopDigestException.ErrorCode.INCORRECT_DIGEST; + case UNSUPPORTED_ALGORITHM: + return LollipopDigestException.ErrorCode.UNSUPPORTED_ALGORITHM; + } + } + + return null; + } + +} diff --git a/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java b/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java new file mode 100644 index 00000000..7c188efe --- /dev/null +++ b/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java @@ -0,0 +1,53 @@ +package it.pagopa.lollipop.consumer.http.verifier.visma; + +import it.pagopa.common.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.common.lollipop.consumer.http_verifier.HttpMessageVerifier; +import net.visma.autopay.http.digest.DigestException; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +/** + Implementation of the @HttpMessageVerifier using Visma-AutoPay http-signature of the http-signature draft + */ +public class VismaHttpMessageVerifier implements HttpMessageVerifier { + + /** + * Validates digest using Visma DigestVerifier method. Applies contentEncoding if present, otherwise defaults + * to UTF-8 + * + * @param digest Request digest + * @param requestBody Request body + * @param encoding Content encoding + * @return boolean with value true if digest validated + * @throws LollipopDigestException if error from DigestVerifier + * @throws UnsupportedEncodingException if attempted to encode with an unsupported format + */ + @Override + public boolean verifyDigest(String digest, String requestBody, String encoding) + throws LollipopDigestException, UnsupportedEncodingException { + try { + net.visma.autopay.http.digest.DigestVerifier.verifyDigestHeader(digest, + requestBody.getBytes(encoding != null ? + encoding : "UTF-8")); + return true; + } catch (DigestException e) { + throw new LollipopDigestException( + ErrorCodeConverter.convertErrorCode(e.getErrorCode()), + e.getMessage(), + e); + } catch (UnsupportedEncodingException e) { + throw e; + } + } + + /* + + */ + @Override + public boolean verifyHttpSignature(String signature, String signatureInput, Map parameters) { + return false; + } + +} diff --git a/http-verifier/src/test/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java b/http-verifier/src/test/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java new file mode 100644 index 00000000..7726b96b --- /dev/null +++ b/http-verifier/src/test/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2022 Visma Autopay AS + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package it.pagopa.lollipop.consumer.http.verifier.visma; + +import it.pagopa.common.lollipop.consumer.exception.LollipopDigestException; +import net.visma.autopay.http.digest.DigestException; +import org.junit.jupiter.api.Test; + +import java.io.UnsupportedEncodingException; + +import static org.assertj.core.api.Assertions.*; + +class VismaHttpMessageVerifierTest { + + public VismaHttpMessageVerifier vismaDigestVerifier = new VismaHttpMessageVerifier(); + + @Test + void correctDigestIsVerified() { + // setup + var content = new String(new byte[]{1, 2, 4}); + var header = "md5=:V9tg6T+1JldSH4+Zy8c5jw==:,sha-256=:1LKaloxAFzY43tjRdMhpV6+iEb5HnO4CDbpd/hJ9kco=:"; + + // execute & verify + assertThatNoException().isThrownBy(() -> vismaDigestVerifier + .verifyDigest(header, content, null)); + } + + @Test + void invalidDigestIsDetected() { + // setup + var content = new String(new byte[]{1, 2, 4}); + var header = "sha-256=:A5BYxvLAy0ksUzsKTRTvd8wPeKvMztUofYShogEc+4E=:"; + + // execute & verify + assertThatThrownBy(() -> vismaDigestVerifier.verifyDigest(header, content,null)) + .isInstanceOfSatisfying(LollipopDigestException.class, e -> { + assertThat(e.getCause()).hasMessageContaining("different"); + assertThat(((DigestException) e.getCause()) + .getErrorCode()).isEqualTo(DigestException.ErrorCode.INCORRECT_DIGEST); + }); + } + + @Test + void malformedDigestIsDetected() { + // setup + var content = new String(new byte[]{1, 2, 4}); + var header = "sha-256=1LKaloxAFzY43tjRdMhpV6+iEb5HnO4CDbpd/hJ9kco="; + + // execute & verify + assertThatThrownBy(() -> vismaDigestVerifier.verifyDigest(header, content, null)) + .isInstanceOfSatisfying(LollipopDigestException.class, e -> { + assertThat(e.getCause()).hasMessageContaining("parsing"); + assertThat(((DigestException) e.getCause()) + .getErrorCode()).isEqualTo(DigestException.ErrorCode.INVALID_HEADER); + }); + } + + @Test + void unsupportedAlgorithmsAreDetected() { + // setup + var content = new String(new byte[]{1, 2, 4}); + var header = "md5=:V9tg6T+1JldSH4+Zy8c5jw==: ,sha=:q3kRUT3rxwFa1QQpqBWXcUWLJM4=:"; + + // execute & verify + assertThatThrownBy(() -> vismaDigestVerifier.verifyDigest(header, content, null)) + .isInstanceOfSatisfying(LollipopDigestException.class, e -> { + assertThat(e.getCause()).hasMessageContaining("Unsupported"); + assertThat(((DigestException) e.getCause()) + .getErrorCode()).isEqualTo(DigestException.ErrorCode.UNSUPPORTED_ALGORITHM); + }); + } + + @Test + void emptyHeaderIsDetected() { + // setup + var content = new String(new byte[]{1, 2, 4}); + var header = ""; + + // execute & verify + assertThatThrownBy(() -> vismaDigestVerifier.verifyDigest(header, content, null)) + .isInstanceOfSatisfying(LollipopDigestException.class, e -> { + assertThat(e).hasMessageContaining("Empty"); + assertThat(((DigestException) e.getCause()) + .getErrorCode()).isEqualTo(DigestException.ErrorCode.INVALID_HEADER); + }); + } + + @Test + void invalidDictionaryValuesAreDetected() { + // setup + var content = new String(new byte[]{1, 2, 4}); + var header = "sha-256=ok"; + + // execute & verify + assertThatThrownBy(() -> vismaDigestVerifier.verifyDigest(header, content, null)) + .isInstanceOfSatisfying(LollipopDigestException.class, e -> { + assertThat(e.getCause()).hasMessageContaining("Invalid"); + assertThat(((DigestException) e.getCause()) + .getErrorCode()).isEqualTo(DigestException.ErrorCode.INVALID_HEADER); + }); + } + + @Test + void invalidContentEncoding() { + // setup + var content = new String(new byte[]{1, 2, 4}); + var header = "sha-256=ok"; + + // execute & verify + assertThatThrownBy(() -> vismaDigestVerifier.verifyDigest(header, content, "UTF-326")) + .isInstanceOf(UnsupportedEncodingException.class); + } + +} \ No newline at end of file diff --git a/redis-storage/src/test/java/.dummy b/redis-storage/src/test/java/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/redis-storage/src/test/resources/.dummy b/redis-storage/src/test/resources/.dummy deleted file mode 100644 index e69de29b..00000000 From d2926f5d941438547bd52cf292830870598ed0d6 Mon Sep 17 00:00:00 2001 From: giomella Date: Tue, 4 Apr 2023 10:27:21 +0200 Subject: [PATCH 014/403] [core_refactor] renamed base package and groupId with it.pagopa.tech. --- core/build.gradle | 2 +- .../consumer/assertion/AssertionService.java | 8 -------- .../assertion/client/AssertionClient.java | 8 -------- .../impl/AssertionServiceFactoryImplStub.java | 15 --------------- .../assertion/impl/AssertionServiceImplStub.java | 16 ---------------- .../command/LollipopConsumerCommand.java | 9 --------- .../LollipopConsumerCommandBuilderImplStub.java | 12 ------------ .../impl/LollipopConsumerCommandImplStub.java | 12 ------------ .../consumer/idp/client/IdpCertClient.java | 8 -------- .../idp/impl/IdpCertProviderFactoryImplStub.java | 16 ---------------- .../service/AssertionVerifierService.java | 8 -------- .../service/HttpMessageVerifierService.java | 8 -------- .../impl/HttpMessageVerifierServiceImplStub.java | 15 --------------- .../consumer/assertion/AssertionService.java | 8 ++++++++ .../assertion/AssertionServiceFactory.java | 2 +- .../assertion/client/AssertionClient.java | 8 ++++++++ .../client/AssertionClientProvider.java | 2 +- .../impl/AssertionServiceFactoryImplStub.java | 15 +++++++++++++++ .../assertion/impl/AssertionServiceImplStub.java | 16 ++++++++++++++++ .../assertion/storage/AssertionStorage.java | 4 ++-- .../storage/AssertionStorageProvider.java | 2 +- .../command/LollipopConsumerCommand.java | 9 +++++++++ .../command/LollipopConsumerCommandBuilder.java | 2 +- .../LollipopConsumerCommandBuilderImplStub.java | 12 ++++++++++++ .../impl/LollipopConsumerCommandImplStub.java | 12 ++++++++++++ .../exception/LollipopDigestException.java | 2 +- .../LollipopConsumerFactoryHelperStub.java | 10 +++++----- .../http_verifier/HttpMessageVerifier.java | 4 ++-- .../HttpMessageVerifierFactory.java | 2 +- .../lollipop/consumer/idp/IdpCertProvider.java | 2 +- .../consumer/idp/IdpCertProviderFactory.java | 2 +- .../consumer/idp/client/IdpCertClient.java | 8 ++++++++ .../idp/client/IdpCertClientProvider.java | 2 +- .../idp/impl/IdpCertProviderFactoryImplStub.java | 16 ++++++++++++++++ .../idp/impl/IdpCertProviderImplStub.java | 8 ++++---- .../consumer/idp/storage/IdpCertStorage.java | 4 ++-- .../idp/storage/IdpCertStorageProvider.java | 2 +- .../lollipop/consumer/model/CommandResult.java | 2 +- .../lollipop/consumer/model/IdpCertData.java | 2 +- .../consumer/model/LollipopConsumerRequest.java | 2 +- .../lollipop/consumer/model/SamlAssertion.java | 2 +- .../service/AssertionVerifierService.java | 8 ++++++++ .../service/HttpMessageVerifierService.java | 8 ++++++++ .../impl/AssertionVerifierServiceImplStub.java | 14 +++++++------- .../impl/HttpMessageVerifierServiceImplStub.java | 15 +++++++++++++++ .../http/verifier/visma/ErrorCodeConverter.java | 2 +- .../verifier/visma/VismaHttpMessageVerifier.java | 5 ++--- .../visma/VismaHttpMessageVerifierTest.java | 2 +- identity-service-rest-client-native/build.gradle | 2 +- redis-storage/build.gradle | 2 +- 50 files changed, 178 insertions(+), 179 deletions(-) delete mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/AssertionService.java delete mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/client/AssertionClient.java delete mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java delete mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java delete mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/command/LollipopConsumerCommand.java delete mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplStub.java delete mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/command/impl/LollipopConsumerCommandImplStub.java delete mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/idp/client/IdpCertClient.java delete mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java delete mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/service/AssertionVerifierService.java delete mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/service/HttpMessageVerifierService.java delete mode 100644 core/src/main/java/it/pagopa/common/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionService.java rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/assertion/AssertionServiceFactory.java (59%) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClient.java rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/assertion/client/AssertionClientProvider.java (57%) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/assertion/storage/AssertionStorage.java (53%) rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/assertion/storage/AssertionStorageProvider.java (58%) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/command/LollipopConsumerCommandBuilder.java (65%) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplStub.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplStub.java rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/exception/LollipopDigestException.java (97%) rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/helper/LollipopConsumerFactoryHelperStub.java (56%) rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/http_verifier/HttpMessageVerifier.java (72%) rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java (59%) rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/idp/IdpCertProvider.java (69%) rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/idp/IdpCertProviderFactory.java (61%) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/idp/client/IdpCertClientProvider.java (59%) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java (51%) rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/idp/storage/IdpCertStorage.java (65%) rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/idp/storage/IdpCertStorageProvider.java (60%) rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/model/CommandResult.java (76%) rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/model/IdpCertData.java (77%) rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/model/LollipopConsumerRequest.java (83%) rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/model/SamlAssertion.java (78%) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java rename core/src/main/java/it/pagopa/{common => tech}/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java (65%) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java diff --git a/core/build.gradle b/core/build.gradle index 560967b8..eafeb47c 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -13,7 +13,7 @@ plugins { id("io.freefair.lombok") version "8.0.0-rc4" } -group 'it.pagopa.commons' +group 'it.pagopa.tech' repositories { mavenLocal() diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/AssertionService.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/AssertionService.java deleted file mode 100644 index c559d067..00000000 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/AssertionService.java +++ /dev/null @@ -1,8 +0,0 @@ -package it.pagopa.common.lollipop.consumer.assertion; - -import it.pagopa.common.lollipop.consumer.model.SamlAssertion; - -public interface AssertionService { - - SamlAssertion getAssertion(String jwt, String assertionRef); -} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/client/AssertionClient.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/client/AssertionClient.java deleted file mode 100644 index b50c4be4..00000000 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/client/AssertionClient.java +++ /dev/null @@ -1,8 +0,0 @@ -package it.pagopa.common.lollipop.consumer.assertion.client; - -import it.pagopa.common.lollipop.consumer.model.SamlAssertion; - -public interface AssertionClient { - - SamlAssertion getAssertion(String jwt, String assertionRef); -} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java deleted file mode 100644 index 995698f8..00000000 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java +++ /dev/null @@ -1,15 +0,0 @@ -package it.pagopa.common.lollipop.consumer.assertion.impl; - -import it.pagopa.common.lollipop.consumer.assertion.AssertionService; -import it.pagopa.common.lollipop.consumer.assertion.AssertionServiceFactory; -import it.pagopa.common.lollipop.consumer.assertion.storage.AssertionStorageProvider; -import it.pagopa.common.lollipop.consumer.assertion.client.AssertionClientProvider; - -public class AssertionServiceFactoryImplStub implements AssertionServiceFactory { - private AssertionStorageProvider assertionStorageProvider; - private AssertionClientProvider assertionClientProvider; - @Override - public AssertionService create() { - return null; - } -} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java deleted file mode 100644 index b619bb7d..00000000 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java +++ /dev/null @@ -1,16 +0,0 @@ -package it.pagopa.common.lollipop.consumer.assertion.impl; - -import it.pagopa.common.lollipop.consumer.assertion.AssertionService; -import it.pagopa.common.lollipop.consumer.assertion.storage.AssertionStorage; -import it.pagopa.common.lollipop.consumer.assertion.client.AssertionClient; -import it.pagopa.common.lollipop.consumer.model.SamlAssertion; - -public class AssertionServiceImplStub implements AssertionService { - - private AssertionStorage assertionStorage; - private AssertionClient assertionClient; - @Override - public SamlAssertion getAssertion(String jwt, String assertionRef) { - return null; - } -} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/command/LollipopConsumerCommand.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/command/LollipopConsumerCommand.java deleted file mode 100644 index edf2c1da..00000000 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/command/LollipopConsumerCommand.java +++ /dev/null @@ -1,9 +0,0 @@ -package it.pagopa.common.lollipop.consumer.command; - -import it.pagopa.common.lollipop.consumer.model.CommandResult; -import it.pagopa.common.lollipop.consumer.model.LollipopConsumerRequest; - -public interface LollipopConsumerCommand { - - CommandResult doExecute(LollipopConsumerRequest request); -} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplStub.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplStub.java deleted file mode 100644 index b6ceeb77..00000000 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplStub.java +++ /dev/null @@ -1,12 +0,0 @@ -package it.pagopa.common.lollipop.consumer.command.impl; - -import it.pagopa.common.lollipop.consumer.command.LollipopConsumerCommand; -import it.pagopa.common.lollipop.consumer.command.LollipopConsumerCommandBuilder; - -public class LollipopConsumerCommandBuilderImplStub implements LollipopConsumerCommandBuilder { - - @Override - public LollipopConsumerCommand createCommand() { - return null; - } -} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/command/impl/LollipopConsumerCommandImplStub.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/command/impl/LollipopConsumerCommandImplStub.java deleted file mode 100644 index 5ba4ab9f..00000000 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/command/impl/LollipopConsumerCommandImplStub.java +++ /dev/null @@ -1,12 +0,0 @@ -package it.pagopa.common.lollipop.consumer.command.impl; - -import it.pagopa.common.lollipop.consumer.command.LollipopConsumerCommand; -import it.pagopa.common.lollipop.consumer.model.CommandResult; -import it.pagopa.common.lollipop.consumer.model.LollipopConsumerRequest; - -public class LollipopConsumerCommandImplStub implements LollipopConsumerCommand { - @Override - public CommandResult doExecute(LollipopConsumerRequest request) { - return null; - } -} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/client/IdpCertClient.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/client/IdpCertClient.java deleted file mode 100644 index 1f7e88ff..00000000 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/client/IdpCertClient.java +++ /dev/null @@ -1,8 +0,0 @@ -package it.pagopa.common.lollipop.consumer.idp.client; - -import it.pagopa.common.lollipop.consumer.model.IdpCertData; - -public interface IdpCertClient { - - IdpCertData getCertData(String entityId, String instant); -} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java deleted file mode 100644 index 0dbe5f1e..00000000 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java +++ /dev/null @@ -1,16 +0,0 @@ -package it.pagopa.common.lollipop.consumer.idp.impl; - -import it.pagopa.common.lollipop.consumer.idp.IdpCertProvider; -import it.pagopa.common.lollipop.consumer.idp.IdpCertProviderFactory; -import it.pagopa.common.lollipop.consumer.idp.client.IdpCertClientProvider; -import it.pagopa.common.lollipop.consumer.idp.storage.IdpCertStorageProvider; - -public class IdpCertProviderFactoryImplStub implements IdpCertProviderFactory { - - private IdpCertClientProvider idpCertClientProvider; - private IdpCertStorageProvider idpCertStorageProvider; - @Override - public IdpCertProvider create() { - return null; - } -} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/service/AssertionVerifierService.java deleted file mode 100644 index a688417f..00000000 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/service/AssertionVerifierService.java +++ /dev/null @@ -1,8 +0,0 @@ -package it.pagopa.common.lollipop.consumer.service; - -import it.pagopa.common.lollipop.consumer.model.LollipopConsumerRequest; - -public interface AssertionVerifierService { - - boolean validateLollipop(LollipopConsumerRequest request); -} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/service/HttpMessageVerifierService.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/service/HttpMessageVerifierService.java deleted file mode 100644 index e3940e46..00000000 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/service/HttpMessageVerifierService.java +++ /dev/null @@ -1,8 +0,0 @@ -package it.pagopa.common.lollipop.consumer.service; - -import it.pagopa.common.lollipop.consumer.model.LollipopConsumerRequest; - -public interface HttpMessageVerifierService { - - boolean verifyHttpMessage(LollipopConsumerRequest request); -} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java b/core/src/main/java/it/pagopa/common/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java deleted file mode 100644 index 1a35b859..00000000 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java +++ /dev/null @@ -1,15 +0,0 @@ -package it.pagopa.common.lollipop.consumer.service.impl; - -import it.pagopa.common.lollipop.consumer.http_verifier.HttpMessageVerifier; -import it.pagopa.common.lollipop.consumer.model.LollipopConsumerRequest; -import it.pagopa.common.lollipop.consumer.service.HttpMessageVerifierService; - -public class HttpMessageVerifierServiceImplStub implements HttpMessageVerifierService { - - private HttpMessageVerifier httpMessageVerifier; - - @Override - public boolean verifyHttpMessage(LollipopConsumerRequest request) { - return false; - } -} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionService.java new file mode 100644 index 00000000..f3a77a64 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionService.java @@ -0,0 +1,8 @@ +package it.pagopa.tech.lollipop.consumer.assertion; + +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; + +public interface AssertionService { + + SamlAssertion getAssertion(String jwt, String assertionRef); +} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/AssertionServiceFactory.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionServiceFactory.java similarity index 59% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/AssertionServiceFactory.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionServiceFactory.java index 0c6da4fc..9d32fc76 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/AssertionServiceFactory.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionServiceFactory.java @@ -1,4 +1,4 @@ -package it.pagopa.common.lollipop.consumer.assertion; +package it.pagopa.tech.lollipop.consumer.assertion; public interface AssertionServiceFactory { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClient.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClient.java new file mode 100644 index 00000000..47f9e744 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClient.java @@ -0,0 +1,8 @@ +package it.pagopa.tech.lollipop.consumer.assertion.client; + +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; + +public interface AssertionClient { + + SamlAssertion getAssertion(String jwt, String assertionRef); +} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/client/AssertionClientProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClientProvider.java similarity index 57% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/client/AssertionClientProvider.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClientProvider.java index 3b2dfe79..89dc738e 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/client/AssertionClientProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClientProvider.java @@ -1,4 +1,4 @@ -package it.pagopa.common.lollipop.consumer.assertion.client; +package it.pagopa.tech.lollipop.consumer.assertion.client; public interface AssertionClientProvider { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java new file mode 100644 index 00000000..2130967c --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java @@ -0,0 +1,15 @@ +package it.pagopa.tech.lollipop.consumer.assertion.impl; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; +import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; +import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorageProvider; +import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClientProvider; + +public class AssertionServiceFactoryImplStub implements AssertionServiceFactory { + private AssertionStorageProvider assertionStorageProvider; + private AssertionClientProvider assertionClientProvider; + @Override + public AssertionService create() { + return null; + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java new file mode 100644 index 00000000..2348974b --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java @@ -0,0 +1,16 @@ +package it.pagopa.tech.lollipop.consumer.assertion.impl; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; +import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorage; +import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClient; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; + +public class AssertionServiceImplStub implements AssertionService { + + private AssertionStorage assertionStorage; + private AssertionClient assertionClient; + @Override + public SamlAssertion getAssertion(String jwt, String assertionRef) { + return null; + } +} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/storage/AssertionStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorage.java similarity index 53% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/storage/AssertionStorage.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorage.java index 0b544107..2655d113 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/storage/AssertionStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorage.java @@ -1,6 +1,6 @@ -package it.pagopa.common.lollipop.consumer.assertion.storage; +package it.pagopa.tech.lollipop.consumer.assertion.storage; -import it.pagopa.common.lollipop.consumer.model.SamlAssertion; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; public interface AssertionStorage { diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/storage/AssertionStorageProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorageProvider.java similarity index 58% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/storage/AssertionStorageProvider.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorageProvider.java index 30cc318c..3f0d47db 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/assertion/storage/AssertionStorageProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorageProvider.java @@ -1,4 +1,4 @@ -package it.pagopa.common.lollipop.consumer.assertion.storage; +package it.pagopa.tech.lollipop.consumer.assertion.storage; public interface AssertionStorageProvider { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java new file mode 100644 index 00000000..3b5b5a75 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java @@ -0,0 +1,9 @@ +package it.pagopa.tech.lollipop.consumer.command; + +import it.pagopa.tech.lollipop.consumer.model.CommandResult; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; + +public interface LollipopConsumerCommand { + + CommandResult doExecute(LollipopConsumerRequest request); +} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/command/LollipopConsumerCommandBuilder.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java similarity index 65% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/command/LollipopConsumerCommandBuilder.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java index 450df727..af6d5a91 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/command/LollipopConsumerCommandBuilder.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java @@ -1,4 +1,4 @@ -package it.pagopa.common.lollipop.consumer.command; +package it.pagopa.tech.lollipop.consumer.command; public interface LollipopConsumerCommandBuilder { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplStub.java new file mode 100644 index 00000000..1b07bb05 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplStub.java @@ -0,0 +1,12 @@ +package it.pagopa.tech.lollipop.consumer.command.impl; + +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; + +public class LollipopConsumerCommandBuilderImplStub implements LollipopConsumerCommandBuilder { + + @Override + public LollipopConsumerCommand createCommand() { + return null; + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplStub.java new file mode 100644 index 00000000..5f0a621b --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplStub.java @@ -0,0 +1,12 @@ +package it.pagopa.tech.lollipop.consumer.command.impl; + +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; +import it.pagopa.tech.lollipop.consumer.model.CommandResult; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; + +public class LollipopConsumerCommandImplStub implements LollipopConsumerCommand { + @Override + public CommandResult doExecute(LollipopConsumerRequest request) { + return null; + } +} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/exception/LollipopDigestException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopDigestException.java similarity index 97% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/exception/LollipopDigestException.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopDigestException.java index b0624c00..a3970dc1 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/exception/LollipopDigestException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopDigestException.java @@ -1,4 +1,4 @@ -package it.pagopa.common.lollipop.consumer.exception; +package it.pagopa.tech.lollipop.consumer.exception; import java.util.Objects; diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/helper/LollipopConsumerFactoryHelperStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelperStub.java similarity index 56% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/helper/LollipopConsumerFactoryHelperStub.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelperStub.java index 3050e527..5b7cb212 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/helper/LollipopConsumerFactoryHelperStub.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelperStub.java @@ -1,9 +1,9 @@ -package it.pagopa.common.lollipop.consumer.helper; +package it.pagopa.tech.lollipop.consumer.helper; -import it.pagopa.common.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; -import it.pagopa.common.lollipop.consumer.idp.IdpCertProviderFactory; -import it.pagopa.common.lollipop.consumer.service.AssertionVerifierService; -import it.pagopa.common.lollipop.consumer.service.HttpMessageVerifierService; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; +import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; public class LollipopConsumerFactoryHelperStub { diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/http_verifier/HttpMessageVerifier.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java similarity index 72% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/http_verifier/HttpMessageVerifier.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java index 699649ae..e0e94d5a 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/http_verifier/HttpMessageVerifier.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java @@ -1,6 +1,6 @@ -package it.pagopa.common.lollipop.consumer.http_verifier; +package it.pagopa.tech.lollipop.consumer.http_verifier; -import it.pagopa.common.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import java.io.UnsupportedEncodingException; import java.util.Map; diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java similarity index 59% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java index ffe2c1bf..aac9ba96 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java @@ -1,4 +1,4 @@ -package it.pagopa.common.lollipop.consumer.http_verifier; +package it.pagopa.tech.lollipop.consumer.http_verifier; public interface HttpMessageVerifierFactory { diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/IdpCertProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java similarity index 69% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/idp/IdpCertProvider.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java index 5b508f5f..819945ee 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/IdpCertProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java @@ -1,4 +1,4 @@ -package it.pagopa.common.lollipop.consumer.idp; +package it.pagopa.tech.lollipop.consumer.idp; public interface IdpCertProvider { diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/IdpCertProviderFactory.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProviderFactory.java similarity index 61% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/idp/IdpCertProviderFactory.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProviderFactory.java index 4111563e..87f86053 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/IdpCertProviderFactory.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProviderFactory.java @@ -1,4 +1,4 @@ -package it.pagopa.common.lollipop.consumer.idp; +package it.pagopa.tech.lollipop.consumer.idp; public interface IdpCertProviderFactory { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java new file mode 100644 index 00000000..0f4eaa96 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java @@ -0,0 +1,8 @@ +package it.pagopa.tech.lollipop.consumer.idp.client; + +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; + +public interface IdpCertClient { + + IdpCertData getCertData(String entityId, String instant); +} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/client/IdpCertClientProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClientProvider.java similarity index 59% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/idp/client/IdpCertClientProvider.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClientProvider.java index 41a36f61..dc49904d 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/client/IdpCertClientProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClientProvider.java @@ -1,4 +1,4 @@ -package it.pagopa.common.lollipop.consumer.idp.client; +package it.pagopa.tech.lollipop.consumer.idp.client; public interface IdpCertClientProvider { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java new file mode 100644 index 00000000..5595a0b4 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java @@ -0,0 +1,16 @@ +package it.pagopa.tech.lollipop.consumer.idp.impl; + +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageProvider; + +public class IdpCertProviderFactoryImplStub implements IdpCertProviderFactory { + + private IdpCertClientProvider idpCertClientProvider; + private IdpCertStorageProvider idpCertStorageProvider; + @Override + public IdpCertProvider create() { + return null; + } +} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java similarity index 51% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java index 3f17c4c2..64b0b838 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java @@ -1,8 +1,8 @@ -package it.pagopa.common.lollipop.consumer.idp.impl; +package it.pagopa.tech.lollipop.consumer.idp.impl; -import it.pagopa.common.lollipop.consumer.idp.IdpCertProvider; -import it.pagopa.common.lollipop.consumer.idp.client.IdpCertClient; -import it.pagopa.common.lollipop.consumer.idp.storage.IdpCertStorage; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; public class IdpCertProviderImplStub implements IdpCertProvider { diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/storage/IdpCertStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java similarity index 65% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/idp/storage/IdpCertStorage.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java index 7d0ae284..3c8a334b 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/storage/IdpCertStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java @@ -1,6 +1,6 @@ -package it.pagopa.common.lollipop.consumer.idp.storage; +package it.pagopa.tech.lollipop.consumer.idp.storage; -import it.pagopa.common.lollipop.consumer.model.IdpCertData; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import java.util.List; diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/storage/IdpCertStorageProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageProvider.java similarity index 60% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/idp/storage/IdpCertStorageProvider.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageProvider.java index c42ac568..a49c3628 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/idp/storage/IdpCertStorageProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageProvider.java @@ -1,4 +1,4 @@ -package it.pagopa.common.lollipop.consumer.idp.storage; +package it.pagopa.tech.lollipop.consumer.idp.storage; public interface IdpCertStorageProvider { diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/model/CommandResult.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/CommandResult.java similarity index 76% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/model/CommandResult.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/model/CommandResult.java index 919d09de..33a8ceb7 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/model/CommandResult.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/CommandResult.java @@ -1,4 +1,4 @@ -package it.pagopa.common.lollipop.consumer.model; +package it.pagopa.tech.lollipop.consumer.model; import lombok.Getter; import lombok.Setter; diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/model/IdpCertData.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java similarity index 77% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/model/IdpCertData.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java index 07a43aa4..f01c3bce 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/model/IdpCertData.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java @@ -1,4 +1,4 @@ -package it.pagopa.common.lollipop.consumer.model; +package it.pagopa.tech.lollipop.consumer.model; import lombok.Getter; import lombok.Setter; diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/model/LollipopConsumerRequest.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java similarity index 83% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/model/LollipopConsumerRequest.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java index 02d385e0..6d8773af 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/model/LollipopConsumerRequest.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java @@ -1,4 +1,4 @@ -package it.pagopa.common.lollipop.consumer.model; +package it.pagopa.tech.lollipop.consumer.model; import lombok.Getter; import lombok.Setter; diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/model/SamlAssertion.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java similarity index 78% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/model/SamlAssertion.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java index c3b3cdfa..0510d980 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/model/SamlAssertion.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java @@ -1,4 +1,4 @@ -package it.pagopa.common.lollipop.consumer.model; +package it.pagopa.tech.lollipop.consumer.model; import lombok.Getter; import lombok.Setter; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java new file mode 100644 index 00000000..ced5d889 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java @@ -0,0 +1,8 @@ +package it.pagopa.tech.lollipop.consumer.service; + +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; + +public interface AssertionVerifierService { + + boolean validateLollipop(LollipopConsumerRequest request); +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java new file mode 100644 index 00000000..0ce11eda --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java @@ -0,0 +1,8 @@ +package it.pagopa.tech.lollipop.consumer.service; + +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; + +public interface HttpMessageVerifierService { + + boolean verifyHttpMessage(LollipopConsumerRequest request); +} diff --git a/core/src/main/java/it/pagopa/common/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java similarity index 65% rename from core/src/main/java/it/pagopa/common/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java index 619c9185..86e763de 100644 --- a/core/src/main/java/it/pagopa/common/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java @@ -1,11 +1,11 @@ -package it.pagopa.common.lollipop.consumer.service.impl; +package it.pagopa.tech.lollipop.consumer.service.impl; -import it.pagopa.common.lollipop.consumer.assertion.AssertionService; -import it.pagopa.common.lollipop.consumer.idp.IdpCertProvider; -import it.pagopa.common.lollipop.consumer.model.IdpCertData; -import it.pagopa.common.lollipop.consumer.model.LollipopConsumerRequest; -import it.pagopa.common.lollipop.consumer.model.SamlAssertion; -import it.pagopa.common.lollipop.consumer.service.AssertionVerifierService; +import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; +import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; public class AssertionVerifierServiceImplStub implements AssertionVerifierService { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java new file mode 100644 index 00000000..ae413b41 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java @@ -0,0 +1,15 @@ +package it.pagopa.tech.lollipop.consumer.service.impl; + +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; + +public class HttpMessageVerifierServiceImplStub implements HttpMessageVerifierService { + + private HttpMessageVerifier httpMessageVerifier; + + @Override + public boolean verifyHttpMessage(LollipopConsumerRequest request) { + return false; + } +} diff --git a/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java b/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java index 9579355b..bdebe657 100644 --- a/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java +++ b/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java @@ -1,6 +1,6 @@ package it.pagopa.lollipop.consumer.http.verifier.visma; -import it.pagopa.common.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import net.visma.autopay.http.digest.DigestException; public class ErrorCodeConverter { diff --git a/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java b/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java index 7c188efe..b243de1d 100644 --- a/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java +++ b/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java @@ -1,11 +1,10 @@ package it.pagopa.lollipop.consumer.http.verifier.visma; -import it.pagopa.common.lollipop.consumer.exception.LollipopDigestException; -import it.pagopa.common.lollipop.consumer.http_verifier.HttpMessageVerifier; +import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; import net.visma.autopay.http.digest.DigestException; import java.io.UnsupportedEncodingException; -import java.nio.charset.StandardCharsets; import java.util.Map; /** diff --git a/http-verifier/src/test/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java b/http-verifier/src/test/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java index 7726b96b..233e9c3c 100644 --- a/http-verifier/src/test/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java +++ b/http-verifier/src/test/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java @@ -22,7 +22,7 @@ package it.pagopa.lollipop.consumer.http.verifier.visma; -import it.pagopa.common.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import net.visma.autopay.http.digest.DigestException; import org.junit.jupiter.api.Test; diff --git a/identity-service-rest-client-native/build.gradle b/identity-service-rest-client-native/build.gradle index 41547144..200c24e8 100644 --- a/identity-service-rest-client-native/build.gradle +++ b/identity-service-rest-client-native/build.gradle @@ -13,7 +13,7 @@ plugins { id("io.freefair.lombok") version "8.0.0-rc4" } -group 'it.pagopa.commons' +group 'it.pagopa.tech' repositories { mavenLocal() diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle index 41547144..200c24e8 100644 --- a/redis-storage/build.gradle +++ b/redis-storage/build.gradle @@ -13,7 +13,7 @@ plugins { id("io.freefair.lombok") version "8.0.0-rc4" } -group 'it.pagopa.commons' +group 'it.pagopa.tech' repositories { mavenLocal() From a69679bde466811380bfff27db1fe43c87733b62 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 4 Apr 2023 11:14:03 +0200 Subject: [PATCH 015/403] [SLS-22] Introducing factory implementation of http verifier and related services --- http-verifier/build.gradle | 2 +- .../verifier/visma/ErrorCodeConverter.java | 9 +++++- .../visma/VismaHttpMessageVerifier.java | 14 ++++++--- .../VismaHttpMessageVerifierFactory.java | 31 +++++++++++++++++++ .../VismaHttpMessageVerifierFactoryTest.java | 31 +++++++++++++++++++ .../visma/VismaHttpMessageVerifierTest.java | 20 ++++++------ 6 files changed, 90 insertions(+), 17 deletions(-) rename http-verifier/src/main/java/it/pagopa/{ => tech}/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java (69%) rename http-verifier/src/main/java/it/pagopa/{ => tech}/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java (85%) create mode 100644 http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactory.java create mode 100644 http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactoryTest.java rename http-verifier/src/test/java/it/pagopa/{ => tech}/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java (91%) diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index 80ee0b8f..9c4f3327 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -13,7 +13,7 @@ plugins { id("io.freefair.lombok") version "8.0.0-rc4" } -group 'it.pagopa.commons' +group 'it.pagopa.tech' repositories { mavenLocal() diff --git a/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java similarity index 69% rename from http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java rename to http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java index bdebe657..e43632f6 100644 --- a/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java @@ -1,10 +1,17 @@ -package it.pagopa.lollipop.consumer.http.verifier.visma; +package it.pagopa.tech.lollipop.consumer.http.verifier.visma; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import net.visma.autopay.http.digest.DigestException; +/** + * Manages the conversion between {@link DigestException.ErrorCode} and {@link LollipopDigestException.ErrorCode} + */ public class ErrorCodeConverter { + /** + * @param errorCode {@link DigestException.ErrorCode} to convert + * @return converted {@link LollipopDigestException.ErrorCode} + */ public static LollipopDigestException.ErrorCode convertErrorCode(DigestException.ErrorCode errorCode) { if (errorCode != null) { diff --git a/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java similarity index 85% rename from http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java rename to http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java index b243de1d..5f8156d3 100644 --- a/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java @@ -1,7 +1,8 @@ -package it.pagopa.lollipop.consumer.http.verifier.visma; +package it.pagopa.tech.lollipop.consumer.http.verifier.visma; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; +import lombok.AllArgsConstructor; import net.visma.autopay.http.digest.DigestException; import java.io.UnsupportedEncodingException; @@ -10,15 +11,18 @@ /** Implementation of the @HttpMessageVerifier using Visma-AutoPay http-signature of the http-signature draft */ +@AllArgsConstructor public class VismaHttpMessageVerifier implements HttpMessageVerifier { + private String defaultEncoding; + /** * Validates digest using Visma DigestVerifier method. Applies contentEncoding if present, otherwise defaults * to UTF-8 * * @param digest Request digest * @param requestBody Request body - * @param encoding Content encoding + * @param encoding Content encoding, if missing uses defaultEncoding * @return boolean with value true if digest validated * @throws LollipopDigestException if error from DigestVerifier * @throws UnsupportedEncodingException if attempted to encode with an unsupported format @@ -29,7 +33,7 @@ public boolean verifyDigest(String digest, String requestBody, String encoding) try { net.visma.autopay.http.digest.DigestVerifier.verifyDigestHeader(digest, requestBody.getBytes(encoding != null ? - encoding : "UTF-8")); + encoding : defaultEncoding)); return true; } catch (DigestException e) { throw new LollipopDigestException( @@ -41,8 +45,8 @@ public boolean verifyDigest(String digest, String requestBody, String encoding) } } - /* - + /** + * TODO: stub */ @Override public boolean verifyHttpSignature(String signature, String signatureInput, Map parameters) { diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactory.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactory.java new file mode 100644 index 00000000..8bd753cc --- /dev/null +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactory.java @@ -0,0 +1,31 @@ +package it.pagopa.tech.lollipop.consumer.http.verifier.visma; + +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; + +import java.nio.charset.Charset; + +/** + * Implements {@link HttpMessageVerifierFactory} with Visma-AutoPay http-signature library + */ +public class VismaHttpMessageVerifierFactory implements HttpMessageVerifierFactory { + + private final String defaultEncoding; + + public VismaHttpMessageVerifierFactory(String defaultEncoding) throws Exception { + if (Charset.availableCharsets().get(defaultEncoding) == null) { + throw new Exception("Unavailable Encoding: " + defaultEncoding); + } + this.defaultEncoding = defaultEncoding; + } + + /** + * {@inheritDoc} + * @return instance of {@link VismaHttpMessageVerifierFactory}, passing the configured default encoding + **/ + @Override + public HttpMessageVerifier create() { + return new VismaHttpMessageVerifier(defaultEncoding); + } + +} diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactoryTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactoryTest.java new file mode 100644 index 00000000..ead71f3f --- /dev/null +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactoryTest.java @@ -0,0 +1,31 @@ +package it.pagopa.tech.lollipop.consumer.http.verifier.visma; + +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; +import lombok.SneakyThrows; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; + +class VismaHttpMessageVerifierFactoryTest { + + @Test + public void encodingInCostructorIsInvalid() { + assertThatThrownBy(() -> new VismaHttpMessageVerifierFactory("UTF-326")) + .isInstanceOfSatisfying(Exception.class, e -> + assertThat(e).hasMessageContaining("Unavailable Encoding: UTF-326")); + } + + @Test + public void encodingInCostructorIsValid() { + assertThatNoException().isThrownBy( + () -> new VismaHttpMessageVerifierFactory("UTF-8")); + } + + @SneakyThrows + @Test + public void instanceIsCreated() { + assertThat(new VismaHttpMessageVerifierFactory("UTF-8").create()) + .isInstanceOf(VismaHttpMessageVerifier.class); + } + +} \ No newline at end of file diff --git a/http-verifier/src/test/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java similarity index 91% rename from http-verifier/src/test/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java rename to http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java index 233e9c3c..ee31e2ba 100644 --- a/http-verifier/src/test/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java @@ -20,7 +20,7 @@ * SOFTWARE. */ -package it.pagopa.lollipop.consumer.http.verifier.visma; +package it.pagopa.tech.lollipop.consumer.http.verifier.visma; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import net.visma.autopay.http.digest.DigestException; @@ -30,12 +30,12 @@ import static org.assertj.core.api.Assertions.*; -class VismaHttpMessageVerifierTest { +public class VismaHttpMessageVerifierTest { - public VismaHttpMessageVerifier vismaDigestVerifier = new VismaHttpMessageVerifier(); + public VismaHttpMessageVerifier vismaDigestVerifier = new VismaHttpMessageVerifier("UTF-8"); @Test - void correctDigestIsVerified() { + public void correctDigestIsVerified() { // setup var content = new String(new byte[]{1, 2, 4}); var header = "md5=:V9tg6T+1JldSH4+Zy8c5jw==:,sha-256=:1LKaloxAFzY43tjRdMhpV6+iEb5HnO4CDbpd/hJ9kco=:"; @@ -46,7 +46,7 @@ void correctDigestIsVerified() { } @Test - void invalidDigestIsDetected() { + public void invalidDigestIsDetected() { // setup var content = new String(new byte[]{1, 2, 4}); var header = "sha-256=:A5BYxvLAy0ksUzsKTRTvd8wPeKvMztUofYShogEc+4E=:"; @@ -61,7 +61,7 @@ void invalidDigestIsDetected() { } @Test - void malformedDigestIsDetected() { + public void malformedDigestIsDetected() { // setup var content = new String(new byte[]{1, 2, 4}); var header = "sha-256=1LKaloxAFzY43tjRdMhpV6+iEb5HnO4CDbpd/hJ9kco="; @@ -76,7 +76,7 @@ void malformedDigestIsDetected() { } @Test - void unsupportedAlgorithmsAreDetected() { + public void unsupportedAlgorithmsAreDetected() { // setup var content = new String(new byte[]{1, 2, 4}); var header = "md5=:V9tg6T+1JldSH4+Zy8c5jw==: ,sha=:q3kRUT3rxwFa1QQpqBWXcUWLJM4=:"; @@ -91,7 +91,7 @@ void unsupportedAlgorithmsAreDetected() { } @Test - void emptyHeaderIsDetected() { + public void emptyHeaderIsDetected() { // setup var content = new String(new byte[]{1, 2, 4}); var header = ""; @@ -106,7 +106,7 @@ void emptyHeaderIsDetected() { } @Test - void invalidDictionaryValuesAreDetected() { + public void invalidDictionaryValuesAreDetected() { // setup var content = new String(new byte[]{1, 2, 4}); var header = "sha-256=ok"; @@ -121,7 +121,7 @@ void invalidDictionaryValuesAreDetected() { } @Test - void invalidContentEncoding() { + public void invalidContentEncoding() { // setup var content = new String(new byte[]{1, 2, 4}); var header = "sha-256=ok"; From 778b9442eba1336f7b0de0a641043314884bd19f Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 4 Apr 2023 11:17:18 +0200 Subject: [PATCH 016/403] [SLS-22] Introducing factory implementation of http verifier and related services --- .../verifier => http_verifier}/visma/ErrorCodeConverter.java | 2 +- .../visma/VismaHttpMessageVerifier.java | 2 +- .../visma/VismaHttpMessageVerifierFactory.java | 2 +- .../visma/VismaHttpMessageVerifierFactoryTest.java | 3 +-- .../visma/VismaHttpMessageVerifierTest.java | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) rename http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/{http/verifier => http_verifier}/visma/ErrorCodeConverter.java (94%) rename http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/{http/verifier => http_verifier}/visma/VismaHttpMessageVerifier.java (96%) rename http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/{http/verifier => http_verifier}/visma/VismaHttpMessageVerifierFactory.java (94%) rename http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/{http/verifier => http_verifier}/visma/VismaHttpMessageVerifierFactoryTest.java (85%) rename http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/{http/verifier => http_verifier}/visma/VismaHttpMessageVerifierTest.java (98%) diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/ErrorCodeConverter.java similarity index 94% rename from http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java rename to http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/ErrorCodeConverter.java index e43632f6..cef315ae 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/ErrorCodeConverter.java @@ -1,4 +1,4 @@ -package it.pagopa.tech.lollipop.consumer.http.verifier.visma; +package it.pagopa.tech.lollipop.consumer.http_verifier.visma; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import net.visma.autopay.http.digest.DigestException; diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java similarity index 96% rename from http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java rename to http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java index 5f8156d3..0fd314ce 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java @@ -1,4 +1,4 @@ -package it.pagopa.tech.lollipop.consumer.http.verifier.visma; +package it.pagopa.tech.lollipop.consumer.http_verifier.visma; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactory.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java similarity index 94% rename from http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactory.java rename to http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java index 8bd753cc..b6de2cb1 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactory.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java @@ -1,4 +1,4 @@ -package it.pagopa.tech.lollipop.consumer.http.verifier.visma; +package it.pagopa.tech.lollipop.consumer.http_verifier.visma; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactoryTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java similarity index 85% rename from http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactoryTest.java rename to http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java index ead71f3f..fd6c327d 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactoryTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java @@ -1,6 +1,5 @@ -package it.pagopa.tech.lollipop.consumer.http.verifier.visma; +package it.pagopa.tech.lollipop.consumer.http_verifier.visma; -import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; import lombok.SneakyThrows; import org.junit.jupiter.api.Test; diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java similarity index 98% rename from http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java rename to http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java index ee31e2ba..65a5725a 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java @@ -20,7 +20,7 @@ * SOFTWARE. */ -package it.pagopa.tech.lollipop.consumer.http.verifier.visma; +package it.pagopa.tech.lollipop.consumer.http_verifier.visma; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import net.visma.autopay.http.digest.DigestException; From 426af9c2613c7d7e7d24d7deb7b014fb04861988 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 4 Apr 2023 14:25:50 +0200 Subject: [PATCH 017/403] [SLS-22] Introducing service method for digest validation using an istance of http-verifier --- core/build.gradle | 1 + .../config/HttpMessageVerifierConfig.java | 12 ++++ .../exception/LollipopDigestException.java | 2 + .../model/LollipopConsumerRequest.java | 6 +- .../service/AssertionVerifierService.java | 2 +- .../service/HttpMessageVerifierService.java | 3 +- ...java => AssertionVerifierServiceImpl.java} | 2 +- .../impl/HttpMessageVerifierServiceImpl.java | 64 +++++++++++++++++++ .../HttpMessageVerifierServiceImplStub.java | 15 ----- .../HttpMessageVerifierServiceImplTest.java | 47 ++++++++++++++ 10 files changed, 134 insertions(+), 20 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/config/HttpMessageVerifierConfig.java rename core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/{AssertionVerifierServiceImplStub.java => AssertionVerifierServiceImpl.java} (93%) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java create mode 100644 core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java diff --git a/core/build.gradle b/core/build.gradle index eafeb47c..b74c00ae 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -22,6 +22,7 @@ repositories { dependencies { implementation 'com.typesafe:config:1.4.2' + implementation 'javax.inject:javax.inject:1' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.mockito:mockito-core:5.2.0' diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/HttpMessageVerifierConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/HttpMessageVerifierConfig.java new file mode 100644 index 00000000..7e0d7f98 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/HttpMessageVerifierConfig.java @@ -0,0 +1,12 @@ +package it.pagopa.tech.lollipop.consumer.config; + +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class HttpMessageVerifierConfig { + + private String contentDigestHeader; + +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopDigestException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopDigestException.java index a3970dc1..29bd4863 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopDigestException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopDigestException.java @@ -48,6 +48,8 @@ public ErrorCode getErrorCode() { * Error codes to classify Digest Exceptions */ public enum ErrorCode { + + MISSING_DIGEST, /** * No supported hash algorithms detected when verifying or processing Want-...-Digest headers. */ diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java index 6d8773af..378eb2cb 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java @@ -1,12 +1,14 @@ package it.pagopa.tech.lollipop.consumer.model; +import lombok.Builder; +import lombok.Data; import lombok.Getter; import lombok.Setter; import java.util.Map; -@Getter -@Setter +@Data +@Builder public class LollipopConsumerRequest { private String requestBody; private Map requestParams; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java index ced5d889..7b9641f0 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java @@ -3,6 +3,6 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; public interface AssertionVerifierService { - boolean validateLollipop(LollipopConsumerRequest request); + } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java index 0ce11eda..4411997c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java @@ -1,8 +1,9 @@ package it.pagopa.tech.lollipop.consumer.service; +import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; public interface HttpMessageVerifierService { + boolean verifyHttpMessage(LollipopConsumerRequest request) throws LollipopDigestException; - boolean verifyHttpMessage(LollipopConsumerRequest request); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java similarity index 93% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index 86e763de..bddd41d9 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -7,7 +7,7 @@ import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; -public class AssertionVerifierServiceImplStub implements AssertionVerifierService { +public class AssertionVerifierServiceImpl implements AssertionVerifierService { private IdpCertProvider idpCertProvider; private AssertionService assertion; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java new file mode 100644 index 00000000..cfa579f1 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java @@ -0,0 +1,64 @@ +package it.pagopa.tech.lollipop.consumer.service.impl; + +import it.pagopa.tech.lollipop.consumer.config.HttpMessageVerifierConfig; +import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; + +import javax.inject.Inject; +import java.io.UnsupportedEncodingException; + +public class HttpMessageVerifierServiceImpl implements HttpMessageVerifierService { + + private HttpMessageVerifier httpMessageVerifier; + private HttpMessageVerifierConfig httpMessageVerifierConfig; + + @Inject + public HttpMessageVerifierServiceImpl(HttpMessageVerifier httpMessageVerifier, + HttpMessageVerifierConfig httpMessageVerifierConfig) { + this.httpMessageVerifier = httpMessageVerifier; + this.httpMessageVerifierConfig = httpMessageVerifierConfig; + } + + @Override + public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest) throws LollipopDigestException { + return verifyContentDigest(lollipopConsumerRequest) && verifyHttpSignature(lollipopConsumerRequest); + } + + protected boolean verifyContentDigest(LollipopConsumerRequest lollipopConsumerRequest) throws LollipopDigestException { + + // Attempt to recover content-digest + String contentDigest = lollipopConsumerRequest.getHeaderParams() + .get(httpMessageVerifierConfig.getContentDigestHeader()); + + if (contentDigest == null) { + throw new LollipopDigestException + (LollipopDigestException.ErrorCode.MISSING_DIGEST, + "Missing required Content-Digest for validation"); + } + + //Attempt to execute digest validation + try { + if (!httpMessageVerifier.verifyDigest( + contentDigest, + lollipopConsumerRequest.getRequestBody(), + null)) { + throw new LollipopDigestException( + LollipopDigestException.ErrorCode.INCORRECT_DIGEST,"Invalid Digest"); + } + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + + return true; + } + + /** + * TODO: stub + */ + private boolean verifyHttpSignature(LollipopConsumerRequest lollipopConsumerRequest) { + return true; + } + +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java deleted file mode 100644 index ae413b41..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java +++ /dev/null @@ -1,15 +0,0 @@ -package it.pagopa.tech.lollipop.consumer.service.impl; - -import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; -import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; -import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; - -public class HttpMessageVerifierServiceImplStub implements HttpMessageVerifierService { - - private HttpMessageVerifier httpMessageVerifier; - - @Override - public boolean verifyHttpMessage(LollipopConsumerRequest request) { - return false; - } -} diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java new file mode 100644 index 00000000..212bae8b --- /dev/null +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java @@ -0,0 +1,47 @@ +package it.pagopa.tech.lollipop.consumer.service.impl; + +import it.pagopa.tech.lollipop.consumer.config.HttpMessageVerifierConfig; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +class HttpMessageVerifierServiceImplTest { + + private HttpMessageVerifierConfig httpMessageVerifierConfig; + private HttpMessageVerifier httpMessageVerifier; + + private HttpMessageVerifierServiceImpl httpMessageVerifierService; + + public HttpMessageVerifierServiceImplTest() { + MockitoAnnotations.openMocks(this); + this.httpMessageVerifierConfig = HttpMessageVerifierConfig + .builder() + .contentDigestHeader("UTF_8") + .build(); + this.httpMessageVerifier = Mockito.mock(HttpMessageVerifier.class); + } + + @BeforeEach + public void beforeEach() { + Mockito.reset(httpMessageVerifier); + this.httpMessageVerifierService = new HttpMessageVerifierServiceImpl( + httpMessageVerifier,httpMessageVerifierConfig); + } + + @Test + public void validDigestIsProcessed() { + + LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); + //httpMessageVerifierService.verifyContentDigest(lollipopConsumerRequest); + + } + + private LollipopConsumerRequest getLollipopConsumerRequest() { + return LollipopConsumerRequest.builder().build(); + } + +} \ No newline at end of file From 0d06fc2c0cfc313d0d18d13bda6439008193ebb7 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 4 Apr 2023 14:33:55 +0200 Subject: [PATCH 018/403] [SLS-5] Introduced gradle plugin to apply reproducible builds and .buildinfo file production --- build.gradle | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/build.gradle b/build.gradle index e2232130..434f23a7 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,6 @@ plugins { id 'java' + id("org.kordamp.gradle.reproducible") version "0.50.0" } repositories { @@ -14,6 +15,7 @@ allprojects { targetCompatibility = '11' } + // Settings for allowing reproducible build tasks.withType(AbstractArchiveTask).configureEach { preserveFileTimestamps = false @@ -23,6 +25,7 @@ tasks.withType(AbstractArchiveTask).configureEach { subprojects { apply plugin: 'java' + apply plugin: 'org.kordamp.gradle.reproducible' apply plugin: 'maven-publish' java { @@ -30,6 +33,14 @@ subprojects { withJavadocJar() } + config { + reproducible { + enabled + additionalProperties + additionalArtifacts + } + } + // Settings for allowing reproducible build tasks.withType(AbstractArchiveTask).configureEach { preserveFileTimestamps = false From 4de449d53d4f544c17b8723ebb75f15023bdc2b3 Mon Sep 17 00:00:00 2001 From: giomella Date: Tue, 4 Apr 2023 17:02:19 +0200 Subject: [PATCH 019/403] [SLS-10] implemented command and commandBuilder interface. Added unit test. --- core/build.gradle | 1 + .../LollipopConsumerCommandBuilderImpl.java | 32 ++++++ ...ollipopConsumerCommandBuilderImplStub.java | 12 --- .../impl/LollipopConsumerCommandImpl.java | 95 ++++++++++++++++++ .../impl/LollipopConsumerCommandImplStub.java | 12 --- .../AssertionVerificationResultCode.java | 17 ++++ .../HttpMessageVerificationResultCode.java | 27 +++++ .../helper/LollipopConsumerFactoryHelper.java | 48 +++++++++ .../LollipopConsumerFactoryHelperStub.java | 26 ----- .../consumer/model/CommandResult.java | 2 + .../service/HttpMessageVerifierService.java | 5 +- ...java => AssertionVerifierServiceImpl.java} | 13 ++- ...va => HttpMessageVerifierServiceImpl.java} | 9 +- .../impl/LollipopConsumerCommandImplTest.java | 99 +++++++++++++++++++ 14 files changed, 344 insertions(+), 54 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplStub.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplStub.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/HttpMessageVerificationResultCode.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelperStub.java rename core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/{AssertionVerifierServiceImplStub.java => AssertionVerifierServiceImpl.java} (75%) rename core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/{HttpMessageVerifierServiceImplStub.java => HttpMessageVerifierServiceImpl.java} (62%) create mode 100644 core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java diff --git a/core/build.gradle b/core/build.gradle index eafeb47c..12f5fdab 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -21,6 +21,7 @@ repositories { } dependencies { + implementation 'javax.inject:javax.inject:1' implementation 'com.typesafe:config:1.4.2' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java new file mode 100644 index 00000000..c92708d4 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java @@ -0,0 +1,32 @@ +package it.pagopa.tech.lollipop.consumer.command.impl; + +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 javax.inject.Inject; + +/** + * Builder class for creating command instance + */ +public class LollipopConsumerCommandBuilderImpl implements LollipopConsumerCommandBuilder { + + private final LollipopConsumerFactoryHelper factoryHelper; + + @Inject + public LollipopConsumerCommandBuilderImpl(LollipopConsumerFactoryHelper factoryHelper) { + this.factoryHelper = factoryHelper; + } + + /** + * Builder for creating an instance of {@link LollipopConsumerCommand} + * @return an instance of {@link LollipopConsumerCommand} + */ + @Override + public LollipopConsumerCommand createCommand() { + return new LollipopConsumerCommandImpl( + factoryHelper.getHttpMessageVerifierService(), + factoryHelper.getAssertionVerifierService() + ); + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplStub.java deleted file mode 100644 index 1b07bb05..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplStub.java +++ /dev/null @@ -1,12 +0,0 @@ -package it.pagopa.tech.lollipop.consumer.command.impl; - -import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; -import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; - -public class LollipopConsumerCommandBuilderImplStub implements LollipopConsumerCommandBuilder { - - @Override - public LollipopConsumerCommand createCommand() { - return null; - } -} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java new file mode 100644 index 00000000..aae4bb4f --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -0,0 +1,95 @@ +package it.pagopa.tech.lollipop.consumer.command.impl; + +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; +import it.pagopa.tech.lollipop.consumer.enumeration.AssertionVerificationResultCode; +import it.pagopa.tech.lollipop.consumer.enumeration.HttpMessageVerificationResultCode; +import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.model.CommandResult; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; +import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; + +import javax.inject.Inject; +import java.io.UnsupportedEncodingException; + +/** + * Implementation of the {@link LollipopConsumerCommand} + */ +public class LollipopConsumerCommandImpl implements LollipopConsumerCommand { + + private final HttpMessageVerifierService messageVerifierService; + private final AssertionVerifierService assertionVerifierService; + + public static final String VERIFICATION_SUCCESS_CODE = "SUCCESS"; + + @Inject + public LollipopConsumerCommandImpl(HttpMessageVerifierService messageVerifierService, AssertionVerifierService assertionVerifierService) { + this.messageVerifierService = messageVerifierService; + this.assertionVerifierService = assertionVerifierService; + } + + /** + * 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) { + + CommandResult messageVerificationResult = getHttpMessageVerificationResult(request); + if (!messageVerificationResult.getResultCode().equals(HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_SUCCESS.name())) { + return messageVerificationResult; + } + CommandResult assertionVerificationResult = getAssertionVerificationResult(request); + if (!assertionVerificationResult.getResultCode().equals(AssertionVerificationResultCode.ASSERTION_VERIFICATION_SUCCESS.name())) { + return assertionVerificationResult; + } + return buildCommandResult(VERIFICATION_SUCCESS_CODE, "Verification completed successfully"); + } + + private CommandResult getAssertionVerificationResult(LollipopConsumerRequest request) { + boolean result = assertionVerifierService.validateLollipop(request); + + if (!result) { + return buildCommandResult( + AssertionVerificationResultCode.ASSERTION_VERIFICATION_FAILED.name(), + "Validation of SAML assertion failed, authentication failed" + ); + } + + return buildCommandResult( + AssertionVerificationResultCode.ASSERTION_VERIFICATION_SUCCESS.name(), + "SAML assertion validated successfully" + ); + } + + private CommandResult getHttpMessageVerificationResult(LollipopConsumerRequest request) { + boolean result; + try { + result = messageVerifierService.verifyHttpMessage(request); + } catch (LollipopDigestException e) { + String message = String.format("HTTP message validation failed on verifying digest with error code %s and message: %s", e.getErrorCode(), e.getMessage()); + return buildCommandResult(HttpMessageVerificationResultCode.DIGEST_VALIDATION_ERROR.name(), message); + } catch (UnsupportedEncodingException e) { + String message = String.format("HTTP message validation failed on encoding request body with message: %s", e.getMessage()); + return buildCommandResult(HttpMessageVerificationResultCode.UNSUPPORTED_ENCODING.name(), message); + } + + if (!result) { + return buildCommandResult( + HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_FAILED.name(), + "Validation of HTTP message failed, authentication failed" + ); + } + return buildCommandResult( + HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_SUCCESS.name(), + "HTTP message validated successfully" + ); + } + + private CommandResult buildCommandResult(String resultCode, String message) { + return new CommandResult(resultCode, message); + } + +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplStub.java deleted file mode 100644 index 5f0a621b..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplStub.java +++ /dev/null @@ -1,12 +0,0 @@ -package it.pagopa.tech.lollipop.consumer.command.impl; - -import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; -import it.pagopa.tech.lollipop.consumer.model.CommandResult; -import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; - -public class LollipopConsumerCommandImplStub implements LollipopConsumerCommand { - @Override - public CommandResult doExecute(LollipopConsumerRequest request) { - return null; - } -} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java new file mode 100644 index 00000000..5747b9b3 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java @@ -0,0 +1,17 @@ +package it.pagopa.tech.lollipop.consumer.enumeration; + +/** + * Result codes to classify Saml assertion validation + */ +public enum AssertionVerificationResultCode { + + /** + * Saml assertion validation failed without throwing an exception + */ + ASSERTION_VERIFICATION_FAILED, + + /** + * Saml assertion validation completed successfully + */ + ASSERTION_VERIFICATION_SUCCESS +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/HttpMessageVerificationResultCode.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/HttpMessageVerificationResultCode.java new file mode 100644 index 00000000..60928581 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/HttpMessageVerificationResultCode.java @@ -0,0 +1,27 @@ +package it.pagopa.tech.lollipop.consumer.enumeration; + +/** + * Result codes to classify HTTP message validation + */ +public enum HttpMessageVerificationResultCode { + + /** + * Digest validation failed throwing an exception + */ + DIGEST_VALIDATION_ERROR, + + /** + * No supported encoding detected when encoding request body + */ + UNSUPPORTED_ENCODING, + + /** + * HTTP message validation failed without throwing an exception + */ + HTTP_MESSAGE_VALIDATION_FAILED, + + /** + * HTTP message validation completed successfully + */ + HTTP_MESSAGE_VALIDATION_SUCCESS +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java new file mode 100644 index 00000000..de2ba466 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -0,0 +1,48 @@ +package it.pagopa.tech.lollipop.consumer.helper; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; +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.impl.AssertionVerifierServiceImpl; +import it.pagopa.tech.lollipop.consumer.service.impl.HttpMessageVerifierServiceImpl; + +/** + * Helper class for retrieving instances + */ +public class LollipopConsumerFactoryHelper { + + private HttpMessageVerifierFactory httpMessageVerifierFactory; + private IdpCertProviderFactory idpCertProviderFactory; + private AssertionServiceFactory assertionServiceFactory; + + /** + * Utility method for retrieving an instance of {@link HttpMessageVerifierService} + * @return an instance of {@link HttpMessageVerifierService} + */ + public HttpMessageVerifierService getHttpMessageVerifierService() { + return new HttpMessageVerifierServiceImpl(getHttpMessageVerifierFactory().create()); + } + + /** + * Utility method for retrieving an instance of {@link AssertionVerifierService} + * @return an instance of {@link AssertionVerifierService} + */ + public AssertionVerifierService getAssertionVerifierService() { + return new AssertionVerifierServiceImpl(getIdpCertProviderFactory().create(), getAssertionServiceFactory().create()); + } + + public HttpMessageVerifierFactory getHttpMessageVerifierFactory() { + return null; + } + + public IdpCertProviderFactory getIdpCertProviderFactory() { + return null; + } + + public AssertionServiceFactory getAssertionServiceFactory() { + return null; + } + +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelperStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelperStub.java deleted file mode 100644 index 5b7cb212..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelperStub.java +++ /dev/null @@ -1,26 +0,0 @@ -package it.pagopa.tech.lollipop.consumer.helper; - -import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; -import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; -import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; -import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; - -public class LollipopConsumerFactoryHelperStub { - - public HttpMessageVerifierService getHttpMessageVerifierService(){ - return null; - } - - public AssertionVerifierService getAssertionVerifierService(){ - return null; - } - - public HttpMessageVerifierFactory getHttpMessageVerifierFactory(){ - return null; - } - - public IdpCertProviderFactory getIdpCertProviderFactory(){ - return null; - } - -} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/CommandResult.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/CommandResult.java index 33a8ceb7..4199263c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/CommandResult.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/CommandResult.java @@ -1,10 +1,12 @@ package it.pagopa.tech.lollipop.consumer.model; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; @Getter @Setter +@AllArgsConstructor public class CommandResult { private String resultCode; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java index 0ce11eda..460cf987 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java @@ -1,8 +1,11 @@ package it.pagopa.tech.lollipop.consumer.service; +import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import java.io.UnsupportedEncodingException; + public interface HttpMessageVerifierService { - boolean verifyHttpMessage(LollipopConsumerRequest request); + boolean verifyHttpMessage(LollipopConsumerRequest request) throws LollipopDigestException, UnsupportedEncodingException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java similarity index 75% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index 86e763de..2e6c71bf 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -7,10 +7,19 @@ import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; -public class AssertionVerifierServiceImplStub implements AssertionVerifierService { +import javax.inject.Inject; + +public class AssertionVerifierServiceImpl implements AssertionVerifierService { private IdpCertProvider idpCertProvider; - private AssertionService assertion; + private AssertionService assertionService; + + @Inject + public AssertionVerifierServiceImpl(IdpCertProvider idpCertProvider, AssertionService assertionService) { + this.idpCertProvider = idpCertProvider; + this.assertionService = assertionService; + } + @Override public boolean validateLollipop(LollipopConsumerRequest request) { return false; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java similarity index 62% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java index ae413b41..f67022dd 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplStub.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java @@ -4,10 +4,17 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; -public class HttpMessageVerifierServiceImplStub implements HttpMessageVerifierService { +import javax.inject.Inject; + +public class HttpMessageVerifierServiceImpl implements HttpMessageVerifierService { private HttpMessageVerifier httpMessageVerifier; + @Inject + public HttpMessageVerifierServiceImpl(HttpMessageVerifier httpMessageVerifier) { + this.httpMessageVerifier = httpMessageVerifier; + } + @Override public boolean verifyHttpMessage(LollipopConsumerRequest request) { return false; diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java new file mode 100644 index 00000000..205655a9 --- /dev/null +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -0,0 +1,99 @@ +package it.pagopa.tech.lollipop.consumer.command.impl; + +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; +import it.pagopa.tech.lollipop.consumer.enumeration.AssertionVerificationResultCode; +import it.pagopa.tech.lollipop.consumer.enumeration.HttpMessageVerificationResultCode; +import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.model.CommandResult; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; +import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; +import org.junit.jupiter.api.*; +import org.mockito.*; + +import java.io.UnsupportedEncodingException; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +class LollipopConsumerCommandImplTest { + + private static HttpMessageVerifierService messageVerifierServiceMock; + private static AssertionVerifierService assertionVerifierServiceMock; + private static LollipopConsumerCommand sut; + + @BeforeEach + void beforeAll() { + messageVerifierServiceMock = Mockito.mock(HttpMessageVerifierService.class); + assertionVerifierServiceMock = Mockito.mock(AssertionVerifierService.class); + sut = Mockito.spy(new LollipopConsumerCommandImpl(messageVerifierServiceMock, assertionVerifierServiceMock)); + } + + @Test + void failedHttpMessageValidationThrowDigestException() throws LollipopDigestException, UnsupportedEncodingException { + + doThrow(new LollipopDigestException(LollipopDigestException.ErrorCode.INCORRECT_DIGEST, "error")) + .when(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + + CommandResult commandResult = sut.doExecute(new LollipopConsumerRequest()); + + Assertions.assertEquals(HttpMessageVerificationResultCode.DIGEST_VALIDATION_ERROR.name(), commandResult.getResultCode()); + + verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock, never()).validateLollipop(any(LollipopConsumerRequest.class)); + } + + @Test + void failedHttpMessageValidationThrowUnsupportedEncodingException() throws LollipopDigestException, UnsupportedEncodingException { + + doThrow(UnsupportedEncodingException.class).when(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + + CommandResult commandResult = sut.doExecute(new LollipopConsumerRequest()); + + Assertions.assertEquals(HttpMessageVerificationResultCode.UNSUPPORTED_ENCODING.name(), commandResult.getResultCode()); + + verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock, never()).validateLollipop(any(LollipopConsumerRequest.class)); + } + + @Test + void failedHttpMessageValidationWithoutThrowingException() throws LollipopDigestException, UnsupportedEncodingException { + + doReturn(false).when(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + + CommandResult commandResult = sut.doExecute(new LollipopConsumerRequest()); + + Assertions.assertEquals(HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_FAILED.name(), commandResult.getResultCode()); + + verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock, never()).validateLollipop(any(LollipopConsumerRequest.class)); + } + + @Test + void failedAssertionValidationWithoutThrowingException() throws LollipopDigestException, UnsupportedEncodingException { + + doReturn(true).when(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + doReturn(false).when(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); + + CommandResult commandResult = sut.doExecute(new LollipopConsumerRequest()); + + Assertions.assertEquals(AssertionVerificationResultCode.ASSERTION_VERIFICATION_FAILED.name(), commandResult.getResultCode()); + + verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); + } + + @Test + void successLollipopRequestValidation() throws LollipopDigestException, UnsupportedEncodingException { + + doReturn(true).when(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + doReturn(true).when(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); + + CommandResult commandResult = sut.doExecute(new LollipopConsumerRequest()); + + Assertions.assertEquals("SUCCESS", commandResult.getResultCode()); + + verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); + } +} \ No newline at end of file From 343e3c42847782da8d4f902f68165cddb3b2e71e Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 4 Apr 2023 18:05:26 +0200 Subject: [PATCH 020/403] [SLS-22] Updated digest verification service --- .../config/HttpMessageVerifierConfig.java | 12 ----- .../config/LollipopConsumerRequestConfig.java | 15 ++++++ ...ava => LollipopConsumerFactoryHelper.java} | 4 +- .../HttpMessageVerifierFactory.java | 1 + .../service/HttpMessageVerifierService.java | 4 +- .../impl/HttpMessageVerifierServiceImpl.java | 53 ++++++++++++------- .../HttpMessageVerifierServiceImplTest.java | 45 ++++++++++++---- 7 files changed, 90 insertions(+), 44 deletions(-) delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/config/HttpMessageVerifierConfig.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java rename core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/{LollipopConsumerFactoryHelperStub.java => LollipopConsumerFactoryHelper.java} (92%) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/HttpMessageVerifierConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/HttpMessageVerifierConfig.java deleted file mode 100644 index 7e0d7f98..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/HttpMessageVerifierConfig.java +++ /dev/null @@ -1,12 +0,0 @@ -package it.pagopa.tech.lollipop.consumer.config; - -import lombok.Builder; -import lombok.Data; - -@Builder -@Data -public class HttpMessageVerifierConfig { - - private String contentDigestHeader; - -} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java new file mode 100644 index 00000000..99da2159 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -0,0 +1,15 @@ +package it.pagopa.tech.lollipop.consumer.config; + +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class LollipopConsumerRequestConfig { + + private String signatureHeader = "signature"; + private String signatureInputHeader = "signature-input"; + private String contentEncodingHeader = "content-encoding"; + private String contentDigestHeader = "content-digest"; + +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelperStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java similarity index 92% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelperStub.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index 5b7cb212..d8fec185 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelperStub.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -5,7 +5,7 @@ import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; -public class LollipopConsumerFactoryHelperStub { +public class LollipopConsumerFactoryHelper { public HttpMessageVerifierService getHttpMessageVerifierService(){ return null; @@ -15,7 +15,7 @@ public AssertionVerifierService getAssertionVerifierService(){ return null; } - public HttpMessageVerifierFactory getHttpMessageVerifierFactory(){ + public HttpMessageVerifierFactory getHttpMessageVerifierFactory() { return null; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java index aac9ba96..d9957de6 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java @@ -3,4 +3,5 @@ public interface HttpMessageVerifierFactory { HttpMessageVerifier create(); + } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java index 4411997c..b600f740 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java @@ -3,7 +3,9 @@ import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import java.io.UnsupportedEncodingException; + public interface HttpMessageVerifierService { - boolean verifyHttpMessage(LollipopConsumerRequest request) throws LollipopDigestException; + boolean verifyHttpMessage(LollipopConsumerRequest request) throws LollipopDigestException, UnsupportedEncodingException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java index cfa579f1..a19b691c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java @@ -1,6 +1,6 @@ package it.pagopa.tech.lollipop.consumer.service.impl; -import it.pagopa.tech.lollipop.consumer.config.HttpMessageVerifierConfig; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; @@ -8,29 +8,45 @@ import javax.inject.Inject; import java.io.UnsupportedEncodingException; +import java.util.Map; public class HttpMessageVerifierServiceImpl implements HttpMessageVerifierService { private HttpMessageVerifier httpMessageVerifier; - private HttpMessageVerifierConfig httpMessageVerifierConfig; + private LollipopConsumerRequestConfig lollipopConsumerRequestConfig; @Inject public HttpMessageVerifierServiceImpl(HttpMessageVerifier httpMessageVerifier, - HttpMessageVerifierConfig httpMessageVerifierConfig) { + LollipopConsumerRequestConfig lollipopConsumerRequestConfig) { this.httpMessageVerifier = httpMessageVerifier; - this.httpMessageVerifierConfig = httpMessageVerifierConfig; + this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; } @Override - public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest) throws LollipopDigestException { - return verifyContentDigest(lollipopConsumerRequest) && verifyHttpSignature(lollipopConsumerRequest); + public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest) + throws LollipopDigestException, UnsupportedEncodingException { + + Map headerParams = lollipopConsumerRequest.getHeaderParams(); + + String signatureInput = headerParams.get(lollipopConsumerRequestConfig.getSignatureInputHeader()); + + if (signatureInput == null) { + + } + + String contentDigest = null; + + String requestBody = null; + + String contentEncoding = null; + + return verifyContentDigest(contentDigest, requestBody, contentEncoding) && verifyHttpSignature(lollipopConsumerRequest); } - protected boolean verifyContentDigest(LollipopConsumerRequest lollipopConsumerRequest) throws LollipopDigestException { + protected boolean verifyContentDigest(String contentDigest, String requestBody, String contentEncoding) + throws LollipopDigestException, UnsupportedEncodingException { + - // Attempt to recover content-digest - String contentDigest = lollipopConsumerRequest.getHeaderParams() - .get(httpMessageVerifierConfig.getContentDigestHeader()); if (contentDigest == null) { throw new LollipopDigestException @@ -38,17 +54,14 @@ protected boolean verifyContentDigest(LollipopConsumerRequest lollipopConsumerRe "Missing required Content-Digest for validation"); } + //Attempt to execute digest validation - try { - if (!httpMessageVerifier.verifyDigest( - contentDigest, - lollipopConsumerRequest.getRequestBody(), - null)) { - throw new LollipopDigestException( - LollipopDigestException.ErrorCode.INCORRECT_DIGEST,"Invalid Digest"); - } - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); + if (!httpMessageVerifier.verifyDigest( + contentDigest, + requestBody, + contentEncoding)) { + throw new LollipopDigestException( + LollipopDigestException.ErrorCode.INCORRECT_DIGEST,"Invalid Digest"); } return true; diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java index 212bae8b..e9a46435 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java @@ -1,47 +1,74 @@ package it.pagopa.tech.lollipop.consumer.service.impl; -import it.pagopa.tech.lollipop.consumer.config.HttpMessageVerifierConfig; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; -import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; + +import static org.mockito.Mockito.when; + class HttpMessageVerifierServiceImplTest { - private HttpMessageVerifierConfig httpMessageVerifierConfig; + final String VALID_DIGEST = "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw="; + final String VALID_PAYLOAD = "a valid message payload"; + final String INVALID_ENCODING = "UTF-326"; + + private LollipopConsumerRequestConfig httpMessageVerifierConfig; private HttpMessageVerifier httpMessageVerifier; private HttpMessageVerifierServiceImpl httpMessageVerifierService; public HttpMessageVerifierServiceImplTest() { MockitoAnnotations.openMocks(this); - this.httpMessageVerifierConfig = HttpMessageVerifierConfig + this.httpMessageVerifierConfig = LollipopConsumerRequestConfig .builder() - .contentDigestHeader("UTF_8") + .contentDigestHeader("Content-Digest") + .contentEncodingHeader("Content-Encoding") + .signatureHeader("Signature-Input") .build(); this.httpMessageVerifier = Mockito.mock(HttpMessageVerifier.class); } @BeforeEach - public void beforeEach() { + public void beforeEach() throws LollipopDigestException, UnsupportedEncodingException { Mockito.reset(httpMessageVerifier); + when(httpMessageVerifier.verifyDigest( + Mockito.eq(VALID_DIGEST), + Mockito.eq(VALID_PAYLOAD), + Mockito.eq("UTF-8"))).thenReturn(true); this.httpMessageVerifierService = new HttpMessageVerifierServiceImpl( httpMessageVerifier,httpMessageVerifierConfig); } @Test - public void validDigestIsProcessed() { + public void validDigestIsProcessed() throws LollipopDigestException, UnsupportedEncodingException { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); - //httpMessageVerifierService.verifyContentDigest(lollipopConsumerRequest); + httpMessageVerifierService.verifyContentDigest(lollipopConsumerRequest); } private LollipopConsumerRequest getLollipopConsumerRequest() { - return LollipopConsumerRequest.builder().build(); + + HashMap lollipopHeaderParams = new HashMap<>(); + lollipopHeaderParams.put("Content-Digest",VALID_DIGEST); + lollipopHeaderParams.put("Content-Encoding", "UTF-8"); + lollipopHeaderParams.put("Signature-Input", "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" " + + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" + + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); + + return LollipopConsumerRequest + .builder() + .requestBody(VALID_PAYLOAD) + .headerParams(lollipopHeaderParams) + .build(); } } \ No newline at end of file From 4b067096263b3c27c7c2832f4ed0b203041ec26a Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 4 Apr 2023 18:22:50 +0200 Subject: [PATCH 021/403] [SLS-5] Introducing verification-metadata.xml and build.gradle and .gitignore --- .gitignore | 3 - assertion-rest-client-native/build.gradle | 2 +- core/build.gradle | 2 +- gradle/verification-metadata.xml | 255 ++++++++++++++++++ http-verifier/build.gradle | 2 +- .../build.gradle | 2 +- redis-storage/build.gradle | 2 +- 7 files changed, 260 insertions(+), 8 deletions(-) create mode 100644 gradle/verification-metadata.xml diff --git a/.gitignore b/.gitignore index 7b524df4..89912179 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,5 @@ # Ignore IntelliJ .idea -# Ignore Gradle -gradle - # Ignore Gradle build output directory build diff --git a/assertion-rest-client-native/build.gradle b/assertion-rest-client-native/build.gradle index bb4d99f8..0c6725c5 100644 --- a/assertion-rest-client-native/build.gradle +++ b/assertion-rest-client-native/build.gradle @@ -10,7 +10,7 @@ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' - id("io.freefair.lombok") version "8.0.0-rc4" + id("io.freefair.lombok") version "8.0.0" } group 'it.pagopa.commons' diff --git a/core/build.gradle b/core/build.gradle index 88334cd9..e54cc377 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -10,7 +10,7 @@ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' - id("io.freefair.lombok") version "8.0.0-rc4" + id("io.freefair.lombok") version "8.0.0" } group 'it.pagopa.commons' diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml new file mode 100644 index 00000000..af28f58b --- /dev/null +++ b/gradle/verification-metadata.xml @@ -0,0 +1,255 @@ + + + + true + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index bb4d99f8..0c6725c5 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -10,7 +10,7 @@ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' - id("io.freefair.lombok") version "8.0.0-rc4" + id("io.freefair.lombok") version "8.0.0" } group 'it.pagopa.commons' diff --git a/identity-service-rest-client-native/build.gradle b/identity-service-rest-client-native/build.gradle index bb4d99f8..0c6725c5 100644 --- a/identity-service-rest-client-native/build.gradle +++ b/identity-service-rest-client-native/build.gradle @@ -10,7 +10,7 @@ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' - id("io.freefair.lombok") version "8.0.0-rc4" + id("io.freefair.lombok") version "8.0.0" } group 'it.pagopa.commons' diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle index bb4d99f8..0c6725c5 100644 --- a/redis-storage/build.gradle +++ b/redis-storage/build.gradle @@ -10,7 +10,7 @@ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' - id("io.freefair.lombok") version "8.0.0-rc4" + id("io.freefair.lombok") version "8.0.0" } group 'it.pagopa.commons' From 7e97ffd50aef82f24d9305a20d7547eb85a082b7 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 4 Apr 2023 11:14:03 +0200 Subject: [PATCH 022/403] [SLS-22] Introducing factory implementation of http verifier and related services --- http-verifier/build.gradle | 2 +- .../verifier/visma/ErrorCodeConverter.java | 9 +++++- .../visma/VismaHttpMessageVerifier.java | 14 ++++++--- .../VismaHttpMessageVerifierFactory.java | 31 +++++++++++++++++++ .../VismaHttpMessageVerifierFactoryTest.java | 31 +++++++++++++++++++ .../visma/VismaHttpMessageVerifierTest.java | 20 ++++++------ 6 files changed, 90 insertions(+), 17 deletions(-) rename http-verifier/src/main/java/it/pagopa/{ => tech}/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java (69%) rename http-verifier/src/main/java/it/pagopa/{ => tech}/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java (85%) create mode 100644 http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactory.java create mode 100644 http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactoryTest.java rename http-verifier/src/test/java/it/pagopa/{ => tech}/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java (91%) diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index 80ee0b8f..9c4f3327 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -13,7 +13,7 @@ plugins { id("io.freefair.lombok") version "8.0.0-rc4" } -group 'it.pagopa.commons' +group 'it.pagopa.tech' repositories { mavenLocal() diff --git a/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java similarity index 69% rename from http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java rename to http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java index bdebe657..e43632f6 100644 --- a/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java @@ -1,10 +1,17 @@ -package it.pagopa.lollipop.consumer.http.verifier.visma; +package it.pagopa.tech.lollipop.consumer.http.verifier.visma; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import net.visma.autopay.http.digest.DigestException; +/** + * Manages the conversion between {@link DigestException.ErrorCode} and {@link LollipopDigestException.ErrorCode} + */ public class ErrorCodeConverter { + /** + * @param errorCode {@link DigestException.ErrorCode} to convert + * @return converted {@link LollipopDigestException.ErrorCode} + */ public static LollipopDigestException.ErrorCode convertErrorCode(DigestException.ErrorCode errorCode) { if (errorCode != null) { diff --git a/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java similarity index 85% rename from http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java rename to http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java index b243de1d..5f8156d3 100644 --- a/http-verifier/src/main/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java @@ -1,7 +1,8 @@ -package it.pagopa.lollipop.consumer.http.verifier.visma; +package it.pagopa.tech.lollipop.consumer.http.verifier.visma; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; +import lombok.AllArgsConstructor; import net.visma.autopay.http.digest.DigestException; import java.io.UnsupportedEncodingException; @@ -10,15 +11,18 @@ /** Implementation of the @HttpMessageVerifier using Visma-AutoPay http-signature of the http-signature draft */ +@AllArgsConstructor public class VismaHttpMessageVerifier implements HttpMessageVerifier { + private String defaultEncoding; + /** * Validates digest using Visma DigestVerifier method. Applies contentEncoding if present, otherwise defaults * to UTF-8 * * @param digest Request digest * @param requestBody Request body - * @param encoding Content encoding + * @param encoding Content encoding, if missing uses defaultEncoding * @return boolean with value true if digest validated * @throws LollipopDigestException if error from DigestVerifier * @throws UnsupportedEncodingException if attempted to encode with an unsupported format @@ -29,7 +33,7 @@ public boolean verifyDigest(String digest, String requestBody, String encoding) try { net.visma.autopay.http.digest.DigestVerifier.verifyDigestHeader(digest, requestBody.getBytes(encoding != null ? - encoding : "UTF-8")); + encoding : defaultEncoding)); return true; } catch (DigestException e) { throw new LollipopDigestException( @@ -41,8 +45,8 @@ public boolean verifyDigest(String digest, String requestBody, String encoding) } } - /* - + /** + * TODO: stub */ @Override public boolean verifyHttpSignature(String signature, String signatureInput, Map parameters) { diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactory.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactory.java new file mode 100644 index 00000000..8bd753cc --- /dev/null +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactory.java @@ -0,0 +1,31 @@ +package it.pagopa.tech.lollipop.consumer.http.verifier.visma; + +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; + +import java.nio.charset.Charset; + +/** + * Implements {@link HttpMessageVerifierFactory} with Visma-AutoPay http-signature library + */ +public class VismaHttpMessageVerifierFactory implements HttpMessageVerifierFactory { + + private final String defaultEncoding; + + public VismaHttpMessageVerifierFactory(String defaultEncoding) throws Exception { + if (Charset.availableCharsets().get(defaultEncoding) == null) { + throw new Exception("Unavailable Encoding: " + defaultEncoding); + } + this.defaultEncoding = defaultEncoding; + } + + /** + * {@inheritDoc} + * @return instance of {@link VismaHttpMessageVerifierFactory}, passing the configured default encoding + **/ + @Override + public HttpMessageVerifier create() { + return new VismaHttpMessageVerifier(defaultEncoding); + } + +} diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactoryTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactoryTest.java new file mode 100644 index 00000000..ead71f3f --- /dev/null +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactoryTest.java @@ -0,0 +1,31 @@ +package it.pagopa.tech.lollipop.consumer.http.verifier.visma; + +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; +import lombok.SneakyThrows; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; + +class VismaHttpMessageVerifierFactoryTest { + + @Test + public void encodingInCostructorIsInvalid() { + assertThatThrownBy(() -> new VismaHttpMessageVerifierFactory("UTF-326")) + .isInstanceOfSatisfying(Exception.class, e -> + assertThat(e).hasMessageContaining("Unavailable Encoding: UTF-326")); + } + + @Test + public void encodingInCostructorIsValid() { + assertThatNoException().isThrownBy( + () -> new VismaHttpMessageVerifierFactory("UTF-8")); + } + + @SneakyThrows + @Test + public void instanceIsCreated() { + assertThat(new VismaHttpMessageVerifierFactory("UTF-8").create()) + .isInstanceOf(VismaHttpMessageVerifier.class); + } + +} \ No newline at end of file diff --git a/http-verifier/src/test/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java similarity index 91% rename from http-verifier/src/test/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java rename to http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java index 233e9c3c..ee31e2ba 100644 --- a/http-verifier/src/test/java/it/pagopa/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java @@ -20,7 +20,7 @@ * SOFTWARE. */ -package it.pagopa.lollipop.consumer.http.verifier.visma; +package it.pagopa.tech.lollipop.consumer.http.verifier.visma; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import net.visma.autopay.http.digest.DigestException; @@ -30,12 +30,12 @@ import static org.assertj.core.api.Assertions.*; -class VismaHttpMessageVerifierTest { +public class VismaHttpMessageVerifierTest { - public VismaHttpMessageVerifier vismaDigestVerifier = new VismaHttpMessageVerifier(); + public VismaHttpMessageVerifier vismaDigestVerifier = new VismaHttpMessageVerifier("UTF-8"); @Test - void correctDigestIsVerified() { + public void correctDigestIsVerified() { // setup var content = new String(new byte[]{1, 2, 4}); var header = "md5=:V9tg6T+1JldSH4+Zy8c5jw==:,sha-256=:1LKaloxAFzY43tjRdMhpV6+iEb5HnO4CDbpd/hJ9kco=:"; @@ -46,7 +46,7 @@ void correctDigestIsVerified() { } @Test - void invalidDigestIsDetected() { + public void invalidDigestIsDetected() { // setup var content = new String(new byte[]{1, 2, 4}); var header = "sha-256=:A5BYxvLAy0ksUzsKTRTvd8wPeKvMztUofYShogEc+4E=:"; @@ -61,7 +61,7 @@ void invalidDigestIsDetected() { } @Test - void malformedDigestIsDetected() { + public void malformedDigestIsDetected() { // setup var content = new String(new byte[]{1, 2, 4}); var header = "sha-256=1LKaloxAFzY43tjRdMhpV6+iEb5HnO4CDbpd/hJ9kco="; @@ -76,7 +76,7 @@ void malformedDigestIsDetected() { } @Test - void unsupportedAlgorithmsAreDetected() { + public void unsupportedAlgorithmsAreDetected() { // setup var content = new String(new byte[]{1, 2, 4}); var header = "md5=:V9tg6T+1JldSH4+Zy8c5jw==: ,sha=:q3kRUT3rxwFa1QQpqBWXcUWLJM4=:"; @@ -91,7 +91,7 @@ void unsupportedAlgorithmsAreDetected() { } @Test - void emptyHeaderIsDetected() { + public void emptyHeaderIsDetected() { // setup var content = new String(new byte[]{1, 2, 4}); var header = ""; @@ -106,7 +106,7 @@ void emptyHeaderIsDetected() { } @Test - void invalidDictionaryValuesAreDetected() { + public void invalidDictionaryValuesAreDetected() { // setup var content = new String(new byte[]{1, 2, 4}); var header = "sha-256=ok"; @@ -121,7 +121,7 @@ void invalidDictionaryValuesAreDetected() { } @Test - void invalidContentEncoding() { + public void invalidContentEncoding() { // setup var content = new String(new byte[]{1, 2, 4}); var header = "sha-256=ok"; From 097e4f916780d32a5502dc890f47ac3a398e83d6 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 4 Apr 2023 11:17:18 +0200 Subject: [PATCH 023/403] [SLS-22] Introducing factory implementation of http verifier and related services --- .../verifier => http_verifier}/visma/ErrorCodeConverter.java | 2 +- .../visma/VismaHttpMessageVerifier.java | 2 +- .../visma/VismaHttpMessageVerifierFactory.java | 2 +- .../visma/VismaHttpMessageVerifierFactoryTest.java | 3 +-- .../visma/VismaHttpMessageVerifierTest.java | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) rename http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/{http/verifier => http_verifier}/visma/ErrorCodeConverter.java (94%) rename http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/{http/verifier => http_verifier}/visma/VismaHttpMessageVerifier.java (96%) rename http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/{http/verifier => http_verifier}/visma/VismaHttpMessageVerifierFactory.java (94%) rename http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/{http/verifier => http_verifier}/visma/VismaHttpMessageVerifierFactoryTest.java (85%) rename http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/{http/verifier => http_verifier}/visma/VismaHttpMessageVerifierTest.java (98%) diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/ErrorCodeConverter.java similarity index 94% rename from http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java rename to http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/ErrorCodeConverter.java index e43632f6..cef315ae 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/ErrorCodeConverter.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/ErrorCodeConverter.java @@ -1,4 +1,4 @@ -package it.pagopa.tech.lollipop.consumer.http.verifier.visma; +package it.pagopa.tech.lollipop.consumer.http_verifier.visma; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import net.visma.autopay.http.digest.DigestException; diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java similarity index 96% rename from http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java rename to http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java index 5f8156d3..0fd314ce 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifier.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java @@ -1,4 +1,4 @@ -package it.pagopa.tech.lollipop.consumer.http.verifier.visma; +package it.pagopa.tech.lollipop.consumer.http_verifier.visma; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactory.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java similarity index 94% rename from http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactory.java rename to http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java index 8bd753cc..b6de2cb1 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactory.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java @@ -1,4 +1,4 @@ -package it.pagopa.tech.lollipop.consumer.http.verifier.visma; +package it.pagopa.tech.lollipop.consumer.http_verifier.visma; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactoryTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java similarity index 85% rename from http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactoryTest.java rename to http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java index ead71f3f..fd6c327d 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierFactoryTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java @@ -1,6 +1,5 @@ -package it.pagopa.tech.lollipop.consumer.http.verifier.visma; +package it.pagopa.tech.lollipop.consumer.http_verifier.visma; -import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; import lombok.SneakyThrows; import org.junit.jupiter.api.Test; diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java similarity index 98% rename from http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java rename to http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java index ee31e2ba..65a5725a 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http/verifier/visma/VismaHttpMessageVerifierTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java @@ -20,7 +20,7 @@ * SOFTWARE. */ -package it.pagopa.tech.lollipop.consumer.http.verifier.visma; +package it.pagopa.tech.lollipop.consumer.http_verifier.visma; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import net.visma.autopay.http.digest.DigestException; From 386abcd9888f2cacda952b16491255638b56fabe Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 4 Apr 2023 14:25:50 +0200 Subject: [PATCH 024/403] [SLS-22] Introducing service method for digest validation using an istance of http-verifier --- core/build.gradle | 1 + .../config/HttpMessageVerifierConfig.java | 12 +++++ .../exception/LollipopDigestException.java | 2 + .../model/LollipopConsumerRequest.java | 6 ++- .../service/AssertionVerifierService.java | 2 +- .../service/HttpMessageVerifierService.java | 2 +- .../impl/HttpMessageVerifierServiceImpl.java | 48 +++++++++++++++++-- .../HttpMessageVerifierServiceImplTest.java | 47 ++++++++++++++++++ 8 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/config/HttpMessageVerifierConfig.java create mode 100644 core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java diff --git a/core/build.gradle b/core/build.gradle index 12f5fdab..dc099cbc 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -23,6 +23,7 @@ repositories { dependencies { implementation 'javax.inject:javax.inject:1' implementation 'com.typesafe:config:1.4.2' + implementation 'javax.inject:javax.inject:1' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.mockito:mockito-core:5.2.0' diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/HttpMessageVerifierConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/HttpMessageVerifierConfig.java new file mode 100644 index 00000000..7e0d7f98 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/HttpMessageVerifierConfig.java @@ -0,0 +1,12 @@ +package it.pagopa.tech.lollipop.consumer.config; + +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class HttpMessageVerifierConfig { + + private String contentDigestHeader; + +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopDigestException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopDigestException.java index a3970dc1..29bd4863 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopDigestException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopDigestException.java @@ -48,6 +48,8 @@ public ErrorCode getErrorCode() { * Error codes to classify Digest Exceptions */ public enum ErrorCode { + + MISSING_DIGEST, /** * No supported hash algorithms detected when verifying or processing Want-...-Digest headers. */ diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java index 6d8773af..378eb2cb 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java @@ -1,12 +1,14 @@ package it.pagopa.tech.lollipop.consumer.model; +import lombok.Builder; +import lombok.Data; import lombok.Getter; import lombok.Setter; import java.util.Map; -@Getter -@Setter +@Data +@Builder public class LollipopConsumerRequest { private String requestBody; private Map requestParams; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java index ced5d889..7b9641f0 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java @@ -3,6 +3,6 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; public interface AssertionVerifierService { - boolean validateLollipop(LollipopConsumerRequest request); + } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java index 460cf987..7556bcc7 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java @@ -1,11 +1,11 @@ package it.pagopa.tech.lollipop.consumer.service; -import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import java.io.UnsupportedEncodingException; public interface HttpMessageVerifierService { + boolean verifyHttpMessage(LollipopConsumerRequest request) throws LollipopDigestException; boolean verifyHttpMessage(LollipopConsumerRequest request) throws LollipopDigestException, UnsupportedEncodingException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java index f67022dd..cfa579f1 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java @@ -1,22 +1,64 @@ package it.pagopa.tech.lollipop.consumer.service.impl; +import it.pagopa.tech.lollipop.consumer.config.HttpMessageVerifierConfig; +import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; import javax.inject.Inject; +import java.io.UnsupportedEncodingException; public class HttpMessageVerifierServiceImpl implements HttpMessageVerifierService { private HttpMessageVerifier httpMessageVerifier; + private HttpMessageVerifierConfig httpMessageVerifierConfig; @Inject - public HttpMessageVerifierServiceImpl(HttpMessageVerifier httpMessageVerifier) { + public HttpMessageVerifierServiceImpl(HttpMessageVerifier httpMessageVerifier, + HttpMessageVerifierConfig httpMessageVerifierConfig) { this.httpMessageVerifier = httpMessageVerifier; + this.httpMessageVerifierConfig = httpMessageVerifierConfig; } @Override - public boolean verifyHttpMessage(LollipopConsumerRequest request) { - return false; + public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest) throws LollipopDigestException { + return verifyContentDigest(lollipopConsumerRequest) && verifyHttpSignature(lollipopConsumerRequest); } + + protected boolean verifyContentDigest(LollipopConsumerRequest lollipopConsumerRequest) throws LollipopDigestException { + + // Attempt to recover content-digest + String contentDigest = lollipopConsumerRequest.getHeaderParams() + .get(httpMessageVerifierConfig.getContentDigestHeader()); + + if (contentDigest == null) { + throw new LollipopDigestException + (LollipopDigestException.ErrorCode.MISSING_DIGEST, + "Missing required Content-Digest for validation"); + } + + //Attempt to execute digest validation + try { + if (!httpMessageVerifier.verifyDigest( + contentDigest, + lollipopConsumerRequest.getRequestBody(), + null)) { + throw new LollipopDigestException( + LollipopDigestException.ErrorCode.INCORRECT_DIGEST,"Invalid Digest"); + } + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + + return true; + } + + /** + * TODO: stub + */ + private boolean verifyHttpSignature(LollipopConsumerRequest lollipopConsumerRequest) { + return true; + } + } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java new file mode 100644 index 00000000..212bae8b --- /dev/null +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java @@ -0,0 +1,47 @@ +package it.pagopa.tech.lollipop.consumer.service.impl; + +import it.pagopa.tech.lollipop.consumer.config.HttpMessageVerifierConfig; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +class HttpMessageVerifierServiceImplTest { + + private HttpMessageVerifierConfig httpMessageVerifierConfig; + private HttpMessageVerifier httpMessageVerifier; + + private HttpMessageVerifierServiceImpl httpMessageVerifierService; + + public HttpMessageVerifierServiceImplTest() { + MockitoAnnotations.openMocks(this); + this.httpMessageVerifierConfig = HttpMessageVerifierConfig + .builder() + .contentDigestHeader("UTF_8") + .build(); + this.httpMessageVerifier = Mockito.mock(HttpMessageVerifier.class); + } + + @BeforeEach + public void beforeEach() { + Mockito.reset(httpMessageVerifier); + this.httpMessageVerifierService = new HttpMessageVerifierServiceImpl( + httpMessageVerifier,httpMessageVerifierConfig); + } + + @Test + public void validDigestIsProcessed() { + + LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); + //httpMessageVerifierService.verifyContentDigest(lollipopConsumerRequest); + + } + + private LollipopConsumerRequest getLollipopConsumerRequest() { + return LollipopConsumerRequest.builder().build(); + } + +} \ No newline at end of file From d8c07cc9a9f2882affd0a1d06b241cfeef396f9b Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 4 Apr 2023 18:05:26 +0200 Subject: [PATCH 025/403] [SLS-22] Updated digest verification service --- .../config/HttpMessageVerifierConfig.java | 12 ----- .../config/LollipopConsumerRequestConfig.java | 15 ++++++ .../HttpMessageVerifierFactory.java | 1 + .../service/HttpMessageVerifierService.java | 2 +- .../impl/HttpMessageVerifierServiceImpl.java | 53 ++++++++++++------- .../HttpMessageVerifierServiceImplTest.java | 45 ++++++++++++---- 6 files changed, 86 insertions(+), 42 deletions(-) delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/config/HttpMessageVerifierConfig.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/HttpMessageVerifierConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/HttpMessageVerifierConfig.java deleted file mode 100644 index 7e0d7f98..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/HttpMessageVerifierConfig.java +++ /dev/null @@ -1,12 +0,0 @@ -package it.pagopa.tech.lollipop.consumer.config; - -import lombok.Builder; -import lombok.Data; - -@Builder -@Data -public class HttpMessageVerifierConfig { - - private String contentDigestHeader; - -} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java new file mode 100644 index 00000000..99da2159 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -0,0 +1,15 @@ +package it.pagopa.tech.lollipop.consumer.config; + +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class LollipopConsumerRequestConfig { + + private String signatureHeader = "signature"; + private String signatureInputHeader = "signature-input"; + private String contentEncodingHeader = "content-encoding"; + private String contentDigestHeader = "content-digest"; + +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java index aac9ba96..d9957de6 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java @@ -3,4 +3,5 @@ public interface HttpMessageVerifierFactory { HttpMessageVerifier create(); + } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java index 7556bcc7..40829822 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java @@ -5,7 +5,7 @@ import java.io.UnsupportedEncodingException; public interface HttpMessageVerifierService { - boolean verifyHttpMessage(LollipopConsumerRequest request) throws LollipopDigestException; + boolean verifyHttpMessage(LollipopConsumerRequest request) throws LollipopDigestException, UnsupportedEncodingException; boolean verifyHttpMessage(LollipopConsumerRequest request) throws LollipopDigestException, UnsupportedEncodingException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java index cfa579f1..a19b691c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java @@ -1,6 +1,6 @@ package it.pagopa.tech.lollipop.consumer.service.impl; -import it.pagopa.tech.lollipop.consumer.config.HttpMessageVerifierConfig; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; @@ -8,29 +8,45 @@ import javax.inject.Inject; import java.io.UnsupportedEncodingException; +import java.util.Map; public class HttpMessageVerifierServiceImpl implements HttpMessageVerifierService { private HttpMessageVerifier httpMessageVerifier; - private HttpMessageVerifierConfig httpMessageVerifierConfig; + private LollipopConsumerRequestConfig lollipopConsumerRequestConfig; @Inject public HttpMessageVerifierServiceImpl(HttpMessageVerifier httpMessageVerifier, - HttpMessageVerifierConfig httpMessageVerifierConfig) { + LollipopConsumerRequestConfig lollipopConsumerRequestConfig) { this.httpMessageVerifier = httpMessageVerifier; - this.httpMessageVerifierConfig = httpMessageVerifierConfig; + this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; } @Override - public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest) throws LollipopDigestException { - return verifyContentDigest(lollipopConsumerRequest) && verifyHttpSignature(lollipopConsumerRequest); + public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest) + throws LollipopDigestException, UnsupportedEncodingException { + + Map headerParams = lollipopConsumerRequest.getHeaderParams(); + + String signatureInput = headerParams.get(lollipopConsumerRequestConfig.getSignatureInputHeader()); + + if (signatureInput == null) { + + } + + String contentDigest = null; + + String requestBody = null; + + String contentEncoding = null; + + return verifyContentDigest(contentDigest, requestBody, contentEncoding) && verifyHttpSignature(lollipopConsumerRequest); } - protected boolean verifyContentDigest(LollipopConsumerRequest lollipopConsumerRequest) throws LollipopDigestException { + protected boolean verifyContentDigest(String contentDigest, String requestBody, String contentEncoding) + throws LollipopDigestException, UnsupportedEncodingException { + - // Attempt to recover content-digest - String contentDigest = lollipopConsumerRequest.getHeaderParams() - .get(httpMessageVerifierConfig.getContentDigestHeader()); if (contentDigest == null) { throw new LollipopDigestException @@ -38,17 +54,14 @@ protected boolean verifyContentDigest(LollipopConsumerRequest lollipopConsumerRe "Missing required Content-Digest for validation"); } + //Attempt to execute digest validation - try { - if (!httpMessageVerifier.verifyDigest( - contentDigest, - lollipopConsumerRequest.getRequestBody(), - null)) { - throw new LollipopDigestException( - LollipopDigestException.ErrorCode.INCORRECT_DIGEST,"Invalid Digest"); - } - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); + if (!httpMessageVerifier.verifyDigest( + contentDigest, + requestBody, + contentEncoding)) { + throw new LollipopDigestException( + LollipopDigestException.ErrorCode.INCORRECT_DIGEST,"Invalid Digest"); } return true; diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java index 212bae8b..e9a46435 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java @@ -1,47 +1,74 @@ package it.pagopa.tech.lollipop.consumer.service.impl; -import it.pagopa.tech.lollipop.consumer.config.HttpMessageVerifierConfig; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; -import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; + +import static org.mockito.Mockito.when; + class HttpMessageVerifierServiceImplTest { - private HttpMessageVerifierConfig httpMessageVerifierConfig; + final String VALID_DIGEST = "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw="; + final String VALID_PAYLOAD = "a valid message payload"; + final String INVALID_ENCODING = "UTF-326"; + + private LollipopConsumerRequestConfig httpMessageVerifierConfig; private HttpMessageVerifier httpMessageVerifier; private HttpMessageVerifierServiceImpl httpMessageVerifierService; public HttpMessageVerifierServiceImplTest() { MockitoAnnotations.openMocks(this); - this.httpMessageVerifierConfig = HttpMessageVerifierConfig + this.httpMessageVerifierConfig = LollipopConsumerRequestConfig .builder() - .contentDigestHeader("UTF_8") + .contentDigestHeader("Content-Digest") + .contentEncodingHeader("Content-Encoding") + .signatureHeader("Signature-Input") .build(); this.httpMessageVerifier = Mockito.mock(HttpMessageVerifier.class); } @BeforeEach - public void beforeEach() { + public void beforeEach() throws LollipopDigestException, UnsupportedEncodingException { Mockito.reset(httpMessageVerifier); + when(httpMessageVerifier.verifyDigest( + Mockito.eq(VALID_DIGEST), + Mockito.eq(VALID_PAYLOAD), + Mockito.eq("UTF-8"))).thenReturn(true); this.httpMessageVerifierService = new HttpMessageVerifierServiceImpl( httpMessageVerifier,httpMessageVerifierConfig); } @Test - public void validDigestIsProcessed() { + public void validDigestIsProcessed() throws LollipopDigestException, UnsupportedEncodingException { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); - //httpMessageVerifierService.verifyContentDigest(lollipopConsumerRequest); + httpMessageVerifierService.verifyContentDigest(lollipopConsumerRequest); } private LollipopConsumerRequest getLollipopConsumerRequest() { - return LollipopConsumerRequest.builder().build(); + + HashMap lollipopHeaderParams = new HashMap<>(); + lollipopHeaderParams.put("Content-Digest",VALID_DIGEST); + lollipopHeaderParams.put("Content-Encoding", "UTF-8"); + lollipopHeaderParams.put("Signature-Input", "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" " + + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" + + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); + + return LollipopConsumerRequest + .builder() + .requestBody(VALID_PAYLOAD) + .headerParams(lollipopHeaderParams) + .build(); } } \ No newline at end of file From 4bf84c8ef9d15fc90c2625712735c61e4df1c79b Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 4 Apr 2023 20:01:36 +0200 Subject: [PATCH 026/403] [SLS-22] Updated digest verification service --- assertion-rest-client-native/build.gradle | 22 ++-- build.gradle | 62 +++++----- core/build.gradle | 30 ++--- .../consumer/assertion/AssertionService.java | 1 + .../assertion/AssertionServiceFactory.java | 1 + .../assertion/client/AssertionClient.java | 1 + .../client/AssertionClientProvider.java | 1 + .../impl/AssertionServiceFactoryImplStub.java | 4 +- .../impl/AssertionServiceImplStub.java | 4 +- .../assertion/storage/AssertionStorage.java | 3 +- .../storage/AssertionStorageProvider.java | 1 + .../command/LollipopConsumerCommand.java | 1 + .../LollipopConsumerCommandBuilder.java | 1 + .../LollipopConsumerCommandBuilderImpl.java | 10 +- .../impl/LollipopConsumerCommandImpl.java | 63 ++++++---- .../config/LollipopConsumerRequestConfig.java | 2 +- .../AssertionVerificationResultCode.java | 13 +- .../HttpMessageVerificationResultCode.java | 23 ++-- .../exception/LollipopDigestException.java | 33 +++-- .../exception/LollipopVerifierException.java | 53 ++++++++ .../helper/LollipopConsumerFactoryHelper.java | 17 ++- .../http_verifier/HttpMessageVerifier.java | 8 +- .../HttpMessageVerifierFactory.java | 2 +- .../consumer/idp/IdpCertProvider.java | 2 +- .../consumer/idp/IdpCertProviderFactory.java | 1 + .../consumer/idp/client/IdpCertClient.java | 1 + .../idp/client/IdpCertClientProvider.java | 1 + .../impl/IdpCertProviderFactoryImplStub.java | 2 + .../idp/impl/IdpCertProviderImplStub.java | 2 + .../consumer/idp/storage/IdpCertStorage.java | 5 +- .../idp/storage/IdpCertStorageProvider.java | 2 +- .../consumer/model/CommandResult.java | 1 + .../lollipop/consumer/model/IdpCertData.java | 2 +- .../model/LollipopConsumerRequest.java | 6 +- .../consumer/model/SamlAssertion.java | 1 + .../service/AssertionVerifierService.java | 2 +- .../service/HttpMessageVerifierService.java | 7 +- .../impl/AssertionVerifierServiceImpl.java | 33 +++-- .../impl/HttpMessageVerifierServiceImpl.java | 73 ++++++----- .../impl/LollipopConsumerCommandImplTest.java | 101 ++++++++++----- .../HttpMessageVerifierServiceImplTest.java | 57 ++++----- http-verifier/build.gradle | 26 ++-- .../visma/ErrorCodeConverter.java | 12 +- .../visma/VismaHttpMessageVerifier.java | 30 ++--- .../VismaHttpMessageVerifierFactory.java | 13 +- .../VismaHttpMessageVerifierFactoryTest.java | 16 +-- .../visma/VismaHttpMessageVerifierTest.java | 116 ++++++++---------- .../build.gradle | 22 ++-- redis-storage/build.gradle | 22 ++-- 49 files changed, 528 insertions(+), 384 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java diff --git a/assertion-rest-client-native/build.gradle b/assertion-rest-client-native/build.gradle index 41547144..fe16fc06 100644 --- a/assertion-rest-client-native/build.gradle +++ b/assertion-rest-client-native/build.gradle @@ -8,25 +8,25 @@ plugins { - // Apply the java-library plugin for API and implementation separation. - id 'java-library' - id("io.freefair.lombok") version "8.0.0-rc4" + // Apply the java-library plugin for API and implementation separation. + id 'java-library' + id("io.freefair.lombok") version "8.0.0-rc4" } group 'it.pagopa.commons' repositories { - mavenLocal() - mavenCentral() + mavenLocal() + mavenCentral() } dependencies { - implementation project(path: ':core') - // Use JUnit Jupiter for testing. - testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + implementation project(path: ':core') + // Use JUnit Jupiter for testing. + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' } tasks.named('test') { - // Use JUnit Platform for unit tests. - useJUnitPlatform() -} \ No newline at end of file + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} diff --git a/build.gradle b/build.gradle index 9402f4c1..b47fb75c 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,34 @@ allprojects { apply plugin: 'com.diffplug.spotless' apply plugin: 'nebula.lint' gradleLint.rules = ['all-dependency'] + + spotless { + // optional: limit format enforcement to just the files changed by this feature branch + ratchetFrom 'origin/main' + + format 'misc', { + // define the files to apply `misc` to + target '*.gradle', '*.md', '.gitignore' + + // define the steps to apply to those files + trimTrailingWhitespace() + indentWithTabs() // or spaces. Takes an integer argument if you don't like 4 + endWithNewline() + } + java { + // don't need to set target, it is inferred from java + + // apply a specific flavor of google-java-format + googleJavaFormat('1.11.0').aosp().reflowLongStrings() + // fix formatting of type annotations + formatAnnotations() + // make sure every file has the following copyright header. + // optionally, Spotless can set copyright years by digging + // through git history (see "license" section below) + licenseHeader '/* (C)$YEAR */' + } + } + } tasks.withType(AbstractArchiveTask).configureEach { @@ -23,36 +51,6 @@ tasks.withType(AbstractArchiveTask).configureEach { reproducibleFileOrder = true } -tasks.withType(JavaCompile) { - options.compilerArgs.add('-Xlint:all') -} - -spotless { - // optional: limit format enforcement to just the files changed by this feature branch - ratchetFrom 'origin/main' - - format 'misc', { - // define the files to apply `misc` to - target '*.gradle', '*.md', '.gitignore' - - // define the steps to apply to those files - trimTrailingWhitespace() - indentWithTabs() // or spaces. Takes an integer argument if you don't like 4 - endWithNewline() - } - java { - // don't need to set target, it is inferred from java - - // apply a specific flavor of google-java-format - googleJavaFormat('1.11.0').aosp().reflowLongStrings() - // fix formatting of type annotations - formatAnnotations() - // make sure every file has the following copyright header. - // optionally, Spotless can set copyright years by digging - // through git history (see "license" section below) - licenseHeader '/* (C)$YEAR */' - } -} subprojects { @@ -66,6 +64,10 @@ subprojects { withJavadocJar() } + tasks.withType(JavaCompile) { + options.compilerArgs.add('-Xlint:all') + } + publishing { publications { maven(MavenPublication) { diff --git a/core/build.gradle b/core/build.gradle index dc099cbc..2c7fe8c3 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -8,29 +8,29 @@ plugins { - // Apply the java-library plugin for API and implementation separation. - id 'java-library' - id("io.freefair.lombok") version "8.0.0-rc4" + // Apply the java-library plugin for API and implementation separation. + id 'java-library' + id("io.freefair.lombok") version "8.0.0-rc4" } group 'it.pagopa.tech' repositories { - mavenLocal() - mavenCentral() + mavenLocal() + mavenCentral() } dependencies { - implementation 'javax.inject:javax.inject:1' - implementation 'com.typesafe:config:1.4.2' - implementation 'javax.inject:javax.inject:1' - // Use JUnit Jupiter for testing. - testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' - testImplementation 'org.mockito:mockito-core:5.2.0' - testImplementation 'org.mockito:mockito-junit-jupiter:5.2.0' + implementation 'javax.inject:javax.inject:1' + implementation 'com.typesafe:config:1.4.2' + implementation 'javax.inject:javax.inject:1' + // Use JUnit Jupiter for testing. + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + testImplementation 'org.mockito:mockito-core:5.2.0' + testImplementation 'org.mockito:mockito-junit-jupiter:5.2.0' } tasks.named('test') { - // Use JUnit Platform for unit tests. - useJUnitPlatform() -} \ No newline at end of file + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionService.java index f3a77a64..f755062f 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionService.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionServiceFactory.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionServiceFactory.java index 9d32fc76..0b1bd266 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionServiceFactory.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionServiceFactory.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion; public interface AssertionServiceFactory { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClient.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClient.java index 47f9e744..3699c68f 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClient.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClient.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClientProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClientProvider.java index 89dc738e..f5758b35 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClientProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClientProvider.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client; public interface AssertionClientProvider { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java index 2130967c..874c1158 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java @@ -1,13 +1,15 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.impl; import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; -import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorageProvider; import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClientProvider; +import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorageProvider; public class AssertionServiceFactoryImplStub implements AssertionServiceFactory { private AssertionStorageProvider assertionStorageProvider; private AssertionClientProvider assertionClientProvider; + @Override public AssertionService create() { return null; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java index 2348974b..a6feea97 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java @@ -1,14 +1,16 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.impl; import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; -import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorage; import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClient; +import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorage; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; public class AssertionServiceImplStub implements AssertionService { private AssertionStorage assertionStorage; private AssertionClient assertionClient; + @Override public SamlAssertion getAssertion(String jwt, String assertionRef) { return null; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorage.java index 2655d113..5883d6f9 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorage.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.storage; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; @@ -5,6 +6,6 @@ public interface AssertionStorage { SamlAssertion getAssertion(String assertionRef); - void saveAssertion(SamlAssertion assertion); + void saveAssertion(SamlAssertion assertion); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorageProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorageProvider.java index 3f0d47db..abe8bb25 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorageProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorageProvider.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.storage; public interface AssertionStorageProvider { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java index 3b5b5a75..90f6c288 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.command; import it.pagopa.tech.lollipop.consumer.model.CommandResult; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java index af6d5a91..63b66261 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.command; public interface LollipopConsumerCommandBuilder { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java index c92708d4..891e789d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java @@ -1,14 +1,12 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.command.impl; 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 javax.inject.Inject; -/** - * Builder class for creating command instance - */ +/** Builder class for creating command instance */ public class LollipopConsumerCommandBuilderImpl implements LollipopConsumerCommandBuilder { private final LollipopConsumerFactoryHelper factoryHelper; @@ -20,13 +18,13 @@ public LollipopConsumerCommandBuilderImpl(LollipopConsumerFactoryHelper factoryH /** * Builder for creating an instance of {@link LollipopConsumerCommand} + * * @return an instance of {@link LollipopConsumerCommand} */ @Override public LollipopConsumerCommand createCommand() { return new LollipopConsumerCommandImpl( factoryHelper.getHttpMessageVerifierService(), - factoryHelper.getAssertionVerifierService() - ); + factoryHelper.getAssertionVerifierService()); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index aae4bb4f..e0702845 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -1,20 +1,19 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.command.impl; import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionVerificationResultCode; import it.pagopa.tech.lollipop.consumer.enumeration.HttpMessageVerificationResultCode; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; import it.pagopa.tech.lollipop.consumer.model.CommandResult; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; - -import javax.inject.Inject; import java.io.UnsupportedEncodingException; +import javax.inject.Inject; -/** - * Implementation of the {@link LollipopConsumerCommand} - */ +/** Implementation of the {@link LollipopConsumerCommand} */ public class LollipopConsumerCommandImpl implements LollipopConsumerCommand { private final HttpMessageVerifierService messageVerifierService; @@ -23,13 +22,16 @@ public class LollipopConsumerCommandImpl implements LollipopConsumerCommand { public static final String VERIFICATION_SUCCESS_CODE = "SUCCESS"; @Inject - public LollipopConsumerCommandImpl(HttpMessageVerifierService messageVerifierService, AssertionVerifierService assertionVerifierService) { + public LollipopConsumerCommandImpl( + HttpMessageVerifierService messageVerifierService, + AssertionVerifierService assertionVerifierService) { this.messageVerifierService = messageVerifierService; this.assertionVerifierService = assertionVerifierService; } /** - * Command that execute all necessary method for validating a Lollipop request: HTTP message verification and Saml assertion verification + * 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 @@ -38,11 +40,15 @@ public LollipopConsumerCommandImpl(HttpMessageVerifierService messageVerifierSer public CommandResult doExecute(LollipopConsumerRequest request) { CommandResult messageVerificationResult = getHttpMessageVerificationResult(request); - if (!messageVerificationResult.getResultCode().equals(HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_SUCCESS.name())) { + if (!messageVerificationResult + .getResultCode() + .equals(HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_SUCCESS.name())) { return messageVerificationResult; } CommandResult assertionVerificationResult = getAssertionVerificationResult(request); - if (!assertionVerificationResult.getResultCode().equals(AssertionVerificationResultCode.ASSERTION_VERIFICATION_SUCCESS.name())) { + if (!assertionVerificationResult + .getResultCode() + .equals(AssertionVerificationResultCode.ASSERTION_VERIFICATION_SUCCESS.name())) { return assertionVerificationResult; } return buildCommandResult(VERIFICATION_SUCCESS_CODE, "Verification completed successfully"); @@ -54,14 +60,12 @@ private CommandResult getAssertionVerificationResult(LollipopConsumerRequest req if (!result) { return buildCommandResult( AssertionVerificationResultCode.ASSERTION_VERIFICATION_FAILED.name(), - "Validation of SAML assertion failed, authentication failed" - ); + "Validation of SAML assertion failed, authentication failed"); } return buildCommandResult( AssertionVerificationResultCode.ASSERTION_VERIFICATION_SUCCESS.name(), - "SAML assertion validated successfully" - ); + "SAML assertion validated successfully"); } private CommandResult getHttpMessageVerificationResult(LollipopConsumerRequest request) { @@ -69,27 +73,42 @@ private CommandResult getHttpMessageVerificationResult(LollipopConsumerRequest r try { result = messageVerifierService.verifyHttpMessage(request); } catch (LollipopDigestException e) { - String message = String.format("HTTP message validation failed on verifying digest with error code %s and message: %s", e.getErrorCode(), e.getMessage()); - return buildCommandResult(HttpMessageVerificationResultCode.DIGEST_VALIDATION_ERROR.name(), message); + String message = + String.format( + "HTTP message validation failed on verifying digest with error code %s" + + " and message: %s", + e.getErrorCode(), e.getMessage()); + return buildCommandResult( + HttpMessageVerificationResultCode.DIGEST_VALIDATION_ERROR.name(), message); } catch (UnsupportedEncodingException e) { - String message = String.format("HTTP message validation failed on encoding request body with message: %s", e.getMessage()); - return buildCommandResult(HttpMessageVerificationResultCode.UNSUPPORTED_ENCODING.name(), message); + String message = + String.format( + "HTTP message validation failed on encoding request body with message:" + + " %s", + e.getMessage()); + return buildCommandResult( + HttpMessageVerificationResultCode.UNSUPPORTED_ENCODING.name(), message); + } catch (LollipopVerifierException e) { + String message = + String.format( + "HTTP message validation failed on content validation with message:" + + " %s", + e.getMessage()); + return buildCommandResult( + HttpMessageVerificationResultCode.REQUEST_VALIDATION_ERROR.name(), message); } if (!result) { return buildCommandResult( HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_FAILED.name(), - "Validation of HTTP message failed, authentication failed" - ); + "Validation of HTTP message failed, authentication failed"); } return buildCommandResult( HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_SUCCESS.name(), - "HTTP message validated successfully" - ); + "HTTP message validated successfully"); } private CommandResult buildCommandResult(String resultCode, String message) { return new CommandResult(resultCode, message); } - } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index 99da2159..b2958e4d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.config; import lombok.Builder; @@ -11,5 +12,4 @@ public class LollipopConsumerRequestConfig { private String signatureInputHeader = "signature-input"; private String contentEncodingHeader = "content-encoding"; private String contentDigestHeader = "content-digest"; - } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java index 5747b9b3..eb4c55da 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java @@ -1,17 +1,12 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.enumeration; -/** - * Result codes to classify Saml assertion validation - */ +/** Result codes to classify Saml assertion validation */ public enum AssertionVerificationResultCode { - /** - * Saml assertion validation failed without throwing an exception - */ + /** Saml assertion validation failed without throwing an exception */ ASSERTION_VERIFICATION_FAILED, - /** - * Saml assertion validation completed successfully - */ + /** Saml assertion validation completed successfully */ ASSERTION_VERIFICATION_SUCCESS } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/HttpMessageVerificationResultCode.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/HttpMessageVerificationResultCode.java index 60928581..ea22ba65 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/HttpMessageVerificationResultCode.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/HttpMessageVerificationResultCode.java @@ -1,27 +1,20 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.enumeration; -/** - * Result codes to classify HTTP message validation - */ +/** Result codes to classify HTTP message validation */ public enum HttpMessageVerificationResultCode { - /** - * Digest validation failed throwing an exception - */ + /** Request validation failed throwing an exception */ + REQUEST_VALIDATION_ERROR, + /** Digest validation failed throwing an exception */ DIGEST_VALIDATION_ERROR, - /** - * No supported encoding detected when encoding request body - */ + /** No supported encoding detected when encoding request body */ UNSUPPORTED_ENCODING, - /** - * HTTP message validation failed without throwing an exception - */ + /** HTTP message validation failed without throwing an exception */ HTTP_MESSAGE_VALIDATION_FAILED, - /** - * HTTP message validation completed successfully - */ + /** HTTP message validation completed successfully */ HTTP_MESSAGE_VALIDATION_SUCCESS } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopDigestException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopDigestException.java index 29bd4863..c0bedde6 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopDigestException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopDigestException.java @@ -1,22 +1,22 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.exception; import java.util.Objects; /** - * Thrown in case of problems when computing or verifying digest, or when verified digest is incorrect + * Thrown in case of problems when computing or verifying digest, or when verified digest is + * incorrect */ public class LollipopDigestException extends Exception { - /** - * Error code of this exception - */ + /** Error code of this exception */ private final ErrorCode errorCode; /** * Constructs new exception with provided error code and message * * @param errorCode Error code - * @param message Detail message + * @param message Detail message */ public LollipopDigestException(ErrorCode errorCode, String message) { super(message); @@ -27,8 +27,8 @@ public LollipopDigestException(ErrorCode errorCode, String message) { * Constructs new exception with provided error code, message and cause * * @param errorCode Error code - * @param message Detail message - * @param cause Exception causing the constructed one + * @param message Detail message + * @param cause Exception causing the constructed one */ public LollipopDigestException(ErrorCode errorCode, String message, Throwable cause) { super(message, cause); @@ -44,26 +44,23 @@ public ErrorCode getErrorCode() { return errorCode; } - /** - * Error codes to classify Digest Exceptions - */ + /** Error codes to classify Digest Exceptions */ public enum ErrorCode { - MISSING_DIGEST, + MISSING_PAYLOAD, /** - * No supported hash algorithms detected when verifying or processing Want-...-Digest headers. + * No supported hash algorithms detected when verifying or processing + * Want-...-Digest headers. */ UNSUPPORTED_ALGORITHM, - /** - * When verifying, provided digest is different from the computed one - */ + /** When verifying, provided digest is different from the computed one */ INCORRECT_DIGEST, /** - * Parsed ...-Digest or Want-...-Digest header is not syntactically correct + * Parsed ...-Digest or Want-...-Digest header is not syntactically + * correct */ INVALID_HEADER, } - -} \ No newline at end of file +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java new file mode 100644 index 00000000..13b5ae0c --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java @@ -0,0 +1,53 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.exception; + +import java.util.Objects; + +/** + * Thrown in case of problems when computing or verifying lollipop request through the http-signature flow + */ +public class LollipopVerifierException extends Exception { + + /** Error code of this exception */ + private final ErrorCode errorCode; + + /** + * Constructs new exception with provided error code and message + * + * @param errorCode Error code + * @param message Detail message + */ + public LollipopVerifierException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Constructs new exception with provided error code, message and cause + * + * @param errorCode Error code + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public LollipopVerifierException(ErrorCode errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Returns error code + * + * @return Error code of this exception + */ + public ErrorCode getErrorCode() { + return errorCode; + } + + /** Error codes to classify Lollipop Request Exceptions */ + public enum ErrorCode { + + MISSING_SIGNATURE, + + MISSING_SIGNATURE_INPUT + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index de2ba466..ba74fe9d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -1,6 +1,8 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.helper; 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.IdpCertProviderFactory; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; @@ -8,9 +10,7 @@ import it.pagopa.tech.lollipop.consumer.service.impl.AssertionVerifierServiceImpl; import it.pagopa.tech.lollipop.consumer.service.impl.HttpMessageVerifierServiceImpl; -/** - * Helper class for retrieving instances - */ +/** Helper class for retrieving instances */ public class LollipopConsumerFactoryHelper { private HttpMessageVerifierFactory httpMessageVerifierFactory; @@ -19,18 +19,22 @@ public class LollipopConsumerFactoryHelper { /** * Utility method for retrieving an instance of {@link HttpMessageVerifierService} + * * @return an instance of {@link HttpMessageVerifierService} */ public HttpMessageVerifierService getHttpMessageVerifierService() { - return new HttpMessageVerifierServiceImpl(getHttpMessageVerifierFactory().create()); + return new HttpMessageVerifierServiceImpl( + getHttpMessageVerifierFactory().create(), getLollipopConsumerRequestConfig()); } /** * Utility method for retrieving an instance of {@link AssertionVerifierService} + * * @return an instance of {@link AssertionVerifierService} */ public AssertionVerifierService getAssertionVerifierService() { - return new AssertionVerifierServiceImpl(getIdpCertProviderFactory().create(), getAssertionServiceFactory().create()); + return new AssertionVerifierServiceImpl( + getIdpCertProviderFactory().create(), getAssertionServiceFactory().create()); } public HttpMessageVerifierFactory getHttpMessageVerifierFactory() { @@ -45,4 +49,7 @@ public AssertionServiceFactory getAssertionServiceFactory() { return null; } + public LollipopConsumerRequestConfig getLollipopConsumerRequestConfig() { + return LollipopConsumerRequestConfig.builder().build(); + } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java index e0e94d5a..eb7c7a4d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java @@ -1,13 +1,15 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.http_verifier; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; - import java.io.UnsupportedEncodingException; import java.util.Map; public interface HttpMessageVerifier { - boolean verifyDigest(String digest, String requestBody, String encoding) throws LollipopDigestException, UnsupportedEncodingException; - boolean verifyHttpSignature(String signature, String signatureInput, Map parameters); + boolean verifyDigest(String digest, String requestBody, String encoding) + throws LollipopDigestException, UnsupportedEncodingException; + boolean verifyHttpSignature( + String signature, String signatureInput, Map parameters); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java index d9957de6..73bfbbf4 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java @@ -1,7 +1,7 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.http_verifier; public interface HttpMessageVerifierFactory { HttpMessageVerifier create(); - } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java index 819945ee..7aaed7a2 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java @@ -1,7 +1,7 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp; public interface IdpCertProvider { boolean getIdpCertData(String assertionInstant, String entityId); - } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProviderFactory.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProviderFactory.java index 87f86053..901084ce 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProviderFactory.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProviderFactory.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp; public interface IdpCertProviderFactory { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java index 0f4eaa96..7629f668 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClientProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClientProvider.java index dc49904d..af94fd0d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClientProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClientProvider.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client; public interface IdpCertClientProvider { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java index 5595a0b4..c72c7da6 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.impl; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; @@ -9,6 +10,7 @@ public class IdpCertProviderFactoryImplStub implements IdpCertProviderFactory { private IdpCertClientProvider idpCertClientProvider; private IdpCertStorageProvider idpCertStorageProvider; + @Override public IdpCertProvider create() { return null; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java index 64b0b838..b6df7d6f 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.impl; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; @@ -8,6 +9,7 @@ public class IdpCertProviderImplStub implements IdpCertProvider { private IdpCertClient idpCertClient; private IdpCertStorage idpCertStorage; + @Override public boolean getIdpCertData(String assertionInstant, String entityId) { return false; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java index 3c8a334b..6226daf2 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java @@ -1,13 +1,16 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.storage; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; - import java.util.List; public interface IdpCertStorage { List getTagList(); + void saveTagList(List tagList); + IdpCertData getIdpCertData(String tag); + void saveIdpCertData(String tag); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageProvider.java index a49c3628..3f045332 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageProvider.java @@ -1,6 +1,6 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.storage; - public interface IdpCertStorageProvider { IdpCertStorage provideStorage(); diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/CommandResult.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/CommandResult.java index 4199263c..af008398 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/CommandResult.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/CommandResult.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.model; import lombok.AllArgsConstructor; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java index f01c3bce..6c0aaa2e 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.model; import lombok.Getter; @@ -10,5 +11,4 @@ public class IdpCertData { private String entityId; private String tag; private String certData; - } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java index 378eb2cb..e6e9f5de 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java @@ -1,11 +1,9 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.model; +import java.util.Map; import lombok.Builder; import lombok.Data; -import lombok.Getter; -import lombok.Setter; - -import java.util.Map; @Data @Builder diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java index 0510d980..c063a711 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.model; import lombok.Getter; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java index 7b9641f0..b5b2c4c9 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java @@ -1,8 +1,8 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; public interface AssertionVerifierService { boolean validateLollipop(LollipopConsumerRequest request); - } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java index 4454412f..70e82c3b 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java @@ -1,9 +1,12 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import java.io.UnsupportedEncodingException; public interface HttpMessageVerifierService { - - boolean verifyHttpMessage(LollipopConsumerRequest request) throws LollipopDigestException, UnsupportedEncodingException; + boolean verifyHttpMessage(LollipopConsumerRequest request) + throws LollipopDigestException, UnsupportedEncodingException, LollipopDigestException, LollipopVerifierException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index 2e6c71bf..9c8243f8 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service.impl; import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; @@ -6,7 +7,6 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; - import javax.inject.Inject; public class AssertionVerifierServiceImpl implements AssertionVerifierService { @@ -15,7 +15,8 @@ public class AssertionVerifierServiceImpl implements AssertionVerifierService { private AssertionService assertionService; @Inject - public AssertionVerifierServiceImpl(IdpCertProvider idpCertProvider, AssertionService assertionService) { + public AssertionVerifierServiceImpl( + IdpCertProvider idpCertProvider, AssertionService assertionService) { this.idpCertProvider = idpCertProvider; this.assertionService = assertionService; } @@ -25,11 +26,27 @@ public boolean validateLollipop(LollipopConsumerRequest request) { return false; } - private SamlAssertion getAssertion(String jwt, String assertionRef) { return null; } - private boolean validateAssertionPeriod(String notBefore) { return false; } - private boolean validateThumbprint(LollipopConsumerRequest request, SamlAssertion assertion) { return false; } - private boolean validateInResponseTo(LollipopConsumerRequest request, SamlAssertion assertion) { return false; } - private IdpCertData getIdpCertData(SamlAssertion assertion) { return null; } - private boolean validateSignature(SamlAssertion assertion, IdpCertData idpCertData) { return false; } + private SamlAssertion getAssertion(String jwt, String assertionRef) { + return null; + } + + private boolean validateAssertionPeriod(String notBefore) { + return false; + } + + private boolean validateThumbprint(LollipopConsumerRequest request, SamlAssertion assertion) { + return false; + } + private boolean validateInResponseTo(LollipopConsumerRequest request, SamlAssertion assertion) { + return false; + } + + private IdpCertData getIdpCertData(SamlAssertion assertion) { + return null; + } + + private boolean validateSignature(SamlAssertion assertion, IdpCertData idpCertData) { + return false; + } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java index a19b691c..5098ab9b 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java @@ -1,14 +1,15 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service.impl; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; - -import javax.inject.Inject; import java.io.UnsupportedEncodingException; import java.util.Map; +import javax.inject.Inject; public class HttpMessageVerifierServiceImpl implements HttpMessageVerifierService { @@ -16,62 +17,78 @@ public class HttpMessageVerifierServiceImpl implements HttpMessageVerifierServic private LollipopConsumerRequestConfig lollipopConsumerRequestConfig; @Inject - public HttpMessageVerifierServiceImpl(HttpMessageVerifier httpMessageVerifier, - LollipopConsumerRequestConfig lollipopConsumerRequestConfig) { + public HttpMessageVerifierServiceImpl( + HttpMessageVerifier httpMessageVerifier, + LollipopConsumerRequestConfig lollipopConsumerRequestConfig) { this.httpMessageVerifier = httpMessageVerifier; this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; } @Override public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest) - throws LollipopDigestException, UnsupportedEncodingException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException { - Map headerParams = lollipopConsumerRequest.getHeaderParams(); + Map headerParams = lollipopConsumerRequest.getHeaderParams(); - String signatureInput = headerParams.get(lollipopConsumerRequestConfig.getSignatureInputHeader()); + String signature = + headerParams.get(lollipopConsumerRequestConfig.getSignatureHeader()); - if (signatureInput == null) { + if (signature == null) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE, + "Missing Signature Header"); + } + + String signatureInput = + headerParams.get(lollipopConsumerRequestConfig.getSignatureInputHeader()); + if (signatureInput == null) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE_INPUT, + "Missing Signature Input Header"); } - String contentDigest = null; + if (signatureInput.contains(lollipopConsumerRequestConfig.getContentDigestHeader())) { - String requestBody = null; + String contentDigest = + headerParams.get(lollipopConsumerRequestConfig.getContentDigestHeader()); - String contentEncoding = null; + String requestBody = lollipopConsumerRequest.getRequestBody(); - return verifyContentDigest(contentDigest, requestBody, contentEncoding) && verifyHttpSignature(lollipopConsumerRequest); - } + String contentEncoding = + headerParams.get(lollipopConsumerRequestConfig.getContentEncodingHeader()); - protected boolean verifyContentDigest(String contentDigest, String requestBody, String contentEncoding) - throws LollipopDigestException, UnsupportedEncodingException { + verifyContentDigest(contentDigest, requestBody, contentEncoding); + } + return verifyHttpSignature(lollipopConsumerRequest); + + } + protected boolean verifyContentDigest( + String contentDigest, String requestBody, String contentEncoding) + throws LollipopDigestException, UnsupportedEncodingException { if (contentDigest == null) { - throw new LollipopDigestException - (LollipopDigestException.ErrorCode.MISSING_DIGEST, - "Missing required Content-Digest for validation"); + throw new LollipopDigestException( + LollipopDigestException.ErrorCode.MISSING_DIGEST, + "Missing required Content-Digest for validation"); } + if (requestBody == null) { + throw new LollipopDigestException(LollipopDigestException.ErrorCode.MISSING_PAYLOAD, + "Missing required payload for digest validation"); + } - //Attempt to execute digest validation - if (!httpMessageVerifier.verifyDigest( - contentDigest, - requestBody, - contentEncoding)) { + // Attempt to execute digest validation + if (!httpMessageVerifier.verifyDigest(contentDigest, requestBody, contentEncoding)) { throw new LollipopDigestException( - LollipopDigestException.ErrorCode.INCORRECT_DIGEST,"Invalid Digest"); + LollipopDigestException.ErrorCode.INCORRECT_DIGEST, "Invalid Digest"); } return true; } - /** - * TODO: stub - */ + /** TODO: stub */ private boolean verifyHttpSignature(LollipopConsumerRequest lollipopConsumerRequest) { return true; } - } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java index 205655a9..8a878102 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -1,20 +1,23 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.command.impl; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionVerificationResultCode; import it.pagopa.tech.lollipop.consumer.enumeration.HttpMessageVerificationResultCode; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; import it.pagopa.tech.lollipop.consumer.model.CommandResult; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; -import org.junit.jupiter.api.*; -import org.mockito.*; - import java.io.UnsupportedEncodingException; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; +import lombok.SneakyThrows; +import org.junit.jupiter.api.*; +import org.mockito.*; class LollipopConsumerCommandImplTest { @@ -26,74 +29,108 @@ class LollipopConsumerCommandImplTest { void beforeAll() { messageVerifierServiceMock = Mockito.mock(HttpMessageVerifierService.class); assertionVerifierServiceMock = Mockito.mock(AssertionVerifierService.class); - sut = Mockito.spy(new LollipopConsumerCommandImpl(messageVerifierServiceMock, assertionVerifierServiceMock)); + sut = + Mockito.spy( + new LollipopConsumerCommandImpl( + messageVerifierServiceMock, assertionVerifierServiceMock)); } @Test - void failedHttpMessageValidationThrowDigestException() throws LollipopDigestException, UnsupportedEncodingException { + void failedHttpMessageValidationThrowDigestException() + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException { - doThrow(new LollipopDigestException(LollipopDigestException.ErrorCode.INCORRECT_DIGEST, "error")) - .when(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + doThrow( + new LollipopDigestException( + LollipopDigestException.ErrorCode.INCORRECT_DIGEST, "error")) + .when(messageVerifierServiceMock) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(new LollipopConsumerRequest()); + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); - Assertions.assertEquals(HttpMessageVerificationResultCode.DIGEST_VALIDATION_ERROR.name(), commandResult.getResultCode()); + Assertions.assertEquals( + HttpMessageVerificationResultCode.DIGEST_VALIDATION_ERROR.name(), + commandResult.getResultCode()); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); - verify(assertionVerifierServiceMock, never()).validateLollipop(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock, never()) + .validateLollipop(any(LollipopConsumerRequest.class)); } + @SneakyThrows @Test - void failedHttpMessageValidationThrowUnsupportedEncodingException() throws LollipopDigestException, UnsupportedEncodingException { + void failedHttpMessageValidationThrowUnsupportedEncodingException() { - doThrow(UnsupportedEncodingException.class).when(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + doThrow(UnsupportedEncodingException.class) + .when(messageVerifierServiceMock) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(new LollipopConsumerRequest()); + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); - Assertions.assertEquals(HttpMessageVerificationResultCode.UNSUPPORTED_ENCODING.name(), commandResult.getResultCode()); + Assertions.assertEquals( + HttpMessageVerificationResultCode.UNSUPPORTED_ENCODING.name(), + commandResult.getResultCode()); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); - verify(assertionVerifierServiceMock, never()).validateLollipop(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock, never()) + .validateLollipop(any(LollipopConsumerRequest.class)); } @Test - void failedHttpMessageValidationWithoutThrowingException() throws LollipopDigestException, UnsupportedEncodingException { + void failedHttpMessageValidationWithoutThrowingException() + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException { - doReturn(false).when(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + doReturn(false) + .when(messageVerifierServiceMock) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(new LollipopConsumerRequest()); + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); - Assertions.assertEquals(HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_FAILED.name(), commandResult.getResultCode()); + Assertions.assertEquals( + HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_FAILED.name(), + commandResult.getResultCode()); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); - verify(assertionVerifierServiceMock, never()).validateLollipop(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock, never()) + .validateLollipop(any(LollipopConsumerRequest.class)); } @Test - void failedAssertionValidationWithoutThrowingException() throws LollipopDigestException, UnsupportedEncodingException { + void failedAssertionValidationWithoutThrowingException() + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException { - doReturn(true).when(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); - doReturn(false).when(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); + doReturn(true) + .when(messageVerifierServiceMock) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); + doReturn(false) + .when(assertionVerifierServiceMock) + .validateLollipop(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(new LollipopConsumerRequest()); + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); - Assertions.assertEquals(AssertionVerificationResultCode.ASSERTION_VERIFICATION_FAILED.name(), commandResult.getResultCode()); + Assertions.assertEquals( + AssertionVerificationResultCode.ASSERTION_VERIFICATION_FAILED.name(), + commandResult.getResultCode()); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } @Test - void successLollipopRequestValidation() throws LollipopDigestException, UnsupportedEncodingException { + void successLollipopRequestValidation() + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException { - doReturn(true).when(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); - doReturn(true).when(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); + doReturn(true) + .when(messageVerifierServiceMock) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); + doReturn(true) + .when(assertionVerifierServiceMock) + .validateLollipop(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(new LollipopConsumerRequest()); + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); Assertions.assertEquals("SUCCESS", commandResult.getResultCode()); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } -} \ No newline at end of file +} diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java index e9a46435..a2395165 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java @@ -1,19 +1,19 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service.impl; +import static org.mockito.Mockito.when; + import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import java.io.UnsupportedEncodingException; -import java.util.HashMap; - -import static org.mockito.Mockito.when; - class HttpMessageVerifierServiceImplTest { final String VALID_DIGEST = "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw="; @@ -27,12 +27,12 @@ class HttpMessageVerifierServiceImplTest { public HttpMessageVerifierServiceImplTest() { MockitoAnnotations.openMocks(this); - this.httpMessageVerifierConfig = LollipopConsumerRequestConfig - .builder() - .contentDigestHeader("Content-Digest") - .contentEncodingHeader("Content-Encoding") - .signatureHeader("Signature-Input") - .build(); + this.httpMessageVerifierConfig = + LollipopConsumerRequestConfig.builder() + .contentDigestHeader("Content-Digest") + .contentEncodingHeader("Content-Encoding") + .signatureHeader("Signature-Input") + .build(); this.httpMessageVerifier = Mockito.mock(HttpMessageVerifier.class); } @@ -40,35 +40,32 @@ public HttpMessageVerifierServiceImplTest() { public void beforeEach() throws LollipopDigestException, UnsupportedEncodingException { Mockito.reset(httpMessageVerifier); when(httpMessageVerifier.verifyDigest( - Mockito.eq(VALID_DIGEST), - Mockito.eq(VALID_PAYLOAD), - Mockito.eq("UTF-8"))).thenReturn(true); - this.httpMessageVerifierService = new HttpMessageVerifierServiceImpl( - httpMessageVerifier,httpMessageVerifierConfig); + Mockito.eq(VALID_DIGEST), Mockito.eq(VALID_PAYLOAD), Mockito.eq("UTF-8"))) + .thenReturn(true); + this.httpMessageVerifierService = + new HttpMessageVerifierServiceImpl(httpMessageVerifier, httpMessageVerifierConfig); } @Test - public void validDigestIsProcessed() throws LollipopDigestException, UnsupportedEncodingException { - - LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); - httpMessageVerifierService.verifyContentDigest(lollipopConsumerRequest); - + public void validDigestIsProcessed() + throws LollipopDigestException, UnsupportedEncodingException { + httpMessageVerifierService.verifyContentDigest(VALID_DIGEST,VALID_PAYLOAD,"UTF-8"); } private LollipopConsumerRequest getLollipopConsumerRequest() { - HashMap lollipopHeaderParams = new HashMap<>(); - lollipopHeaderParams.put("Content-Digest",VALID_DIGEST); + HashMap lollipopHeaderParams = new HashMap<>(); + lollipopHeaderParams.put("Content-Digest", VALID_DIGEST); lollipopHeaderParams.put("Content-Encoding", "UTF-8"); - lollipopHeaderParams.put("Signature-Input", "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" " + - "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" + - "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); + lollipopHeaderParams.put( + "Signature-Input", + "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" " + + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" + + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); - return LollipopConsumerRequest - .builder() + return LollipopConsumerRequest.builder() .requestBody(VALID_PAYLOAD) .headerParams(lollipopHeaderParams) .build(); } - -} \ No newline at end of file +} diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index 9c4f3327..a0686a16 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -8,27 +8,27 @@ plugins { - // Apply the java-library plugin for API and implementation separation. - id 'java-library' - id("io.freefair.lombok") version "8.0.0-rc4" + // Apply the java-library plugin for API and implementation separation. + id 'java-library' + id("io.freefair.lombok") version "8.0.0-rc4" } group 'it.pagopa.tech' repositories { - mavenLocal() - mavenCentral() + mavenLocal() + mavenCentral() } dependencies { - implementation project(path: ':core') - implementation 'net.visma.autopay:http-signatures:1.1.0' - // Use JUnit Jupiter for testing. - testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' - testImplementation 'org.assertj:assertj-core:3.24.2' + implementation project(path: ':core') + implementation 'net.visma.autopay:http-signatures:1.1.0' + // Use JUnit Jupiter for testing. + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + testImplementation 'org.assertj:assertj-core:3.24.2' } tasks.named('test') { - // Use JUnit Platform for unit tests. - useJUnitPlatform() -} \ No newline at end of file + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/ErrorCodeConverter.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/ErrorCodeConverter.java index cef315ae..92ba18b7 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/ErrorCodeConverter.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/ErrorCodeConverter.java @@ -1,18 +1,21 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.http_verifier.visma; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import net.visma.autopay.http.digest.DigestException; /** - * Manages the conversion between {@link DigestException.ErrorCode} and {@link LollipopDigestException.ErrorCode} - */ + * Manages the conversion between {@link DigestException.ErrorCode} and {@link + * LollipopDigestException.ErrorCode} + */ public class ErrorCodeConverter { /** - * @param errorCode {@link DigestException.ErrorCode} to convert + * @param errorCode {@link DigestException.ErrorCode} to convert * @return converted {@link LollipopDigestException.ErrorCode} */ - public static LollipopDigestException.ErrorCode convertErrorCode(DigestException.ErrorCode errorCode) { + public static LollipopDigestException.ErrorCode convertErrorCode( + DigestException.ErrorCode errorCode) { if (errorCode != null) { switch (errorCode) { @@ -27,5 +30,4 @@ public static LollipopDigestException.ErrorCode convertErrorCode(DigestException return null; } - } diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java index 0fd314ce..14f71baf 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java @@ -1,15 +1,16 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.http_verifier.visma; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; -import lombok.AllArgsConstructor; -import net.visma.autopay.http.digest.DigestException; - import java.io.UnsupportedEncodingException; import java.util.Map; +import lombok.AllArgsConstructor; +import net.visma.autopay.http.digest.DigestException; /** - Implementation of the @HttpMessageVerifier using Visma-AutoPay http-signature of the http-signature draft + * Implementation of the @HttpMessageVerifier using Visma-AutoPay http-signature of the + * http-signature draft */ @AllArgsConstructor public class VismaHttpMessageVerifier implements HttpMessageVerifier { @@ -17,8 +18,8 @@ public class VismaHttpMessageVerifier implements HttpMessageVerifier { private String defaultEncoding; /** - * Validates digest using Visma DigestVerifier method. Applies contentEncoding if present, otherwise defaults - * to UTF-8 + * Validates digest using Visma DigestVerifier method. Applies contentEncoding if present, + * otherwise defaults to UTF-8 * * @param digest Request digest * @param requestBody Request body @@ -31,26 +32,21 @@ public class VismaHttpMessageVerifier implements HttpMessageVerifier { public boolean verifyDigest(String digest, String requestBody, String encoding) throws LollipopDigestException, UnsupportedEncodingException { try { - net.visma.autopay.http.digest.DigestVerifier.verifyDigestHeader(digest, - requestBody.getBytes(encoding != null ? - encoding : defaultEncoding)); + net.visma.autopay.http.digest.DigestVerifier.verifyDigestHeader( + digest, requestBody.getBytes(encoding != null ? encoding : defaultEncoding)); return true; } catch (DigestException e) { throw new LollipopDigestException( - ErrorCodeConverter.convertErrorCode(e.getErrorCode()), - e.getMessage(), - e); + ErrorCodeConverter.convertErrorCode(e.getErrorCode()), e.getMessage(), e); } catch (UnsupportedEncodingException e) { throw e; } } - /** - * TODO: stub - */ + /** TODO: stub */ @Override - public boolean verifyHttpSignature(String signature, String signatureInput, Map parameters) { + public boolean verifyHttpSignature( + String signature, String signatureInput, Map parameters) { return false; } - } diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java index b6de2cb1..4f794987 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java @@ -1,13 +1,11 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.http_verifier.visma; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; - import java.nio.charset.Charset; -/** - * Implements {@link HttpMessageVerifierFactory} with Visma-AutoPay http-signature library - */ +/** Implements {@link HttpMessageVerifierFactory} with Visma-AutoPay http-signature library */ public class VismaHttpMessageVerifierFactory implements HttpMessageVerifierFactory { private final String defaultEncoding; @@ -21,11 +19,12 @@ public VismaHttpMessageVerifierFactory(String defaultEncoding) throws Exception /** * {@inheritDoc} - * @return instance of {@link VismaHttpMessageVerifierFactory}, passing the configured default encoding - **/ + * + * @return instance of {@link VismaHttpMessageVerifierFactory}, passing the configured default + * encoding + */ @Override public HttpMessageVerifier create() { return new VismaHttpMessageVerifier(defaultEncoding); } - } diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java index fd6c327d..a60932d6 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java @@ -1,23 +1,24 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.http_verifier.visma; +import static org.assertj.core.api.Assertions.*; + import lombok.SneakyThrows; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.*; - class VismaHttpMessageVerifierFactoryTest { @Test public void encodingInCostructorIsInvalid() { assertThatThrownBy(() -> new VismaHttpMessageVerifierFactory("UTF-326")) - .isInstanceOfSatisfying(Exception.class, e -> - assertThat(e).hasMessageContaining("Unavailable Encoding: UTF-326")); + .isInstanceOfSatisfying( + Exception.class, + e -> assertThat(e).hasMessageContaining("Unavailable Encoding: UTF-326")); } @Test public void encodingInCostructorIsValid() { - assertThatNoException().isThrownBy( - () -> new VismaHttpMessageVerifierFactory("UTF-8")); + assertThatNoException().isThrownBy(() -> new VismaHttpMessageVerifierFactory("UTF-8")); } @SneakyThrows @@ -26,5 +27,4 @@ public void instanceIsCreated() { assertThat(new VismaHttpMessageVerifierFactory("UTF-8").create()) .isInstanceOf(VismaHttpMessageVerifier.class); } - -} \ No newline at end of file +} diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java index 65a5725a..157ec82e 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java @@ -1,35 +1,13 @@ -/* - * Copyright (c) 2022 Visma Autopay AS - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.http_verifier.visma; +import static org.assertj.core.api.Assertions.*; + import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; +import java.io.UnsupportedEncodingException; import net.visma.autopay.http.digest.DigestException; import org.junit.jupiter.api.Test; -import java.io.UnsupportedEncodingException; - -import static org.assertj.core.api.Assertions.*; - public class VismaHttpMessageVerifierTest { public VismaHttpMessageVerifier vismaDigestVerifier = new VismaHttpMessageVerifier("UTF-8"); @@ -37,98 +15,108 @@ public class VismaHttpMessageVerifierTest { @Test public void correctDigestIsVerified() { // setup - var content = new String(new byte[]{1, 2, 4}); - var header = "md5=:V9tg6T+1JldSH4+Zy8c5jw==:,sha-256=:1LKaloxAFzY43tjRdMhpV6+iEb5HnO4CDbpd/hJ9kco=:"; + var content = new String(new byte[] {1, 2, 4}); + var header = + "md5=:V9tg6T+1JldSH4+Zy8c5jw==:,sha-256=:1LKaloxAFzY43tjRdMhpV6+iEb5HnO4CDbpd/hJ9kco=:"; // execute & verify - assertThatNoException().isThrownBy(() -> vismaDigestVerifier - .verifyDigest(header, content, null)); + assertThatNoException() + .isThrownBy(() -> vismaDigestVerifier.verifyDigest(header, content, null)); } @Test public void invalidDigestIsDetected() { // setup - var content = new String(new byte[]{1, 2, 4}); + var content = new String(new byte[] {1, 2, 4}); var header = "sha-256=:A5BYxvLAy0ksUzsKTRTvd8wPeKvMztUofYShogEc+4E=:"; // execute & verify - assertThatThrownBy(() -> vismaDigestVerifier.verifyDigest(header, content,null)) - .isInstanceOfSatisfying(LollipopDigestException.class, e -> { - assertThat(e.getCause()).hasMessageContaining("different"); - assertThat(((DigestException) e.getCause()) - .getErrorCode()).isEqualTo(DigestException.ErrorCode.INCORRECT_DIGEST); - }); + assertThatThrownBy(() -> vismaDigestVerifier.verifyDigest(header, content, null)) + .isInstanceOfSatisfying( + LollipopDigestException.class, + e -> { + assertThat(e.getCause()).hasMessageContaining("different"); + assertThat(((DigestException) e.getCause()).getErrorCode()) + .isEqualTo(DigestException.ErrorCode.INCORRECT_DIGEST); + }); } @Test public void malformedDigestIsDetected() { // setup - var content = new String(new byte[]{1, 2, 4}); + var content = new String(new byte[] {1, 2, 4}); var header = "sha-256=1LKaloxAFzY43tjRdMhpV6+iEb5HnO4CDbpd/hJ9kco="; // execute & verify assertThatThrownBy(() -> vismaDigestVerifier.verifyDigest(header, content, null)) - .isInstanceOfSatisfying(LollipopDigestException.class, e -> { - assertThat(e.getCause()).hasMessageContaining("parsing"); - assertThat(((DigestException) e.getCause()) - .getErrorCode()).isEqualTo(DigestException.ErrorCode.INVALID_HEADER); - }); + .isInstanceOfSatisfying( + LollipopDigestException.class, + e -> { + assertThat(e.getCause()).hasMessageContaining("parsing"); + assertThat(((DigestException) e.getCause()).getErrorCode()) + .isEqualTo(DigestException.ErrorCode.INVALID_HEADER); + }); } @Test public void unsupportedAlgorithmsAreDetected() { // setup - var content = new String(new byte[]{1, 2, 4}); + var content = new String(new byte[] {1, 2, 4}); var header = "md5=:V9tg6T+1JldSH4+Zy8c5jw==: ,sha=:q3kRUT3rxwFa1QQpqBWXcUWLJM4=:"; // execute & verify assertThatThrownBy(() -> vismaDigestVerifier.verifyDigest(header, content, null)) - .isInstanceOfSatisfying(LollipopDigestException.class, e -> { - assertThat(e.getCause()).hasMessageContaining("Unsupported"); - assertThat(((DigestException) e.getCause()) - .getErrorCode()).isEqualTo(DigestException.ErrorCode.UNSUPPORTED_ALGORITHM); - }); + .isInstanceOfSatisfying( + LollipopDigestException.class, + e -> { + assertThat(e.getCause()).hasMessageContaining("Unsupported"); + assertThat(((DigestException) e.getCause()).getErrorCode()) + .isEqualTo(DigestException.ErrorCode.UNSUPPORTED_ALGORITHM); + }); } @Test public void emptyHeaderIsDetected() { // setup - var content = new String(new byte[]{1, 2, 4}); + var content = new String(new byte[] {1, 2, 4}); var header = ""; // execute & verify assertThatThrownBy(() -> vismaDigestVerifier.verifyDigest(header, content, null)) - .isInstanceOfSatisfying(LollipopDigestException.class, e -> { - assertThat(e).hasMessageContaining("Empty"); - assertThat(((DigestException) e.getCause()) - .getErrorCode()).isEqualTo(DigestException.ErrorCode.INVALID_HEADER); - }); + .isInstanceOfSatisfying( + LollipopDigestException.class, + e -> { + assertThat(e).hasMessageContaining("Empty"); + assertThat(((DigestException) e.getCause()).getErrorCode()) + .isEqualTo(DigestException.ErrorCode.INVALID_HEADER); + }); } @Test public void invalidDictionaryValuesAreDetected() { // setup - var content = new String(new byte[]{1, 2, 4}); + var content = new String(new byte[] {1, 2, 4}); var header = "sha-256=ok"; // execute & verify assertThatThrownBy(() -> vismaDigestVerifier.verifyDigest(header, content, null)) - .isInstanceOfSatisfying(LollipopDigestException.class, e -> { - assertThat(e.getCause()).hasMessageContaining("Invalid"); - assertThat(((DigestException) e.getCause()) - .getErrorCode()).isEqualTo(DigestException.ErrorCode.INVALID_HEADER); - }); + .isInstanceOfSatisfying( + LollipopDigestException.class, + e -> { + assertThat(e.getCause()).hasMessageContaining("Invalid"); + assertThat(((DigestException) e.getCause()).getErrorCode()) + .isEqualTo(DigestException.ErrorCode.INVALID_HEADER); + }); } @Test public void invalidContentEncoding() { // setup - var content = new String(new byte[]{1, 2, 4}); + var content = new String(new byte[] {1, 2, 4}); var header = "sha-256=ok"; // execute & verify assertThatThrownBy(() -> vismaDigestVerifier.verifyDigest(header, content, "UTF-326")) .isInstanceOf(UnsupportedEncodingException.class); } - -} \ No newline at end of file +} diff --git a/identity-service-rest-client-native/build.gradle b/identity-service-rest-client-native/build.gradle index 200c24e8..7b5c140a 100644 --- a/identity-service-rest-client-native/build.gradle +++ b/identity-service-rest-client-native/build.gradle @@ -8,25 +8,25 @@ plugins { - // Apply the java-library plugin for API and implementation separation. - id 'java-library' - id("io.freefair.lombok") version "8.0.0-rc4" + // Apply the java-library plugin for API and implementation separation. + id 'java-library' + id("io.freefair.lombok") version "8.0.0-rc4" } group 'it.pagopa.tech' repositories { - mavenLocal() - mavenCentral() + mavenLocal() + mavenCentral() } dependencies { - implementation project(path: ':core') - // Use JUnit Jupiter for testing. - testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + implementation project(path: ':core') + // Use JUnit Jupiter for testing. + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' } tasks.named('test') { - // Use JUnit Platform for unit tests. - useJUnitPlatform() -} \ No newline at end of file + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle index 200c24e8..7b5c140a 100644 --- a/redis-storage/build.gradle +++ b/redis-storage/build.gradle @@ -8,25 +8,25 @@ plugins { - // Apply the java-library plugin for API and implementation separation. - id 'java-library' - id("io.freefair.lombok") version "8.0.0-rc4" + // Apply the java-library plugin for API and implementation separation. + id 'java-library' + id("io.freefair.lombok") version "8.0.0-rc4" } group 'it.pagopa.tech' repositories { - mavenLocal() - mavenCentral() + mavenLocal() + mavenCentral() } dependencies { - implementation project(path: ':core') - // Use JUnit Jupiter for testing. - testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + implementation project(path: ':core') + // Use JUnit Jupiter for testing. + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' } tasks.named('test') { - // Use JUnit Platform for unit tests. - useJUnitPlatform() -} \ No newline at end of file + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} From 4ee39057a3a6afaa0a0149c74d88db9470cc6e1b Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 5 Apr 2023 10:52:13 +0200 Subject: [PATCH 027/403] [SLS-9] Generated openAPI REST Client for retrieving assertion --- assertion-rest-client-native/build.gradle | 26 +- .../openapi/openapi-spec.yml | 166 +++++++ .../client/simple/internal/ApiClient.java | 456 ++++++++++++++++++ .../client/simple/internal/ApiException.java | 90 ++++ .../client/simple/internal/ApiResponse.java | 59 +++ .../client/simple/internal/Configuration.java | 39 ++ .../client/simple/internal/JSON.java | 248 ++++++++++ .../client/simple/internal/Pair.java | 57 +++ .../simple/internal/RFC3339DateFormat.java | 57 +++ .../simple/internal/ServerConfiguration.java | 58 +++ .../simple/internal/ServerVariable.java | 23 + .../simple/internal/api/DefaultApi.java | 167 +++++++ .../internal/model/AbstractOpenApiSchema.java | 147 ++++++ .../simple/internal/model/AssertionRef.java | 247 ++++++++++ .../simple/internal/model/AssertionType.java | 79 +++ .../simple/internal/model/LCUserInfo.java | 275 +++++++++++ .../simple/internal/model/OidcUserInfo.java | 186 +++++++ .../simple/internal/model/ProblemJson.java | 297 ++++++++++++ .../simple/internal/model/SamlUserInfo.java | 150 ++++++ 19 files changed, 2826 insertions(+), 1 deletion(-) create mode 100644 assertion-rest-client-native/openapi/openapi-spec.yml create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiClient.java create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiException.java create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiResponse.java create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Configuration.java create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/JSON.java create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Pair.java create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/RFC3339DateFormat.java create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerConfiguration.java create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerVariable.java create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/api/DefaultApi.java create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AbstractOpenApiSchema.java create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionRef.java create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionType.java create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/LCUserInfo.java create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/OidcUserInfo.java create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/ProblemJson.java create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/SamlUserInfo.java diff --git a/assertion-rest-client-native/build.gradle b/assertion-rest-client-native/build.gradle index 41547144..db482452 100644 --- a/assertion-rest-client-native/build.gradle +++ b/assertion-rest-client-native/build.gradle @@ -11,6 +11,7 @@ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' id("io.freefair.lombok") version "8.0.0-rc4" + /*id("org.openapi.generator") version "6.5.0"*/ } group 'it.pagopa.commons' @@ -22,11 +23,34 @@ repositories { dependencies { implementation project(path: ':core') + + implementation 'javax.annotation:javax.annotation-api:1.3.2' + implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.13.0' + implementation 'org.openapitools:jackson-databind-nullable:0.2.6' + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.2' + implementation 'com.google.code.findbugs:jsr305:3.0.2' + + implementation 'javax.inject:javax.inject:1' //TODO // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + testImplementation 'org.assertj:assertj-core:3.24.2' } tasks.named('test') { // Use JUnit Platform for unit tests. useJUnitPlatform() -} \ No newline at end of file +} +/* +compileJava.dependsOn tasks.openApiGenerate + +openApiGenerate { + generatorName = "java" + inputSpec = "$projectDir/openapi/openapi-spec.yml" + outputDir = "$projectDir/generated" + configOptions = [ + dataLibrary: "java8", + library: "native", + useRuntimeException: "true", + sourceFolder: "build/generated/sources/" + ] +}*/ \ No newline at end of file diff --git a/assertion-rest-client-native/openapi/openapi-spec.yml b/assertion-rest-client-native/openapi/openapi-spec.yml new file mode 100644 index 00000000..97f30e2b --- /dev/null +++ b/assertion-rest-client-native/openapi/openapi-spec.yml @@ -0,0 +1,166 @@ +openapi: "3.0.1" +info: + title: Assertion Client + version: $npm_package_version + x-logo: + url: https://io.italia.it/assets/img/io-logo-blue.svg + description: |- + Client used to get the assertion from the identity provider +servers: + - url: http://localhost:3000 +security: + - ApiKeyAuth: [] +paths: + /assertions/{assertion_ref}: + get: + operationId: getAssertion + summary: Get Assertion related to a given assertion ref + parameters: + - name: assertion_ref + required: true + in: path + schema: + $ref: '#/components/schemas/AssertionRef' + - name: x-pagopa-lollipop-auth + required: true + in: header + schema: + $ref: '#/components/schemas/LollipopAuthBearer' + responses: + '200': + description: The assertion related to a valid assertion_ref + content: + application/json: + schema: + $ref: '#/components/schemas/LCUserInfo' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' + '410': + description: Assertion gone + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' +components: + securitySchemes: + ApiKeyAuth: + type: apiKey + in: header + name: Ocp-Apim-Subscription-Key + schemas: + ProblemJson: + type: object + properties: + type: + type: string + format: uri + description: |- + An absolute URI that identifies the problem type. When dereferenced, + it SHOULD provide human-readable documentation for the problem type + (e.g., using HTML). + default: about:blank + example: https://example.com/problem/constraint-violation + title: + type: string + description: >- + A short, summary of the problem type. Written in english and + readable + + for engineers (usually not suited for non technical stakeholders and + + not localized); example: Service Unavailable + status: + type: integer + format: int32 + description: >- + The HTTP status code generated by the origin server for this + occurrence + + of the problem. + minimum: 100 + maximum: 600 + exclusiveMaximum: true + example: 200 + detail: + type: string + description: |- + A human readable explanation specific to this occurrence of the + problem. + example: There was an error processing the request + instance: + type: string + format: uri + description: >- + An absolute URI that identifies the specific occurrence of the + problem. + + It may or may not yield further information if dereferenced. + AssertionType: + type: string + enum: + - SAML + - OIDC + AssertionRefSha256: + type: string + pattern: ^(sha256-[A-Za-z0-9-_=]{1,44})$ + AssertionRefSha384: + type: string + pattern: ^(sha384-[A-Za-z0-9-_=]{1,66})$ + AssertionRefSha512: + type: string + pattern: ^(sha512-[A-Za-z0-9-_=]{1,88})$ + AssertionRef: + oneOf: + - $ref: '#/components/schemas/AssertionRefSha256' + - $ref: '#/components/schemas/AssertionRefSha384' + - $ref: '#/components/schemas/AssertionRefSha512' + LollipopAuthBearer: + type: string + pattern: ^Bearer [a-zA-Z0-9-_].+ + description: A lollipop's JWT auth custom header as `Bearer ` + example: >- + Bearer + eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c + SamlUserInfo: + type: object + properties: + response_xml: + type: string + description: A string representation of a signed SPID/CIE response + minLength: 1 + required: + - response_xml + OidcSignedJwt: + type: string + description: A JWT representation of a signed SPID/CIE OIDC Idp + minLength: 1 + OidcUserInfo: + type: object + properties: + id_token: + $ref: '#/components/schemas/OidcSignedJwt' + claims_token: + $ref: '#/components/schemas/OidcSignedJwt' + required: + - id_token + - claims_token + LCUserInfo: + oneOf: + - $ref: '#/components/schemas/SamlUserInfo' + - $ref: '#/components/schemas/OidcUserInfo' \ No newline at end of file diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiClient.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiClient.java new file mode 100644 index 00000000..1c23ef0b --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiClient.java @@ -0,0 +1,456 @@ +/* + * Assertion Client + * Client used to get the assertion from the identity provider + * + * The version of the OpenAPI document: $npm_package_version + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.openapitools.jackson.nullable.JsonNullableModule; + +import java.io.InputStream; +import java.net.URI; +import java.net.URLEncoder; +import java.net.http.HttpClient; +import java.net.http.HttpConnectTimeoutException; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.StringJoiner; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +import static java.nio.charset.StandardCharsets.UTF_8; + +/** + * Configuration and utility class for API clients. + * + *

This class can be constructed and modified, then used to instantiate the + * various API classes. The API classes use the settings in this class to + * configure themselves, but otherwise do not store a link to this class.

+ * + *

This class is mutable and not synchronized, so it is not thread-safe. + * The API classes generated from this are immutable and thread-safe.

+ * + *

The setter methods of this class return the current object to facilitate + * a fluent style of configuration.

+ */ +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +public class ApiClient { + + private HttpClient.Builder builder; + private ObjectMapper mapper; + private String scheme; + private String host; + private int port; + private String basePath; + private Consumer interceptor; + private Consumer> responseInterceptor; + private Consumer> asyncResponseInterceptor; + private Duration readTimeout; + private Duration connectTimeout; + + private static String valueToString(Object value) { + if (value == null) { + return ""; + } + if (value instanceof OffsetDateTime) { + return ((OffsetDateTime) value).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } + return value.toString(); + } + + /** + * URL encode a string in the UTF-8 encoding. + * + * @param s String to encode. + * @return URL-encoded representation of the input string. + */ + public static String urlEncode(String s) { + return URLEncoder.encode(s, UTF_8).replaceAll("\\+", "%20"); + } + + /** + * Convert a URL query name/value parameter to a list of encoded {@link Pair} + * objects. + * + *

The value can be null, in which case an empty list is returned.

+ * + * @param name The query name parameter. + * @param value The query value, which may not be a collection but may be + * null. + * @return A singleton list of the {@link Pair} objects representing the input + * parameters, which is encoded for use in a URL. If the value is null, an + * empty list is returned. + */ + public static List parameterToPairs(String name, Object value) { + if (name == null || name.isEmpty() || value == null) { + return Collections.emptyList(); + } + return Collections.singletonList(new Pair(urlEncode(name), urlEncode(valueToString(value)))); + } + + /** + * Convert a URL query name/collection parameter to a list of encoded + * {@link Pair} objects. + * + * @param collectionFormat The swagger collectionFormat string (csv, tsv, etc). + * @param name The query name parameter. + * @param values A collection of values for the given query name, which may be + * null. + * @return A list of {@link Pair} objects representing the input parameters, + * which is encoded for use in a URL. If the values collection is null, an + * empty list is returned. + */ + public static List parameterToPairs( + String collectionFormat, String name, Collection values) { + if (name == null || name.isEmpty() || values == null || values.isEmpty()) { + return Collections.emptyList(); + } + + // get the collection format (default: csv) + String format = collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat; + + // create the params based on the collection format + if ("multi".equals(format)) { + return values.stream() + .map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value)))) + .collect(Collectors.toList()); + } + + String delimiter; + switch(format) { + case "csv": + delimiter = urlEncode(","); + break; + case "ssv": + delimiter = urlEncode(" "); + break; + case "tsv": + delimiter = urlEncode("\t"); + break; + case "pipes": + delimiter = urlEncode("|"); + break; + default: + throw new IllegalArgumentException("Illegal collection format: " + collectionFormat); + } + + StringJoiner joiner = new StringJoiner(delimiter); + for (Object value : values) { + joiner.add(urlEncode(valueToString(value))); + } + + return Collections.singletonList(new Pair(urlEncode(name), joiner.toString())); + } + + /** + * Create an instance of ApiClient. + */ + public ApiClient() { + this.builder = createDefaultHttpClientBuilder(); + this.mapper = createDefaultObjectMapper(); + updateBaseUri(getDefaultBaseUri()); + interceptor = null; + readTimeout = null; + connectTimeout = null; + responseInterceptor = null; + asyncResponseInterceptor = null; + } + + /** + * Create an instance of ApiClient. + * + * @param builder Http client builder. + * @param mapper Object mapper. + * @param baseUri Base URI + */ + public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, String baseUri) { + this.builder = builder; + this.mapper = mapper; + updateBaseUri(baseUri != null ? baseUri : getDefaultBaseUri()); + interceptor = null; + readTimeout = null; + connectTimeout = null; + responseInterceptor = null; + asyncResponseInterceptor = null; + } + + protected ObjectMapper createDefaultObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); + mapper.registerModule(new JavaTimeModule()); + mapper.registerModule(new JsonNullableModule()); + return mapper; + } + + protected String getDefaultBaseUri() { + return "http://localhost:3000"; + } + + protected HttpClient.Builder createDefaultHttpClientBuilder() { + return HttpClient.newBuilder(); + } + + public void updateBaseUri(String baseUri) { + URI uri = URI.create(baseUri); + scheme = uri.getScheme(); + host = uri.getHost(); + port = uri.getPort(); + basePath = uri.getRawPath(); + } + + /** + * Set a custom {@link HttpClient.Builder} object to use when creating the + * {@link HttpClient} that is used by the API client. + * + * @param builder Custom client builder. + * @return This object. + */ + public ApiClient setHttpClientBuilder(HttpClient.Builder builder) { + this.builder = builder; + return this; + } + + /** + * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}. + * + *

The returned object is immutable and thread-safe.

+ * + * @return The HTTP client. + */ + public HttpClient getHttpClient() { + return builder.build(); + } + + /** + * Set a custom {@link ObjectMapper} to serialize and deserialize the request + * and response bodies. + * + * @param mapper Custom object mapper. + * @return This object. + */ + public ApiClient setObjectMapper(ObjectMapper mapper) { + this.mapper = mapper; + return this; + } + + /** + * Get a copy of the current {@link ObjectMapper}. + * + * @return A copy of the current object mapper. + */ + public ObjectMapper getObjectMapper() { + return mapper.copy(); + } + + /** + * Set a custom host name for the target service. + * + * @param host The host name of the target service. + * @return This object. + */ + public ApiClient setHost(String host) { + this.host = host; + return this; + } + + /** + * Set a custom port number for the target service. + * + * @param port The port of the target service. Set this to -1 to reset the + * value to the default for the scheme. + * @return This object. + */ + public ApiClient setPort(int port) { + this.port = port; + return this; + } + + /** + * Set a custom base path for the target service, for example '/v2'. + * + * @param basePath The base path against which the rest of the path is + * resolved. + * @return This object. + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get the base URI to resolve the endpoint paths against. + * + * @return The complete base URI that the rest of the API parameters are + * resolved against. + */ + public String getBaseUri() { + return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; + } + + /** + * Set a custom scheme for the target service, for example 'https'. + * + * @param scheme The scheme of the target service + * @return This object. + */ + public ApiClient setScheme(String scheme){ + this.scheme = scheme; + return this; + } + + /** + * Set a custom request interceptor. + * + *

A request interceptor is a mechanism for altering each request before it + * is sent. After the request has been fully configured but not yet built, the + * request builder is passed into this function for further modification, + * after which it is sent out.

+ * + *

This is useful for altering the requests in a custom manner, such as + * adding headers. It could also be used for logging and monitoring.

+ * + * @param interceptor A function invoked before creating each request. A value + * of null resets the interceptor to a no-op. + * @return This object. + */ + public ApiClient setRequestInterceptor(Consumer interceptor) { + this.interceptor = interceptor; + return this; + } + + /** + * Get the custom interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer getRequestInterceptor() { + return interceptor; + } + + /** + * Set a custom response interceptor. + * + *

This is useful for logging, monitoring or extraction of header variables

+ * + * @param interceptor A function invoked before creating each request. A value + * of null resets the interceptor to a no-op. + * @return This object. + */ + public ApiClient setResponseInterceptor(Consumer> interceptor) { + this.responseInterceptor = interceptor; + return this; + } + + /** + * Get the custom response interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getResponseInterceptor() { + return responseInterceptor; + } + + /** + * Set a custom async response interceptor. Use this interceptor when asyncNative is set to 'true'. + * + *

This is useful for logging, monitoring or extraction of header variables

+ * + * @param interceptor A function invoked before creating each request. A value + * of null resets the interceptor to a no-op. + * @return This object. + */ + public ApiClient setAsyncResponseInterceptor(Consumer> interceptor) { + this.asyncResponseInterceptor = interceptor; + return this; + } + + /** + * Get the custom async response interceptor. Use this interceptor when asyncNative is set to 'true'. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getAsyncResponseInterceptor() { + return asyncResponseInterceptor; + } + + /** + * Set the read timeout for the http client. + * + *

This is the value used by default for each request, though it can be + * overridden on a per-request basis with a request interceptor.

+ * + * @param readTimeout The read timeout used by default by the http client. + * Setting this value to null resets the timeout to an + * effectively infinite value. + * @return This object. + */ + public ApiClient setReadTimeout(Duration readTimeout) { + this.readTimeout = readTimeout; + return this; + } + + /** + * Get the read timeout that was set. + * + * @return The read timeout, or null if no timeout was set. Null represents + * an infinite wait time. + */ + public Duration getReadTimeout() { + return readTimeout; + } + /** + * Sets the connect timeout (in milliseconds) for the http client. + * + *

In the case where a new connection needs to be established, if + * the connection cannot be established within the given {@code + * duration}, then {@link HttpClient#send(HttpRequest,BodyHandler) + * HttpClient::send} throws an {@link HttpConnectTimeoutException}, or + * {@link HttpClient#sendAsync(HttpRequest,BodyHandler) + * HttpClient::sendAsync} completes exceptionally with an + * {@code HttpConnectTimeoutException}. If a new connection does not + * need to be established, for example if a connection can be reused + * from a previous request, then this timeout duration has no effect. + * + * @param connectTimeout connection timeout in milliseconds + * + * @return This object. + */ + public ApiClient setConnectTimeout(Duration connectTimeout) { + this.connectTimeout = connectTimeout; + this.builder.connectTimeout(connectTimeout); + return this; + } + + /** + * Get connection timeout (in milliseconds). + * + * @return Timeout in milliseconds + */ + public Duration getConnectTimeout() { + return connectTimeout; + } +} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiException.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiException.java new file mode 100644 index 00000000..97857935 --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiException.java @@ -0,0 +1,90 @@ +/* + * Assertion Client + * Client used to get the assertion from the identity provider + * + * The version of the OpenAPI document: $npm_package_version + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; + +import java.net.http.HttpHeaders; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +public class ApiException extends RuntimeException { + private int code = 0; + private HttpHeaders responseHeaders = null; + private String responseBody = null; + + public ApiException() {} + + public ApiException(Throwable throwable) { + super(throwable); + } + + public ApiException(String message) { + super(message); + } + + public ApiException(String message, Throwable throwable, int code, HttpHeaders responseHeaders, String responseBody) { + super(message, throwable); + this.code = code; + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + public ApiException(String message, int code, HttpHeaders responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(String message, Throwable throwable, int code, HttpHeaders responseHeaders) { + this(message, throwable, code, responseHeaders, null); + } + + public ApiException(int code, HttpHeaders responseHeaders, String responseBody) { + this((String) null, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(int code, String message) { + super(message); + this.code = code; + } + + public ApiException(int code, String message, HttpHeaders responseHeaders, String responseBody) { + this(code, message); + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + /** + * Get the HTTP status code. + * + * @return HTTP status code + */ + public int getCode() { + return code; + } + + /** + * Get the HTTP response headers. + * + * @return Headers as an HttpHeaders object + */ + public HttpHeaders getResponseHeaders() { + return responseHeaders; + } + + /** + * Get the HTTP response body. + * + * @return Response body in the form of string + */ + public String getResponseBody() { + return responseBody; + } +} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiResponse.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiResponse.java new file mode 100644 index 00000000..0b6f0590 --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiResponse.java @@ -0,0 +1,59 @@ +/* + * Assertion Client + * Client used to get the assertion from the identity provider + * + * The version of the OpenAPI document: $npm_package_version + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; + +import java.util.List; +import java.util.Map; + +/** + * API response returned by API call. + * + * @param The type of data that is deserialized from response body + */ +public class ApiResponse { + final private int statusCode; + final private Map> headers; + final private T data; + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + */ + public ApiResponse(int statusCode, Map> headers) { + this(statusCode, headers, null); + } + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + * @param data The object deserialized from response bod + */ + public ApiResponse(int statusCode, Map> headers, T data) { + this.statusCode = statusCode; + this.headers = headers; + this.data = data; + } + + public int getStatusCode() { + return statusCode; + } + + public Map> getHeaders() { + return headers; + } + + public T getData() { + return data; + } +} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Configuration.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Configuration.java new file mode 100644 index 00000000..335ec4fa --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Configuration.java @@ -0,0 +1,39 @@ +/* + * Assertion Client + * Client used to get the assertion from the identity provider + * + * The version of the OpenAPI document: $npm_package_version + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +public class Configuration { + private static ApiClient defaultApiClient = new ApiClient(); + + /** + * Get the default API client, which would be used when creating API + * instances without providing an API client. + * + * @return Default API client + */ + public static ApiClient getDefaultApiClient() { + return defaultApiClient; + } + + /** + * Set the default API client, which would be used when creating API + * instances without providing an API client. + * + * @param apiClient API client + */ + public static void setDefaultApiClient(ApiClient apiClient) { + defaultApiClient = apiClient; + } +} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/JSON.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/JSON.java new file mode 100644 index 00000000..00092b9d --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/JSON.java @@ -0,0 +1,248 @@ +package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +import org.openapitools.jackson.nullable.JsonNullableModule; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.*; + +import java.text.DateFormat; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +public class JSON { + private ObjectMapper mapper; + + public JSON() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + mapper.registerModule(new JavaTimeModule()); + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + } + + /** + * Set the date format for JSON (de)serialization with Date properties. + * + * @param dateFormat Date format + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + + /** + * Get the object mapper + * + * @return object mapper + */ + public ObjectMapper getMapper() { return mapper; } + + /** + * Returns the target model class that should be used to deserialize the input data. + * The discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param modelClass The class that contains the discriminator mappings. + * + * @return the target model class. + */ + public static Class getClassForElement(JsonNode node, Class modelClass) { + ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass); + if (cdm != null) { + return cdm.getClassForElement(node, new HashSet>()); + } + return null; + } + + /** + * Helper class to register the discriminator mappings. + */ + private static class ClassDiscriminatorMapping { + // The model class name. + Class modelClass; + // The name of the discriminator property. + String discriminatorName; + // The discriminator mappings for a model class. + Map> discriminatorMappings; + + // Constructs a new class discriminator. + ClassDiscriminatorMapping(Class cls, String propertyName, Map> mappings) { + modelClass = cls; + discriminatorName = propertyName; + discriminatorMappings = new HashMap>(); + if (mappings != null) { + discriminatorMappings.putAll(mappings); + } + } + + // Return the name of the discriminator property for this model class. + String getDiscriminatorPropertyName() { + return discriminatorName; + } + + // Return the discriminator value or null if the discriminator is not + // present in the payload. + String getDiscriminatorValue(JsonNode node) { + // Determine the value of the discriminator property in the input data. + if (discriminatorName != null) { + // Get the value of the discriminator property, if present in the input payload. + node = node.get(discriminatorName); + if (node != null && node.isValueNode()) { + String discrValue = node.asText(); + if (discrValue != null) { + return discrValue; + } + } + } + return null; + } + + /** + * Returns the target model class that should be used to deserialize the input data. + * This function can be invoked for anyOf/oneOf composed models with discriminator mappings. + * The discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param visitedClasses The set of classes that have already been visited. + * + * @return the target model class. + */ + Class getClassForElement(JsonNode node, Set> visitedClasses) { + if (visitedClasses.contains(modelClass)) { + // Class has already been visited. + return null; + } + // Determine the value of the discriminator property in the input data. + String discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + return null; + } + Class cls = discriminatorMappings.get(discrValue); + // It may not be sufficient to return this cls directly because that target class + // may itself be a composed schema, possibly with its own discriminator. + visitedClasses.add(modelClass); + for (Class childClass : discriminatorMappings.values()) { + ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass); + if (childCdm == null) { + continue; + } + if (!discriminatorName.equals(childCdm.discriminatorName)) { + discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + continue; + } + } + if (childCdm != null) { + // Recursively traverse the discriminator mappings. + Class childDiscr = childCdm.getClassForElement(node, visitedClasses); + if (childDiscr != null) { + return childDiscr; + } + } + } + return cls; + } + } + + /** + * Returns true if inst is an instance of modelClass in the OpenAPI model hierarchy. + * + * The Java class hierarchy is not implemented the same way as the OpenAPI model hierarchy, + * so it's not possible to use the instanceof keyword. + * + * @param modelClass A OpenAPI model class. + * @param inst The instance object. + * @param visitedClasses The set of classes that have already been visited. + * + * @return true if inst is an instance of modelClass in the OpenAPI model hierarchy. + */ + public static boolean isInstanceOf(Class modelClass, Object inst, Set> visitedClasses) { + if (modelClass.isInstance(inst)) { + // This handles the 'allOf' use case with single parent inheritance. + return true; + } + if (visitedClasses.contains(modelClass)) { + // This is to prevent infinite recursion when the composed schemas have + // a circular dependency. + return false; + } + visitedClasses.add(modelClass); + + // Traverse the oneOf/anyOf composed schemas. + Map> descendants = modelDescendants.get(modelClass); + if (descendants != null) { + for (Class childType : descendants.values()) { + if (isInstanceOf(childType, inst, visitedClasses)) { + return true; + } + } + } + return false; + } + + /** + * A map of discriminators for all model classes. + */ + private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap<>(); + + /** + * A map of oneOf/anyOf descendants for each model class. + */ + private static Map, Map>> modelDescendants = new HashMap<>(); + + /** + * Register a model class discriminator. + * + * @param modelClass the model class + * @param discriminatorPropertyName the name of the discriminator property + * @param mappings a map with the discriminator mappings. + */ + public static void registerDiscriminator(Class modelClass, String discriminatorPropertyName, Map> mappings) { + ClassDiscriminatorMapping m = new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings); + modelDiscriminators.put(modelClass, m); + } + + /** + * Register the oneOf/anyOf descendants of the modelClass. + * + * @param modelClass the model class + * @param descendants a map of oneOf/anyOf descendants. + */ + public static void registerDescendants(Class modelClass, Map> descendants) { + modelDescendants.put(modelClass, descendants); + } + + private static JSON json; + + static { + json = new JSON(); + } + + /** + * Get the default JSON instance. + * + * @return the default JSON instance + */ + public static JSON getDefault() { + return json; + } + + /** + * Set the default JSON instance. + * + * @param json JSON instance to be used + */ + public static void setDefault(JSON json) { + JSON.json = json; + } +} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Pair.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Pair.java new file mode 100644 index 00000000..4556c728 --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Pair.java @@ -0,0 +1,57 @@ +/* + * Assertion Client + * Client used to get the assertion from the identity provider + * + * The version of the OpenAPI document: $npm_package_version + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +public class Pair { + private String name = ""; + private String value = ""; + + public Pair (String name, String value) { + setName(name); + setValue(value); + } + + private void setName(String name) { + if (!isValidString(name)) { + return; + } + + this.name = name; + } + + private void setValue(String value) { + if (!isValidString(value)) { + return; + } + + this.value = value; + } + + public String getName() { + return this.name; + } + + public String getValue() { + return this.value; + } + + private boolean isValidString(String arg) { + if (arg == null) { + return false; + } + + return true; + } +} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/RFC3339DateFormat.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/RFC3339DateFormat.java new file mode 100644 index 00000000..9ab4c4e8 --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/RFC3339DateFormat.java @@ -0,0 +1,57 @@ +/* + * Assertion Client + * Client used to get the assertion from the identity provider + * + * The version of the OpenAPI document: $npm_package_version + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; + +import com.fasterxml.jackson.databind.util.StdDateFormat; + +import java.text.DateFormat; +import java.text.FieldPosition; +import java.text.ParsePosition; +import java.util.Date; +import java.text.DecimalFormat; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +public class RFC3339DateFormat extends DateFormat { + private static final long serialVersionUID = 1L; + private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); + + private final StdDateFormat fmt = new StdDateFormat() + .withTimeZone(TIMEZONE_Z) + .withColonInTimeZone(true); + + public RFC3339DateFormat() { + this.calendar = new GregorianCalendar(); + this.numberFormat = new DecimalFormat(); + } + + @Override + public Date parse(String source) { + return parse(source, new ParsePosition(0)); + } + + @Override + public Date parse(String source, ParsePosition pos) { + return fmt.parse(source, pos); + } + + @Override + public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { + return fmt.format(date, toAppendTo, fieldPosition); + } + + @Override + public Object clone() { + return super.clone(); + } +} \ No newline at end of file diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerConfiguration.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerConfiguration.java new file mode 100644 index 00000000..62d41981 --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerConfiguration.java @@ -0,0 +1,58 @@ +package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; + +import java.util.Map; + +/** + * Representing a Server configuration. + */ +public class ServerConfiguration { + public String URL; + public String description; + public Map variables; + + /** + * @param URL A URL to the target host. + * @param description A description of the host designated by the URL. + * @param variables A map between a variable name and its value. The value is used for substitution in the server's URL template. + */ + public ServerConfiguration(String URL, String description, Map variables) { + this.URL = URL; + this.description = description; + this.variables = variables; + } + + /** + * Format URL template using given variables. + * + * @param variables A map between a variable name and its value. + * @return Formatted URL. + */ + public String URL(Map variables) { + String url = this.URL; + + // go through variables and replace placeholders + for (Map.Entry variable: this.variables.entrySet()) { + String name = variable.getKey(); + ServerVariable serverVariable = variable.getValue(); + String value = serverVariable.defaultValue; + + if (variables != null && variables.containsKey(name)) { + value = variables.get(name); + if (serverVariable.enumValues.size() > 0 && !serverVariable.enumValues.contains(value)) { + throw new IllegalArgumentException("The variable " + name + " in the server URL has invalid value " + value + "."); + } + } + url = url.replace("{" + name + "}", value); + } + return url; + } + + /** + * Format URL template using default server variables. + * + * @return Formatted URL. + */ + public String URL() { + return URL(null); + } +} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerVariable.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerVariable.java new file mode 100644 index 00000000..b1bd047e --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerVariable.java @@ -0,0 +1,23 @@ +package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; + +import java.util.HashSet; + +/** + * Representing a Server Variable for server URL template substitution. + */ +public class ServerVariable { + public String description; + public String defaultValue; + public HashSet enumValues = null; + + /** + * @param description A description for the server variable. + * @param defaultValue The default value to use for substitution. + * @param enumValues An enumeration of string values to be used if the substitution options are from a limited set. + */ + public ServerVariable(String description, String defaultValue, HashSet enumValues) { + this.description = description; + this.defaultValue = defaultValue; + this.enumValues = enumValues; + } +} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/api/DefaultApi.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/api/DefaultApi.java new file mode 100644 index 00000000..17fc8125 --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/api/DefaultApi.java @@ -0,0 +1,167 @@ +/* + * Assertion Client + * Client used to get the assertion from the identity provider + * + * The version of the OpenAPI document: $npm_package_version + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.api; + +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiClient; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiException; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiResponse; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.Pair; + +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.AssertionRef; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.LCUserInfo; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.ProblemJson; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.net.http.HttpRequest; +import java.nio.channels.Channels; +import java.nio.channels.Pipe; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; + +import java.util.ArrayList; +import java.util.StringJoiner; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Consumer; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +public class DefaultApi { + private final HttpClient memberVarHttpClient; + private final ObjectMapper memberVarObjectMapper; + private final String memberVarBaseUri; + private final Consumer memberVarInterceptor; + private final Duration memberVarReadTimeout; + private final Consumer> memberVarResponseInterceptor; + private final Consumer> memberVarAsyncResponseInterceptor; + + public DefaultApi() { + this(new ApiClient()); + } + + public DefaultApi(ApiClient apiClient) { + memberVarHttpClient = apiClient.getHttpClient(); + memberVarObjectMapper = apiClient.getObjectMapper(); + memberVarBaseUri = apiClient.getBaseUri(); + memberVarInterceptor = apiClient.getRequestInterceptor(); + memberVarReadTimeout = apiClient.getReadTimeout(); + memberVarResponseInterceptor = apiClient.getResponseInterceptor(); + memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); + } + + protected ApiException getApiException(String operationId, HttpResponse response) throws IOException { + String body = response.body() == null ? null : new String(response.body().readAllBytes()); + String message = formatExceptionMessage(operationId, response.statusCode(), body); + return new ApiException(response.statusCode(), message, response.headers(), body); + } + + private String formatExceptionMessage(String operationId, int statusCode, String body) { + if (body == null || body.isEmpty()) { + body = "[no body]"; + } + return operationId + " call failed with: " + statusCode + " - " + body; + } + + /** + * Get Assertion related to a given assertion ref + * + * @param assertionRef (required) + * @param xPagopaLollipopAuth (required) + * @return LCUserInfo + * @throws ApiException if fails to make API call + */ + public LCUserInfo getAssertion(AssertionRef assertionRef, String xPagopaLollipopAuth) throws ApiException { + ApiResponse localVarResponse = getAssertionWithHttpInfo(assertionRef, xPagopaLollipopAuth); + return localVarResponse.getData(); + } + + /** + * Get Assertion related to a given assertion ref + * + * @param assertionRef (required) + * @param xPagopaLollipopAuth (required) + * @return ApiResponse<LCUserInfo> + * @throws ApiException if fails to make API call + */ + public ApiResponse getAssertionWithHttpInfo(AssertionRef assertionRef, String xPagopaLollipopAuth) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = getAssertionRequestBuilder(assertionRef, xPagopaLollipopAuth); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode()/ 100 != 2) { + throw getApiException("getAssertion", localVarResponse); + } + return new ApiResponse( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } + + private HttpRequest.Builder getAssertionRequestBuilder(AssertionRef assertionRef, String xPagopaLollipopAuth) throws ApiException { + // verify the required parameter 'assertionRef' is set + if (assertionRef == null) { + throw new ApiException(400, "Missing the required parameter 'assertionRef' when calling getAssertion"); + } + // verify the required parameter 'xPagopaLollipopAuth' is set + if (xPagopaLollipopAuth == null) { + throw new ApiException(400, "Missing the required parameter 'xPagopaLollipopAuth' when calling getAssertion"); + } + + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + + String localVarPath = "/assertions/{assertion_ref}" + .replace("{assertion_ref}", ApiClient.urlEncode(assertionRef.getActualInstance().toString())); + + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + + if (xPagopaLollipopAuth != null) { + localVarRequestBuilder.header("x-pagopa-lollipop-auth", xPagopaLollipopAuth.toString()); + } + localVarRequestBuilder.header("Accept", "application/json"); + + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; + } +} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AbstractOpenApiSchema.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AbstractOpenApiSchema.java new file mode 100644 index 00000000..b2fd66c6 --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AbstractOpenApiSchema.java @@ -0,0 +1,147 @@ +/* + * Assertion Client + * Client used to get the assertion from the identity provider + * + * The version of the OpenAPI document: $npm_package_version + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model; + +import java.util.Objects; +import java.lang.reflect.Type; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Abstract class for oneOf,anyOf schemas defined in OpenAPI spec + */ +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +public abstract class AbstractOpenApiSchema { + + // store the actual instance of the schema/object + private Object instance; + + // is nullable + private Boolean isNullable; + + // schema type (e.g. oneOf, anyOf) + private final String schemaType; + + public AbstractOpenApiSchema(String schemaType, Boolean isNullable) { + this.schemaType = schemaType; + this.isNullable = isNullable; + } + + /** + * Get the list of oneOf/anyOf composed schemas allowed to be stored in this object + * + * @return an instance of the actual schema/object + */ + public abstract Map> getSchemas(); + + /** + * Get the actual instance + * + * @return an instance of the actual schema/object + */ + @JsonValue + public Object getActualInstance() {return instance;} + + /** + * Set the actual instance + * + * @param instance the actual instance of the schema/object + */ + public void setActualInstance(Object instance) {this.instance = instance;} + + /** + * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf schema as well + * + * @return an instance of the actual schema/object + */ + public Object getActualInstanceRecursively() { + return getActualInstanceRecursively(this); + } + + private Object getActualInstanceRecursively(AbstractOpenApiSchema object) { + if (object.getActualInstance() == null) { + return null; + } else if (object.getActualInstance() instanceof AbstractOpenApiSchema) { + return getActualInstanceRecursively((AbstractOpenApiSchema)object.getActualInstance()); + } else { + return object.getActualInstance(); + } + } + + /** + * Get the schema type (e.g. anyOf, oneOf) + * + * @return the schema type + */ + public String getSchemaType() { + return schemaType; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ").append(getClass()).append(" {\n"); + sb.append(" instance: ").append(toIndentedString(instance)).append("\n"); + sb.append(" isNullable: ").append(toIndentedString(isNullable)).append("\n"); + sb.append(" schemaType: ").append(toIndentedString(schemaType)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AbstractOpenApiSchema a = (AbstractOpenApiSchema) o; + return Objects.equals(this.instance, a.instance) && + Objects.equals(this.isNullable, a.isNullable) && + Objects.equals(this.schemaType, a.schemaType); + } + + @Override + public int hashCode() { + return Objects.hash(instance, isNullable, schemaType); + } + + /** + * Is nullable + * + * @return true if it's nullable + */ + public Boolean isNullable() { + if (Boolean.TRUE.equals(isNullable)) { + return Boolean.TRUE; + } else { + return Boolean.FALSE; + } + } + + + +} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionRef.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionRef.java new file mode 100644 index 00000000..df24ebda --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionRef.java @@ -0,0 +1,247 @@ +/* + * Assertion Client + * Client used to get the assertion from the identity provider + * + * The version of the OpenAPI document: $npm_package_version + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Arrays; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import com.fasterxml.jackson.core.type.TypeReference; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.JSON; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +@JsonDeserialize(using = AssertionRef.AssertionRefDeserializer.class) +@JsonSerialize(using = AssertionRef.AssertionRefSerializer.class) +public class AssertionRef extends AbstractOpenApiSchema { + private static final Logger log = Logger.getLogger(AssertionRef.class.getName()); + + public static class AssertionRefSerializer extends StdSerializer { + public AssertionRefSerializer(Class t) { + super(t); + } + + public AssertionRefSerializer() { + this(null); + } + + @Override + public void serialize(AssertionRef value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + + public static class AssertionRefDeserializer extends StdDeserializer { + public AssertionRefDeserializer() { + this(AssertionRef.class); + } + + public AssertionRefDeserializer(Class vc) { + super(vc); + } + + @Override + public AssertionRef deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + Object deserialized = null; + boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS); + int match = 0; + JsonToken token = tree.traverse(jp.getCodec()).nextToken(); + // deserialize String + try { + boolean attemptParsing = true; + // ensure that we respect type coercion as set on the client ObjectMapper + if (String.class.equals(Integer.class) || String.class.equals(Long.class) || String.class.equals(Float.class) || String.class.equals(Double.class) || String.class.equals(Boolean.class) || String.class.equals(String.class)) { + attemptParsing = typeCoercion; + if (!attemptParsing) { + attemptParsing |= ((String.class.equals(Integer.class) || String.class.equals(Long.class)) && token == JsonToken.VALUE_NUMBER_INT); + attemptParsing |= ((String.class.equals(Float.class) || String.class.equals(Double.class)) && token == JsonToken.VALUE_NUMBER_FLOAT); + attemptParsing |= (String.class.equals(Boolean.class) && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE)); + attemptParsing |= (String.class.equals(String.class) && token == JsonToken.VALUE_STRING); + } + } + if (attemptParsing) { + deserialized = tree.traverse(jp.getCodec()).readValueAs(String.class); + // TODO: there is no validation against JSON schema constraints + // (min, max, enum, pattern...), this does not perform a strict JSON + // validation, which means the 'match' count may be higher than it should be. + match++; + log.log(Level.FINER, "Input data matches schema 'String'"); + } + } catch (Exception e) { + // deserialization failed, continue + log.log(Level.FINER, "Input data does not match schema 'String'", e); + } + + if (match == 1) { + AssertionRef ret = new AssertionRef(); + ret.setActualInstance(deserialized); + return ret; + } + throw new IOException(String.format("Failed deserialization for AssertionRef: %d classes match result, expected 1", match)); + } + + /** + * Handle deserialization of the 'null' value. + */ + @Override + public AssertionRef getNullValue(DeserializationContext ctxt) throws JsonMappingException { + throw new JsonMappingException(ctxt.getParser(), "AssertionRef cannot be null"); + } + } + + // store a list of schema names defined in oneOf + public static final Map> schemas = new HashMap<>(); + + public AssertionRef() { + super("oneOf", Boolean.FALSE); + } + + public AssertionRef(String o) { + super("oneOf", Boolean.FALSE); + setActualInstance(o); + } + + static { + schemas.put("String", String.class); + JSON.registerDescendants(AssertionRef.class, Collections.unmodifiableMap(schemas)); + } + + @Override + public Map> getSchemas() { + return AssertionRef.schemas; + } + + /** + * Set the instance that matches the oneOf child schema, check + * the instance parameter is valid against the oneOf child schemas: + * String + * + * It could be an instance of the 'oneOf' schemas. + * The oneOf child schemas may themselves be a composed schema (allOf, anyOf, oneOf). + */ + @Override + public void setActualInstance(Object instance) { + if (JSON.isInstanceOf(String.class, instance, new HashSet>())) { + super.setActualInstance(instance); + return; + } + + throw new RuntimeException("Invalid instance type. Must be String"); + } + + /** + * Get the actual instance, which can be the following: + * String + * + * @return The actual instance (String) + */ + @Override + public Object getActualInstance() { + return super.getActualInstance(); + } + + /** + * Get the actual instance of `String`. If the actual instance is not `String`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `String` + * @throws ClassCastException if the instance is not `String` + */ + public String getString() throws ClassCastException { + return (String)super.getActualInstance(); + } + + + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + if (getActualInstance() instanceof String) { + if (getActualInstance() != null) { + joiner.add(String.format("%sone_of_0%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getActualInstance()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + return joiner.toString(); + } + if (getActualInstance() instanceof String) { + if (getActualInstance() != null) { + joiner.add(String.format("%sone_of_1%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getActualInstance()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + return joiner.toString(); + } + if (getActualInstance() instanceof String) { + if (getActualInstance() != null) { + joiner.add(String.format("%sone_of_2%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getActualInstance()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + return joiner.toString(); + } + return null; + } + +} + diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionType.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionType.java new file mode 100644 index 00000000..f881672c --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionType.java @@ -0,0 +1,79 @@ +/* + * Assertion Client + * Client used to get the assertion from the identity provider + * + * The version of the OpenAPI document: $npm_package_version + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Arrays; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Gets or Sets AssertionType + */ +public enum AssertionType { + + SAML("SAML"), + + OIDC("OIDC"); + + private String value; + + AssertionType(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static AssertionType fromValue(String value) { + for (AssertionType b : AssertionType.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + if (prefix == null) { + prefix = ""; + } + + return String.format("%s=%s", prefix, this.toString()); + } + +} + diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/LCUserInfo.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/LCUserInfo.java new file mode 100644 index 00000000..17f793dd --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/LCUserInfo.java @@ -0,0 +1,275 @@ +/* + * Assertion Client + * Client used to get the assertion from the identity provider + * + * The version of the OpenAPI document: $npm_package_version + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Arrays; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.OidcUserInfo; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.SamlUserInfo; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import com.fasterxml.jackson.core.type.TypeReference; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.JSON; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +@JsonDeserialize(using = LCUserInfo.LCUserInfoDeserializer.class) +@JsonSerialize(using = LCUserInfo.LCUserInfoSerializer.class) +public class LCUserInfo extends AbstractOpenApiSchema { + private static final Logger log = Logger.getLogger(LCUserInfo.class.getName()); + + public static class LCUserInfoSerializer extends StdSerializer { + public LCUserInfoSerializer(Class t) { + super(t); + } + + public LCUserInfoSerializer() { + this(null); + } + + @Override + public void serialize(LCUserInfo value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + + public static class LCUserInfoDeserializer extends StdDeserializer { + public LCUserInfoDeserializer() { + this(LCUserInfo.class); + } + + public LCUserInfoDeserializer(Class vc) { + super(vc); + } + + @Override + public LCUserInfo deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + Object deserialized = null; + boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS); + int match = 0; + JsonToken token = tree.traverse(jp.getCodec()).nextToken(); + // deserialize OidcUserInfo + try { + deserialized = tree.traverse(jp.getCodec()).readValueAs(OidcUserInfo.class); + // TODO: there is no validation against JSON schema constraints + // (min, max, enum, pattern...), this does not perform a strict JSON + // validation, which means the 'match' count may be higher than it should be. + if(((OidcUserInfo)deserialized).getIdToken() != null) { + match++; + + log.log(Level.FINER, "Input data matches schema 'OidcUserInfo'"); + } + } catch (Exception e) { + // deserialization failed, continue + log.log(Level.FINER, "Input data does not match schema 'OidcUserInfo'", e); + } + + // deserialize SamlUserInfo + try { + deserialized = tree.traverse(jp.getCodec()).readValueAs(SamlUserInfo.class); + // TODO: there is no validation against JSON schema constraints + // (min, max, enum, pattern...), this does not perform a strict JSON + // validation, which means the 'match' count may be higher than it should be. + if(((SamlUserInfo)deserialized).getResponseXml() != null) { + match++; + log.log(Level.FINER, "Input data matches schema 'SamlUserInfo'"); + } + } catch (Exception e) { + // deserialization failed, continue + log.log(Level.FINER, "Input data does not match schema 'SamlUserInfo'", e); + } + + if (match == 1) { + LCUserInfo ret = new LCUserInfo(); + ret.setActualInstance(deserialized); + return ret; + } + throw new IOException(String.format("Failed deserialization for LCUserInfo: %d classes match result, expected 1", match)); + } + + /** + * Handle deserialization of the 'null' value. + */ + @Override + public LCUserInfo getNullValue(DeserializationContext ctxt) throws JsonMappingException { + throw new JsonMappingException(ctxt.getParser(), "LCUserInfo cannot be null"); + } + } + + // store a list of schema names defined in oneOf + public static final Map> schemas = new HashMap<>(); + + public LCUserInfo() { + super("oneOf", Boolean.FALSE); + } + + public LCUserInfo(OidcUserInfo o) { + super("oneOf", Boolean.FALSE); + setActualInstance(o); + } + + public LCUserInfo(SamlUserInfo o) { + super("oneOf", Boolean.FALSE); + setActualInstance(o); + } + + static { + schemas.put("OidcUserInfo", OidcUserInfo.class); + schemas.put("SamlUserInfo", SamlUserInfo.class); + JSON.registerDescendants(LCUserInfo.class, Collections.unmodifiableMap(schemas)); + } + + @Override + public Map> getSchemas() { + return LCUserInfo.schemas; + } + + /** + * Set the instance that matches the oneOf child schema, check + * the instance parameter is valid against the oneOf child schemas: + * OidcUserInfo, SamlUserInfo + * + * It could be an instance of the 'oneOf' schemas. + * The oneOf child schemas may themselves be a composed schema (allOf, anyOf, oneOf). + */ + @Override + public void setActualInstance(Object instance) { + if (JSON.isInstanceOf(OidcUserInfo.class, instance, new HashSet>())) { + super.setActualInstance(instance); + return; + } + + if (JSON.isInstanceOf(SamlUserInfo.class, instance, new HashSet>())) { + super.setActualInstance(instance); + return; + } + + throw new RuntimeException("Invalid instance type. Must be OidcUserInfo, SamlUserInfo"); + } + + /** + * Get the actual instance, which can be the following: + * OidcUserInfo, SamlUserInfo + * + * @return The actual instance (OidcUserInfo, SamlUserInfo) + */ + @Override + public Object getActualInstance() { + return super.getActualInstance(); + } + + /** + * Get the actual instance of `OidcUserInfo`. If the actual instance is not `OidcUserInfo`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `OidcUserInfo` + * @throws ClassCastException if the instance is not `OidcUserInfo` + */ + public OidcUserInfo getOidcUserInfo() throws ClassCastException { + return (OidcUserInfo)super.getActualInstance(); + } + + /** + * Get the actual instance of `SamlUserInfo`. If the actual instance is not `SamlUserInfo`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `SamlUserInfo` + * @throws ClassCastException if the instance is not `SamlUserInfo` + */ + public SamlUserInfo getSamlUserInfo() throws ClassCastException { + return (SamlUserInfo)super.getActualInstance(); + } + + + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + if (getActualInstance() instanceof SamlUserInfo) { + if (getActualInstance() != null) { + joiner.add(((SamlUserInfo)getActualInstance()).toUrlQueryString(prefix + "one_of_0" + suffix)); + } + return joiner.toString(); + } + if (getActualInstance() instanceof OidcUserInfo) { + if (getActualInstance() != null) { + joiner.add(((OidcUserInfo)getActualInstance()).toUrlQueryString(prefix + "one_of_1" + suffix)); + } + return joiner.toString(); + } + return null; + } + +} + diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/OidcUserInfo.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/OidcUserInfo.java new file mode 100644 index 00000000..42c3fd86 --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/OidcUserInfo.java @@ -0,0 +1,186 @@ +/* + * Assertion Client + * Client used to get the assertion from the identity provider + * + * The version of the OpenAPI document: $npm_package_version + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Arrays; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * OidcUserInfo + */ +@JsonPropertyOrder({ + OidcUserInfo.JSON_PROPERTY_ID_TOKEN, + OidcUserInfo.JSON_PROPERTY_CLAIMS_TOKEN +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +public class OidcUserInfo { + public static final String JSON_PROPERTY_ID_TOKEN = "id_token"; + private String idToken; + + public static final String JSON_PROPERTY_CLAIMS_TOKEN = "claims_token"; + private String claimsToken; + + public OidcUserInfo() { + } + + public OidcUserInfo idToken(String idToken) { + this.idToken = idToken; + return this; + } + + /** + * A JWT representation of a signed SPID/CIE OIDC Idp + * @return idToken + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_ID_TOKEN) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + + public String getIdToken() { + return idToken; + } + + + @JsonProperty(JSON_PROPERTY_ID_TOKEN) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setIdToken(String idToken) { + this.idToken = idToken; + } + + + public OidcUserInfo claimsToken(String claimsToken) { + this.claimsToken = claimsToken; + return this; + } + + /** + * A JWT representation of a signed SPID/CIE OIDC Idp + * @return claimsToken + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_CLAIMS_TOKEN) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + + public String getClaimsToken() { + return claimsToken; + } + + + @JsonProperty(JSON_PROPERTY_CLAIMS_TOKEN) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setClaimsToken(String claimsToken) { + this.claimsToken = claimsToken; + } + + + /** + * Return true if this OidcUserInfo object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OidcUserInfo oidcUserInfo = (OidcUserInfo) o; + return Objects.equals(this.idToken, oidcUserInfo.idToken) && + Objects.equals(this.claimsToken, oidcUserInfo.claimsToken); + } + + @Override + public int hashCode() { + return Objects.hash(idToken, claimsToken); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class OidcUserInfo {\n"); + sb.append(" idToken: ").append(toIndentedString(idToken)).append("\n"); + sb.append(" claimsToken: ").append(toIndentedString(claimsToken)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `id_token` to the URL query string + if (getIdToken() != null) { + joiner.add(String.format("%sid_token%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getIdToken()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `claims_token` to the URL query string + if (getClaimsToken() != null) { + joiner.add(String.format("%sclaims_token%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getClaimsToken()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} + diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/ProblemJson.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/ProblemJson.java new file mode 100644 index 00000000..2ad7c4d7 --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/ProblemJson.java @@ -0,0 +1,297 @@ +/* + * Assertion Client + * Client used to get the assertion from the identity provider + * + * The version of the OpenAPI document: $npm_package_version + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Arrays; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.net.URI; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * ProblemJson + */ +@JsonPropertyOrder({ + ProblemJson.JSON_PROPERTY_TYPE, + ProblemJson.JSON_PROPERTY_TITLE, + ProblemJson.JSON_PROPERTY_STATUS, + ProblemJson.JSON_PROPERTY_DETAIL, + ProblemJson.JSON_PROPERTY_INSTANCE +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +public class ProblemJson { + public static final String JSON_PROPERTY_TYPE = "type"; + private URI type = URI.create("about:blank"); + + public static final String JSON_PROPERTY_TITLE = "title"; + private String title; + + public static final String JSON_PROPERTY_STATUS = "status"; + private Integer status; + + public static final String JSON_PROPERTY_DETAIL = "detail"; + private String detail; + + public static final String JSON_PROPERTY_INSTANCE = "instance"; + private URI instance; + + public ProblemJson() { + } + + public ProblemJson type(URI type) { + this.type = type; + return this; + } + + /** + * An absolute URI that identifies the problem type. When dereferenced, it SHOULD provide human-readable documentation for the problem type (e.g., using HTML). + * @return type + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public URI getType() { + return type; + } + + + @JsonProperty(JSON_PROPERTY_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setType(URI type) { + this.type = type; + } + + + public ProblemJson title(String title) { + this.title = title; + return this; + } + + /** + * A short, summary of the problem type. Written in english and readable for engineers (usually not suited for non technical stakeholders and not localized); example: Service Unavailable + * @return title + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_TITLE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getTitle() { + return title; + } + + + @JsonProperty(JSON_PROPERTY_TITLE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setTitle(String title) { + this.title = title; + } + + + public ProblemJson status(Integer status) { + this.status = status; + return this; + } + + /** + * The HTTP status code generated by the origin server for this occurrence of the problem. + * minimum: 100 + * maximum: 600 + * @return status + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Integer getStatus() { + return status; + } + + + @JsonProperty(JSON_PROPERTY_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setStatus(Integer status) { + this.status = status; + } + + + public ProblemJson detail(String detail) { + this.detail = detail; + return this; + } + + /** + * A human readable explanation specific to this occurrence of the problem. + * @return detail + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_DETAIL) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getDetail() { + return detail; + } + + + @JsonProperty(JSON_PROPERTY_DETAIL) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setDetail(String detail) { + this.detail = detail; + } + + + public ProblemJson instance(URI instance) { + this.instance = instance; + return this; + } + + /** + * An absolute URI that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced. + * @return instance + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_INSTANCE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public URI getInstance() { + return instance; + } + + + @JsonProperty(JSON_PROPERTY_INSTANCE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setInstance(URI instance) { + this.instance = instance; + } + + + /** + * Return true if this ProblemJson object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProblemJson problemJson = (ProblemJson) o; + return Objects.equals(this.type, problemJson.type) && + Objects.equals(this.title, problemJson.title) && + Objects.equals(this.status, problemJson.status) && + Objects.equals(this.detail, problemJson.detail) && + Objects.equals(this.instance, problemJson.instance); + } + + @Override + public int hashCode() { + return Objects.hash(type, title, status, detail, instance); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ProblemJson {\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append(" title: ").append(toIndentedString(title)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" detail: ").append(toIndentedString(detail)).append("\n"); + sb.append(" instance: ").append(toIndentedString(instance)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `type` to the URL query string + if (getType() != null) { + joiner.add(String.format("%stype%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getType()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `title` to the URL query string + if (getTitle() != null) { + joiner.add(String.format("%stitle%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getTitle()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `status` to the URL query string + if (getStatus() != null) { + joiner.add(String.format("%sstatus%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getStatus()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `detail` to the URL query string + if (getDetail() != null) { + joiner.add(String.format("%sdetail%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getDetail()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `instance` to the URL query string + if (getInstance() != null) { + joiner.add(String.format("%sinstance%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getInstance()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} + diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/SamlUserInfo.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/SamlUserInfo.java new file mode 100644 index 00000000..6191fe2f --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/SamlUserInfo.java @@ -0,0 +1,150 @@ +/* + * Assertion Client + * Client used to get the assertion from the identity provider + * + * The version of the OpenAPI document: $npm_package_version + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Arrays; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * SamlUserInfo + */ +@JsonPropertyOrder({ + SamlUserInfo.JSON_PROPERTY_RESPONSE_XML +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +public class SamlUserInfo { + public static final String JSON_PROPERTY_RESPONSE_XML = "response_xml"; + private String responseXml; + + public SamlUserInfo() { + } + + public SamlUserInfo responseXml(String responseXml) { + this.responseXml = responseXml; + return this; + } + + /** + * A string representation of a signed SPID/CIE response + * @return responseXml + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_RESPONSE_XML) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + + public String getResponseXml() { + return responseXml; + } + + + @JsonProperty(JSON_PROPERTY_RESPONSE_XML) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setResponseXml(String responseXml) { + this.responseXml = responseXml; + } + + + /** + * Return true if this SamlUserInfo object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SamlUserInfo samlUserInfo = (SamlUserInfo) o; + return Objects.equals(this.responseXml, samlUserInfo.responseXml); + } + + @Override + public int hashCode() { + return Objects.hash(responseXml); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class SamlUserInfo {\n"); + sb.append(" responseXml: ").append(toIndentedString(responseXml)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `response_xml` to the URL query string + if (getResponseXml() != null) { + joiner.add(String.format("%sresponse_xml%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getResponseXml()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} + From ec4d6924e6e49643e77d163e964b6e011ae8ab7b Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 5 Apr 2023 10:54:22 +0200 Subject: [PATCH 028/403] [SLS-22] Updated test and comments --- core/build.gradle | 1 + .../command/LollipopConsumerCommand.java | 10 ++ .../LollipopConsumerCommandBuilder.java | 6 + .../LollipopConsumerCommandBuilderImpl.java | 2 +- .../config/LollipopConsumerRequestConfig.java | 1 + .../helper/LollipopConsumerFactoryHelper.java | 12 ++ .../http_verifier/HttpMessageVerifier.java | 21 +++ .../HttpMessageVerifierFactory.java | 6 + .../service/AssertionVerifierService.java | 9 ++ .../service/HttpMessageVerifierService.java | 15 ++- .../impl/HttpMessageVerifierServiceImpl.java | 55 ++++++-- .../HttpMessageVerifierServiceImplTest.java | 120 +++++++++++++++++- 12 files changed, 240 insertions(+), 18 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index 2c7fe8c3..a75b9aa1 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -28,6 +28,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.mockito:mockito-core:5.2.0' testImplementation 'org.mockito:mockito-junit-jupiter:5.2.0' + testImplementation 'org.assertj:assertj-core:3.24.2' } tasks.named('test') { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java index 90f6c288..3631fd1d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java @@ -4,7 +4,17 @@ 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 { + /** + * 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); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java index 63b66261..3031657a 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java @@ -1,7 +1,13 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.command; +/** Builder class for creating command instance */ public interface LollipopConsumerCommandBuilder { + /** + * Builder for creating an instance of {@link LollipopConsumerCommand} + * + * @return an instance of {@link LollipopConsumerCommand} + */ LollipopConsumerCommand createCommand(); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java index 891e789d..4bc0e67a 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java @@ -6,7 +6,7 @@ import it.pagopa.tech.lollipop.consumer.helper.LollipopConsumerFactoryHelper; import javax.inject.Inject; -/** Builder class for creating command instance */ +/** Implementation of {@link LollipopConsumerCommandBuilder}, used to create istances of {@link LollipopConsumerCommandImpl} */ public class LollipopConsumerCommandBuilderImpl implements LollipopConsumerCommandBuilder { private final LollipopConsumerFactoryHelper factoryHelper; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index b2958e4d..f517a70c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -12,4 +12,5 @@ public class LollipopConsumerRequestConfig { private String signatureInputHeader = "signature-input"; private String contentEncodingHeader = "content-encoding"; private String contentDigestHeader = "content-digest"; + private boolean strictDigestVerify = false; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index ba74fe9d..325e07e9 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -10,6 +10,8 @@ import it.pagopa.tech.lollipop.consumer.service.impl.AssertionVerifierServiceImpl; import it.pagopa.tech.lollipop.consumer.service.impl.HttpMessageVerifierServiceImpl; +import javax.inject.Inject; + /** Helper class for retrieving instances */ public class LollipopConsumerFactoryHelper { @@ -17,6 +19,16 @@ public class LollipopConsumerFactoryHelper { private IdpCertProviderFactory idpCertProviderFactory; private AssertionServiceFactory assertionServiceFactory; + @Inject + public LollipopConsumerFactoryHelper( + HttpMessageVerifierFactory httpMessageVerifierFactory, + IdpCertProviderFactory idpCertProviderFactory, + AssertionServiceFactory assertionServiceFactory) { + this.httpMessageVerifierFactory = httpMessageVerifierFactory; + this.idpCertProviderFactory = idpCertProviderFactory; + this.assertionServiceFactory = assertionServiceFactory; + } + /** * Utility method for retrieving an instance of {@link HttpMessageVerifierService} * diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java index eb7c7a4d..10cc2d69 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java @@ -5,11 +5,32 @@ import java.io.UnsupportedEncodingException; import java.util.Map; +/** + * Interface of the Http Verifier. This interface provides services through an implementation of the http-signature draft + */ public interface HttpMessageVerifier { + /** + * Checks whether the calculated digest of the payload matches the content-digest of the http request + * @param digest Content-Digest for the request payload + * @param requestBody Request payload + * @param encoding Encoding to be used for the payload. To be used if the underlying implementation checks uses the + * content byte array + * @return boolean set to true if the digest check is valid + * @throws LollipopDigestException + * @throws UnsupportedEncodingException + */ boolean verifyDigest(String digest, String requestBody, String encoding) throws LollipopDigestException, UnsupportedEncodingException; + /** + * Checks whether the calculated signatures of the required parameter matches with those provided within + * the Signature param + * @param signature + * @param signatureInput + * @param parameters + * @return boolean set to true if the signature check is valid + */ boolean verifyHttpSignature( String signature, String signatureInput, Map parameters); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java index 73bfbbf4..5d51334c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java @@ -1,7 +1,13 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.http_verifier; +/** Interface for the factory used to create instances of {@link HttpMessageVerifier} */ public interface HttpMessageVerifierFactory { + /** + * + * @return instance of HttpMessageVerifier + */ HttpMessageVerifier create(); + } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java index b5b2c4c9..ddfaa72d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java @@ -3,6 +3,15 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +/** + * Interface of the service to be used for validating SAML Assertions obtained using the content passed in the {@link LollipopConsumerRequest} + */ public interface AssertionVerifierService { + + /** + * Validates Lollipop request Assertion, using the assertion-ref within the request header params + * @param request + * @return + */ boolean validateLollipop(LollipopConsumerRequest request); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java index 70e82c3b..c214a16a 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java @@ -6,7 +6,20 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import java.io.UnsupportedEncodingException; +/** + * Interface of the service to be used for validating the http {@link LollipopConsumerRequest} through the digest and signature + * validation of the http-signature draft + */ public interface HttpMessageVerifierService { + + /** + * Validates the http request + * @param request + * @return flag to true if the request is validated + * @throws UnsupportedEncodingException + * @throws LollipopDigestException + * @throws LollipopVerifierException + */ boolean verifyHttpMessage(LollipopConsumerRequest request) - throws LollipopDigestException, UnsupportedEncodingException, LollipopDigestException, LollipopVerifierException; + throws UnsupportedEncodingException, LollipopDigestException, LollipopVerifierException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java index 5098ab9b..84836ec4 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java @@ -8,9 +8,15 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; import java.io.UnsupportedEncodingException; +import java.util.Arrays; +import java.util.Locale; import java.util.Map; import javax.inject.Inject; + +/** + * Standard implementation of {@link HttpMessageVerifierService} + */ public class HttpMessageVerifierServiceImpl implements HttpMessageVerifierService { private HttpMessageVerifier httpMessageVerifier; @@ -24,6 +30,14 @@ public HttpMessageVerifierServiceImpl( this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; } + /** + * {@see HttpMessageVerifierService.verifyHttpMessage()} + * @param lollipopConsumerRequest + * @return + * @throws LollipopDigestException + * @throws UnsupportedEncodingException + * @throws LollipopVerifierException + */ @Override public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest) throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException { @@ -43,10 +57,11 @@ public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest if (signatureInput == null) { throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE_INPUT, - "Missing Signature Input Header"); + "Missing Signature-Input Header"); } - if (signatureInput.contains(lollipopConsumerRequestConfig.getContentDigestHeader())) { + + if (lollipopConsumerRequestConfig.isStrictDigestVerify() || hasDigestInSignatureInput(signatureInput)) { String contentDigest = headerParams.get(lollipopConsumerRequestConfig.getContentDigestHeader()); @@ -56,14 +71,39 @@ public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest String contentEncoding = headerParams.get(lollipopConsumerRequestConfig.getContentEncodingHeader()); - verifyContentDigest(contentDigest, requestBody, contentEncoding); + if (!verifyContentDigest(contentDigest, requestBody, contentEncoding)) { + throw new LollipopDigestException(LollipopDigestException.ErrorCode.INCORRECT_DIGEST, + "Content-Digest does not match the request payload"); + } } return verifyHttpSignature(lollipopConsumerRequest); } - protected boolean verifyContentDigest( + /** + * Checks if any of the signatures have the content-digest param within the signature input, to determine + * if in non-strict mode the digest should be validated + * @param signatureInput + * @return flag to determine if the content-digest is present + */ + private boolean hasDigestInSignatureInput(String signatureInput) { + return Arrays.stream(signatureInput.split(";")).anyMatch( + signaturePart -> signaturePart.contains("=") && signaturePart.toLowerCase(Locale.ROOT).contains( + lollipopConsumerRequestConfig.getContentDigestHeader().toLowerCase(Locale.ROOT))); + } + + /** + * Checks for required params to be used within the digest validation process, and executes the validation + * through the usage of the provided implementation of the {@link HttpMessageVerifier} + * @param contentDigest + * @param requestBody + * @param contentEncoding + * @return + * @throws LollipopDigestException + * @throws UnsupportedEncodingException + */ + private boolean verifyContentDigest( String contentDigest, String requestBody, String contentEncoding) throws LollipopDigestException, UnsupportedEncodingException { @@ -79,12 +119,7 @@ protected boolean verifyContentDigest( } // Attempt to execute digest validation - if (!httpMessageVerifier.verifyDigest(contentDigest, requestBody, contentEncoding)) { - throw new LollipopDigestException( - LollipopDigestException.ErrorCode.INCORRECT_DIGEST, "Invalid Digest"); - } - - return true; + return httpMessageVerifier.verifyDigest(contentDigest, requestBody, contentEncoding); } /** TODO: stub */ diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java index a2395165..3bfa8994 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java @@ -2,9 +2,11 @@ package it.pagopa.tech.lollipop.consumer.service.impl; import static org.mockito.Mockito.when; +import static org.assertj.core.api.Assertions.*; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import java.io.UnsupportedEncodingException; @@ -18,7 +20,10 @@ class HttpMessageVerifierServiceImplTest { final String VALID_DIGEST = "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw="; final String VALID_PAYLOAD = "a valid message payload"; + final String INVALID_PAYLOAD = "an invalid payload"; final String INVALID_ENCODING = "UTF-326"; + final String VALID_ENCODING = "UTF-8"; + private LollipopConsumerRequestConfig httpMessageVerifierConfig; private HttpMessageVerifier httpMessageVerifier; @@ -31,7 +36,8 @@ public HttpMessageVerifierServiceImplTest() { LollipopConsumerRequestConfig.builder() .contentDigestHeader("Content-Digest") .contentEncodingHeader("Content-Encoding") - .signatureHeader("Signature-Input") + .signatureHeader("Signature") + .signatureInputHeader("Signature-Input") .build(); this.httpMessageVerifier = Mockito.mock(HttpMessageVerifier.class); } @@ -40,32 +46,134 @@ public HttpMessageVerifierServiceImplTest() { public void beforeEach() throws LollipopDigestException, UnsupportedEncodingException { Mockito.reset(httpMessageVerifier); when(httpMessageVerifier.verifyDigest( - Mockito.eq(VALID_DIGEST), Mockito.eq(VALID_PAYLOAD), Mockito.eq("UTF-8"))) + Mockito.eq(VALID_DIGEST), Mockito.eq(VALID_PAYLOAD), Mockito.eq(VALID_ENCODING))) .thenReturn(true); + when(httpMessageVerifier.verifyDigest( + Mockito.eq(VALID_DIGEST), Mockito.eq(INVALID_PAYLOAD), Mockito.eq(VALID_ENCODING))) + .thenReturn(false); this.httpMessageVerifierService = new HttpMessageVerifierServiceImpl(httpMessageVerifier, httpMessageVerifierConfig); } @Test - public void validDigestIsProcessed() - throws LollipopDigestException, UnsupportedEncodingException { - httpMessageVerifierService.verifyContentDigest(VALID_DIGEST,VALID_PAYLOAD,"UTF-8"); + public void validRequestIsProcessed() { + assertThatNoException() + .isThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(getLollipopConsumerRequest())); + } + + @Test + public void invalidRequestIsProcessedWithStrictDigestValidation() { + LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); + this.httpMessageVerifierConfig.setStrictDigestVerify(true); + lollipopConsumerRequest.setRequestBody(INVALID_PAYLOAD); + lollipopConsumerRequest.getHeaderParams().put( + "Signature-Input", + "sig1=(\"x-pagopa-lollipop-original-method\" " + + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" + + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); + // execute & verify + assertThatThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) + .isInstanceOfSatisfying( + LollipopDigestException.class, + e -> { + assertThat(e).hasMessageContaining("Content-Digest does not match the request payload"); + assertThat(e.getErrorCode()) + .isEqualTo(LollipopDigestException.ErrorCode.INCORRECT_DIGEST); + }); + } + + @Test + public void requestWithInvalidDigestThrowsException() { + LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); + lollipopConsumerRequest.setRequestBody(INVALID_PAYLOAD); + // execute & verify + assertThatThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) + .isInstanceOfSatisfying( + LollipopDigestException.class, + e -> { + assertThat(e).hasMessageContaining("Content-Digest does not match the request payload"); + assertThat(e.getErrorCode()) + .isEqualTo(LollipopDigestException.ErrorCode.INCORRECT_DIGEST); + }); + } + + @Test + public void requestWithoutContentDigestToValidateThrowsException() { + LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); + lollipopConsumerRequest.getHeaderParams().remove("Content-Digest"); + // execute & verify + assertThatThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) + .isInstanceOfSatisfying( + LollipopDigestException.class, + e -> { + assertThat(e).hasMessageContaining("Missing required Content-Digest for validation"); + assertThat(e.getErrorCode()) + .isEqualTo(LollipopDigestException.ErrorCode.MISSING_DIGEST); + }); + } + + @Test + public void requestWithoutRequestBodyToValidateThrowsException() { + LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); + lollipopConsumerRequest.setRequestBody(null); + // execute & verify + assertThatThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) + .isInstanceOfSatisfying( + LollipopDigestException.class, + e -> { + assertThat(e).hasMessageContaining("Missing required payload for digest validation"); + assertThat(e.getErrorCode()) + .isEqualTo(LollipopDigestException.ErrorCode.MISSING_PAYLOAD); + }); + } + + @Test + public void requestWithoutSignatureToValidateThrowsException() { + LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); + lollipopConsumerRequest.getHeaderParams().remove("Signature"); + // execute & verify + assertThatThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) + .isInstanceOfSatisfying( + LollipopVerifierException.class, + e -> { + assertThat(e).hasMessageContaining("Missing Signature Header"); + assertThat(e.getErrorCode()) + .isEqualTo(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE); + }); + } + + @Test + public void requestWithoutSignatureInputToValidateThrowsException() { + LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); + lollipopConsumerRequest.getHeaderParams().remove("Signature-Input"); + // execute & verify + assertThatThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) + .isInstanceOfSatisfying( + LollipopVerifierException.class, + e -> { + assertThat(e).hasMessageContaining("Missing Signature-Input Header"); + assertThat(e.getErrorCode()) + .isEqualTo(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE_INPUT); + }); } private LollipopConsumerRequest getLollipopConsumerRequest() { HashMap lollipopHeaderParams = new HashMap<>(); lollipopHeaderParams.put("Content-Digest", VALID_DIGEST); - lollipopHeaderParams.put("Content-Encoding", "UTF-8"); + lollipopHeaderParams.put("Content-Encoding", VALID_ENCODING); lollipopHeaderParams.put( "Signature-Input", "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" " + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); + lollipopHeaderParams.put( + "Signature", "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"); return LollipopConsumerRequest.builder() .requestBody(VALID_PAYLOAD) .headerParams(lollipopHeaderParams) .build(); } + } From dcba9821bb342f3c3d888bcf5c0f24da87338e5c Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 5 Apr 2023 10:53:08 +0200 Subject: [PATCH 029/403] [SLS-9] Implemented AssertionClient with getAssertion method --- .../client/simple/AssertionSimpleClient.java | 56 +++++++++++++++++++ .../simple/AssertionSimpleClientProvider.java | 14 +++++ .../assertion/client/AssertionClient.java | 3 +- .../consumer/model/SamlAssertion.java | 3 +- 4 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientProvider.java diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java new file mode 100644 index 00000000..25662f0a --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java @@ -0,0 +1,56 @@ +package it.pagopa.tech.lollipop.consumer.assertion.client.simple; + +import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClient; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiClient; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiException; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.api.DefaultApi; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.AssertionRef; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.LCUserInfo; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.SamlUserInfo; +import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; + +import javax.inject.Inject; + +public class AssertionSimpleClient implements AssertionClient { + + ApiClient apiClient; + DefaultApi defaultApi; + + @Inject + public AssertionSimpleClient(ApiClient client) { + this.apiClient = client; + this.defaultApi = new DefaultApi(client); + } + + @Override + public SamlAssertion getAssertion(String jwt, String assertionRef) throws LollipopAssertionNotFoundException { + AssertionRef ref = new AssertionRef(assertionRef); + + if(jwt.isEmpty() || assertionRef.isEmpty()){ + throw new IllegalArgumentException("Jwt or Assertion Ref missing"); + } + + LCUserInfo responseAssertion = new LCUserInfo(); + + try{ + responseAssertion = this.defaultApi.getAssertion(ref, jwt); + } + catch(ApiException e){ + throw new LollipopAssertionNotFoundException("Error retrieving assertion: "+e.getMessage(), e); + } + + if(responseAssertion.getActualInstance().getClass().equals(SamlUserInfo.class)){ + SamlAssertion response = new SamlAssertion(); + SamlUserInfo data = (SamlUserInfo)responseAssertion.getActualInstance(); + String assertionData = data.getResponseXml(); + response.setAssertionRef(assertionRef); + response.setAssertionData(assertionData); + return response; + } + + //TODO handle oidc assertion + + return null; + } +} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientProvider.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientProvider.java new file mode 100644 index 00000000..55e71a74 --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientProvider.java @@ -0,0 +1,14 @@ +package it.pagopa.tech.lollipop.consumer.assertion.client.simple; + +import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClient; +import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClientProvider; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiClient; + +public class AssertionSimpleClientProvider implements AssertionClientProvider { + @Override + public AssertionClient provideClient() { + AssertionClient client = new AssertionSimpleClient(new ApiClient()); + + return client; + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClient.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClient.java index 47f9e744..59c8de62 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClient.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClient.java @@ -1,8 +1,9 @@ package it.pagopa.tech.lollipop.consumer.assertion.client; +import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; public interface AssertionClient { - SamlAssertion getAssertion(String jwt, String assertionRef); + SamlAssertion getAssertion(String jwt, String assertionRef) throws LollipopAssertionNotFoundException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java index 0510d980..605f287d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java @@ -8,6 +8,5 @@ public class SamlAssertion { private String assertionRef; - private String inResponseTo; - private Long notBefore; + private String assertionData; } From c3889240d9361a1370b3a661bac49284a3e7b8d4 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 5 Apr 2023 10:53:28 +0200 Subject: [PATCH 030/403] [SLS-9] Unit test for AssertionSimpleClient --- .../simple/AssertionSimpleClientTest.java | 59 +++++++++++++++++++ .../LollipopAssertionNotFoundException.java | 20 +++++++ 2 files changed, 79 insertions(+) create mode 100644 assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopAssertionNotFoundException.java diff --git a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java new file mode 100644 index 00000000..70381fd1 --- /dev/null +++ b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java @@ -0,0 +1,59 @@ +package it.pagopa.tech.lollipop.consumer.assertion.client.simple; + +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiClient; +import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatNoException; +class AssertionSimpleClientTest { + + AssertionSimpleClient assertionSimpleClient = new AssertionSimpleClient(new ApiClient()); + @Test + void samlAssertionFound() throws LollipopAssertionNotFoundException { + // setup + String assertionRef = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; + String jwt = "Bearer aValidJWT"; + String xmlResponse = " https://posteid.poste.it IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU= GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9 HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4 fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1 MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0 uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc= https://posteid.poste.it ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I= O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4 xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4 fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1 MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0 uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc= SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd https://app-backend.io.italia.it https://www.spid.gov.it/SpidL2 TINIT-AAAAAA89S20I111X "; + SamlAssertion response = assertionSimpleClient.getAssertion(jwt, assertionRef); + + Assertions.assertNotNull(response); + Assertions.assertNotNull(response.getAssertionRef()); + Assertions.assertNotNull(response.getAssertionData()); + Assertions.assertEquals(assertionRef, response.getAssertionRef()); + Assertions.assertEquals(xmlResponse, response.getAssertionData()); + } + + //TODO test oidcAssertionFound + + @Test + void assertionNotFound() { + // setup + String assertionRef = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfXXXXX"; + String jwt = "{kty: \"EC\", crv: \"P-256\", x: \"SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74\",y: \"lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI\"}"; + + Assertions.assertThrows(LollipopAssertionNotFoundException.class, () -> assertionSimpleClient.getAssertion(jwt, assertionRef)); + } + + //TODO wrong jwt test + @Test + void noJwt() { + // setup + String assertionRef = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; + String jwt = ""; + + Assertions.assertThrows(IllegalArgumentException.class, () -> assertionSimpleClient.getAssertion(jwt, assertionRef)); + } + @Test + void noAssertionRef() { + // setup + String assertionRef = ""; + String jwt = "Bearer aValidJWT"; + + Assertions.assertThrows(IllegalArgumentException.class, () -> assertionSimpleClient.getAssertion(jwt, assertionRef)); + } + + + +} \ No newline at end of file diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopAssertionNotFoundException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopAssertionNotFoundException.java new file mode 100644 index 00000000..30be9288 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopAssertionNotFoundException.java @@ -0,0 +1,20 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +import java.util.Objects; + +/** + * Thrown in case of problems retrieving assertion + */ +public class LollipopAssertionNotFoundException extends Exception { + + /** + * Constructs new exception with provided message and cause + * + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public LollipopAssertionNotFoundException(String message, Throwable cause) { + super(message, cause); + } + +} From 17575ca635f13ce23bf2fbefe5a623870f9f21cc Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 5 Apr 2023 11:07:40 +0200 Subject: [PATCH 031/403] [SLS-9] Added javadoc --- .../client/simple/AssertionSimpleClient.java | 17 ++++++++++++++++- .../simple/AssertionSimpleClientProvider.java | 12 +++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java index 25662f0a..48711da1 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java @@ -12,6 +12,9 @@ import javax.inject.Inject; +/** + Implementation of the @AssertionClient using generated openAPI REST Client + */ public class AssertionSimpleClient implements AssertionClient { ApiClient apiClient; @@ -23,6 +26,18 @@ public AssertionSimpleClient(ApiClient client) { this.defaultApi = new DefaultApi(client); } + + /** + * Retrieve assertion from IdentityProvider using REST Client + * The retrieved assertion can be of two types: + * SAML or OIDC + * Only SAML assertions are supported at this moment + * + * @param jwt Auth token for header param x-pagopa-lollipop-auth + * @param assertionRef Assertion unique identification + * @return the retrieved assertion or null if the assertion is not supported (not SAML) + * @throws LollipopAssertionNotFoundException if some error occurred in the request + */ @Override public SamlAssertion getAssertion(String jwt, String assertionRef) throws LollipopAssertionNotFoundException { AssertionRef ref = new AssertionRef(assertionRef); @@ -31,7 +46,7 @@ public SamlAssertion getAssertion(String jwt, String assertionRef) throws Lollip throw new IllegalArgumentException("Jwt or Assertion Ref missing"); } - LCUserInfo responseAssertion = new LCUserInfo(); + LCUserInfo responseAssertion; try{ responseAssertion = this.defaultApi.getAssertion(ref, jwt); diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientProvider.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientProvider.java index 55e71a74..3716829e 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientProvider.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientProvider.java @@ -4,11 +4,17 @@ import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClientProvider; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiClient; +/** + * Provider class for retrieving an instance of {@link AssertionSimpleClient} + */ public class AssertionSimpleClientProvider implements AssertionClientProvider { + + /** + * Provide an instance of {@link AssertionSimpleClient} + * @return {@link AssertionSimpleClient} + */ @Override public AssertionClient provideClient() { - AssertionClient client = new AssertionSimpleClient(new ApiClient()); - - return client; + return new AssertionSimpleClient(new ApiClient()); } } From 0b5161327388b0b54c574531ec46f53667186415 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 5 Apr 2023 11:17:41 +0200 Subject: [PATCH 032/403] [core_sprint_1_fix] Removed lombok rc version --- assertion-rest-client-native/build.gradle | 2 +- core/build.gradle | 2 +- http-verifier/build.gradle | 2 +- identity-service-rest-client-native/build.gradle | 3 +-- redis-storage/build.gradle | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/assertion-rest-client-native/build.gradle b/assertion-rest-client-native/build.gradle index fe16fc06..107f1673 100644 --- a/assertion-rest-client-native/build.gradle +++ b/assertion-rest-client-native/build.gradle @@ -10,7 +10,7 @@ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' - id("io.freefair.lombok") version "8.0.0-rc4" + id("io.freefair.lombok") version "8.0.0" } group 'it.pagopa.commons' diff --git a/core/build.gradle b/core/build.gradle index a75b9aa1..847684c0 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -10,7 +10,7 @@ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' - id("io.freefair.lombok") version "8.0.0-rc4" + id("io.freefair.lombok") version "8.0.0" } group 'it.pagopa.tech' diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index a0686a16..7fcb39ce 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -10,7 +10,7 @@ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' - id("io.freefair.lombok") version "8.0.0-rc4" + id("io.freefair.lombok") version "8.0.0" } group 'it.pagopa.tech' diff --git a/identity-service-rest-client-native/build.gradle b/identity-service-rest-client-native/build.gradle index 7b5c140a..a9f3f323 100644 --- a/identity-service-rest-client-native/build.gradle +++ b/identity-service-rest-client-native/build.gradle @@ -6,11 +6,10 @@ * User Manual available at https://docs.gradle.org/8.0.2/userguide/building_java_projects.html */ - plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' - id("io.freefair.lombok") version "8.0.0-rc4" + id("io.freefair.lombok") version '8.0.0' } group 'it.pagopa.tech' diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle index 7b5c140a..6abef762 100644 --- a/redis-storage/build.gradle +++ b/redis-storage/build.gradle @@ -10,7 +10,7 @@ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' - id("io.freefair.lombok") version "8.0.0-rc4" + id("io.freefair.lombok") version "8.0.0" } group 'it.pagopa.tech' From 5e89684bc30a4a562fc4db5f3e9df5d5173d31ed Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 5 Apr 2023 11:18:36 +0200 Subject: [PATCH 033/403] [core_sprint_1_fix] Applied spotless formatting --- .../command/LollipopConsumerCommand.java | 4 +- .../LollipopConsumerCommandBuilderImpl.java | 5 +- .../exception/LollipopVerifierException.java | 4 +- .../helper/LollipopConsumerFactoryHelper.java | 1 - .../http_verifier/HttpMessageVerifier.java | 16 ++-- .../HttpMessageVerifierFactory.java | 6 +- .../service/AssertionVerifierService.java | 7 +- .../service/HttpMessageVerifierService.java | 5 +- .../impl/HttpMessageVerifierServiceImpl.java | 53 ++++++++------ .../impl/LollipopConsumerCommandImplTest.java | 13 ++-- .../HttpMessageVerifierServiceImplTest.java | 73 +++++++++++++------ 11 files changed, 115 insertions(+), 72 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java index 3631fd1d..9bb161a6 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java @@ -4,9 +4,7 @@ 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 - * */ +/** Interface for the command executing the lollipop request consumption */ public interface LollipopConsumerCommand { /** diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java index 4bc0e67a..3f4e22e7 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java @@ -6,7 +6,10 @@ import it.pagopa.tech.lollipop.consumer.helper.LollipopConsumerFactoryHelper; import javax.inject.Inject; -/** Implementation of {@link LollipopConsumerCommandBuilder}, used to create istances of {@link LollipopConsumerCommandImpl} */ +/** + * Implementation of {@link LollipopConsumerCommandBuilder}, used to create istances of {@link + * LollipopConsumerCommandImpl} + */ public class LollipopConsumerCommandBuilderImpl implements LollipopConsumerCommandBuilder { private final LollipopConsumerFactoryHelper factoryHelper; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java index 13b5ae0c..04e98686 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java @@ -4,7 +4,8 @@ import java.util.Objects; /** - * Thrown in case of problems when computing or verifying lollipop request through the http-signature flow + * Thrown in case of problems when computing or verifying lollipop request through the + * http-signature flow */ public class LollipopVerifierException extends Exception { @@ -45,7 +46,6 @@ public ErrorCode getErrorCode() { /** Error codes to classify Lollipop Request Exceptions */ public enum ErrorCode { - MISSING_SIGNATURE, MISSING_SIGNATURE_INPUT diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index 325e07e9..d9be8966 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -9,7 +9,6 @@ import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; import it.pagopa.tech.lollipop.consumer.service.impl.AssertionVerifierServiceImpl; import it.pagopa.tech.lollipop.consumer.service.impl.HttpMessageVerifierServiceImpl; - import javax.inject.Inject; /** Helper class for retrieving instances */ diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java index 10cc2d69..f3abfc58 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java @@ -6,16 +6,19 @@ import java.util.Map; /** - * Interface of the Http Verifier. This interface provides services through an implementation of the http-signature draft + * Interface of the Http Verifier. This interface provides services through an implementation of the + * http-signature draft */ public interface HttpMessageVerifier { /** - * Checks whether the calculated digest of the payload matches the content-digest of the http request + * Checks whether the calculated digest of the payload matches the content-digest of the http + * request + * * @param digest Content-Digest for the request payload * @param requestBody Request payload - * @param encoding Encoding to be used for the payload. To be used if the underlying implementation checks uses the - * content byte array + * @param encoding Encoding to be used for the payload. To be used if the underlying + * implementation checks uses the content byte array * @return boolean set to true if the digest check is valid * @throws LollipopDigestException * @throws UnsupportedEncodingException @@ -24,8 +27,9 @@ boolean verifyDigest(String digest, String requestBody, String encoding) throws LollipopDigestException, UnsupportedEncodingException; /** - * Checks whether the calculated signatures of the required parameter matches with those provided within - * the Signature param + * Checks whether the calculated signatures of the required parameter matches with those + * provided within the Signature param + * * @param signature * @param signatureInput * @param parameters diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java index 5d51334c..ec1de3f7 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java @@ -4,10 +4,6 @@ /** Interface for the factory used to create instances of {@link HttpMessageVerifier} */ public interface HttpMessageVerifierFactory { - /** - * - * @return instance of HttpMessageVerifier - */ + /** @return instance of HttpMessageVerifier */ HttpMessageVerifier create(); - } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java index ddfaa72d..758422bf 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java @@ -4,12 +4,15 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; /** - * Interface of the service to be used for validating SAML Assertions obtained using the content passed in the {@link LollipopConsumerRequest} + * Interface of the service to be used for validating SAML Assertions obtained using the content + * passed in the {@link LollipopConsumerRequest} */ public interface AssertionVerifierService { /** - * Validates Lollipop request Assertion, using the assertion-ref within the request header params + * Validates Lollipop request Assertion, using the assertion-ref within the request header + * params + * * @param request * @return */ diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java index c214a16a..b8885342 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java @@ -7,13 +7,14 @@ import java.io.UnsupportedEncodingException; /** - * Interface of the service to be used for validating the http {@link LollipopConsumerRequest} through the digest and signature - * validation of the http-signature draft + * Interface of the service to be used for validating the http {@link LollipopConsumerRequest} + * through the digest and signature validation of the http-signature draft */ public interface HttpMessageVerifierService { /** * Validates the http request + * * @param request * @return flag to true if the request is validated * @throws UnsupportedEncodingException diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java index 84836ec4..df3dce17 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java @@ -13,10 +13,7 @@ import java.util.Map; import javax.inject.Inject; - -/** - * Standard implementation of {@link HttpMessageVerifierService} - */ +/** Standard implementation of {@link HttpMessageVerifierService} */ public class HttpMessageVerifierServiceImpl implements HttpMessageVerifierService { private HttpMessageVerifier httpMessageVerifier; @@ -32,6 +29,7 @@ public HttpMessageVerifierServiceImpl( /** * {@see HttpMessageVerifierService.verifyHttpMessage()} + * * @param lollipopConsumerRequest * @return * @throws LollipopDigestException @@ -40,15 +38,16 @@ public HttpMessageVerifierServiceImpl( */ @Override public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest) - throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException { + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException { Map headerParams = lollipopConsumerRequest.getHeaderParams(); - String signature = - headerParams.get(lollipopConsumerRequestConfig.getSignatureHeader()); + String signature = headerParams.get(lollipopConsumerRequestConfig.getSignatureHeader()); if (signature == null) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE, + throw new LollipopVerifierException( + LollipopVerifierException.ErrorCode.MISSING_SIGNATURE, "Missing Signature Header"); } @@ -56,12 +55,13 @@ public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest headerParams.get(lollipopConsumerRequestConfig.getSignatureInputHeader()); if (signatureInput == null) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE_INPUT, + throw new LollipopVerifierException( + LollipopVerifierException.ErrorCode.MISSING_SIGNATURE_INPUT, "Missing Signature-Input Header"); } - - if (lollipopConsumerRequestConfig.isStrictDigestVerify() || hasDigestInSignatureInput(signatureInput)) { + if (lollipopConsumerRequestConfig.isStrictDigestVerify() + || hasDigestInSignatureInput(signatureInput)) { String contentDigest = headerParams.get(lollipopConsumerRequestConfig.getContentDigestHeader()); @@ -72,30 +72,40 @@ public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest headerParams.get(lollipopConsumerRequestConfig.getContentEncodingHeader()); if (!verifyContentDigest(contentDigest, requestBody, contentEncoding)) { - throw new LollipopDigestException(LollipopDigestException.ErrorCode.INCORRECT_DIGEST, + throw new LollipopDigestException( + LollipopDigestException.ErrorCode.INCORRECT_DIGEST, "Content-Digest does not match the request payload"); } } return verifyHttpSignature(lollipopConsumerRequest); - } /** - * Checks if any of the signatures have the content-digest param within the signature input, to determine - * if in non-strict mode the digest should be validated + * Checks if any of the signatures have the content-digest param within the signature input, to + * determine if in non-strict mode the digest should be validated + * * @param signatureInput * @return flag to determine if the content-digest is present */ private boolean hasDigestInSignatureInput(String signatureInput) { - return Arrays.stream(signatureInput.split(";")).anyMatch( - signaturePart -> signaturePart.contains("=") && signaturePart.toLowerCase(Locale.ROOT).contains( - lollipopConsumerRequestConfig.getContentDigestHeader().toLowerCase(Locale.ROOT))); + return Arrays.stream(signatureInput.split(";")) + .anyMatch( + signaturePart -> + signaturePart.contains("=") + && signaturePart + .toLowerCase(Locale.ROOT) + .contains( + lollipopConsumerRequestConfig + .getContentDigestHeader() + .toLowerCase(Locale.ROOT))); } /** - * Checks for required params to be used within the digest validation process, and executes the validation - * through the usage of the provided implementation of the {@link HttpMessageVerifier} + * Checks for required params to be used within the digest validation process, and executes the + * validation through the usage of the provided implementation of the {@link + * HttpMessageVerifier} + * * @param contentDigest * @param requestBody * @param contentEncoding @@ -114,7 +124,8 @@ private boolean verifyContentDigest( } if (requestBody == null) { - throw new LollipopDigestException(LollipopDigestException.ErrorCode.MISSING_PAYLOAD, + throw new LollipopDigestException( + LollipopDigestException.ErrorCode.MISSING_PAYLOAD, "Missing required payload for digest validation"); } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java index 8a878102..7f943d56 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -14,7 +14,6 @@ import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; import java.io.UnsupportedEncodingException; - import lombok.SneakyThrows; import org.junit.jupiter.api.*; import org.mockito.*; @@ -37,7 +36,8 @@ void beforeAll() { @Test void failedHttpMessageValidationThrowDigestException() - throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException { + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException { doThrow( new LollipopDigestException( @@ -77,7 +77,8 @@ void failedHttpMessageValidationThrowUnsupportedEncodingException() { @Test void failedHttpMessageValidationWithoutThrowingException() - throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException { + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException { doReturn(false) .when(messageVerifierServiceMock) @@ -96,7 +97,8 @@ void failedHttpMessageValidationWithoutThrowingException() @Test void failedAssertionValidationWithoutThrowingException() - throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException { + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException { doReturn(true) .when(messageVerifierServiceMock) @@ -117,7 +119,8 @@ void failedAssertionValidationWithoutThrowingException() @Test void successLollipopRequestValidation() - throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException { + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException { doReturn(true) .when(messageVerifierServiceMock) diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java index 3bfa8994..61ef2e7b 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java @@ -1,8 +1,8 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service.impl; -import static org.mockito.Mockito.when; import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.when; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; @@ -24,7 +24,6 @@ class HttpMessageVerifierServiceImplTest { final String INVALID_ENCODING = "UTF-326"; final String VALID_ENCODING = "UTF-8"; - private LollipopConsumerRequestConfig httpMessageVerifierConfig; private HttpMessageVerifier httpMessageVerifier; @@ -46,10 +45,14 @@ public HttpMessageVerifierServiceImplTest() { public void beforeEach() throws LollipopDigestException, UnsupportedEncodingException { Mockito.reset(httpMessageVerifier); when(httpMessageVerifier.verifyDigest( - Mockito.eq(VALID_DIGEST), Mockito.eq(VALID_PAYLOAD), Mockito.eq(VALID_ENCODING))) + Mockito.eq(VALID_DIGEST), + Mockito.eq(VALID_PAYLOAD), + Mockito.eq(VALID_ENCODING))) .thenReturn(true); when(httpMessageVerifier.verifyDigest( - Mockito.eq(VALID_DIGEST), Mockito.eq(INVALID_PAYLOAD), Mockito.eq(VALID_ENCODING))) + Mockito.eq(VALID_DIGEST), + Mockito.eq(INVALID_PAYLOAD), + Mockito.eq(VALID_ENCODING))) .thenReturn(false); this.httpMessageVerifierService = new HttpMessageVerifierServiceImpl(httpMessageVerifier, httpMessageVerifierConfig); @@ -58,7 +61,10 @@ public void beforeEach() throws LollipopDigestException, UnsupportedEncodingExce @Test public void validRequestIsProcessed() { assertThatNoException() - .isThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(getLollipopConsumerRequest())); + .isThrownBy( + () -> + httpMessageVerifierService.verifyHttpMessage( + getLollipopConsumerRequest())); } @Test @@ -66,17 +72,22 @@ public void invalidRequestIsProcessedWithStrictDigestValidation() { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); this.httpMessageVerifierConfig.setStrictDigestVerify(true); lollipopConsumerRequest.setRequestBody(INVALID_PAYLOAD); - lollipopConsumerRequest.getHeaderParams().put( - "Signature-Input", - "sig1=(\"x-pagopa-lollipop-original-method\" " - + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" - + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); + lollipopConsumerRequest + .getHeaderParams() + .put( + "Signature-Input", + "sig1=(\"x-pagopa-lollipop-original-method\" " + + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" + + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); // execute & verify - assertThatThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) + assertThatThrownBy( + () -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) .isInstanceOfSatisfying( LollipopDigestException.class, e -> { - assertThat(e).hasMessageContaining("Content-Digest does not match the request payload"); + assertThat(e) + .hasMessageContaining( + "Content-Digest does not match the request payload"); assertThat(e.getErrorCode()) .isEqualTo(LollipopDigestException.ErrorCode.INCORRECT_DIGEST); }); @@ -87,11 +98,14 @@ public void requestWithInvalidDigestThrowsException() { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); lollipopConsumerRequest.setRequestBody(INVALID_PAYLOAD); // execute & verify - assertThatThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) + assertThatThrownBy( + () -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) .isInstanceOfSatisfying( LollipopDigestException.class, e -> { - assertThat(e).hasMessageContaining("Content-Digest does not match the request payload"); + assertThat(e) + .hasMessageContaining( + "Content-Digest does not match the request payload"); assertThat(e.getErrorCode()) .isEqualTo(LollipopDigestException.ErrorCode.INCORRECT_DIGEST); }); @@ -102,11 +116,14 @@ public void requestWithoutContentDigestToValidateThrowsException() { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); lollipopConsumerRequest.getHeaderParams().remove("Content-Digest"); // execute & verify - assertThatThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) + assertThatThrownBy( + () -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) .isInstanceOfSatisfying( LollipopDigestException.class, e -> { - assertThat(e).hasMessageContaining("Missing required Content-Digest for validation"); + assertThat(e) + .hasMessageContaining( + "Missing required Content-Digest for validation"); assertThat(e.getErrorCode()) .isEqualTo(LollipopDigestException.ErrorCode.MISSING_DIGEST); }); @@ -117,11 +134,14 @@ public void requestWithoutRequestBodyToValidateThrowsException() { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); lollipopConsumerRequest.setRequestBody(null); // execute & verify - assertThatThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) + assertThatThrownBy( + () -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) .isInstanceOfSatisfying( LollipopDigestException.class, e -> { - assertThat(e).hasMessageContaining("Missing required payload for digest validation"); + assertThat(e) + .hasMessageContaining( + "Missing required payload for digest validation"); assertThat(e.getErrorCode()) .isEqualTo(LollipopDigestException.ErrorCode.MISSING_PAYLOAD); }); @@ -132,13 +152,15 @@ public void requestWithoutSignatureToValidateThrowsException() { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); lollipopConsumerRequest.getHeaderParams().remove("Signature"); // execute & verify - assertThatThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) + assertThatThrownBy( + () -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) .isInstanceOfSatisfying( LollipopVerifierException.class, e -> { assertThat(e).hasMessageContaining("Missing Signature Header"); assertThat(e.getErrorCode()) - .isEqualTo(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE); + .isEqualTo( + LollipopVerifierException.ErrorCode.MISSING_SIGNATURE); }); } @@ -147,13 +169,16 @@ public void requestWithoutSignatureInputToValidateThrowsException() { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); lollipopConsumerRequest.getHeaderParams().remove("Signature-Input"); // execute & verify - assertThatThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) + assertThatThrownBy( + () -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) .isInstanceOfSatisfying( LollipopVerifierException.class, e -> { assertThat(e).hasMessageContaining("Missing Signature-Input Header"); assertThat(e.getErrorCode()) - .isEqualTo(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE_INPUT); + .isEqualTo( + LollipopVerifierException.ErrorCode + .MISSING_SIGNATURE_INPUT); }); } @@ -168,12 +193,12 @@ private LollipopConsumerRequest getLollipopConsumerRequest() { + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); lollipopHeaderParams.put( - "Signature", "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"); + "Signature", + "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"); return LollipopConsumerRequest.builder() .requestBody(VALID_PAYLOAD) .headerParams(lollipopHeaderParams) .build(); } - } From 51012ae413cf87efc0c6b79dcb172da67439bb5e Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 5 Apr 2023 11:49:47 +0200 Subject: [PATCH 034/403] [core_sprint_1_fix] Updated docs. Applied spotless formatting --- .../config/LollipopConsumerRequestConfig.java | 10 ++++---- .../service/HttpMessageVerifierService.java | 8 +++--- .../impl/HttpMessageVerifierServiceImpl.java | 25 +++++++------------ 3 files changed, 18 insertions(+), 25 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index f517a70c..90e88b57 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -8,9 +8,9 @@ @Data public class LollipopConsumerRequestConfig { - private String signatureHeader = "signature"; - private String signatureInputHeader = "signature-input"; - private String contentEncodingHeader = "content-encoding"; - private String contentDigestHeader = "content-digest"; - private boolean strictDigestVerify = false; + @Builder.Default private String signatureHeader = "signature"; + @Builder.Default private String signatureInputHeader = "signature-input"; + @Builder.Default private String contentEncodingHeader = "content-encoding"; + @Builder.Default private String contentDigestHeader = "content-digest"; + @Builder.Default private boolean strictDigestVerify = false; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java index b8885342..39fb6b76 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java @@ -15,11 +15,11 @@ public interface HttpMessageVerifierService { /** * Validates the http request * - * @param request + * @param request instance of lollipop request to validate * @return flag to true if the request is validated - * @throws UnsupportedEncodingException - * @throws LollipopDigestException - * @throws LollipopVerifierException + * @throws UnsupportedEncodingException thrown if the provided encoding is invalid + * @throws LollipopDigestException thrown for digest validation exceptions + * @throws LollipopVerifierException thrown for general errors in the verification process */ boolean verifyHttpMessage(LollipopConsumerRequest request) throws UnsupportedEncodingException, LollipopDigestException, LollipopVerifierException; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java index df3dce17..d3b2eba2 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java @@ -27,15 +27,7 @@ public HttpMessageVerifierServiceImpl( this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; } - /** - * {@see HttpMessageVerifierService.verifyHttpMessage()} - * - * @param lollipopConsumerRequest - * @return - * @throws LollipopDigestException - * @throws UnsupportedEncodingException - * @throws LollipopVerifierException - */ + /** @see HttpMessageVerifierService#verifyHttpMessage(LollipopConsumerRequest) */ @Override public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest) throws LollipopDigestException, UnsupportedEncodingException, @@ -85,7 +77,7 @@ public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest * Checks if any of the signatures have the content-digest param within the signature input, to * determine if in non-strict mode the digest should be validated * - * @param signatureInput + * @param signatureInput request Signature-Input content * @return flag to determine if the content-digest is present */ private boolean hasDigestInSignatureInput(String signatureInput) { @@ -106,12 +98,13 @@ private boolean hasDigestInSignatureInput(String signatureInput) { * validation through the usage of the provided implementation of the {@link * HttpMessageVerifier} * - * @param contentDigest - * @param requestBody - * @param contentEncoding - * @return - * @throws LollipopDigestException - * @throws UnsupportedEncodingException + * @param contentDigest content digest provided by the request to check + * @param requestBody payload to be used for digest verification + * @param contentEncoding encoding for the related payload, if necessary + * @return flag to determine if the content digest matches the calculated one with the provided + * request Body + * @throws LollipopDigestException exceptions related to the digest validation process + * @throws UnsupportedEncodingException exceptions related to encoding errors */ private boolean verifyContentDigest( String contentDigest, String requestBody, String contentEncoding) From fbe2e9cf23ff7df7664d1e9026a27d46aa96d9fc Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 5 Apr 2023 11:17:41 +0200 Subject: [PATCH 035/403] [core_sprint_1_fix] Removed lombok rc version --- identity-service-rest-client-native/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/identity-service-rest-client-native/build.gradle b/identity-service-rest-client-native/build.gradle index bb81b05c..389a4653 100644 --- a/identity-service-rest-client-native/build.gradle +++ b/identity-service-rest-client-native/build.gradle @@ -6,7 +6,6 @@ * User Manual available at https://docs.gradle.org/8.0.2/userguide/building_java_projects.html */ - plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' From e605a83de21aeb4ff580742c629b45bb284b0914 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 5 Apr 2023 11:18:36 +0200 Subject: [PATCH 036/403] [core_sprint_1_fix] Applied spotless formatting --- .../command/LollipopConsumerCommand.java | 4 +- .../LollipopConsumerCommandBuilderImpl.java | 5 +- .../exception/LollipopVerifierException.java | 4 +- .../helper/LollipopConsumerFactoryHelper.java | 1 - .../http_verifier/HttpMessageVerifier.java | 16 ++-- .../HttpMessageVerifierFactory.java | 6 +- .../service/AssertionVerifierService.java | 7 +- .../service/HttpMessageVerifierService.java | 5 +- .../impl/HttpMessageVerifierServiceImpl.java | 53 ++++++++------ .../impl/LollipopConsumerCommandImplTest.java | 13 ++-- .../HttpMessageVerifierServiceImplTest.java | 73 +++++++++++++------ 11 files changed, 115 insertions(+), 72 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java index 3631fd1d..9bb161a6 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java @@ -4,9 +4,7 @@ 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 - * */ +/** Interface for the command executing the lollipop request consumption */ public interface LollipopConsumerCommand { /** diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java index 4bc0e67a..3f4e22e7 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java @@ -6,7 +6,10 @@ import it.pagopa.tech.lollipop.consumer.helper.LollipopConsumerFactoryHelper; import javax.inject.Inject; -/** Implementation of {@link LollipopConsumerCommandBuilder}, used to create istances of {@link LollipopConsumerCommandImpl} */ +/** + * Implementation of {@link LollipopConsumerCommandBuilder}, used to create istances of {@link + * LollipopConsumerCommandImpl} + */ public class LollipopConsumerCommandBuilderImpl implements LollipopConsumerCommandBuilder { private final LollipopConsumerFactoryHelper factoryHelper; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java index 13b5ae0c..04e98686 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java @@ -4,7 +4,8 @@ import java.util.Objects; /** - * Thrown in case of problems when computing or verifying lollipop request through the http-signature flow + * Thrown in case of problems when computing or verifying lollipop request through the + * http-signature flow */ public class LollipopVerifierException extends Exception { @@ -45,7 +46,6 @@ public ErrorCode getErrorCode() { /** Error codes to classify Lollipop Request Exceptions */ public enum ErrorCode { - MISSING_SIGNATURE, MISSING_SIGNATURE_INPUT diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index 325e07e9..d9be8966 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -9,7 +9,6 @@ import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; import it.pagopa.tech.lollipop.consumer.service.impl.AssertionVerifierServiceImpl; import it.pagopa.tech.lollipop.consumer.service.impl.HttpMessageVerifierServiceImpl; - import javax.inject.Inject; /** Helper class for retrieving instances */ diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java index 10cc2d69..f3abfc58 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java @@ -6,16 +6,19 @@ import java.util.Map; /** - * Interface of the Http Verifier. This interface provides services through an implementation of the http-signature draft + * Interface of the Http Verifier. This interface provides services through an implementation of the + * http-signature draft */ public interface HttpMessageVerifier { /** - * Checks whether the calculated digest of the payload matches the content-digest of the http request + * Checks whether the calculated digest of the payload matches the content-digest of the http + * request + * * @param digest Content-Digest for the request payload * @param requestBody Request payload - * @param encoding Encoding to be used for the payload. To be used if the underlying implementation checks uses the - * content byte array + * @param encoding Encoding to be used for the payload. To be used if the underlying + * implementation checks uses the content byte array * @return boolean set to true if the digest check is valid * @throws LollipopDigestException * @throws UnsupportedEncodingException @@ -24,8 +27,9 @@ boolean verifyDigest(String digest, String requestBody, String encoding) throws LollipopDigestException, UnsupportedEncodingException; /** - * Checks whether the calculated signatures of the required parameter matches with those provided within - * the Signature param + * Checks whether the calculated signatures of the required parameter matches with those + * provided within the Signature param + * * @param signature * @param signatureInput * @param parameters diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java index 5d51334c..ec1de3f7 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java @@ -4,10 +4,6 @@ /** Interface for the factory used to create instances of {@link HttpMessageVerifier} */ public interface HttpMessageVerifierFactory { - /** - * - * @return instance of HttpMessageVerifier - */ + /** @return instance of HttpMessageVerifier */ HttpMessageVerifier create(); - } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java index ddfaa72d..758422bf 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java @@ -4,12 +4,15 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; /** - * Interface of the service to be used for validating SAML Assertions obtained using the content passed in the {@link LollipopConsumerRequest} + * Interface of the service to be used for validating SAML Assertions obtained using the content + * passed in the {@link LollipopConsumerRequest} */ public interface AssertionVerifierService { /** - * Validates Lollipop request Assertion, using the assertion-ref within the request header params + * Validates Lollipop request Assertion, using the assertion-ref within the request header + * params + * * @param request * @return */ diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java index c214a16a..b8885342 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java @@ -7,13 +7,14 @@ import java.io.UnsupportedEncodingException; /** - * Interface of the service to be used for validating the http {@link LollipopConsumerRequest} through the digest and signature - * validation of the http-signature draft + * Interface of the service to be used for validating the http {@link LollipopConsumerRequest} + * through the digest and signature validation of the http-signature draft */ public interface HttpMessageVerifierService { /** * Validates the http request + * * @param request * @return flag to true if the request is validated * @throws UnsupportedEncodingException diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java index 84836ec4..df3dce17 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java @@ -13,10 +13,7 @@ import java.util.Map; import javax.inject.Inject; - -/** - * Standard implementation of {@link HttpMessageVerifierService} - */ +/** Standard implementation of {@link HttpMessageVerifierService} */ public class HttpMessageVerifierServiceImpl implements HttpMessageVerifierService { private HttpMessageVerifier httpMessageVerifier; @@ -32,6 +29,7 @@ public HttpMessageVerifierServiceImpl( /** * {@see HttpMessageVerifierService.verifyHttpMessage()} + * * @param lollipopConsumerRequest * @return * @throws LollipopDigestException @@ -40,15 +38,16 @@ public HttpMessageVerifierServiceImpl( */ @Override public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest) - throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException { + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException { Map headerParams = lollipopConsumerRequest.getHeaderParams(); - String signature = - headerParams.get(lollipopConsumerRequestConfig.getSignatureHeader()); + String signature = headerParams.get(lollipopConsumerRequestConfig.getSignatureHeader()); if (signature == null) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE, + throw new LollipopVerifierException( + LollipopVerifierException.ErrorCode.MISSING_SIGNATURE, "Missing Signature Header"); } @@ -56,12 +55,13 @@ public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest headerParams.get(lollipopConsumerRequestConfig.getSignatureInputHeader()); if (signatureInput == null) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE_INPUT, + throw new LollipopVerifierException( + LollipopVerifierException.ErrorCode.MISSING_SIGNATURE_INPUT, "Missing Signature-Input Header"); } - - if (lollipopConsumerRequestConfig.isStrictDigestVerify() || hasDigestInSignatureInput(signatureInput)) { + if (lollipopConsumerRequestConfig.isStrictDigestVerify() + || hasDigestInSignatureInput(signatureInput)) { String contentDigest = headerParams.get(lollipopConsumerRequestConfig.getContentDigestHeader()); @@ -72,30 +72,40 @@ public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest headerParams.get(lollipopConsumerRequestConfig.getContentEncodingHeader()); if (!verifyContentDigest(contentDigest, requestBody, contentEncoding)) { - throw new LollipopDigestException(LollipopDigestException.ErrorCode.INCORRECT_DIGEST, + throw new LollipopDigestException( + LollipopDigestException.ErrorCode.INCORRECT_DIGEST, "Content-Digest does not match the request payload"); } } return verifyHttpSignature(lollipopConsumerRequest); - } /** - * Checks if any of the signatures have the content-digest param within the signature input, to determine - * if in non-strict mode the digest should be validated + * Checks if any of the signatures have the content-digest param within the signature input, to + * determine if in non-strict mode the digest should be validated + * * @param signatureInput * @return flag to determine if the content-digest is present */ private boolean hasDigestInSignatureInput(String signatureInput) { - return Arrays.stream(signatureInput.split(";")).anyMatch( - signaturePart -> signaturePart.contains("=") && signaturePart.toLowerCase(Locale.ROOT).contains( - lollipopConsumerRequestConfig.getContentDigestHeader().toLowerCase(Locale.ROOT))); + return Arrays.stream(signatureInput.split(";")) + .anyMatch( + signaturePart -> + signaturePart.contains("=") + && signaturePart + .toLowerCase(Locale.ROOT) + .contains( + lollipopConsumerRequestConfig + .getContentDigestHeader() + .toLowerCase(Locale.ROOT))); } /** - * Checks for required params to be used within the digest validation process, and executes the validation - * through the usage of the provided implementation of the {@link HttpMessageVerifier} + * Checks for required params to be used within the digest validation process, and executes the + * validation through the usage of the provided implementation of the {@link + * HttpMessageVerifier} + * * @param contentDigest * @param requestBody * @param contentEncoding @@ -114,7 +124,8 @@ private boolean verifyContentDigest( } if (requestBody == null) { - throw new LollipopDigestException(LollipopDigestException.ErrorCode.MISSING_PAYLOAD, + throw new LollipopDigestException( + LollipopDigestException.ErrorCode.MISSING_PAYLOAD, "Missing required payload for digest validation"); } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java index 8a878102..7f943d56 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -14,7 +14,6 @@ import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; import java.io.UnsupportedEncodingException; - import lombok.SneakyThrows; import org.junit.jupiter.api.*; import org.mockito.*; @@ -37,7 +36,8 @@ void beforeAll() { @Test void failedHttpMessageValidationThrowDigestException() - throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException { + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException { doThrow( new LollipopDigestException( @@ -77,7 +77,8 @@ void failedHttpMessageValidationThrowUnsupportedEncodingException() { @Test void failedHttpMessageValidationWithoutThrowingException() - throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException { + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException { doReturn(false) .when(messageVerifierServiceMock) @@ -96,7 +97,8 @@ void failedHttpMessageValidationWithoutThrowingException() @Test void failedAssertionValidationWithoutThrowingException() - throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException { + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException { doReturn(true) .when(messageVerifierServiceMock) @@ -117,7 +119,8 @@ void failedAssertionValidationWithoutThrowingException() @Test void successLollipopRequestValidation() - throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException { + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException { doReturn(true) .when(messageVerifierServiceMock) diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java index 3bfa8994..61ef2e7b 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java @@ -1,8 +1,8 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service.impl; -import static org.mockito.Mockito.when; import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.when; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; @@ -24,7 +24,6 @@ class HttpMessageVerifierServiceImplTest { final String INVALID_ENCODING = "UTF-326"; final String VALID_ENCODING = "UTF-8"; - private LollipopConsumerRequestConfig httpMessageVerifierConfig; private HttpMessageVerifier httpMessageVerifier; @@ -46,10 +45,14 @@ public HttpMessageVerifierServiceImplTest() { public void beforeEach() throws LollipopDigestException, UnsupportedEncodingException { Mockito.reset(httpMessageVerifier); when(httpMessageVerifier.verifyDigest( - Mockito.eq(VALID_DIGEST), Mockito.eq(VALID_PAYLOAD), Mockito.eq(VALID_ENCODING))) + Mockito.eq(VALID_DIGEST), + Mockito.eq(VALID_PAYLOAD), + Mockito.eq(VALID_ENCODING))) .thenReturn(true); when(httpMessageVerifier.verifyDigest( - Mockito.eq(VALID_DIGEST), Mockito.eq(INVALID_PAYLOAD), Mockito.eq(VALID_ENCODING))) + Mockito.eq(VALID_DIGEST), + Mockito.eq(INVALID_PAYLOAD), + Mockito.eq(VALID_ENCODING))) .thenReturn(false); this.httpMessageVerifierService = new HttpMessageVerifierServiceImpl(httpMessageVerifier, httpMessageVerifierConfig); @@ -58,7 +61,10 @@ public void beforeEach() throws LollipopDigestException, UnsupportedEncodingExce @Test public void validRequestIsProcessed() { assertThatNoException() - .isThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(getLollipopConsumerRequest())); + .isThrownBy( + () -> + httpMessageVerifierService.verifyHttpMessage( + getLollipopConsumerRequest())); } @Test @@ -66,17 +72,22 @@ public void invalidRequestIsProcessedWithStrictDigestValidation() { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); this.httpMessageVerifierConfig.setStrictDigestVerify(true); lollipopConsumerRequest.setRequestBody(INVALID_PAYLOAD); - lollipopConsumerRequest.getHeaderParams().put( - "Signature-Input", - "sig1=(\"x-pagopa-lollipop-original-method\" " - + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" - + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); + lollipopConsumerRequest + .getHeaderParams() + .put( + "Signature-Input", + "sig1=(\"x-pagopa-lollipop-original-method\" " + + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" + + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); // execute & verify - assertThatThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) + assertThatThrownBy( + () -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) .isInstanceOfSatisfying( LollipopDigestException.class, e -> { - assertThat(e).hasMessageContaining("Content-Digest does not match the request payload"); + assertThat(e) + .hasMessageContaining( + "Content-Digest does not match the request payload"); assertThat(e.getErrorCode()) .isEqualTo(LollipopDigestException.ErrorCode.INCORRECT_DIGEST); }); @@ -87,11 +98,14 @@ public void requestWithInvalidDigestThrowsException() { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); lollipopConsumerRequest.setRequestBody(INVALID_PAYLOAD); // execute & verify - assertThatThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) + assertThatThrownBy( + () -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) .isInstanceOfSatisfying( LollipopDigestException.class, e -> { - assertThat(e).hasMessageContaining("Content-Digest does not match the request payload"); + assertThat(e) + .hasMessageContaining( + "Content-Digest does not match the request payload"); assertThat(e.getErrorCode()) .isEqualTo(LollipopDigestException.ErrorCode.INCORRECT_DIGEST); }); @@ -102,11 +116,14 @@ public void requestWithoutContentDigestToValidateThrowsException() { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); lollipopConsumerRequest.getHeaderParams().remove("Content-Digest"); // execute & verify - assertThatThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) + assertThatThrownBy( + () -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) .isInstanceOfSatisfying( LollipopDigestException.class, e -> { - assertThat(e).hasMessageContaining("Missing required Content-Digest for validation"); + assertThat(e) + .hasMessageContaining( + "Missing required Content-Digest for validation"); assertThat(e.getErrorCode()) .isEqualTo(LollipopDigestException.ErrorCode.MISSING_DIGEST); }); @@ -117,11 +134,14 @@ public void requestWithoutRequestBodyToValidateThrowsException() { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); lollipopConsumerRequest.setRequestBody(null); // execute & verify - assertThatThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) + assertThatThrownBy( + () -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) .isInstanceOfSatisfying( LollipopDigestException.class, e -> { - assertThat(e).hasMessageContaining("Missing required payload for digest validation"); + assertThat(e) + .hasMessageContaining( + "Missing required payload for digest validation"); assertThat(e.getErrorCode()) .isEqualTo(LollipopDigestException.ErrorCode.MISSING_PAYLOAD); }); @@ -132,13 +152,15 @@ public void requestWithoutSignatureToValidateThrowsException() { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); lollipopConsumerRequest.getHeaderParams().remove("Signature"); // execute & verify - assertThatThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) + assertThatThrownBy( + () -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) .isInstanceOfSatisfying( LollipopVerifierException.class, e -> { assertThat(e).hasMessageContaining("Missing Signature Header"); assertThat(e.getErrorCode()) - .isEqualTo(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE); + .isEqualTo( + LollipopVerifierException.ErrorCode.MISSING_SIGNATURE); }); } @@ -147,13 +169,16 @@ public void requestWithoutSignatureInputToValidateThrowsException() { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); lollipopConsumerRequest.getHeaderParams().remove("Signature-Input"); // execute & verify - assertThatThrownBy(() -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) + assertThatThrownBy( + () -> httpMessageVerifierService.verifyHttpMessage(lollipopConsumerRequest)) .isInstanceOfSatisfying( LollipopVerifierException.class, e -> { assertThat(e).hasMessageContaining("Missing Signature-Input Header"); assertThat(e.getErrorCode()) - .isEqualTo(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE_INPUT); + .isEqualTo( + LollipopVerifierException.ErrorCode + .MISSING_SIGNATURE_INPUT); }); } @@ -168,12 +193,12 @@ private LollipopConsumerRequest getLollipopConsumerRequest() { + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); lollipopHeaderParams.put( - "Signature", "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"); + "Signature", + "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"); return LollipopConsumerRequest.builder() .requestBody(VALID_PAYLOAD) .headerParams(lollipopHeaderParams) .build(); } - } From 875c286a9d32233c3d517d383f0e19a3fcc9f16b Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 5 Apr 2023 11:49:47 +0200 Subject: [PATCH 037/403] [core_sprint_1_fix] Updated docs. Applied spotless formatting --- .../config/LollipopConsumerRequestConfig.java | 10 ++++---- .../service/HttpMessageVerifierService.java | 8 +++--- .../impl/HttpMessageVerifierServiceImpl.java | 25 +++++++------------ 3 files changed, 18 insertions(+), 25 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index f517a70c..90e88b57 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -8,9 +8,9 @@ @Data public class LollipopConsumerRequestConfig { - private String signatureHeader = "signature"; - private String signatureInputHeader = "signature-input"; - private String contentEncodingHeader = "content-encoding"; - private String contentDigestHeader = "content-digest"; - private boolean strictDigestVerify = false; + @Builder.Default private String signatureHeader = "signature"; + @Builder.Default private String signatureInputHeader = "signature-input"; + @Builder.Default private String contentEncodingHeader = "content-encoding"; + @Builder.Default private String contentDigestHeader = "content-digest"; + @Builder.Default private boolean strictDigestVerify = false; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java index b8885342..39fb6b76 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java @@ -15,11 +15,11 @@ public interface HttpMessageVerifierService { /** * Validates the http request * - * @param request + * @param request instance of lollipop request to validate * @return flag to true if the request is validated - * @throws UnsupportedEncodingException - * @throws LollipopDigestException - * @throws LollipopVerifierException + * @throws UnsupportedEncodingException thrown if the provided encoding is invalid + * @throws LollipopDigestException thrown for digest validation exceptions + * @throws LollipopVerifierException thrown for general errors in the verification process */ boolean verifyHttpMessage(LollipopConsumerRequest request) throws UnsupportedEncodingException, LollipopDigestException, LollipopVerifierException; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java index df3dce17..d3b2eba2 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java @@ -27,15 +27,7 @@ public HttpMessageVerifierServiceImpl( this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; } - /** - * {@see HttpMessageVerifierService.verifyHttpMessage()} - * - * @param lollipopConsumerRequest - * @return - * @throws LollipopDigestException - * @throws UnsupportedEncodingException - * @throws LollipopVerifierException - */ + /** @see HttpMessageVerifierService#verifyHttpMessage(LollipopConsumerRequest) */ @Override public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest) throws LollipopDigestException, UnsupportedEncodingException, @@ -85,7 +77,7 @@ public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest * Checks if any of the signatures have the content-digest param within the signature input, to * determine if in non-strict mode the digest should be validated * - * @param signatureInput + * @param signatureInput request Signature-Input content * @return flag to determine if the content-digest is present */ private boolean hasDigestInSignatureInput(String signatureInput) { @@ -106,12 +98,13 @@ private boolean hasDigestInSignatureInput(String signatureInput) { * validation through the usage of the provided implementation of the {@link * HttpMessageVerifier} * - * @param contentDigest - * @param requestBody - * @param contentEncoding - * @return - * @throws LollipopDigestException - * @throws UnsupportedEncodingException + * @param contentDigest content digest provided by the request to check + * @param requestBody payload to be used for digest verification + * @param contentEncoding encoding for the related payload, if necessary + * @return flag to determine if the content digest matches the calculated one with the provided + * request Body + * @throws LollipopDigestException exceptions related to the digest validation process + * @throws UnsupportedEncodingException exceptions related to encoding errors */ private boolean verifyContentDigest( String contentDigest, String requestBody, String contentEncoding) From 6613b4e93cf1564bff7357c6962bd39c33b66002 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 5 Apr 2023 12:35:42 +0200 Subject: [PATCH 038/403] [core_sprint_1_fix] Updated verification-metadata.xml after merge. Updated build.gradle --- assertion-rest-client-native/build.gradle | 44 +- build.gradle | 102 ++- core/build.gradle | 28 +- gradle/verification-metadata.xml | 640 ++++++++++++++++++ http-verifier/build.gradle | 38 +- .../build.gradle | 44 +- redis-storage/build.gradle | 44 +- 7 files changed, 789 insertions(+), 151 deletions(-) diff --git a/assertion-rest-client-native/build.gradle b/assertion-rest-client-native/build.gradle index ca1d2bb9..02bf4890 100644 --- a/assertion-rest-client-native/build.gradle +++ b/assertion-rest-client-native/build.gradle @@ -8,9 +8,9 @@ plugins { - // Apply the java-library plugin for API and implementation separation. - id 'java-library' - id("io.freefair.lombok") version "8.0.0" + // Apply the java-library plugin for API and implementation separation. + id 'java-library' + id("io.freefair.lombok") version "8.0.0" } group 'it.pagopa.commons' @@ -21,32 +21,32 @@ repositories { } configurations { - implementation { - attributes { - attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, 'instrumented-core-jar')) - } - } + implementation { + attributes { + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, 'instrumented-core-jar')) + } + } } abstract class InstrumentedJarsRule implements AttributeCompatibilityRule { - @Override - void execute(CompatibilityCheckDetails details) { - if (details.consumerValue.name == 'instrumented-core-jar' && details.producerValue.name == 'jar') { - details.compatible() - } - } + @Override + void execute(CompatibilityCheckDetails details) { + if (details.consumerValue.name == 'instrumented-core-jar' && details.producerValue.name == 'jar') { + details.compatible() + } + } } dependencies { - attributesSchema { - attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE) { - compatibilityRules.add(InstrumentedJarsRule) - } - } - implementation project(path: ':core') - // Use JUnit Jupiter for testing. - testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + attributesSchema { + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE) { + compatibilityRules.add(InstrumentedJarsRule) + } + } + implementation project(path: ':core') + // Use JUnit Jupiter for testing. + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' } tasks.named('test') { diff --git a/build.gradle b/build.gradle index 883336fb..626781fa 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ plugins { id 'org.graalvm.buildtools.native' version '0.9.20' id("com.diffplug.spotless") version "6.17.0" id("nebula.lint") version "18.0.3" - id("org.kordamp.gradle.reproducible") version "0.50.0" + id("org.kordamp.gradle.reproducible") version "0.50.0" } repositories { @@ -12,10 +12,10 @@ repositories { } allprojects { - version = "1.0.0-SNAPSHOT" - group = 'it.pagopa.tech' - sourceCompatibility = '11' - targetCompatibility = '11' + version = "1.0.0-SNAPSHOT" + group = 'it.pagopa.tech' + sourceCompatibility = '11' + targetCompatibility = '11' apply plugin: 'com.diffplug.spotless' apply plugin: 'nebula.lint' gradleLint.rules = ['all-dependency'] @@ -58,54 +58,53 @@ tasks.withType(AbstractArchiveTask).configureEach { subprojects { - apply plugin: 'java' - apply plugin: 'org.kordamp.gradle.reproducible' - apply plugin: 'maven-publish' - apply plugin: 'org.graalvm.buildtools.native' - - - java { - withSourcesJar() - withJavadocJar() - } - - tasks.withType(JavaCompile) { - options.compilerArgs.add('-Xlint:all') - } - - config { - reproducible { - enabled - additionalProperties - additionalArtifacts - } - } - - // Settings for allowing reproducible build - tasks.withType(AbstractArchiveTask).configureEach { - preserveFileTimestamps = false - reproducibleFileOrder = true - } - - - // Generate MD5 checksum on eng-lollipop-consumer-java-sdk jar file - jar.doLast { task -> - ant.checksum file: task.archivePath - } - - publishing { - publications { - maven(MavenPublication) { - groupId project.group - artifactId project.name - version project.version - from components.java - } - } - } + apply plugin: 'java' + apply plugin: 'org.kordamp.gradle.reproducible' + apply plugin: 'maven-publish' + apply plugin: 'org.graalvm.buildtools.native' + + + java { + withSourcesJar() + withJavadocJar() + } + + tasks.withType(JavaCompile) { + options.compilerArgs.add('-Xlint:all') + } + + config { + reproducible { + enabled + additionalProperties + additionalArtifacts + } + } + + // Settings for allowing reproducible build + tasks.withType(AbstractArchiveTask).configureEach { + preserveFileTimestamps = false + reproducibleFileOrder = true + } -} + // Generate MD5 checksum on eng-lollipop-consumer-java-sdk jar file + jar.doLast { task -> + ant.checksum file: task.archivePath + } + + publishing { + publications { + maven(MavenPublication) { + groupId project.group + artifactId project.name + version project.version + from components.java + } + } + } + +} graalvmNative { binaries { @@ -114,4 +113,3 @@ graalvmNative { } } } - diff --git a/core/build.gradle b/core/build.gradle index a6bd0dfa..a5d2b770 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -8,9 +8,9 @@ plugins { - // Apply the java-library plugin for API and implementation separation. - id 'java-library' - id("io.freefair.lombok") version "8.0.0" + // Apply the java-library plugin for API and implementation separation. + id 'java-library' + id("io.freefair.lombok") version "8.0.0" } group 'it.pagopa.tech' @@ -21,17 +21,17 @@ repositories { } configurations { - instrumentedJars { - canBeConsumed = true - canBeResolved = false - attributes { - attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.LIBRARY)) - attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME)) - attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, Bundling.EXTERNAL)) - attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, JavaVersion.current().majorVersion.toInteger()) - attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, 'instrumented-core-jar')) - } - } + instrumentedJars { + canBeConsumed = true + canBeResolved = false + attributes { + attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.LIBRARY)) + attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME)) + attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, Bundling.EXTERNAL)) + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, JavaVersion.current().majorVersion.toInteger()) + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, 'instrumented-core-jar')) + } + } } dependencies { diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index af28f58b..950e30c9 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -5,6 +5,243 @@ false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -13,6 +250,14 @@ + + + + + + + + @@ -34,6 +279,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -67,11 +359,21 @@ + + + + + + + + + + @@ -80,6 +382,11 @@ + + + + + @@ -88,6 +395,11 @@ + + + + + @@ -96,6 +408,11 @@ + + + + + @@ -104,6 +421,11 @@ + + + + + @@ -117,6 +439,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -130,6 +494,11 @@ + + + + + @@ -138,6 +507,27 @@ + + + + + + + + + + + + + + + + + + + + + @@ -151,11 +541,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -164,6 +652,14 @@ + + + + + + + + @@ -172,6 +668,14 @@ + + + + + + + + @@ -180,6 +684,14 @@ + + + + + + + + @@ -188,6 +700,14 @@ + + + + + + + + @@ -196,6 +716,22 @@ + + + + + + + + + + + + + + + + @@ -204,6 +740,22 @@ + + + + + + + + + + + + + + + + @@ -230,6 +782,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -246,10 +845,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index 52e003e9..6b3963c7 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -8,9 +8,9 @@ plugins { - // Apply the java-library plugin for API and implementation separation. - id 'java-library' - id("io.freefair.lombok") version "8.0.0" + // Apply the java-library plugin for API and implementation separation. + id 'java-library' + id("io.freefair.lombok") version "8.0.0" } group 'it.pagopa.tech' @@ -21,29 +21,29 @@ repositories { } configurations { - implementation { - attributes { - attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, 'instrumented-core-jar')) - } - } + implementation { + attributes { + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, 'instrumented-core-jar')) + } + } } abstract class InstrumentedJarsRule implements AttributeCompatibilityRule { - @Override - void execute(CompatibilityCheckDetails details) { - if (details.consumerValue.name == 'instrumented-core-jar' && details.producerValue.name == 'jar') { - details.compatible() - } - } + @Override + void execute(CompatibilityCheckDetails details) { + if (details.consumerValue.name == 'instrumented-core-jar' && details.producerValue.name == 'jar') { + details.compatible() + } + } } dependencies { - attributesSchema { - attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE) { - compatibilityRules.add(InstrumentedJarsRule) - } - } +attributesSchema { + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE) { + compatibilityRules.add(InstrumentedJarsRule) + } +} implementation 'net.visma.autopay:http-signatures:1.1.0' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' diff --git a/identity-service-rest-client-native/build.gradle b/identity-service-rest-client-native/build.gradle index 389a4653..713ec2f3 100644 --- a/identity-service-rest-client-native/build.gradle +++ b/identity-service-rest-client-native/build.gradle @@ -7,9 +7,9 @@ */ plugins { - // Apply the java-library plugin for API and implementation separation. - id 'java-library' - id("io.freefair.lombok") version "8.0.0" + // Apply the java-library plugin for API and implementation separation. + id 'java-library' + id("io.freefair.lombok") version "8.0.0" } group 'it.pagopa.tech' @@ -20,32 +20,32 @@ repositories { } configurations { - implementation { - attributes { - attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, 'instrumented-core-jar')) - } - } + implementation { + attributes { + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, 'instrumented-core-jar')) + } + } } abstract class InstrumentedJarsRule implements AttributeCompatibilityRule { - @Override - void execute(CompatibilityCheckDetails details) { - if (details.consumerValue.name == 'instrumented-core-jar' && details.producerValue.name == 'jar') { - details.compatible() - } - } + @Override + void execute(CompatibilityCheckDetails details) { + if (details.consumerValue.name == 'instrumented-core-jar' && details.producerValue.name == 'jar') { + details.compatible() + } + } } dependencies { - attributesSchema { - attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE) { - compatibilityRules.add(InstrumentedJarsRule) - } - } - implementation project(path: ':core') - // Use JUnit Jupiter for testing. - testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + attributesSchema { + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE) { + compatibilityRules.add(InstrumentedJarsRule) + } + } + implementation project(path: ':core') + // Use JUnit Jupiter for testing. + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' } tasks.named('test') { diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle index bb81b05c..86f23568 100644 --- a/redis-storage/build.gradle +++ b/redis-storage/build.gradle @@ -8,9 +8,9 @@ plugins { - // Apply the java-library plugin for API and implementation separation. - id 'java-library' - id("io.freefair.lombok") version "8.0.0" + // Apply the java-library plugin for API and implementation separation. + id 'java-library' + id("io.freefair.lombok") version "8.0.0" } group 'it.pagopa.tech' @@ -21,32 +21,32 @@ repositories { } configurations { - implementation { - attributes { - attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, 'instrumented-core-jar')) - } - } + implementation { + attributes { + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, 'instrumented-core-jar')) + } + } } abstract class InstrumentedJarsRule implements AttributeCompatibilityRule { - @Override - void execute(CompatibilityCheckDetails details) { - if (details.consumerValue.name == 'instrumented-core-jar' && details.producerValue.name == 'jar') { - details.compatible() - } - } + @Override + void execute(CompatibilityCheckDetails details) { + if (details.consumerValue.name == 'instrumented-core-jar' && details.producerValue.name == 'jar') { + details.compatible() + } + } } dependencies { - attributesSchema { - attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE) { - compatibilityRules.add(InstrumentedJarsRule) - } - } - implementation project(path: ':core') - // Use JUnit Jupiter for testing. - testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + attributesSchema { + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE) { + compatibilityRules.add(InstrumentedJarsRule) + } + } + implementation project(path: ':core') + // Use JUnit Jupiter for testing. + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' } tasks.named('test') { From 0021c0a80aa29f9a85bc491e4d2f45c8f1e34d3a Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 5 Apr 2023 13:05:43 +0200 Subject: [PATCH 039/403] [core_sprint_1_fix] Updated verification-metadata.xml to skip sources check (to be compatible with IDE building) and updated build.gradle for instrumented recovery --- gradle/verification-metadata.xml | 20 ++++++++++++++++++++ http-verifier/build.gradle | 9 +++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 950e30c9..6b3e07c3 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -3,6 +3,10 @@ true false + + + + @@ -266,11 +270,24 @@ + + + + + + + + + + + + + @@ -632,6 +649,9 @@ + + + diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index 6b3963c7..dbb59380 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -39,15 +39,16 @@ abstract class InstrumentedJarsRule implements AttributeCompatibilityRule Date: Wed, 5 Apr 2023 15:38:15 +0200 Subject: [PATCH 040/403] [SLS-9] Implemented MockServer for AssertionSimpleClient testing --- assertion-rest-client-native/build.gradle | 6 +- .../client/simple/AssertionSimpleClient.java | 2 - .../simple/AssertionSimpleClientTest.java | 86 ++++++++++++++++--- 3 files changed, 77 insertions(+), 17 deletions(-) diff --git a/assertion-rest-client-native/build.gradle b/assertion-rest-client-native/build.gradle index db482452..a2572f33 100644 --- a/assertion-rest-client-native/build.gradle +++ b/assertion-rest-client-native/build.gradle @@ -30,10 +30,14 @@ dependencies { implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.2' implementation 'com.google.code.findbugs:jsr305:3.0.2' - implementation 'javax.inject:javax.inject:1' //TODO + implementation 'org.mock-server:mockserver-client-java:5.15.0' + implementation 'javax.inject:javax.inject:1' + implementation 'junit:junit:4.13.1' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.assertj:assertj-core:3.24.2' + //Mockserver for testing api + testImplementation 'org.mock-server:mockserver-netty:5.15.0' } tasks.named('test') { diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java index 48711da1..62bc5990 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java @@ -64,8 +64,6 @@ public SamlAssertion getAssertion(String jwt, String assertionRef) throws Lollip return response; } - //TODO handle oidc assertion - return null; } } diff --git a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java index 70381fd1..b34cb029 100644 --- a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java +++ b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java @@ -3,40 +3,56 @@ import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.mockserver.client.MockServerClient; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.model.Header; + +import static org.mockserver.integration.ClientAndServer.startClientAndServer; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; -import static org.assertj.core.api.Assertions.assertThatNoException; class AssertionSimpleClientTest { - AssertionSimpleClient assertionSimpleClient = new AssertionSimpleClient(new ApiClient()); + private static AssertionSimpleClient assertionSimpleClient; + private static ClientAndServer mockServer; + private static final String RESPONSE_STRING = "{\"response_xml\": \" https://posteid.poste.it IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU= GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9 HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4 fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1 MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0 uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc= https://posteid.poste.it ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I= O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4 xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4 fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1 MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0 uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc= SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd https://app-backend.io.italia.it https://www.spid.gov.it/SpidL2 TINIT-AAAAAA89S20I111X \"}"; + private static final String ASSERTION_REF = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; + private static final String WRONG_ASSERTION_REF = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfXXXXX"; + private static final String JWT = "Bearer aValidJWT"; + + @BeforeAll + public static void startServer() { + ApiClient client = new ApiClient(); + client.updateBaseUri("http://localhost:2000"); + assertionSimpleClient = new AssertionSimpleClient(client); + mockServer = startClientAndServer(2000); + } + @Test void samlAssertionFound() throws LollipopAssertionNotFoundException { // setup - String assertionRef = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; - String jwt = "Bearer aValidJWT"; String xmlResponse = " https://posteid.poste.it IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU= GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9 HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4 fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1 MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0 uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc= https://posteid.poste.it ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I= O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4 xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4 fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1 MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0 uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc= SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd https://app-backend.io.italia.it https://www.spid.gov.it/SpidL2 TINIT-AAAAAA89S20I111X "; - SamlAssertion response = assertionSimpleClient.getAssertion(jwt, assertionRef); + createExpectationAssertionFound(); + SamlAssertion response = assertionSimpleClient.getAssertion(JWT, ASSERTION_REF); Assertions.assertNotNull(response); Assertions.assertNotNull(response.getAssertionRef()); Assertions.assertNotNull(response.getAssertionData()); - Assertions.assertEquals(assertionRef, response.getAssertionRef()); + Assertions.assertEquals(ASSERTION_REF, response.getAssertionRef()); Assertions.assertEquals(xmlResponse, response.getAssertionData()); } - //TODO test oidcAssertionFound - @Test void assertionNotFound() { + createExpectationAssertionNotFound(); // setup - String assertionRef = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfXXXXX"; - String jwt = "{kty: \"EC\", crv: \"P-256\", x: \"SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74\",y: \"lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI\"}"; - - Assertions.assertThrows(LollipopAssertionNotFoundException.class, () -> assertionSimpleClient.getAssertion(jwt, assertionRef)); + Assertions.assertThrows(LollipopAssertionNotFoundException.class, () -> assertionSimpleClient.getAssertion(JWT, WRONG_ASSERTION_REF)); } - //TODO wrong jwt test @Test void noJwt() { // setup @@ -45,6 +61,7 @@ void noJwt() { Assertions.assertThrows(IllegalArgumentException.class, () -> assertionSimpleClient.getAssertion(jwt, assertionRef)); } + @Test void noAssertionRef() { // setup @@ -54,6 +71,47 @@ void noAssertionRef() { Assertions.assertThrows(IllegalArgumentException.class, () -> assertionSimpleClient.getAssertion(jwt, assertionRef)); } + private void createExpectationAssertionFound() { + new MockServerClient("localhost", 2000) + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", JWT) + ) + ) + .respond( + response() + .withStatusCode(200) + .withBody(RESPONSE_STRING) + ); + } + + private void createExpectationAssertionNotFound() { + new MockServerClient("localhost", 2000) + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", WRONG_ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", JWT) + ) + ) + .respond( + response() + .withStatusCode(404) + .withBody("{}") + ); + } + + @AfterAll + public static void stopServer() { + mockServer.stop(); + } - } \ No newline at end of file From 4370651f4aad587c23bb217faae91e19653de803 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 5 Apr 2023 17:46:01 +0200 Subject: [PATCH 041/403] [core_sprint_1_fix] Updated verification-metadata.xml, Applied spotless formatting --- assertion-rest-client-native/build.gradle | 64 +- .../client/simple/AssertionSimpleClient.java | 40 +- .../simple/AssertionSimpleClientProvider.java | 6 +- .../client/simple/internal/ApiClient.java | 802 ++++---- .../client/simple/internal/ApiException.java | 34 +- .../client/simple/internal/ApiResponse.java | 20 +- .../client/simple/internal/Configuration.java | 26 +- .../client/simple/internal/JSON.java | 429 +++-- .../client/simple/internal/Pair.java | 20 +- .../simple/internal/RFC3339DateFormat.java | 79 +- .../simple/internal/ServerConfiguration.java | 23 +- .../simple/internal/ServerVariable.java | 8 +- .../simple/internal/api/DefaultApi.java | 261 ++- .../internal/model/AbstractOpenApiSchema.java | 54 +- .../simple/internal/model/AssertionRef.java | 224 ++- .../simple/internal/model/AssertionType.java | 99 +- .../simple/internal/model/LCUserInfo.java | 213 +- .../simple/internal/model/OidcUserInfo.java | 320 ++-- .../simple/internal/model/ProblemJson.java | 530 +++-- .../simple/internal/model/SamlUserInfo.java | 237 ++- .../simple/AssertionSimpleClientTest.java | 300 ++- .../assertion/client/AssertionClient.java | 3 +- .../LollipopAssertionNotFoundException.java | 14 +- gradle/verification-metadata.xml | 1705 +++++++++++++++++ 24 files changed, 3648 insertions(+), 1863 deletions(-) diff --git a/assertion-rest-client-native/build.gradle b/assertion-rest-client-native/build.gradle index 50e5326a..55886112 100644 --- a/assertion-rest-client-native/build.gradle +++ b/assertion-rest-client-native/build.gradle @@ -11,7 +11,7 @@ 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"*/ +/*id("org.openapi.generator") version "6.5.0"*/ } group 'it.pagopa.commons' @@ -40,44 +40,44 @@ abstract class InstrumentedJarsRule implements AttributeCompatibilityRuleThis class can be constructed and modified, then used to instantiate the - * various API classes. The API classes use the settings in this class to - * configure themselves, but otherwise do not store a link to this class.

+ *

This class can be constructed and modified, then used to instantiate the various API classes. + * The API classes use the settings in this class to configure themselves, but otherwise do not + * store a link to this class. * - *

This class is mutable and not synchronized, so it is not thread-safe. - * The API classes generated from this are immutable and thread-safe.

+ *

This class is mutable and not synchronized, so it is not thread-safe. The API classes + * generated from this are immutable and thread-safe. * - *

The setter methods of this class return the current object to facilitate - * a fluent style of configuration.

+ *

The setter methods of this class return the current object to facilitate a fluent style of + * configuration. */ -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") public class ApiClient { - private HttpClient.Builder builder; - private ObjectMapper mapper; - private String scheme; - private String host; - private int port; - private String basePath; - private Consumer interceptor; - private Consumer> responseInterceptor; - private Consumer> asyncResponseInterceptor; - private Duration readTimeout; - private Duration connectTimeout; - - private static String valueToString(Object value) { - if (value == null) { - return ""; + private HttpClient.Builder builder; + private ObjectMapper mapper; + private String scheme; + private String host; + private int port; + private String basePath; + private Consumer interceptor; + private Consumer> responseInterceptor; + private Consumer> asyncResponseInterceptor; + private Duration readTimeout; + private Duration connectTimeout; + + private static String valueToString(Object value) { + if (value == null) { + return ""; + } + if (value instanceof OffsetDateTime) { + return ((OffsetDateTime) value).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } + return value.toString(); + } + + /** + * URL encode a string in the UTF-8 encoding. + * + * @param s String to encode. + * @return URL-encoded representation of the input string. + */ + public static String urlEncode(String s) { + return URLEncoder.encode(s, UTF_8).replaceAll("\\+", "%20"); + } + + /** + * Convert a URL query name/value parameter to a list of encoded {@link Pair} objects. + * + *

The value can be null, in which case an empty list is returned. + * + * @param name The query name parameter. + * @param value The query value, which may not be a collection but may be null. + * @return A singleton list of the {@link Pair} objects representing the input parameters, which + * is encoded for use in a URL. If the value is null, an empty list is returned. + */ + public static List parameterToPairs(String name, Object value) { + if (name == null || name.isEmpty() || value == null) { + return Collections.emptyList(); + } + return Collections.singletonList( + new Pair(urlEncode(name), urlEncode(valueToString(value)))); + } + + /** + * Convert a URL query name/collection parameter to a list of encoded {@link Pair} objects. + * + * @param collectionFormat The swagger collectionFormat string (csv, tsv, etc). + * @param name The query name parameter. + * @param values A collection of values for the given query name, which may be null. + * @return A list of {@link Pair} objects representing the input parameters, which is encoded + * for use in a URL. If the values collection is null, an empty list is returned. + */ + public static List parameterToPairs( + String collectionFormat, String name, Collection values) { + if (name == null || name.isEmpty() || values == null || values.isEmpty()) { + return Collections.emptyList(); + } + + // get the collection format (default: csv) + String format = + collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat; + + // create the params based on the collection format + if ("multi".equals(format)) { + return values.stream() + .map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value)))) + .collect(Collectors.toList()); + } + + String delimiter; + switch (format) { + case "csv": + delimiter = urlEncode(","); + break; + case "ssv": + delimiter = urlEncode(" "); + break; + case "tsv": + delimiter = urlEncode("\t"); + break; + case "pipes": + delimiter = urlEncode("|"); + break; + default: + throw new IllegalArgumentException( + "Illegal collection format: " + collectionFormat); + } + + StringJoiner joiner = new StringJoiner(delimiter); + for (Object value : values) { + joiner.add(urlEncode(valueToString(value))); + } + + return Collections.singletonList(new Pair(urlEncode(name), joiner.toString())); + } + + /** Create an instance of ApiClient. */ + public ApiClient() { + this.builder = createDefaultHttpClientBuilder(); + this.mapper = createDefaultObjectMapper(); + updateBaseUri(getDefaultBaseUri()); + interceptor = null; + readTimeout = null; + connectTimeout = null; + responseInterceptor = null; + asyncResponseInterceptor = null; + } + + /** + * Create an instance of ApiClient. + * + * @param builder Http client builder. + * @param mapper Object mapper. + * @param baseUri Base URI + */ + public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, String baseUri) { + this.builder = builder; + this.mapper = mapper; + updateBaseUri(baseUri != null ? baseUri : getDefaultBaseUri()); + interceptor = null; + readTimeout = null; + connectTimeout = null; + responseInterceptor = null; + asyncResponseInterceptor = null; } - if (value instanceof OffsetDateTime) { - return ((OffsetDateTime) value).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + + protected ObjectMapper createDefaultObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); + mapper.registerModule(new JavaTimeModule()); + mapper.registerModule(new JsonNullableModule()); + return mapper; } - return value.toString(); - } - - /** - * URL encode a string in the UTF-8 encoding. - * - * @param s String to encode. - * @return URL-encoded representation of the input string. - */ - public static String urlEncode(String s) { - return URLEncoder.encode(s, UTF_8).replaceAll("\\+", "%20"); - } - - /** - * Convert a URL query name/value parameter to a list of encoded {@link Pair} - * objects. - * - *

The value can be null, in which case an empty list is returned.

- * - * @param name The query name parameter. - * @param value The query value, which may not be a collection but may be - * null. - * @return A singleton list of the {@link Pair} objects representing the input - * parameters, which is encoded for use in a URL. If the value is null, an - * empty list is returned. - */ - public static List parameterToPairs(String name, Object value) { - if (name == null || name.isEmpty() || value == null) { - return Collections.emptyList(); + + protected String getDefaultBaseUri() { + return "http://localhost:3000"; } - return Collections.singletonList(new Pair(urlEncode(name), urlEncode(valueToString(value)))); - } - - /** - * Convert a URL query name/collection parameter to a list of encoded - * {@link Pair} objects. - * - * @param collectionFormat The swagger collectionFormat string (csv, tsv, etc). - * @param name The query name parameter. - * @param values A collection of values for the given query name, which may be - * null. - * @return A list of {@link Pair} objects representing the input parameters, - * which is encoded for use in a URL. If the values collection is null, an - * empty list is returned. - */ - public static List parameterToPairs( - String collectionFormat, String name, Collection values) { - if (name == null || name.isEmpty() || values == null || values.isEmpty()) { - return Collections.emptyList(); + + protected HttpClient.Builder createDefaultHttpClientBuilder() { + return HttpClient.newBuilder(); } - // get the collection format (default: csv) - String format = collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat; + public void updateBaseUri(String baseUri) { + URI uri = URI.create(baseUri); + scheme = uri.getScheme(); + host = uri.getHost(); + port = uri.getPort(); + basePath = uri.getRawPath(); + } - // create the params based on the collection format - if ("multi".equals(format)) { - return values.stream() - .map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value)))) - .collect(Collectors.toList()); + /** + * Set a custom {@link HttpClient.Builder} object to use when creating the {@link HttpClient} + * that is used by the API client. + * + * @param builder Custom client builder. + * @return This object. + */ + public ApiClient setHttpClientBuilder(HttpClient.Builder builder) { + this.builder = builder; + return this; } - String delimiter; - switch(format) { - case "csv": - delimiter = urlEncode(","); - break; - case "ssv": - delimiter = urlEncode(" "); - break; - case "tsv": - delimiter = urlEncode("\t"); - break; - case "pipes": - delimiter = urlEncode("|"); - break; - default: - throw new IllegalArgumentException("Illegal collection format: " + collectionFormat); + /** + * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}. + * + *

The returned object is immutable and thread-safe. + * + * @return The HTTP client. + */ + public HttpClient getHttpClient() { + return builder.build(); } - StringJoiner joiner = new StringJoiner(delimiter); - for (Object value : values) { - joiner.add(urlEncode(valueToString(value))); + /** + * Set a custom {@link ObjectMapper} to serialize and deserialize the request and response + * bodies. + * + * @param mapper Custom object mapper. + * @return This object. + */ + public ApiClient setObjectMapper(ObjectMapper mapper) { + this.mapper = mapper; + return this; } - return Collections.singletonList(new Pair(urlEncode(name), joiner.toString())); - } - - /** - * Create an instance of ApiClient. - */ - public ApiClient() { - this.builder = createDefaultHttpClientBuilder(); - this.mapper = createDefaultObjectMapper(); - updateBaseUri(getDefaultBaseUri()); - interceptor = null; - readTimeout = null; - connectTimeout = null; - responseInterceptor = null; - asyncResponseInterceptor = null; - } - - /** - * Create an instance of ApiClient. - * - * @param builder Http client builder. - * @param mapper Object mapper. - * @param baseUri Base URI - */ - public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, String baseUri) { - this.builder = builder; - this.mapper = mapper; - updateBaseUri(baseUri != null ? baseUri : getDefaultBaseUri()); - interceptor = null; - readTimeout = null; - connectTimeout = null; - responseInterceptor = null; - asyncResponseInterceptor = null; - } - - protected ObjectMapper createDefaultObjectMapper() { - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); - mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); - mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); - mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); - mapper.registerModule(new JavaTimeModule()); - mapper.registerModule(new JsonNullableModule()); - return mapper; - } - - protected String getDefaultBaseUri() { - return "http://localhost:3000"; - } - - protected HttpClient.Builder createDefaultHttpClientBuilder() { - return HttpClient.newBuilder(); - } - - public void updateBaseUri(String baseUri) { - URI uri = URI.create(baseUri); - scheme = uri.getScheme(); - host = uri.getHost(); - port = uri.getPort(); - basePath = uri.getRawPath(); - } - - /** - * Set a custom {@link HttpClient.Builder} object to use when creating the - * {@link HttpClient} that is used by the API client. - * - * @param builder Custom client builder. - * @return This object. - */ - public ApiClient setHttpClientBuilder(HttpClient.Builder builder) { - this.builder = builder; - return this; - } - - /** - * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}. - * - *

The returned object is immutable and thread-safe.

- * - * @return The HTTP client. - */ - public HttpClient getHttpClient() { - return builder.build(); - } - - /** - * Set a custom {@link ObjectMapper} to serialize and deserialize the request - * and response bodies. - * - * @param mapper Custom object mapper. - * @return This object. - */ - public ApiClient setObjectMapper(ObjectMapper mapper) { - this.mapper = mapper; - return this; - } - - /** - * Get a copy of the current {@link ObjectMapper}. - * - * @return A copy of the current object mapper. - */ - public ObjectMapper getObjectMapper() { - return mapper.copy(); - } - - /** - * Set a custom host name for the target service. - * - * @param host The host name of the target service. - * @return This object. - */ - public ApiClient setHost(String host) { - this.host = host; - return this; - } - - /** - * Set a custom port number for the target service. - * - * @param port The port of the target service. Set this to -1 to reset the - * value to the default for the scheme. - * @return This object. - */ - public ApiClient setPort(int port) { - this.port = port; - return this; - } - - /** - * Set a custom base path for the target service, for example '/v2'. - * - * @param basePath The base path against which the rest of the path is - * resolved. - * @return This object. - */ - public ApiClient setBasePath(String basePath) { - this.basePath = basePath; - return this; - } - - /** - * Get the base URI to resolve the endpoint paths against. - * - * @return The complete base URI that the rest of the API parameters are - * resolved against. - */ - public String getBaseUri() { - return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; - } - - /** - * Set a custom scheme for the target service, for example 'https'. - * - * @param scheme The scheme of the target service - * @return This object. - */ - public ApiClient setScheme(String scheme){ - this.scheme = scheme; - return this; - } - - /** - * Set a custom request interceptor. - * - *

A request interceptor is a mechanism for altering each request before it - * is sent. After the request has been fully configured but not yet built, the - * request builder is passed into this function for further modification, - * after which it is sent out.

- * - *

This is useful for altering the requests in a custom manner, such as - * adding headers. It could also be used for logging and monitoring.

- * - * @param interceptor A function invoked before creating each request. A value - * of null resets the interceptor to a no-op. - * @return This object. - */ - public ApiClient setRequestInterceptor(Consumer interceptor) { - this.interceptor = interceptor; - return this; - } - - /** - * Get the custom interceptor. - * - * @return The custom interceptor that was set, or null if there isn't any. - */ - public Consumer getRequestInterceptor() { - return interceptor; - } - - /** - * Set a custom response interceptor. - * - *

This is useful for logging, monitoring or extraction of header variables

- * - * @param interceptor A function invoked before creating each request. A value - * of null resets the interceptor to a no-op. - * @return This object. - */ - public ApiClient setResponseInterceptor(Consumer> interceptor) { - this.responseInterceptor = interceptor; - return this; - } - - /** - * Get the custom response interceptor. - * - * @return The custom interceptor that was set, or null if there isn't any. - */ - public Consumer> getResponseInterceptor() { - return responseInterceptor; - } - - /** - * Set a custom async response interceptor. Use this interceptor when asyncNative is set to 'true'. - * - *

This is useful for logging, monitoring or extraction of header variables

- * - * @param interceptor A function invoked before creating each request. A value - * of null resets the interceptor to a no-op. - * @return This object. - */ - public ApiClient setAsyncResponseInterceptor(Consumer> interceptor) { - this.asyncResponseInterceptor = interceptor; - return this; - } - - /** - * Get the custom async response interceptor. Use this interceptor when asyncNative is set to 'true'. - * - * @return The custom interceptor that was set, or null if there isn't any. - */ - public Consumer> getAsyncResponseInterceptor() { - return asyncResponseInterceptor; - } - - /** - * Set the read timeout for the http client. - * - *

This is the value used by default for each request, though it can be - * overridden on a per-request basis with a request interceptor.

- * - * @param readTimeout The read timeout used by default by the http client. - * Setting this value to null resets the timeout to an - * effectively infinite value. - * @return This object. - */ - public ApiClient setReadTimeout(Duration readTimeout) { - this.readTimeout = readTimeout; - return this; - } - - /** - * Get the read timeout that was set. - * - * @return The read timeout, or null if no timeout was set. Null represents - * an infinite wait time. - */ - public Duration getReadTimeout() { - return readTimeout; - } - /** - * Sets the connect timeout (in milliseconds) for the http client. - * - *

In the case where a new connection needs to be established, if - * the connection cannot be established within the given {@code - * duration}, then {@link HttpClient#send(HttpRequest,BodyHandler) - * HttpClient::send} throws an {@link HttpConnectTimeoutException}, or - * {@link HttpClient#sendAsync(HttpRequest,BodyHandler) - * HttpClient::sendAsync} completes exceptionally with an - * {@code HttpConnectTimeoutException}. If a new connection does not - * need to be established, for example if a connection can be reused - * from a previous request, then this timeout duration has no effect. - * - * @param connectTimeout connection timeout in milliseconds - * - * @return This object. - */ - public ApiClient setConnectTimeout(Duration connectTimeout) { - this.connectTimeout = connectTimeout; - this.builder.connectTimeout(connectTimeout); - return this; - } - - /** - * Get connection timeout (in milliseconds). - * - * @return Timeout in milliseconds - */ - public Duration getConnectTimeout() { - return connectTimeout; - } + /** + * Get a copy of the current {@link ObjectMapper}. + * + * @return A copy of the current object mapper. + */ + public ObjectMapper getObjectMapper() { + return mapper.copy(); + } + + /** + * Set a custom host name for the target service. + * + * @param host The host name of the target service. + * @return This object. + */ + public ApiClient setHost(String host) { + this.host = host; + return this; + } + + /** + * Set a custom port number for the target service. + * + * @param port The port of the target service. Set this to -1 to reset the value to the default + * for the scheme. + * @return This object. + */ + public ApiClient setPort(int port) { + this.port = port; + return this; + } + + /** + * Set a custom base path for the target service, for example '/v2'. + * + * @param basePath The base path against which the rest of the path is resolved. + * @return This object. + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get the base URI to resolve the endpoint paths against. + * + * @return The complete base URI that the rest of the API parameters are resolved against. + */ + public String getBaseUri() { + return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; + } + + /** + * Set a custom scheme for the target service, for example 'https'. + * + * @param scheme The scheme of the target service + * @return This object. + */ + public ApiClient setScheme(String scheme) { + this.scheme = scheme; + return this; + } + + /** + * Set a custom request interceptor. + * + *

A request interceptor is a mechanism for altering each request before it is sent. After + * the request has been fully configured but not yet built, the request builder is passed into + * this function for further modification, after which it is sent out. + * + *

This is useful for altering the requests in a custom manner, such as adding headers. It + * could also be used for logging and monitoring. + * + * @param interceptor A function invoked before creating each request. A value of null resets + * the interceptor to a no-op. + * @return This object. + */ + public ApiClient setRequestInterceptor(Consumer interceptor) { + this.interceptor = interceptor; + return this; + } + + /** + * Get the custom interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer getRequestInterceptor() { + return interceptor; + } + + /** + * Set a custom response interceptor. + * + *

This is useful for logging, monitoring or extraction of header variables + * + * @param interceptor A function invoked before creating each request. A value of null resets + * the interceptor to a no-op. + * @return This object. + */ + public ApiClient setResponseInterceptor(Consumer> interceptor) { + this.responseInterceptor = interceptor; + return this; + } + + /** + * Get the custom response interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getResponseInterceptor() { + return responseInterceptor; + } + + /** + * Set a custom async response interceptor. Use this interceptor when asyncNative is set to + * 'true'. + * + *

This is useful for logging, monitoring or extraction of header variables + * + * @param interceptor A function invoked before creating each request. A value of null resets + * the interceptor to a no-op. + * @return This object. + */ + public ApiClient setAsyncResponseInterceptor(Consumer> interceptor) { + this.asyncResponseInterceptor = interceptor; + return this; + } + + /** + * Get the custom async response interceptor. Use this interceptor when asyncNative is set to + * 'true'. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getAsyncResponseInterceptor() { + return asyncResponseInterceptor; + } + + /** + * Set the read timeout for the http client. + * + *

This is the value used by default for each request, though it can be overridden on a + * per-request basis with a request interceptor. + * + * @param readTimeout The read timeout used by default by the http client. Setting this value to + * null resets the timeout to an effectively infinite value. + * @return This object. + */ + public ApiClient setReadTimeout(Duration readTimeout) { + this.readTimeout = readTimeout; + return this; + } + + /** + * Get the read timeout that was set. + * + * @return The read timeout, or null if no timeout was set. Null represents an infinite wait + * time. + */ + public Duration getReadTimeout() { + return readTimeout; + } + /** + * Sets the connect timeout (in milliseconds) for the http client. + * + *

In the case where a new connection needs to be established, if the connection cannot be + * established within the given {@code duration}, then {@link + * HttpClient#send(HttpRequest,BodyHandler) HttpClient::send} throws an {@link + * HttpConnectTimeoutException}, or {@link HttpClient#sendAsync(HttpRequest,BodyHandler) + * HttpClient::sendAsync} completes exceptionally with an {@code HttpConnectTimeoutException}. + * If a new connection does not need to be established, for example if a connection can be + * reused from a previous request, then this timeout duration has no effect. + * + * @param connectTimeout connection timeout in milliseconds + * @return This object. + */ + public ApiClient setConnectTimeout(Duration connectTimeout) { + this.connectTimeout = connectTimeout; + this.builder.connectTimeout(connectTimeout); + return this; + } + + /** + * Get connection timeout (in milliseconds). + * + * @return Timeout in milliseconds + */ + public Duration getConnectTimeout() { + return connectTimeout; + } } diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiException.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiException.java index 97857935..e2e55152 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiException.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiException.java @@ -1,21 +1,11 @@ -/* - * Assertion Client - * Client used to get the assertion from the identity provider - * - * The version of the OpenAPI document: $npm_package_version - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; import java.net.http.HttpHeaders; -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") public class ApiException extends RuntimeException { private int code = 0; private HttpHeaders responseHeaders = null; @@ -31,18 +21,25 @@ public ApiException(String message) { super(message); } - public ApiException(String message, Throwable throwable, int code, HttpHeaders responseHeaders, String responseBody) { + public ApiException( + String message, + Throwable throwable, + int code, + HttpHeaders responseHeaders, + String responseBody) { super(message, throwable); this.code = code; this.responseHeaders = responseHeaders; this.responseBody = responseBody; } - public ApiException(String message, int code, HttpHeaders responseHeaders, String responseBody) { + public ApiException( + String message, int code, HttpHeaders responseHeaders, String responseBody) { this(message, (Throwable) null, code, responseHeaders, responseBody); } - public ApiException(String message, Throwable throwable, int code, HttpHeaders responseHeaders) { + public ApiException( + String message, Throwable throwable, int code, HttpHeaders responseHeaders) { this(message, throwable, code, responseHeaders, null); } @@ -55,7 +52,8 @@ public ApiException(int code, String message) { this.code = code; } - public ApiException(int code, String message, HttpHeaders responseHeaders, String responseBody) { + public ApiException( + int code, String message, HttpHeaders responseHeaders, String responseBody) { this(code, message); this.responseHeaders = responseHeaders; this.responseBody = responseBody; diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiResponse.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiResponse.java index 0b6f0590..dbe9cb01 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiResponse.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiResponse.java @@ -1,16 +1,4 @@ -/* - * Assertion Client - * Client used to get the assertion from the identity provider - * - * The version of the OpenAPI document: $npm_package_version - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; import java.util.List; @@ -22,9 +10,9 @@ * @param The type of data that is deserialized from response body */ public class ApiResponse { - final private int statusCode; - final private Map> headers; - final private T data; + private final int statusCode; + private final Map> headers; + private final T data; /** * @param statusCode The status code of HTTP response diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Configuration.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Configuration.java index 335ec4fa..291806fa 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Configuration.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Configuration.java @@ -1,25 +1,15 @@ -/* - * Assertion Client - * Client used to get the assertion from the identity provider - * - * The version of the OpenAPI document: $npm_package_version - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") public class Configuration { private static ApiClient defaultApiClient = new ApiClient(); /** - * Get the default API client, which would be used when creating API - * instances without providing an API client. + * Get the default API client, which would be used when creating API instances without providing + * an API client. * * @return Default API client */ @@ -28,8 +18,8 @@ public static ApiClient getDefaultApiClient() { } /** - * Set the default API client, which would be used when creating API - * instances without providing an API client. + * Set the default API client, which would be used when creating API instances without providing + * an API client. * * @param apiClient API client */ diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/JSON.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/JSON.java index 00092b9d..85ea11dc 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/JSON.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/JSON.java @@ -1,248 +1,247 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; -import org.openapitools.jackson.nullable.JsonNullableModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.*; - import java.text.DateFormat; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import org.openapitools.jackson.nullable.JsonNullableModule; -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") public class JSON { - private ObjectMapper mapper; - - public JSON() { - mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); - mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); - mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); - mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); - mapper.setDateFormat(new RFC3339DateFormat()); - mapper.registerModule(new JavaTimeModule()); - JsonNullableModule jnm = new JsonNullableModule(); - mapper.registerModule(jnm); - } - - /** - * Set the date format for JSON (de)serialization with Date properties. - * - * @param dateFormat Date format - */ - public void setDateFormat(DateFormat dateFormat) { - mapper.setDateFormat(dateFormat); - } - - /** - * Get the object mapper - * - * @return object mapper - */ - public ObjectMapper getMapper() { return mapper; } - - /** - * Returns the target model class that should be used to deserialize the input data. - * The discriminator mappings are used to determine the target model class. - * - * @param node The input data. - * @param modelClass The class that contains the discriminator mappings. - * - * @return the target model class. - */ - public static Class getClassForElement(JsonNode node, Class modelClass) { - ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass); - if (cdm != null) { - return cdm.getClassForElement(node, new HashSet>()); - } - return null; - } - - /** - * Helper class to register the discriminator mappings. - */ - private static class ClassDiscriminatorMapping { - // The model class name. - Class modelClass; - // The name of the discriminator property. - String discriminatorName; - // The discriminator mappings for a model class. - Map> discriminatorMappings; - - // Constructs a new class discriminator. - ClassDiscriminatorMapping(Class cls, String propertyName, Map> mappings) { - modelClass = cls; - discriminatorName = propertyName; - discriminatorMappings = new HashMap>(); - if (mappings != null) { - discriminatorMappings.putAll(mappings); - } + private ObjectMapper mapper; + + public JSON() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + mapper.registerModule(new JavaTimeModule()); + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); } - // Return the name of the discriminator property for this model class. - String getDiscriminatorPropertyName() { - return discriminatorName; + /** + * Set the date format for JSON (de)serialization with Date properties. + * + * @param dateFormat Date format + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); } - // Return the discriminator value or null if the discriminator is not - // present in the payload. - String getDiscriminatorValue(JsonNode node) { - // Determine the value of the discriminator property in the input data. - if (discriminatorName != null) { - // Get the value of the discriminator property, if present in the input payload. - node = node.get(discriminatorName); - if (node != null && node.isValueNode()) { - String discrValue = node.asText(); - if (discrValue != null) { - return discrValue; - } - } - } - return null; + /** + * Get the object mapper + * + * @return object mapper + */ + public ObjectMapper getMapper() { + return mapper; } /** - * Returns the target model class that should be used to deserialize the input data. - * This function can be invoked for anyOf/oneOf composed models with discriminator mappings. - * The discriminator mappings are used to determine the target model class. + * Returns the target model class that should be used to deserialize the input data. The + * discriminator mappings are used to determine the target model class. * * @param node The input data. - * @param visitedClasses The set of classes that have already been visited. - * + * @param modelClass The class that contains the discriminator mappings. * @return the target model class. */ - Class getClassForElement(JsonNode node, Set> visitedClasses) { - if (visitedClasses.contains(modelClass)) { - // Class has already been visited. - return null; - } - // Determine the value of the discriminator property in the input data. - String discrValue = getDiscriminatorValue(node); - if (discrValue == null) { + public static Class getClassForElement(JsonNode node, Class modelClass) { + ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass); + if (cdm != null) { + return cdm.getClassForElement(node, new HashSet>()); + } return null; - } - Class cls = discriminatorMappings.get(discrValue); - // It may not be sufficient to return this cls directly because that target class - // may itself be a composed schema, possibly with its own discriminator. - visitedClasses.add(modelClass); - for (Class childClass : discriminatorMappings.values()) { - ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass); - if (childCdm == null) { - continue; + } + + /** Helper class to register the discriminator mappings. */ + private static class ClassDiscriminatorMapping { + // The model class name. + Class modelClass; + // The name of the discriminator property. + String discriminatorName; + // The discriminator mappings for a model class. + Map> discriminatorMappings; + + // Constructs a new class discriminator. + ClassDiscriminatorMapping( + Class cls, String propertyName, Map> mappings) { + modelClass = cls; + discriminatorName = propertyName; + discriminatorMappings = new HashMap>(); + if (mappings != null) { + discriminatorMappings.putAll(mappings); + } + } + + // Return the name of the discriminator property for this model class. + String getDiscriminatorPropertyName() { + return discriminatorName; + } + + // Return the discriminator value or null if the discriminator is not + // present in the payload. + String getDiscriminatorValue(JsonNode node) { + // Determine the value of the discriminator property in the input data. + if (discriminatorName != null) { + // Get the value of the discriminator property, if present in the input payload. + node = node.get(discriminatorName); + if (node != null && node.isValueNode()) { + String discrValue = node.asText(); + if (discrValue != null) { + return discrValue; + } + } + } + return null; + } + + /** + * Returns the target model class that should be used to deserialize the input data. This + * function can be invoked for anyOf/oneOf composed models with discriminator mappings. The + * discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param visitedClasses The set of classes that have already been visited. + * @return the target model class. + */ + Class getClassForElement(JsonNode node, Set> visitedClasses) { + if (visitedClasses.contains(modelClass)) { + // Class has already been visited. + return null; + } + // Determine the value of the discriminator property in the input data. + String discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + return null; + } + Class cls = discriminatorMappings.get(discrValue); + // It may not be sufficient to return this cls directly because that target class + // may itself be a composed schema, possibly with its own discriminator. + visitedClasses.add(modelClass); + for (Class childClass : discriminatorMappings.values()) { + ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass); + if (childCdm == null) { + continue; + } + if (!discriminatorName.equals(childCdm.discriminatorName)) { + discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + continue; + } + } + if (childCdm != null) { + // Recursively traverse the discriminator mappings. + Class childDiscr = childCdm.getClassForElement(node, visitedClasses); + if (childDiscr != null) { + return childDiscr; + } + } + } + return cls; + } + } + + /** + * Returns true if inst is an instance of modelClass in the OpenAPI model hierarchy. + * + *

The Java class hierarchy is not implemented the same way as the OpenAPI model hierarchy, + * so it's not possible to use the instanceof keyword. + * + * @param modelClass A OpenAPI model class. + * @param inst The instance object. + * @param visitedClasses The set of classes that have already been visited. + * @return true if inst is an instance of modelClass in the OpenAPI model hierarchy. + */ + public static boolean isInstanceOf( + Class modelClass, Object inst, Set> visitedClasses) { + if (modelClass.isInstance(inst)) { + // This handles the 'allOf' use case with single parent inheritance. + return true; } - if (!discriminatorName.equals(childCdm.discriminatorName)) { - discrValue = getDiscriminatorValue(node); - if (discrValue == null) { - continue; - } + if (visitedClasses.contains(modelClass)) { + // This is to prevent infinite recursion when the composed schemas have + // a circular dependency. + return false; } - if (childCdm != null) { - // Recursively traverse the discriminator mappings. - Class childDiscr = childCdm.getClassForElement(node, visitedClasses); - if (childDiscr != null) { - return childDiscr; - } + visitedClasses.add(modelClass); + + // Traverse the oneOf/anyOf composed schemas. + Map> descendants = modelDescendants.get(modelClass); + if (descendants != null) { + for (Class childType : descendants.values()) { + if (isInstanceOf(childType, inst, visitedClasses)) { + return true; + } + } } - } - return cls; + return false; } - } - - /** - * Returns true if inst is an instance of modelClass in the OpenAPI model hierarchy. - * - * The Java class hierarchy is not implemented the same way as the OpenAPI model hierarchy, - * so it's not possible to use the instanceof keyword. - * - * @param modelClass A OpenAPI model class. - * @param inst The instance object. - * @param visitedClasses The set of classes that have already been visited. - * - * @return true if inst is an instance of modelClass in the OpenAPI model hierarchy. - */ - public static boolean isInstanceOf(Class modelClass, Object inst, Set> visitedClasses) { - if (modelClass.isInstance(inst)) { - // This handles the 'allOf' use case with single parent inheritance. - return true; + + /** A map of discriminators for all model classes. */ + private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap<>(); + + /** A map of oneOf/anyOf descendants for each model class. */ + private static Map, Map>> modelDescendants = new HashMap<>(); + + /** + * Register a model class discriminator. + * + * @param modelClass the model class + * @param discriminatorPropertyName the name of the discriminator property + * @param mappings a map with the discriminator mappings. + */ + public static void registerDiscriminator( + Class modelClass, String discriminatorPropertyName, Map> mappings) { + ClassDiscriminatorMapping m = + new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings); + modelDiscriminators.put(modelClass, m); } - if (visitedClasses.contains(modelClass)) { - // This is to prevent infinite recursion when the composed schemas have - // a circular dependency. - return false; + + /** + * Register the oneOf/anyOf descendants of the modelClass. + * + * @param modelClass the model class + * @param descendants a map of oneOf/anyOf descendants. + */ + public static void registerDescendants(Class modelClass, Map> descendants) { + modelDescendants.put(modelClass, descendants); } - visitedClasses.add(modelClass); - - // Traverse the oneOf/anyOf composed schemas. - Map> descendants = modelDescendants.get(modelClass); - if (descendants != null) { - for (Class childType : descendants.values()) { - if (isInstanceOf(childType, inst, visitedClasses)) { - return true; - } - } + + private static JSON json; + + static { + json = new JSON(); + } + + /** + * Get the default JSON instance. + * + * @return the default JSON instance + */ + public static JSON getDefault() { + return json; + } + + /** + * Set the default JSON instance. + * + * @param json JSON instance to be used + */ + public static void setDefault(JSON json) { + JSON.json = json; } - return false; - } - - /** - * A map of discriminators for all model classes. - */ - private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap<>(); - - /** - * A map of oneOf/anyOf descendants for each model class. - */ - private static Map, Map>> modelDescendants = new HashMap<>(); - - /** - * Register a model class discriminator. - * - * @param modelClass the model class - * @param discriminatorPropertyName the name of the discriminator property - * @param mappings a map with the discriminator mappings. - */ - public static void registerDiscriminator(Class modelClass, String discriminatorPropertyName, Map> mappings) { - ClassDiscriminatorMapping m = new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings); - modelDiscriminators.put(modelClass, m); - } - - /** - * Register the oneOf/anyOf descendants of the modelClass. - * - * @param modelClass the model class - * @param descendants a map of oneOf/anyOf descendants. - */ - public static void registerDescendants(Class modelClass, Map> descendants) { - modelDescendants.put(modelClass, descendants); - } - - private static JSON json; - - static { - json = new JSON(); - } - - /** - * Get the default JSON instance. - * - * @return the default JSON instance - */ - public static JSON getDefault() { - return json; - } - - /** - * Set the default JSON instance. - * - * @param json JSON instance to be used - */ - public static void setDefault(JSON json) { - JSON.json = json; - } } diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Pair.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Pair.java index 4556c728..71f7801d 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Pair.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Pair.java @@ -1,24 +1,14 @@ -/* - * Assertion Client - * Client used to get the assertion from the identity provider - * - * The version of the OpenAPI document: $npm_package_version - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") public class Pair { private String name = ""; private String value = ""; - public Pair (String name, String value) { + public Pair(String name, String value) { setName(name); setValue(value); } diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/RFC3339DateFormat.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/RFC3339DateFormat.java index 9ab4c4e8..c8d0934d 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/RFC3339DateFormat.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/RFC3339DateFormat.java @@ -1,57 +1,44 @@ -/* - * Assertion Client - * Client used to get the assertion from the identity provider - * - * The version of the OpenAPI document: $npm_package_version - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; import com.fasterxml.jackson.databind.util.StdDateFormat; - import java.text.DateFormat; +import java.text.DecimalFormat; import java.text.FieldPosition; import java.text.ParsePosition; import java.util.Date; -import java.text.DecimalFormat; import java.util.GregorianCalendar; import java.util.TimeZone; public class RFC3339DateFormat extends DateFormat { - private static final long serialVersionUID = 1L; - private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); - - private final StdDateFormat fmt = new StdDateFormat() - .withTimeZone(TIMEZONE_Z) - .withColonInTimeZone(true); - - public RFC3339DateFormat() { - this.calendar = new GregorianCalendar(); - this.numberFormat = new DecimalFormat(); - } - - @Override - public Date parse(String source) { - return parse(source, new ParsePosition(0)); - } - - @Override - public Date parse(String source, ParsePosition pos) { - return fmt.parse(source, pos); - } - - @Override - public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { - return fmt.format(date, toAppendTo, fieldPosition); - } - - @Override - public Object clone() { - return super.clone(); - } -} \ No newline at end of file + private static final long serialVersionUID = 1L; + private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); + + private final StdDateFormat fmt = + new StdDateFormat().withTimeZone(TIMEZONE_Z).withColonInTimeZone(true); + + public RFC3339DateFormat() { + this.calendar = new GregorianCalendar(); + this.numberFormat = new DecimalFormat(); + } + + @Override + public Date parse(String source) { + return parse(source, new ParsePosition(0)); + } + + @Override + public Date parse(String source, ParsePosition pos) { + return fmt.parse(source, pos); + } + + @Override + public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { + return fmt.format(date, toAppendTo, fieldPosition); + } + + @Override + public Object clone() { + return super.clone(); + } +} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerConfiguration.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerConfiguration.java index 62d41981..eb6f73d1 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerConfiguration.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerConfiguration.java @@ -1,10 +1,9 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; import java.util.Map; -/** - * Representing a Server configuration. - */ +/** Representing a Server configuration. */ public class ServerConfiguration { public String URL; public String description; @@ -13,9 +12,11 @@ public class ServerConfiguration { /** * @param URL A URL to the target host. * @param description A description of the host designated by the URL. - * @param variables A map between a variable name and its value. The value is used for substitution in the server's URL template. + * @param variables A map between a variable name and its value. The value is used for + * substitution in the server's URL template. */ - public ServerConfiguration(String URL, String description, Map variables) { + public ServerConfiguration( + String URL, String description, Map variables) { this.URL = URL; this.description = description; this.variables = variables; @@ -31,15 +32,21 @@ public String URL(Map variables) { String url = this.URL; // go through variables and replace placeholders - for (Map.Entry variable: this.variables.entrySet()) { + for (Map.Entry variable : this.variables.entrySet()) { String name = variable.getKey(); ServerVariable serverVariable = variable.getValue(); String value = serverVariable.defaultValue; if (variables != null && variables.containsKey(name)) { value = variables.get(name); - if (serverVariable.enumValues.size() > 0 && !serverVariable.enumValues.contains(value)) { - throw new IllegalArgumentException("The variable " + name + " in the server URL has invalid value " + value + "."); + if (serverVariable.enumValues.size() > 0 + && !serverVariable.enumValues.contains(value)) { + throw new IllegalArgumentException( + "The variable " + + name + + " in the server URL has invalid value " + + value + + "."); } } url = url.replace("{" + name + "}", value); diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerVariable.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerVariable.java index b1bd047e..f1db28ef 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerVariable.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerVariable.java @@ -1,10 +1,9 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; import java.util.HashSet; -/** - * Representing a Server Variable for server URL template substitution. - */ +/** Representing a Server Variable for server URL template substitution. */ public class ServerVariable { public String description; public String defaultValue; @@ -13,7 +12,8 @@ public class ServerVariable { /** * @param description A description for the server variable. * @param defaultValue The default value to use for substitution. - * @param enumValues An enumeration of string values to be used if the substitution options are from a limited set. + * @param enumValues An enumeration of string values to be used if the substitution options are + * from a limited set. */ public ServerVariable(String description, String defaultValue, HashSet enumValues) { this.description = description; diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/api/DefaultApi.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/api/DefaultApi.java index 17fc8125..1c71e359 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/api/DefaultApi.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/api/DefaultApi.java @@ -1,167 +1,158 @@ -/* - * Assertion Client - * Client used to get the assertion from the identity provider - * - * The version of the OpenAPI document: $npm_package_version - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.api; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiException; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiResponse; -import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.Pair; - import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.AssertionRef; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.LCUserInfo; -import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.ProblemJson; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; - -import java.io.InputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.IOException; -import java.io.OutputStream; -import java.net.http.HttpRequest; -import java.nio.channels.Channels; -import java.nio.channels.Pipe; +import java.io.InputStream; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; - -import java.util.ArrayList; -import java.util.StringJoiner; -import java.util.List; -import java.util.Map; -import java.util.Set; import java.util.function.Consumer; -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") public class DefaultApi { - private final HttpClient memberVarHttpClient; - private final ObjectMapper memberVarObjectMapper; - private final String memberVarBaseUri; - private final Consumer memberVarInterceptor; - private final Duration memberVarReadTimeout; - private final Consumer> memberVarResponseInterceptor; - private final Consumer> memberVarAsyncResponseInterceptor; - - public DefaultApi() { - this(new ApiClient()); - } - - public DefaultApi(ApiClient apiClient) { - memberVarHttpClient = apiClient.getHttpClient(); - memberVarObjectMapper = apiClient.getObjectMapper(); - memberVarBaseUri = apiClient.getBaseUri(); - memberVarInterceptor = apiClient.getRequestInterceptor(); - memberVarReadTimeout = apiClient.getReadTimeout(); - memberVarResponseInterceptor = apiClient.getResponseInterceptor(); - memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); - } - - protected ApiException getApiException(String operationId, HttpResponse response) throws IOException { - String body = response.body() == null ? null : new String(response.body().readAllBytes()); - String message = formatExceptionMessage(operationId, response.statusCode(), body); - return new ApiException(response.statusCode(), message, response.headers(), body); - } + private final HttpClient memberVarHttpClient; + private final ObjectMapper memberVarObjectMapper; + private final String memberVarBaseUri; + private final Consumer memberVarInterceptor; + private final Duration memberVarReadTimeout; + private final Consumer> memberVarResponseInterceptor; + private final Consumer> memberVarAsyncResponseInterceptor; + + public DefaultApi() { + this(new ApiClient()); + } - private String formatExceptionMessage(String operationId, int statusCode, String body) { - if (body == null || body.isEmpty()) { - body = "[no body]"; + public DefaultApi(ApiClient apiClient) { + memberVarHttpClient = apiClient.getHttpClient(); + memberVarObjectMapper = apiClient.getObjectMapper(); + memberVarBaseUri = apiClient.getBaseUri(); + memberVarInterceptor = apiClient.getRequestInterceptor(); + memberVarReadTimeout = apiClient.getReadTimeout(); + memberVarResponseInterceptor = apiClient.getResponseInterceptor(); + memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); } - return operationId + " call failed with: " + statusCode + " - " + body; - } - /** - * Get Assertion related to a given assertion ref - * - * @param assertionRef (required) - * @param xPagopaLollipopAuth (required) - * @return LCUserInfo - * @throws ApiException if fails to make API call - */ - public LCUserInfo getAssertion(AssertionRef assertionRef, String xPagopaLollipopAuth) throws ApiException { - ApiResponse localVarResponse = getAssertionWithHttpInfo(assertionRef, xPagopaLollipopAuth); - return localVarResponse.getData(); - } + protected ApiException getApiException(String operationId, HttpResponse response) + throws IOException { + String body = response.body() == null ? null : new String(response.body().readAllBytes()); + String message = formatExceptionMessage(operationId, response.statusCode(), body); + return new ApiException(response.statusCode(), message, response.headers(), body); + } - /** - * Get Assertion related to a given assertion ref - * - * @param assertionRef (required) - * @param xPagopaLollipopAuth (required) - * @return ApiResponse<LCUserInfo> - * @throws ApiException if fails to make API call - */ - public ApiResponse getAssertionWithHttpInfo(AssertionRef assertionRef, String xPagopaLollipopAuth) throws ApiException { - HttpRequest.Builder localVarRequestBuilder = getAssertionRequestBuilder(assertionRef, xPagopaLollipopAuth); - try { - HttpResponse localVarResponse = memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - try { - if (localVarResponse.statusCode()/ 100 != 2) { - throw getApiException("getAssertion", localVarResponse); + private String formatExceptionMessage(String operationId, int statusCode, String body) { + if (body == null || body.isEmpty()) { + body = "[no body]"; } - return new ApiResponse( - localVarResponse.statusCode(), - localVarResponse.headers().map(), - localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream - ); - } finally { - } - } catch (IOException e) { - throw new ApiException(e); - } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); + return operationId + " call failed with: " + statusCode + " - " + body; } - } - private HttpRequest.Builder getAssertionRequestBuilder(AssertionRef assertionRef, String xPagopaLollipopAuth) throws ApiException { - // verify the required parameter 'assertionRef' is set - if (assertionRef == null) { - throw new ApiException(400, "Missing the required parameter 'assertionRef' when calling getAssertion"); + /** + * Get Assertion related to a given assertion ref + * + * @param assertionRef (required) + * @param xPagopaLollipopAuth (required) + * @return LCUserInfo + * @throws ApiException if fails to make API call + */ + public LCUserInfo getAssertion(AssertionRef assertionRef, String xPagopaLollipopAuth) + throws ApiException { + ApiResponse localVarResponse = + getAssertionWithHttpInfo(assertionRef, xPagopaLollipopAuth); + return localVarResponse.getData(); } - // verify the required parameter 'xPagopaLollipopAuth' is set - if (xPagopaLollipopAuth == null) { - throw new ApiException(400, "Missing the required parameter 'xPagopaLollipopAuth' when calling getAssertion"); + + /** + * Get Assertion related to a given assertion ref + * + * @param assertionRef (required) + * @param xPagopaLollipopAuth (required) + * @return ApiResponse<LCUserInfo> + * @throws ApiException if fails to make API call + */ + public ApiResponse getAssertionWithHttpInfo( + AssertionRef assertionRef, String xPagopaLollipopAuth) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = + getAssertionRequestBuilder(assertionRef, xPagopaLollipopAuth); + try { + HttpResponse localVarResponse = + memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode() / 100 != 2) { + throw getApiException("getAssertion", localVarResponse); + } + return new ApiResponse( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null + ? null + : memberVarObjectMapper.readValue( + localVarResponse.body(), + new TypeReference< + LCUserInfo>() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } } - HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + private HttpRequest.Builder getAssertionRequestBuilder( + AssertionRef assertionRef, String xPagopaLollipopAuth) throws ApiException { + // verify the required parameter 'assertionRef' is set + if (assertionRef == null) { + throw new ApiException( + 400, "Missing the required parameter 'assertionRef' when calling getAssertion"); + } + // verify the required parameter 'xPagopaLollipopAuth' is set + if (xPagopaLollipopAuth == null) { + throw new ApiException( + 400, + "Missing the required parameter 'xPagopaLollipopAuth' when calling" + + " getAssertion"); + } + + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); - String localVarPath = "/assertions/{assertion_ref}" - .replace("{assertion_ref}", ApiClient.urlEncode(assertionRef.getActualInstance().toString())); + String localVarPath = + "/assertions/{assertion_ref}" + .replace( + "{assertion_ref}", + ApiClient.urlEncode(assertionRef.getActualInstance().toString())); - localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); - if (xPagopaLollipopAuth != null) { - localVarRequestBuilder.header("x-pagopa-lollipop-auth", xPagopaLollipopAuth.toString()); - } - localVarRequestBuilder.header("Accept", "application/json"); + if (xPagopaLollipopAuth != null) { + localVarRequestBuilder.header("x-pagopa-lollipop-auth", xPagopaLollipopAuth.toString()); + } + localVarRequestBuilder.header("Accept", "application/json"); - localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; } - return localVarRequestBuilder; - } } diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AbstractOpenApiSchema.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AbstractOpenApiSchema.java index b2fd66c6..f4b070e4 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AbstractOpenApiSchema.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AbstractOpenApiSchema.java @@ -1,28 +1,14 @@ -/* - * Assertion Client - * Client used to get the assertion from the identity provider - * - * The version of the OpenAPI document: $npm_package_version - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model; -import java.util.Objects; -import java.lang.reflect.Type; -import java.util.Map; - import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Map; +import java.util.Objects; -/** - * Abstract class for oneOf,anyOf schemas defined in OpenAPI spec - */ -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +/** Abstract class for oneOf,anyOf schemas defined in OpenAPI spec */ +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") public abstract class AbstractOpenApiSchema { // store the actual instance of the schema/object @@ -52,17 +38,22 @@ public AbstractOpenApiSchema(String schemaType, Boolean isNullable) { * @return an instance of the actual schema/object */ @JsonValue - public Object getActualInstance() {return instance;} + public Object getActualInstance() { + return instance; + } /** * Set the actual instance * * @param instance the actual instance of the schema/object */ - public void setActualInstance(Object instance) {this.instance = instance;} + public void setActualInstance(Object instance) { + this.instance = instance; + } /** - * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf schema as well + * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf + * schema as well * * @return an instance of the actual schema/object */ @@ -74,7 +65,7 @@ private Object getActualInstanceRecursively(AbstractOpenApiSchema object) { if (object.getActualInstance() == null) { return null; } else if (object.getActualInstance() instanceof AbstractOpenApiSchema) { - return getActualInstanceRecursively((AbstractOpenApiSchema)object.getActualInstance()); + return getActualInstanceRecursively((AbstractOpenApiSchema) object.getActualInstance()); } else { return object.getActualInstance(); } @@ -101,8 +92,8 @@ public String toString() { } /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). + * Convert the given object to string with each line indented by 4 spaces (except the first + * line). */ private String toIndentedString(Object o) { if (o == null) { @@ -119,9 +110,9 @@ public boolean equals(Object o) { return false; } AbstractOpenApiSchema a = (AbstractOpenApiSchema) o; - return Objects.equals(this.instance, a.instance) && - Objects.equals(this.isNullable, a.isNullable) && - Objects.equals(this.schemaType, a.schemaType); + return Objects.equals(this.instance, a.instance) + && Objects.equals(this.isNullable, a.isNullable) + && Objects.equals(this.schemaType, a.schemaType); } @Override @@ -141,7 +132,4 @@ public Boolean isNullable() { return Boolean.FALSE; } } - - - } diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionRef.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionRef.java index df24ebda..005daa74 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionRef.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionRef.java @@ -1,36 +1,6 @@ -/* - * Assertion Client - * Client used to get the assertion from the identity provider - * - * The version of the OpenAPI document: $npm_package_version - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.StringJoiner; -import java.util.Objects; -import java.util.Arrays; -import java.util.Map; -import java.util.HashMap; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; - -import com.fasterxml.jackson.core.type.TypeReference; - -import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; - import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; @@ -45,8 +15,20 @@ import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.JSON; +import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.StringJoiner; +import java.util.logging.Level; +import java.util.logging.Logger; -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") @JsonDeserialize(using = AssertionRef.AssertionRefDeserializer.class) @JsonSerialize(using = AssertionRef.AssertionRefSerializer.class) public class AssertionRef extends AbstractOpenApiSchema { @@ -62,7 +44,8 @@ public AssertionRefSerializer() { } @Override - public void serialize(AssertionRef value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + public void serialize(AssertionRef value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException { jgen.writeObject(value.getActualInstance()); } } @@ -77,7 +60,8 @@ public AssertionRefDeserializer(Class vc) { } @Override - public AssertionRef deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + public AssertionRef deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException { JsonNode tree = jp.readValueAsTree(); Object deserialized = null; boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS); @@ -87,13 +71,29 @@ public AssertionRef deserialize(JsonParser jp, DeserializationContext ctxt) thro try { boolean attemptParsing = true; // ensure that we respect type coercion as set on the client ObjectMapper - if (String.class.equals(Integer.class) || String.class.equals(Long.class) || String.class.equals(Float.class) || String.class.equals(Double.class) || String.class.equals(Boolean.class) || String.class.equals(String.class)) { + if (String.class.equals(Integer.class) + || String.class.equals(Long.class) + || String.class.equals(Float.class) + || String.class.equals(Double.class) + || String.class.equals(Boolean.class) + || String.class.equals(String.class)) { attemptParsing = typeCoercion; if (!attemptParsing) { - attemptParsing |= ((String.class.equals(Integer.class) || String.class.equals(Long.class)) && token == JsonToken.VALUE_NUMBER_INT); - attemptParsing |= ((String.class.equals(Float.class) || String.class.equals(Double.class)) && token == JsonToken.VALUE_NUMBER_FLOAT); - attemptParsing |= (String.class.equals(Boolean.class) && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE)); - attemptParsing |= (String.class.equals(String.class) && token == JsonToken.VALUE_STRING); + attemptParsing |= + ((String.class.equals(Integer.class) + || String.class.equals(Long.class)) + && token == JsonToken.VALUE_NUMBER_INT); + attemptParsing |= + ((String.class.equals(Float.class) + || String.class.equals(Double.class)) + && token == JsonToken.VALUE_NUMBER_FLOAT); + attemptParsing |= + (String.class.equals(Boolean.class) + && (token == JsonToken.VALUE_FALSE + || token == JsonToken.VALUE_TRUE)); + attemptParsing |= + (String.class.equals(String.class) + && token == JsonToken.VALUE_STRING); } } if (attemptParsing) { @@ -114,12 +114,14 @@ public AssertionRef deserialize(JsonParser jp, DeserializationContext ctxt) thro ret.setActualInstance(deserialized); return ret; } - throw new IOException(String.format("Failed deserialization for AssertionRef: %d classes match result, expected 1", match)); + throw new IOException( + String.format( + "Failed deserialization for AssertionRef: %d classes match result," + + " expected 1", + match)); } - /** - * Handle deserialization of the 'null' value. - */ + /** Handle deserialization of the 'null' value. */ @Override public AssertionRef getNullValue(DeserializationContext ctxt) throws JsonMappingException { throw new JsonMappingException(ctxt.getParser(), "AssertionRef cannot be null"); @@ -149,12 +151,11 @@ public Map> getSchemas() { } /** - * Set the instance that matches the oneOf child schema, check - * the instance parameter is valid against the oneOf child schemas: - * String + * Set the instance that matches the oneOf child schema, check the instance parameter is valid + * against the oneOf child schemas: String * - * It could be an instance of the 'oneOf' schemas. - * The oneOf child schemas may themselves be a composed schema (allOf, anyOf, oneOf). + *

It could be an instance of the 'oneOf' schemas. The oneOf child schemas may themselves be + * a composed schema (allOf, anyOf, oneOf). */ @Override public void setActualInstance(Object instance) { @@ -167,8 +168,7 @@ public void setActualInstance(Object instance) { } /** - * Get the actual instance, which can be the following: - * String + * Get the actual instance, which can be the following: String * * @return The actual instance (String) */ @@ -178,70 +178,90 @@ public Object getActualInstance() { } /** - * Get the actual instance of `String`. If the actual instance is not `String`, - * the ClassCastException will be thrown. + * Get the actual instance of `String`. If the actual instance is not `String`, the + * ClassCastException will be thrown. * * @return The actual instance of `String` * @throws ClassCastException if the instance is not `String` */ public String getString() throws ClassCastException { - return (String)super.getActualInstance(); + return (String) super.getActualInstance(); } - - - /** - * Convert the instance into URL query string. - * - * @return URL query string - */ - public String toUrlQueryString() { - return toUrlQueryString(null); - } - - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - String suffix = ""; - String containerSuffix = ""; - String containerPrefix = ""; - if (prefix == null) { - // style=form, explode=true, e.g. /pet?name=cat&type=manx - prefix = ""; - } else { - // deepObject style e.g. /pet?id[name]=cat&id[type]=manx - prefix = prefix + "["; - suffix = "]"; - containerSuffix = "]"; - containerPrefix = "["; + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); } - StringJoiner joiner = new StringJoiner("&"); + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } - if (getActualInstance() instanceof String) { - if (getActualInstance() != null) { - joiner.add(String.format("%sone_of_0%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getActualInstance()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + StringJoiner joiner = new StringJoiner("&"); + + if (getActualInstance() instanceof String) { + if (getActualInstance() != null) { + joiner.add( + String.format( + "%sone_of_0%s=%s", + prefix, + suffix, + URLEncoder.encode( + String.valueOf(getActualInstance()), + StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + return joiner.toString(); } - return joiner.toString(); - } - if (getActualInstance() instanceof String) { - if (getActualInstance() != null) { - joiner.add(String.format("%sone_of_1%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getActualInstance()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + if (getActualInstance() instanceof String) { + if (getActualInstance() != null) { + joiner.add( + String.format( + "%sone_of_1%s=%s", + prefix, + suffix, + URLEncoder.encode( + String.valueOf(getActualInstance()), + StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + return joiner.toString(); } - return joiner.toString(); - } - if (getActualInstance() instanceof String) { - if (getActualInstance() != null) { - joiner.add(String.format("%sone_of_2%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getActualInstance()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + if (getActualInstance() instanceof String) { + if (getActualInstance() != null) { + joiner.add( + String.format( + "%sone_of_2%s=%s", + prefix, + suffix, + URLEncoder.encode( + String.valueOf(getActualInstance()), + StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + return joiner.toString(); } - return joiner.toString(); + return null; } - return null; - } - } - diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionType.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionType.java index f881672c..72a92f33 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionType.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionType.java @@ -1,79 +1,52 @@ -/* - * Assertion Client - * Client used to get the assertion from the identity provider - * - * The version of the OpenAPI document: $npm_package_version - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.StringJoiner; -import java.util.Objects; -import java.util.Arrays; -import java.util.Map; -import java.util.HashMap; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; - - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; -/** - * Gets or Sets AssertionType - */ +/** Gets or Sets AssertionType */ public enum AssertionType { - - SAML("SAML"), - - OIDC("OIDC"); - - private String value; + SAML("SAML"), - AssertionType(String value) { - this.value = value; - } + OIDC("OIDC"); - @JsonValue - public String getValue() { - return value; - } + private String value; - @Override - public String toString() { - return String.valueOf(value); - } + AssertionType(String value) { + this.value = value; + } - @JsonCreator - public static AssertionType fromValue(String value) { - for (AssertionType b : AssertionType.values()) { - if (b.value.equals(value)) { - return b; - } + @JsonValue + public String getValue() { + return value; } - throw new IllegalArgumentException("Unexpected value '" + value + "'"); - } - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - if (prefix == null) { - prefix = ""; + @Override + public String toString() { + return String.valueOf(value); } - return String.format("%s=%s", prefix, this.toString()); - } + @JsonCreator + public static AssertionType fromValue(String value) { + for (AssertionType b : AssertionType.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + if (prefix == null) { + prefix = ""; + } + + return String.format("%s=%s", prefix, this.toString()); + } } - diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/LCUserInfo.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/LCUserInfo.java index 17f793dd..6986313e 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/LCUserInfo.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/LCUserInfo.java @@ -1,43 +1,6 @@ -/* - * Assertion Client - * Client used to get the assertion from the identity provider - * - * The version of the OpenAPI document: $npm_package_version - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.StringJoiner; -import java.util.Objects; -import java.util.Arrays; -import java.util.Map; -import java.util.HashMap; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonTypeName; -import com.fasterxml.jackson.annotation.JsonValue; -import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.OidcUserInfo; -import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.SamlUserInfo; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; - -import com.fasterxml.jackson.core.type.TypeReference; - -import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; - import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; @@ -52,8 +15,18 @@ import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.JSON; +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.StringJoiner; +import java.util.logging.Level; +import java.util.logging.Logger; -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") @JsonDeserialize(using = LCUserInfo.LCUserInfoDeserializer.class) @JsonSerialize(using = LCUserInfo.LCUserInfoSerializer.class) public class LCUserInfo extends AbstractOpenApiSchema { @@ -69,7 +42,8 @@ public LCUserInfoSerializer() { } @Override - public void serialize(LCUserInfo value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + public void serialize(LCUserInfo value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException { jgen.writeObject(value.getActualInstance()); } } @@ -84,7 +58,8 @@ public LCUserInfoDeserializer(Class vc) { } @Override - public LCUserInfo deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + public LCUserInfo deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException { JsonNode tree = jp.readValueAsTree(); Object deserialized = null; boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS); @@ -92,15 +67,15 @@ public LCUserInfo deserialize(JsonParser jp, DeserializationContext ctxt) throws JsonToken token = tree.traverse(jp.getCodec()).nextToken(); // deserialize OidcUserInfo try { - deserialized = tree.traverse(jp.getCodec()).readValueAs(OidcUserInfo.class); - // TODO: there is no validation against JSON schema constraints - // (min, max, enum, pattern...), this does not perform a strict JSON - // validation, which means the 'match' count may be higher than it should be. - if(((OidcUserInfo)deserialized).getIdToken() != null) { - match++; - - log.log(Level.FINER, "Input data matches schema 'OidcUserInfo'"); - } + deserialized = tree.traverse(jp.getCodec()).readValueAs(OidcUserInfo.class); + // TODO: there is no validation against JSON schema constraints + // (min, max, enum, pattern...), this does not perform a strict JSON + // validation, which means the 'match' count may be higher than it should be. + if (((OidcUserInfo) deserialized).getIdToken() != null) { + match++; + + log.log(Level.FINER, "Input data matches schema 'OidcUserInfo'"); + } } catch (Exception e) { // deserialization failed, continue log.log(Level.FINER, "Input data does not match schema 'OidcUserInfo'", e); @@ -108,14 +83,14 @@ public LCUserInfo deserialize(JsonParser jp, DeserializationContext ctxt) throws // deserialize SamlUserInfo try { - deserialized = tree.traverse(jp.getCodec()).readValueAs(SamlUserInfo.class); - // TODO: there is no validation against JSON schema constraints - // (min, max, enum, pattern...), this does not perform a strict JSON - // validation, which means the 'match' count may be higher than it should be. - if(((SamlUserInfo)deserialized).getResponseXml() != null) { - match++; - log.log(Level.FINER, "Input data matches schema 'SamlUserInfo'"); - } + deserialized = tree.traverse(jp.getCodec()).readValueAs(SamlUserInfo.class); + // TODO: there is no validation against JSON schema constraints + // (min, max, enum, pattern...), this does not perform a strict JSON + // validation, which means the 'match' count may be higher than it should be. + if (((SamlUserInfo) deserialized).getResponseXml() != null) { + match++; + log.log(Level.FINER, "Input data matches schema 'SamlUserInfo'"); + } } catch (Exception e) { // deserialization failed, continue log.log(Level.FINER, "Input data does not match schema 'SamlUserInfo'", e); @@ -126,12 +101,14 @@ public LCUserInfo deserialize(JsonParser jp, DeserializationContext ctxt) throws ret.setActualInstance(deserialized); return ret; } - throw new IOException(String.format("Failed deserialization for LCUserInfo: %d classes match result, expected 1", match)); + throw new IOException( + String.format( + "Failed deserialization for LCUserInfo: %d classes match result," + + " expected 1", + match)); } - /** - * Handle deserialization of the 'null' value. - */ + /** Handle deserialization of the 'null' value. */ @Override public LCUserInfo getNullValue(DeserializationContext ctxt) throws JsonMappingException { throw new JsonMappingException(ctxt.getParser(), "LCUserInfo cannot be null"); @@ -167,12 +144,11 @@ public Map> getSchemas() { } /** - * Set the instance that matches the oneOf child schema, check - * the instance parameter is valid against the oneOf child schemas: - * OidcUserInfo, SamlUserInfo + * Set the instance that matches the oneOf child schema, check the instance parameter is valid + * against the oneOf child schemas: OidcUserInfo, SamlUserInfo * - * It could be an instance of the 'oneOf' schemas. - * The oneOf child schemas may themselves be a composed schema (allOf, anyOf, oneOf). + *

It could be an instance of the 'oneOf' schemas. The oneOf child schemas may themselves be + * a composed schema (allOf, anyOf, oneOf). */ @Override public void setActualInstance(Object instance) { @@ -190,8 +166,7 @@ public void setActualInstance(Object instance) { } /** - * Get the actual instance, which can be the following: - * OidcUserInfo, SamlUserInfo + * Get the actual instance, which can be the following: OidcUserInfo, SamlUserInfo * * @return The actual instance (OidcUserInfo, SamlUserInfo) */ @@ -201,75 +176,75 @@ public Object getActualInstance() { } /** - * Get the actual instance of `OidcUserInfo`. If the actual instance is not `OidcUserInfo`, - * the ClassCastException will be thrown. + * Get the actual instance of `OidcUserInfo`. If the actual instance is not `OidcUserInfo`, the + * ClassCastException will be thrown. * * @return The actual instance of `OidcUserInfo` * @throws ClassCastException if the instance is not `OidcUserInfo` */ public OidcUserInfo getOidcUserInfo() throws ClassCastException { - return (OidcUserInfo)super.getActualInstance(); + return (OidcUserInfo) super.getActualInstance(); } /** - * Get the actual instance of `SamlUserInfo`. If the actual instance is not `SamlUserInfo`, - * the ClassCastException will be thrown. + * Get the actual instance of `SamlUserInfo`. If the actual instance is not `SamlUserInfo`, the + * ClassCastException will be thrown. * * @return The actual instance of `SamlUserInfo` * @throws ClassCastException if the instance is not `SamlUserInfo` */ public SamlUserInfo getSamlUserInfo() throws ClassCastException { - return (SamlUserInfo)super.getActualInstance(); + return (SamlUserInfo) super.getActualInstance(); } - - - /** - * Convert the instance into URL query string. - * - * @return URL query string - */ - public String toUrlQueryString() { - return toUrlQueryString(null); - } - - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - String suffix = ""; - String containerSuffix = ""; - String containerPrefix = ""; - if (prefix == null) { - // style=form, explode=true, e.g. /pet?name=cat&type=manx - prefix = ""; - } else { - // deepObject style e.g. /pet?id[name]=cat&id[type]=manx - prefix = prefix + "["; - suffix = "]"; - containerSuffix = "]"; - containerPrefix = "["; + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); } - StringJoiner joiner = new StringJoiner("&"); + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } - if (getActualInstance() instanceof SamlUserInfo) { - if (getActualInstance() != null) { - joiner.add(((SamlUserInfo)getActualInstance()).toUrlQueryString(prefix + "one_of_0" + suffix)); + StringJoiner joiner = new StringJoiner("&"); + + if (getActualInstance() instanceof SamlUserInfo) { + if (getActualInstance() != null) { + joiner.add( + ((SamlUserInfo) getActualInstance()) + .toUrlQueryString(prefix + "one_of_0" + suffix)); + } + return joiner.toString(); } - return joiner.toString(); - } - if (getActualInstance() instanceof OidcUserInfo) { - if (getActualInstance() != null) { - joiner.add(((OidcUserInfo)getActualInstance()).toUrlQueryString(prefix + "one_of_1" + suffix)); + if (getActualInstance() instanceof OidcUserInfo) { + if (getActualInstance() != null) { + joiner.add( + ((OidcUserInfo) getActualInstance()) + .toUrlQueryString(prefix + "one_of_1" + suffix)); + } + return joiner.toString(); } - return joiner.toString(); + return null; } - return null; - } - } - diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/OidcUserInfo.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/OidcUserInfo.java index 42c3fd86..872e4eb6 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/OidcUserInfo.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/OidcUserInfo.java @@ -1,186 +1,170 @@ -/* - * Assertion Client - * Client used to get the assertion from the identity provider - * - * The version of the OpenAPI document: $npm_package_version - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.StringJoiner; -import java.util.Objects; -import java.util.Arrays; -import java.util.Map; -import java.util.HashMap; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonTypeName; -import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import java.util.StringJoiner; - -/** - * OidcUserInfo - */ -@JsonPropertyOrder({ - OidcUserInfo.JSON_PROPERTY_ID_TOKEN, - OidcUserInfo.JSON_PROPERTY_CLAIMS_TOKEN -}) -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +/** OidcUserInfo */ +@JsonPropertyOrder({OidcUserInfo.JSON_PROPERTY_ID_TOKEN, OidcUserInfo.JSON_PROPERTY_CLAIMS_TOKEN}) +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") public class OidcUserInfo { - public static final String JSON_PROPERTY_ID_TOKEN = "id_token"; - private String idToken; - - public static final String JSON_PROPERTY_CLAIMS_TOKEN = "claims_token"; - private String claimsToken; - - public OidcUserInfo() { - } - - public OidcUserInfo idToken(String idToken) { - this.idToken = idToken; - return this; - } - - /** - * A JWT representation of a signed SPID/CIE OIDC Idp - * @return idToken - **/ - @javax.annotation.Nonnull - @JsonProperty(JSON_PROPERTY_ID_TOKEN) - @JsonInclude(value = JsonInclude.Include.ALWAYS) - - public String getIdToken() { - return idToken; - } - - - @JsonProperty(JSON_PROPERTY_ID_TOKEN) - @JsonInclude(value = JsonInclude.Include.ALWAYS) - public void setIdToken(String idToken) { - this.idToken = idToken; - } - - - public OidcUserInfo claimsToken(String claimsToken) { - this.claimsToken = claimsToken; - return this; - } - - /** - * A JWT representation of a signed SPID/CIE OIDC Idp - * @return claimsToken - **/ - @javax.annotation.Nonnull - @JsonProperty(JSON_PROPERTY_CLAIMS_TOKEN) - @JsonInclude(value = JsonInclude.Include.ALWAYS) - - public String getClaimsToken() { - return claimsToken; - } - - - @JsonProperty(JSON_PROPERTY_CLAIMS_TOKEN) - @JsonInclude(value = JsonInclude.Include.ALWAYS) - public void setClaimsToken(String claimsToken) { - this.claimsToken = claimsToken; - } - - - /** - * Return true if this OidcUserInfo object is equal to o. - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public static final String JSON_PROPERTY_ID_TOKEN = "id_token"; + private String idToken; + + public static final String JSON_PROPERTY_CLAIMS_TOKEN = "claims_token"; + private String claimsToken; + + public OidcUserInfo() {} + + public OidcUserInfo idToken(String idToken) { + this.idToken = idToken; + return this; } - if (o == null || getClass() != o.getClass()) { - return false; + + /** + * A JWT representation of a signed SPID/CIE OIDC Idp + * + * @return idToken + */ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_ID_TOKEN) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getIdToken() { + return idToken; } - OidcUserInfo oidcUserInfo = (OidcUserInfo) o; - return Objects.equals(this.idToken, oidcUserInfo.idToken) && - Objects.equals(this.claimsToken, oidcUserInfo.claimsToken); - } - - @Override - public int hashCode() { - return Objects.hash(idToken, claimsToken); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class OidcUserInfo {\n"); - sb.append(" idToken: ").append(toIndentedString(idToken)).append("\n"); - sb.append(" claimsToken: ").append(toIndentedString(claimsToken)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; + + @JsonProperty(JSON_PROPERTY_ID_TOKEN) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setIdToken(String idToken) { + this.idToken = idToken; } - return o.toString().replace("\n", "\n "); - } - - /** - * Convert the instance into URL query string. - * - * @return URL query string - */ - public String toUrlQueryString() { - return toUrlQueryString(null); - } - - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - String suffix = ""; - String containerSuffix = ""; - String containerPrefix = ""; - if (prefix == null) { - // style=form, explode=true, e.g. /pet?name=cat&type=manx - prefix = ""; - } else { - // deepObject style e.g. /pet?id[name]=cat&id[type]=manx - prefix = prefix + "["; - suffix = "]"; - containerSuffix = "]"; - containerPrefix = "["; + + public OidcUserInfo claimsToken(String claimsToken) { + this.claimsToken = claimsToken; + return this; } - StringJoiner joiner = new StringJoiner("&"); + /** + * A JWT representation of a signed SPID/CIE OIDC Idp + * + * @return claimsToken + */ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_CLAIMS_TOKEN) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getClaimsToken() { + return claimsToken; + } - // add `id_token` to the URL query string - if (getIdToken() != null) { - joiner.add(String.format("%sid_token%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getIdToken()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + @JsonProperty(JSON_PROPERTY_CLAIMS_TOKEN) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setClaimsToken(String claimsToken) { + this.claimsToken = claimsToken; } - // add `claims_token` to the URL query string - if (getClaimsToken() != null) { - joiner.add(String.format("%sclaims_token%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getClaimsToken()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + /** Return true if this OidcUserInfo object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OidcUserInfo oidcUserInfo = (OidcUserInfo) o; + return Objects.equals(this.idToken, oidcUserInfo.idToken) + && Objects.equals(this.claimsToken, oidcUserInfo.claimsToken); } - return joiner.toString(); - } -} + @Override + public int hashCode() { + return Objects.hash(idToken, claimsToken); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class OidcUserInfo {\n"); + sb.append(" idToken: ").append(toIndentedString(idToken)).append("\n"); + sb.append(" claimsToken: ").append(toIndentedString(claimsToken)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first + * line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `id_token` to the URL query string + if (getIdToken() != null) { + joiner.add( + String.format( + "%sid_token%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getIdToken()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `claims_token` to the URL query string + if (getClaimsToken() != null) { + joiner.add( + String.format( + "%sclaims_token%s=%s", + prefix, + suffix, + URLEncoder.encode( + String.valueOf(getClaimsToken()), + StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/ProblemJson.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/ProblemJson.java index 2ad7c4d7..91b8588a 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/ProblemJson.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/ProblemJson.java @@ -1,297 +1,291 @@ -/* - * Assertion Client - * Client used to get the assertion from the identity provider - * - * The version of the OpenAPI document: $npm_package_version - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.StringJoiner; -import java.util.Objects; -import java.util.Arrays; -import java.util.Map; -import java.util.HashMap; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonTypeName; -import com.fasterxml.jackson.annotation.JsonValue; -import java.net.URI; import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.net.URI; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import java.util.StringJoiner; - -/** - * ProblemJson - */ +/** ProblemJson */ @JsonPropertyOrder({ - ProblemJson.JSON_PROPERTY_TYPE, - ProblemJson.JSON_PROPERTY_TITLE, - ProblemJson.JSON_PROPERTY_STATUS, - ProblemJson.JSON_PROPERTY_DETAIL, - ProblemJson.JSON_PROPERTY_INSTANCE + ProblemJson.JSON_PROPERTY_TYPE, + ProblemJson.JSON_PROPERTY_TITLE, + ProblemJson.JSON_PROPERTY_STATUS, + ProblemJson.JSON_PROPERTY_DETAIL, + ProblemJson.JSON_PROPERTY_INSTANCE }) -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") public class ProblemJson { - public static final String JSON_PROPERTY_TYPE = "type"; - private URI type = URI.create("about:blank"); + public static final String JSON_PROPERTY_TYPE = "type"; + private URI type = URI.create("about:blank"); + + public static final String JSON_PROPERTY_TITLE = "title"; + private String title; + + public static final String JSON_PROPERTY_STATUS = "status"; + private Integer status; + + public static final String JSON_PROPERTY_DETAIL = "detail"; + private String detail; - public static final String JSON_PROPERTY_TITLE = "title"; - private String title; - - public static final String JSON_PROPERTY_STATUS = "status"; - private Integer status; - - public static final String JSON_PROPERTY_DETAIL = "detail"; - private String detail; - - public static final String JSON_PROPERTY_INSTANCE = "instance"; - private URI instance; + public static final String JSON_PROPERTY_INSTANCE = "instance"; + private URI instance; - public ProblemJson() { - } - - public ProblemJson type(URI type) { - this.type = type; - return this; - } + public ProblemJson() {} - /** - * An absolute URI that identifies the problem type. When dereferenced, it SHOULD provide human-readable documentation for the problem type (e.g., using HTML). - * @return type - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_TYPE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public URI getType() { - return type; - } - - - @JsonProperty(JSON_PROPERTY_TYPE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setType(URI type) { - this.type = type; - } - - - public ProblemJson title(String title) { - this.title = title; - return this; - } - - /** - * A short, summary of the problem type. Written in english and readable for engineers (usually not suited for non technical stakeholders and not localized); example: Service Unavailable - * @return title - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_TITLE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public String getTitle() { - return title; - } - - - @JsonProperty(JSON_PROPERTY_TITLE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setTitle(String title) { - this.title = title; - } - - - public ProblemJson status(Integer status) { - this.status = status; - return this; - } - - /** - * The HTTP status code generated by the origin server for this occurrence of the problem. - * minimum: 100 - * maximum: 600 - * @return status - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_STATUS) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public Integer getStatus() { - return status; - } - - - @JsonProperty(JSON_PROPERTY_STATUS) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setStatus(Integer status) { - this.status = status; - } - - - public ProblemJson detail(String detail) { - this.detail = detail; - return this; - } - - /** - * A human readable explanation specific to this occurrence of the problem. - * @return detail - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_DETAIL) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public String getDetail() { - return detail; - } - - - @JsonProperty(JSON_PROPERTY_DETAIL) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setDetail(String detail) { - this.detail = detail; - } - - - public ProblemJson instance(URI instance) { - this.instance = instance; - return this; - } - - /** - * An absolute URI that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced. - * @return instance - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_INSTANCE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public URI getInstance() { - return instance; - } - - - @JsonProperty(JSON_PROPERTY_INSTANCE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setInstance(URI instance) { - this.instance = instance; - } - - - /** - * Return true if this ProblemJson object is equal to o. - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public ProblemJson type(URI type) { + this.type = type; + return this; } - if (o == null || getClass() != o.getClass()) { - return false; + + /** + * An absolute URI that identifies the problem type. When dereferenced, it SHOULD provide + * human-readable documentation for the problem type (e.g., using HTML). + * + * @return type + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public URI getType() { + return type; } - ProblemJson problemJson = (ProblemJson) o; - return Objects.equals(this.type, problemJson.type) && - Objects.equals(this.title, problemJson.title) && - Objects.equals(this.status, problemJson.status) && - Objects.equals(this.detail, problemJson.detail) && - Objects.equals(this.instance, problemJson.instance); - } - - @Override - public int hashCode() { - return Objects.hash(type, title, status, detail, instance); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class ProblemJson {\n"); - sb.append(" type: ").append(toIndentedString(type)).append("\n"); - sb.append(" title: ").append(toIndentedString(title)).append("\n"); - sb.append(" status: ").append(toIndentedString(status)).append("\n"); - sb.append(" detail: ").append(toIndentedString(detail)).append("\n"); - sb.append(" instance: ").append(toIndentedString(instance)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; + + @JsonProperty(JSON_PROPERTY_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setType(URI type) { + this.type = type; } - return o.toString().replace("\n", "\n "); - } - - /** - * Convert the instance into URL query string. - * - * @return URL query string - */ - public String toUrlQueryString() { - return toUrlQueryString(null); - } - - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - String suffix = ""; - String containerSuffix = ""; - String containerPrefix = ""; - if (prefix == null) { - // style=form, explode=true, e.g. /pet?name=cat&type=manx - prefix = ""; - } else { - // deepObject style e.g. /pet?id[name]=cat&id[type]=manx - prefix = prefix + "["; - suffix = "]"; - containerSuffix = "]"; - containerPrefix = "["; + + public ProblemJson title(String title) { + this.title = title; + return this; } - StringJoiner joiner = new StringJoiner("&"); + /** + * A short, summary of the problem type. Written in english and readable for engineers (usually + * not suited for non technical stakeholders and not localized); example: Service Unavailable + * + * @return title + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_TITLE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public String getTitle() { + return title; + } - // add `type` to the URL query string - if (getType() != null) { - joiner.add(String.format("%stype%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getType()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + @JsonProperty(JSON_PROPERTY_TITLE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setTitle(String title) { + this.title = title; } - // add `title` to the URL query string - if (getTitle() != null) { - joiner.add(String.format("%stitle%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getTitle()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + public ProblemJson status(Integer status) { + this.status = status; + return this; } - // add `status` to the URL query string - if (getStatus() != null) { - joiner.add(String.format("%sstatus%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getStatus()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + /** + * The HTTP status code generated by the origin server for this occurrence of the problem. + * minimum: 100 maximum: 600 + * + * @return status + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public Integer getStatus() { + return status; } - // add `detail` to the URL query string - if (getDetail() != null) { - joiner.add(String.format("%sdetail%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getDetail()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + @JsonProperty(JSON_PROPERTY_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setStatus(Integer status) { + this.status = status; } - // add `instance` to the URL query string - if (getInstance() != null) { - joiner.add(String.format("%sinstance%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getInstance()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + public ProblemJson detail(String detail) { + this.detail = detail; + return this; } - return joiner.toString(); - } -} + /** + * A human readable explanation specific to this occurrence of the problem. + * + * @return detail + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_DETAIL) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public String getDetail() { + return detail; + } + + @JsonProperty(JSON_PROPERTY_DETAIL) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setDetail(String detail) { + this.detail = detail; + } + + public ProblemJson instance(URI instance) { + this.instance = instance; + return this; + } + + /** + * An absolute URI that identifies the specific occurrence of the problem. It may or may not + * yield further information if dereferenced. + * + * @return instance + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_INSTANCE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public URI getInstance() { + return instance; + } + + @JsonProperty(JSON_PROPERTY_INSTANCE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setInstance(URI instance) { + this.instance = instance; + } + + /** Return true if this ProblemJson object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProblemJson problemJson = (ProblemJson) o; + return Objects.equals(this.type, problemJson.type) + && Objects.equals(this.title, problemJson.title) + && Objects.equals(this.status, problemJson.status) + && Objects.equals(this.detail, problemJson.detail) + && Objects.equals(this.instance, problemJson.instance); + } + @Override + public int hashCode() { + return Objects.hash(type, title, status, detail, instance); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ProblemJson {\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append(" title: ").append(toIndentedString(title)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" detail: ").append(toIndentedString(detail)).append("\n"); + sb.append(" instance: ").append(toIndentedString(instance)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first + * line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `type` to the URL query string + if (getType() != null) { + joiner.add( + String.format( + "%stype%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getType()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `title` to the URL query string + if (getTitle() != null) { + joiner.add( + String.format( + "%stitle%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getTitle()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `status` to the URL query string + if (getStatus() != null) { + joiner.add( + String.format( + "%sstatus%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getStatus()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `detail` to the URL query string + if (getDetail() != null) { + joiner.add( + String.format( + "%sdetail%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getDetail()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `instance` to the URL query string + if (getInstance() != null) { + joiner.add( + String.format( + "%sinstance%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getInstance()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/SamlUserInfo.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/SamlUserInfo.java index 6191fe2f..a751ce96 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/SamlUserInfo.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/SamlUserInfo.java @@ -1,150 +1,131 @@ -/* - * Assertion Client - * Client used to get the assertion from the identity provider - * - * The version of the OpenAPI document: $npm_package_version - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.StringJoiner; -import java.util.Objects; -import java.util.Arrays; -import java.util.Map; -import java.util.HashMap; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonTypeName; -import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import java.util.StringJoiner; - -/** - * SamlUserInfo - */ -@JsonPropertyOrder({ - SamlUserInfo.JSON_PROPERTY_RESPONSE_XML -}) -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") +/** SamlUserInfo */ +@JsonPropertyOrder({SamlUserInfo.JSON_PROPERTY_RESPONSE_XML}) +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") public class SamlUserInfo { - public static final String JSON_PROPERTY_RESPONSE_XML = "response_xml"; - private String responseXml; - - public SamlUserInfo() { - } + public static final String JSON_PROPERTY_RESPONSE_XML = "response_xml"; + private String responseXml; - public SamlUserInfo responseXml(String responseXml) { - this.responseXml = responseXml; - return this; - } + public SamlUserInfo() {} - /** - * A string representation of a signed SPID/CIE response - * @return responseXml - **/ - @javax.annotation.Nonnull - @JsonProperty(JSON_PROPERTY_RESPONSE_XML) - @JsonInclude(value = JsonInclude.Include.ALWAYS) - - public String getResponseXml() { - return responseXml; - } - - - @JsonProperty(JSON_PROPERTY_RESPONSE_XML) - @JsonInclude(value = JsonInclude.Include.ALWAYS) - public void setResponseXml(String responseXml) { - this.responseXml = responseXml; - } - - - /** - * Return true if this SamlUserInfo object is equal to o. - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; + public SamlUserInfo responseXml(String responseXml) { + this.responseXml = responseXml; + return this; } - SamlUserInfo samlUserInfo = (SamlUserInfo) o; - return Objects.equals(this.responseXml, samlUserInfo.responseXml); - } - @Override - public int hashCode() { - return Objects.hash(responseXml); - } + /** + * A string representation of a signed SPID/CIE response + * + * @return responseXml + */ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_RESPONSE_XML) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getResponseXml() { + return responseXml; + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class SamlUserInfo {\n"); - sb.append(" responseXml: ").append(toIndentedString(responseXml)).append("\n"); - sb.append("}"); - return sb.toString(); - } + @JsonProperty(JSON_PROPERTY_RESPONSE_XML) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setResponseXml(String responseXml) { + this.responseXml = responseXml; + } - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; + /** Return true if this SamlUserInfo object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SamlUserInfo samlUserInfo = (SamlUserInfo) o; + return Objects.equals(this.responseXml, samlUserInfo.responseXml); } - return o.toString().replace("\n", "\n "); - } - /** - * Convert the instance into URL query string. - * - * @return URL query string - */ - public String toUrlQueryString() { - return toUrlQueryString(null); - } + @Override + public int hashCode() { + return Objects.hash(responseXml); + } - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - String suffix = ""; - String containerSuffix = ""; - String containerPrefix = ""; - if (prefix == null) { - // style=form, explode=true, e.g. /pet?name=cat&type=manx - prefix = ""; - } else { - // deepObject style e.g. /pet?id[name]=cat&id[type]=manx - prefix = prefix + "["; - suffix = "]"; - containerSuffix = "]"; - containerPrefix = "["; + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class SamlUserInfo {\n"); + sb.append(" responseXml: ").append(toIndentedString(responseXml)).append("\n"); + sb.append("}"); + return sb.toString(); } - StringJoiner joiner = new StringJoiner("&"); + /** + * Convert the given object to string with each line indented by 4 spaces (except the first + * line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } - // add `response_xml` to the URL query string - if (getResponseXml() != null) { - joiner.add(String.format("%sresponse_xml%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getResponseXml()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); } - return joiner.toString(); - } + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `response_xml` to the URL query string + if (getResponseXml() != null) { + joiner.add( + String.format( + "%sresponse_xml%s=%s", + prefix, + suffix, + URLEncoder.encode( + String.valueOf(getResponseXml()), + StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } } - diff --git a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java index b34cb029..291f0516 100644 --- a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java +++ b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java @@ -1,5 +1,10 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple; +import static org.mockserver.integration.ClientAndServer.startClientAndServer; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; @@ -11,17 +16,138 @@ import org.mockserver.integration.ClientAndServer; import org.mockserver.model.Header; -import static org.mockserver.integration.ClientAndServer.startClientAndServer; -import static org.mockserver.model.HttpRequest.request; -import static org.mockserver.model.HttpResponse.response; - class AssertionSimpleClientTest { private static AssertionSimpleClient assertionSimpleClient; private static ClientAndServer mockServer; - private static final String RESPONSE_STRING = "{\"response_xml\": \" https://posteid.poste.it IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU= GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9 HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4 fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1 MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0 uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc= https://posteid.poste.it ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I= O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4 xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4 fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1 MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0 uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc= SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd https://app-backend.io.italia.it https://www.spid.gov.it/SpidL2 TINIT-AAAAAA89S20I111X \"}"; - private static final String ASSERTION_REF = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; - private static final String WRONG_ASSERTION_REF = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfXXXXX"; + private static final String RESPONSE_STRING = + "{\"response_xml\": \" " + + " https://posteid.poste.it" + + " " + + " " + + " " + + " " + + " " + + " " + + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" + + " " + + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" + + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" + + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" + + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" + + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " " + + " " + + " " + + " https://posteid.poste.it " + + " " + + " " + + " " + + " " + + " " + + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" + + " " + + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" + + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" + + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" + + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" + + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + " " + + " " + + " " + + " https://app-backend.io.italia.it" + + " " + + " https://www.spid.gov.it/SpidL2" + + " " + + " " + + " TINIT-AAAAAA89S20I111X" + + " " + + " \"}"; + private static final String ASSERTION_REF = + "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; + private static final String WRONG_ASSERTION_REF = + "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfXXXXX"; private static final String JWT = "Bearer aValidJWT"; @BeforeAll @@ -35,7 +161,130 @@ public static void startServer() { @Test void samlAssertionFound() throws LollipopAssertionNotFoundException { // setup - String xmlResponse = " https://posteid.poste.it IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU= GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9 HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4 fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1 MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0 uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc= https://posteid.poste.it ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I= O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4 xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4 fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1 MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0 uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc= SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd https://app-backend.io.italia.it https://www.spid.gov.it/SpidL2 TINIT-AAAAAA89S20I111X "; + String xmlResponse = + " https://posteid.poste.it" + + " " + + " " + + " " + + " " + + " " + + " " + + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" + + " " + + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" + + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" + + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" + + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" + + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " + + " " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " " + + " " + + " https://posteid.poste.it " + + " " + + " " + + " " + + " " + + " " + + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" + + " " + + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" + + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" + + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" + + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" + + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " + + " " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + " " + + " " + + " " + + " https://app-backend.io.italia.it" + + " " + + " https://www.spid.gov.it/SpidL2" + + " " + + " " + + " TINIT-AAAAAA89S20I111X" + + " " + + " "; createExpectationAssertionFound(); SamlAssertion response = assertionSimpleClient.getAssertion(JWT, ASSERTION_REF); @@ -50,7 +299,9 @@ void samlAssertionFound() throws LollipopAssertionNotFoundException { void assertionNotFound() { createExpectationAssertionNotFound(); // setup - Assertions.assertThrows(LollipopAssertionNotFoundException.class, () -> assertionSimpleClient.getAssertion(JWT, WRONG_ASSERTION_REF)); + Assertions.assertThrows( + LollipopAssertionNotFoundException.class, + () -> assertionSimpleClient.getAssertion(JWT, WRONG_ASSERTION_REF)); } @Test @@ -59,7 +310,9 @@ void noJwt() { String assertionRef = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; String jwt = ""; - Assertions.assertThrows(IllegalArgumentException.class, () -> assertionSimpleClient.getAssertion(jwt, assertionRef)); + Assertions.assertThrows( + IllegalArgumentException.class, + () -> assertionSimpleClient.getAssertion(jwt, assertionRef)); } @Test @@ -68,7 +321,9 @@ void noAssertionRef() { String assertionRef = ""; String jwt = "Bearer aValidJWT"; - Assertions.assertThrows(IllegalArgumentException.class, () -> assertionSimpleClient.getAssertion(jwt, assertionRef)); + Assertions.assertThrows( + IllegalArgumentException.class, + () -> assertionSimpleClient.getAssertion(jwt, assertionRef)); } private void createExpectationAssertionFound() { @@ -80,14 +335,8 @@ private void createExpectationAssertionFound() { .withPathParameter("assertion", ASSERTION_REF) .withHeaders( new Header("Accept", "application/json"), - new Header("x-pagopa-lollipop-auth", JWT) - ) - ) - .respond( - response() - .withStatusCode(200) - .withBody(RESPONSE_STRING) - ); + new Header("x-pagopa-lollipop-auth", JWT))) + .respond(response().withStatusCode(200).withBody(RESPONSE_STRING)); } private void createExpectationAssertionNotFound() { @@ -99,19 +348,12 @@ private void createExpectationAssertionNotFound() { .withPathParameter("assertion", WRONG_ASSERTION_REF) .withHeaders( new Header("Accept", "application/json"), - new Header("x-pagopa-lollipop-auth", JWT) - ) - ) - .respond( - response() - .withStatusCode(404) - .withBody("{}") - ); + new Header("x-pagopa-lollipop-auth", JWT))) + .respond(response().withStatusCode(404).withBody("{}")); } @AfterAll public static void stopServer() { mockServer.stop(); } - -} \ No newline at end of file +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClient.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClient.java index 8c54200f..acf09626 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClient.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/AssertionClient.java @@ -6,5 +6,6 @@ public interface AssertionClient { - SamlAssertion getAssertion(String jwt, String assertionRef) throws LollipopAssertionNotFoundException; + SamlAssertion getAssertion(String jwt, String assertionRef) + throws LollipopAssertionNotFoundException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopAssertionNotFoundException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopAssertionNotFoundException.java index 30be9288..7fe6f67f 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopAssertionNotFoundException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopAssertionNotFoundException.java @@ -1,20 +1,16 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.exception; -import java.util.Objects; - -/** - * Thrown in case of problems retrieving assertion - */ +/** Thrown in case of problems retrieving assertion */ public class LollipopAssertionNotFoundException extends Exception { /** * Constructs new exception with provided message and cause * - * @param message Detail message - * @param cause Exception causing the constructed one + * @param message Detail message + * @param cause Exception causing the constructed one */ public LollipopAssertionNotFoundException(String message, Throwable cause) { - super(message, cause); + super(message, cause); } - } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 6b3e07c3..6c75bfc6 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -11,112 +11,462 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -125,6 +475,12 @@ + + + + + + @@ -145,9 +501,11 @@ + + @@ -159,8 +517,19 @@ + + + + + + + + + + + @@ -169,311 +538,1312 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -484,93 +1854,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -579,337 +2021,600 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 36265b182d91095cf9a69afdb5a4bbe24802329f Mon Sep 17 00:00:00 2001 From: gquadrati Date: Wed, 5 Apr 2023 19:14:09 +0200 Subject: [PATCH 042/403] update verification-metadata.xml --- build.gradle | 2 +- .../HttpMessageVerifierFactory.java | 4 +- .../impl/HttpMessageVerifierServiceImpl.java | 4 +- gradle/verification-metadata.xml | 122 ++++++++++++++++++ 4 files changed, 129 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 626781fa..16e65d8c 100644 --- a/build.gradle +++ b/build.gradle @@ -37,7 +37,7 @@ allprojects { // don't need to set target, it is inferred from java // apply a specific flavor of google-java-format - googleJavaFormat('1.11.0').aosp().reflowLongStrings() + googleJavaFormat('1.15.0').aosp().reflowLongStrings() // fix formatting of type annotations formatAnnotations() // make sure every file has the following copyright header. diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java index ec1de3f7..571555fd 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifierFactory.java @@ -4,6 +4,8 @@ /** Interface for the factory used to create instances of {@link HttpMessageVerifier} */ public interface HttpMessageVerifierFactory { - /** @return instance of HttpMessageVerifier */ + /** + * @return instance of HttpMessageVerifier + */ HttpMessageVerifier create(); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java index d3b2eba2..410bfaa6 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java @@ -27,7 +27,9 @@ public HttpMessageVerifierServiceImpl( this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; } - /** @see HttpMessageVerifierService#verifyHttpMessage(LollipopConsumerRequest) */ + /** + * @see HttpMessageVerifierService#verifyHttpMessage(LollipopConsumerRequest) + */ @Override public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest) throws LollipopDigestException, UnsupportedEncodingException, diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 6c75bfc6..3fb50f0b 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -475,6 +475,14 @@ + + + + + + + + @@ -486,6 +494,11 @@ + + + + + @@ -494,11 +507,24 @@ + + + + + + + + + + + + + @@ -517,6 +543,14 @@ + + + + + + + + @@ -538,6 +572,11 @@ + + + + + @@ -1839,6 +1878,9 @@ + + + @@ -2087,6 +2129,14 @@ + + + + + + + + @@ -2097,6 +2147,14 @@ + + + + + + + + @@ -2107,6 +2165,14 @@ + + + + + + + + @@ -2117,6 +2183,14 @@ + + + + + + + + @@ -2149,12 +2223,18 @@ + + + + + + @@ -2185,6 +2265,9 @@ + + + @@ -2205,6 +2288,9 @@ + + + @@ -2225,6 +2311,9 @@ + + + @@ -2245,6 +2334,9 @@ + + + @@ -2265,6 +2357,9 @@ + + + @@ -2280,6 +2375,14 @@ + + + + + + + + @@ -2295,6 +2398,9 @@ + + + @@ -2310,6 +2416,14 @@ + + + + + + + + @@ -2320,6 +2434,14 @@ + + + + + + + + From 7595659ded8f9e93524e04da17406d92dd7c8427 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 5 Apr 2023 19:23:23 +0200 Subject: [PATCH 043/403] [core_sprint_1_fix] Updated gradle wrapper --- gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59821 bytes gradle/wrapper/gradle-wrapper.properties | 5 +++++ 2 files changed, 5 insertions(+) create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..41d9927a4d4fb3f96a785543079b8df6723c946b GIT binary patch literal 59821 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 literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..41dfb879 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists From 333716dd580cafa5e3f317eef176e2540b1e83db Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 6 Apr 2023 10:04:52 +0200 Subject: [PATCH 044/403] [core-spring-1-sample] create sample LollipopConsumer application. --- .../helper/LollipopConsumerFactoryHelper.java | 10 ++-- ... => AssertionVerifierServiceImplStub.java} | 6 +-- gradle/verification-metadata.xml | 45 ++++++++++++++++ sample/build.gradle | 36 +++++++++++++ sample/settings.gradle | 9 ++++ .../tech/sample/LollipopConsumerSample.java | 54 +++++++++++++++++++ 6 files changed, 152 insertions(+), 8 deletions(-) rename core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/{AssertionVerifierServiceImpl.java => AssertionVerifierServiceImplStub.java} (91%) create mode 100644 sample/build.gradle create mode 100644 sample/settings.gradle create mode 100644 sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index d9be8966..04f28480 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -7,7 +7,7 @@ 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.impl.AssertionVerifierServiceImpl; +import it.pagopa.tech.lollipop.consumer.service.impl.AssertionVerifierServiceImplStub; import it.pagopa.tech.lollipop.consumer.service.impl.HttpMessageVerifierServiceImpl; import javax.inject.Inject; @@ -44,20 +44,20 @@ public HttpMessageVerifierService getHttpMessageVerifierService() { * @return an instance of {@link AssertionVerifierService} */ public AssertionVerifierService getAssertionVerifierService() { - return new AssertionVerifierServiceImpl( + return new AssertionVerifierServiceImplStub( getIdpCertProviderFactory().create(), getAssertionServiceFactory().create()); } public HttpMessageVerifierFactory getHttpMessageVerifierFactory() { - return null; + return httpMessageVerifierFactory; } public IdpCertProviderFactory getIdpCertProviderFactory() { - return null; + return idpCertProviderFactory; } public AssertionServiceFactory getAssertionServiceFactory() { - return null; + return assertionServiceFactory; } public LollipopConsumerRequestConfig getLollipopConsumerRequestConfig() { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java similarity index 91% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java index 9c8243f8..f7c91447 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java @@ -9,13 +9,13 @@ import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; import javax.inject.Inject; -public class AssertionVerifierServiceImpl implements AssertionVerifierService { +public class AssertionVerifierServiceImplStub implements AssertionVerifierService { private IdpCertProvider idpCertProvider; private AssertionService assertionService; @Inject - public AssertionVerifierServiceImpl( + public AssertionVerifierServiceImplStub( IdpCertProvider idpCertProvider, AssertionService assertionService) { this.idpCertProvider = idpCertProvider; this.assertionService = assertionService; @@ -23,7 +23,7 @@ public AssertionVerifierServiceImpl( @Override public boolean validateLollipop(LollipopConsumerRequest request) { - return false; + return true; } private SamlAssertion getAssertion(String jwt, String assertionRef) { diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 6b3e07c3..ff53ab00 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -452,6 +452,9 @@ + + + @@ -668,6 +671,9 @@ + + + @@ -684,6 +690,9 @@ + + + @@ -700,6 +709,9 @@ + + + @@ -716,6 +728,9 @@ + + + @@ -732,6 +747,9 @@ + + + @@ -744,6 +762,14 @@ + + + + + + + + @@ -756,6 +782,9 @@ + + + @@ -768,6 +797,14 @@ + + + + + + + + @@ -776,6 +813,14 @@ + + + + + + + + diff --git a/sample/build.gradle b/sample/build.gradle new file mode 100644 index 00000000..9bf6b880 --- /dev/null +++ b/sample/build.gradle @@ -0,0 +1,36 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Java library project to get you started. + * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle + * User Manual available at https://docs.gradle.org/8.0.2/userguide/building_java_projects.html + */ + + +plugins { + // Apply the java-library plugin for API and implementation separation. + id 'application' +} + +application { + mainClassName = "it.pagopa.tech.sample.LollipopConsumerSample" +} + +group 'it.pagopa.tech' + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + implementation 'it.pagopa.tech:core:1.0.0-SNAPSHOT' + implementation 'it.pagopa.tech:http-verifier:1.0.0-SNAPSHOT' + // Use JUnit Jupiter for testing. + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' +} + +tasks.named('test') { + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} diff --git a/sample/settings.gradle b/sample/settings.gradle new file mode 100644 index 00000000..763affdd --- /dev/null +++ b/sample/settings.gradle @@ -0,0 +1,9 @@ +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } +} + + +rootProject.name = 'sample' \ No newline at end of file diff --git a/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java b/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java new file mode 100644 index 00000000..95b70da5 --- /dev/null +++ b/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java @@ -0,0 +1,54 @@ +package it.pagopa.tech.sample; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; +import it.pagopa.tech.lollipop.consumer.assertion.impl.AssertionServiceFactoryImplStub; +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; +import it.pagopa.tech.lollipop.consumer.command.impl.LollipopConsumerCommandBuilderImpl; +import it.pagopa.tech.lollipop.consumer.helper.LollipopConsumerFactoryHelper; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.http_verifier.visma.VismaHttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImplStub; +import it.pagopa.tech.lollipop.consumer.model.CommandResult; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; + +import java.util.HashMap; + +public class LollipopConsumerSample { + + private static final String ENCODING = "UTF-8"; + + public static void main(String[] args) throws Exception { + LollipopConsumerCommandBuilder commandBuilder = new LollipopConsumerCommandBuilderImpl(buildLollipopConsumerFactoryHelper()); + LollipopConsumerCommand command = commandBuilder.createCommand(); + CommandResult commandResult = command.doExecute(buildLollipopRequest()); + System.out.println("Validation ended with status code " + commandResult.getResultCode() + " and message " + commandResult.getResultMessage()); + } + + private static LollipopConsumerFactoryHelper buildLollipopConsumerFactoryHelper() throws Exception { + HttpMessageVerifierFactory messageVerifierFactory = new VismaHttpMessageVerifierFactory(ENCODING); + IdpCertProviderFactory idpCertProviderFactory = new IdpCertProviderFactoryImplStub(); + AssertionServiceFactory assertionServiceFactory = new AssertionServiceFactoryImplStub(); + return new LollipopConsumerFactoryHelper(messageVerifierFactory, idpCertProviderFactory, assertionServiceFactory); + } + + private static LollipopConsumerRequest buildLollipopRequest() { + HashMap lollipopHeaderParams = new HashMap<>(); + lollipopHeaderParams.put("content-digest", "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"); + lollipopHeaderParams.put("content-encoding", ENCODING); + lollipopHeaderParams.put( + "signature-input", + "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" " + + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" + + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); + lollipopHeaderParams.put( + "signature", + "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"); + + return LollipopConsumerRequest.builder() + .requestBody("{\"message\":\"a valid message payload\"}") + .headerParams(lollipopHeaderParams) + .build(); + } +} From b4376ae6dae0a51efc478d7e1bd39833592331e7 Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 6 Apr 2023 10:52:48 +0200 Subject: [PATCH 045/403] [core-spring-1-sample] added validation of invalid Lollipop requests. --- .../AssertionVerifierServiceImplStub.java | 1 + sample/gradlew | 185 ++++++++++++++++++ sample/gradlew.bat | 89 +++++++++ .../tech/sample/LollipopConsumerSample.java | 48 ++++- 4 files changed, 320 insertions(+), 3 deletions(-) create mode 100644 sample/gradlew create mode 100644 sample/gradlew.bat diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java index f7c91447..f87d7cf6 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java @@ -21,6 +21,7 @@ public AssertionVerifierServiceImplStub( this.assertionService = assertionService; } + /** TODO: stub */ @Override public boolean validateLollipop(LollipopConsumerRequest request) { return true; diff --git a/sample/gradlew b/sample/gradlew new file mode 100644 index 00000000..4f906e0c --- /dev/null +++ b/sample/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/sample/gradlew.bat b/sample/gradlew.bat new file mode 100644 index 00000000..107acd32 --- /dev/null +++ b/sample/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java b/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java index 95b70da5..cc855752 100644 --- a/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java +++ b/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java @@ -22,8 +22,12 @@ public class LollipopConsumerSample { public static void main(String[] args) throws Exception { LollipopConsumerCommandBuilder commandBuilder = new LollipopConsumerCommandBuilderImpl(buildLollipopConsumerFactoryHelper()); LollipopConsumerCommand command = commandBuilder.createCommand(); - CommandResult commandResult = command.doExecute(buildLollipopRequest()); - System.out.println("Validation ended with status code " + commandResult.getResultCode() + " and message " + commandResult.getResultMessage()); + CommandResult commandResult = command.doExecute(buildValidLollipopRequest()); + System.out.println("Validation of a valid Lollipop request ended with status code " + commandResult.getResultCode() + " and message " + commandResult.getResultMessage()); + commandResult = command.doExecute(buildLollipopRequestWithInvalidDigestHeader()); + System.out.println("Validation of a Lollipop request with invalid digest header ended with status code " + commandResult.getResultCode() + " and message " + commandResult.getResultMessage()); + commandResult = command.doExecute(buildLollipopRequestWithInvalidContent()); + System.out.println("Validation of a Lollipop request with invalid content ended with status code " + commandResult.getResultCode() + " and message " + commandResult.getResultMessage()); } private static LollipopConsumerFactoryHelper buildLollipopConsumerFactoryHelper() throws Exception { @@ -33,7 +37,7 @@ private static LollipopConsumerFactoryHelper buildLollipopConsumerFactoryHelper( return new LollipopConsumerFactoryHelper(messageVerifierFactory, idpCertProviderFactory, assertionServiceFactory); } - private static LollipopConsumerRequest buildLollipopRequest() { + private static LollipopConsumerRequest buildValidLollipopRequest() { HashMap lollipopHeaderParams = new HashMap<>(); lollipopHeaderParams.put("content-digest", "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"); lollipopHeaderParams.put("content-encoding", ENCODING); @@ -51,4 +55,42 @@ private static LollipopConsumerRequest buildLollipopRequest() { .headerParams(lollipopHeaderParams) .build(); } + + private static LollipopConsumerRequest buildLollipopRequestWithInvalidDigestHeader() { + HashMap lollipopHeaderParams = new HashMap<>(); + lollipopHeaderParams.put("content-digest", "sha-256=:fadsfeagsdage76ad564=:"); + lollipopHeaderParams.put("content-encoding", ENCODING); + lollipopHeaderParams.put( + "signature-input", + "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" " + + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" + + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); + lollipopHeaderParams.put( + "signature", + "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"); + + return LollipopConsumerRequest.builder() + .requestBody("{\"message\":\"a valid message payload\"}") + .headerParams(lollipopHeaderParams) + .build(); + } + + private static LollipopConsumerRequest buildLollipopRequestWithInvalidContent() { + HashMap lollipopHeaderParams = new HashMap<>(); + lollipopHeaderParams.put("content-digest", "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"); + lollipopHeaderParams.put("content-encoding", ENCODING); + lollipopHeaderParams.put( + "signature-input", + "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" " + + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" + + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); + lollipopHeaderParams.put( + "signature", + "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"); + + return LollipopConsumerRequest.builder() + .requestBody("{\"message\":\"an invalid message payload\"}") + .headerParams(lollipopHeaderParams) + .build(); + } } From e5193d744aa11cd29403248f8974b5bd5033a203 Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 6 Apr 2023 12:10:50 +0200 Subject: [PATCH 046/403] [core-spring-1-sample] refactor sample. --- .../java/it/pagopa/tech/sample/Constants.java | 20 +++++ .../tech/sample/LollipopConsumerSample.java | 80 ++++++------------- 2 files changed, 43 insertions(+), 57 deletions(-) create mode 100644 sample/src/main/java/it/pagopa/tech/sample/Constants.java diff --git a/sample/src/main/java/it/pagopa/tech/sample/Constants.java b/sample/src/main/java/it/pagopa/tech/sample/Constants.java new file mode 100644 index 00000000..086f0d9f --- /dev/null +++ b/sample/src/main/java/it/pagopa/tech/sample/Constants.java @@ -0,0 +1,20 @@ +package it.pagopa.tech.sample; + +public class Constants { + public static final String CONTENT_DIGEST = "content-digest"; + public static final String CONTENT_ENCODING = "content-encoding"; + public static final String SIGNATURE_INPUT = "signature-input"; + public static final String SIGNATURE = "signature"; + public static final String VALID_ENCODING_UTF8 = "UTF-8"; + public static final String INVALID_ENCODING_UTF_326 = "UTF-326"; + public static final String VALID_CONTENT_DIGEST = "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"; + public static final String INVALID_CONTENT_DIGEST = "sha-256=:fadsfeagsdage76ad564=:"; + public static final String VALID_MESSAGE_PAYLOAD = "{\"message\":\"a valid message payload\"}"; + public static final String INVALID_MESSAGE_PAYLOAD = "{\"message\":\"an invalid message payload\"}"; + public static final String SIGNATURE_HEADER_VALUE = "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + public static final String SIGNATURE_INPUT_HEADER_VALUE = "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" " + + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" + + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; + + private Constants() {} +} diff --git a/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java b/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java index cc855752..78234924 100644 --- a/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java +++ b/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java @@ -15,82 +15,48 @@ import java.util.HashMap; -public class LollipopConsumerSample { +import static it.pagopa.tech.sample.Constants.*; - private static final String ENCODING = "UTF-8"; +public class LollipopConsumerSample { public static void main(String[] args) throws Exception { LollipopConsumerCommandBuilder commandBuilder = new LollipopConsumerCommandBuilderImpl(buildLollipopConsumerFactoryHelper()); LollipopConsumerCommand command = commandBuilder.createCommand(); - CommandResult commandResult = command.doExecute(buildValidLollipopRequest()); - System.out.println("Validation of a valid Lollipop request ended with status code " + commandResult.getResultCode() + " and message " + commandResult.getResultMessage()); - commandResult = command.doExecute(buildLollipopRequestWithInvalidDigestHeader()); - System.out.println("Validation of a Lollipop request with invalid digest header ended with status code " + commandResult.getResultCode() + " and message " + commandResult.getResultMessage()); - commandResult = command.doExecute(buildLollipopRequestWithInvalidContent()); - System.out.println("Validation of a Lollipop request with invalid content ended with status code " + commandResult.getResultCode() + " and message " + commandResult.getResultMessage()); + + CommandResult commandResult = command.doExecute(buildLollipopRequest(VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD)); + System.out.println(buildMessage(commandResult, "Validation of a valid Lollipop request ended with status code ")); + + commandResult = command.doExecute(buildLollipopRequest(INVALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD)); + System.out.println(buildMessage(commandResult, "Validation of a Lollipop request with invalid digest header ended with status code ")); + + commandResult = command.doExecute(buildLollipopRequest(VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, INVALID_MESSAGE_PAYLOAD)); + System.out.println(buildMessage(commandResult, "Validation of a Lollipop request with invalid content ended with status code ")); + + commandResult = command.doExecute(buildLollipopRequest(VALID_CONTENT_DIGEST, INVALID_ENCODING_UTF_326, VALID_MESSAGE_PAYLOAD)); + System.out.println(buildMessage(commandResult, "Validation of a Lollipop request with unsupported encoding ended with status code ")); } private static LollipopConsumerFactoryHelper buildLollipopConsumerFactoryHelper() throws Exception { - HttpMessageVerifierFactory messageVerifierFactory = new VismaHttpMessageVerifierFactory(ENCODING); + HttpMessageVerifierFactory messageVerifierFactory = new VismaHttpMessageVerifierFactory(VALID_ENCODING_UTF8); IdpCertProviderFactory idpCertProviderFactory = new IdpCertProviderFactoryImplStub(); AssertionServiceFactory assertionServiceFactory = new AssertionServiceFactoryImplStub(); return new LollipopConsumerFactoryHelper(messageVerifierFactory, idpCertProviderFactory, assertionServiceFactory); } - private static LollipopConsumerRequest buildValidLollipopRequest() { - HashMap lollipopHeaderParams = new HashMap<>(); - lollipopHeaderParams.put("content-digest", "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"); - lollipopHeaderParams.put("content-encoding", ENCODING); - lollipopHeaderParams.put( - "signature-input", - "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" " - + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" - + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); - lollipopHeaderParams.put( - "signature", - "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"); - - return LollipopConsumerRequest.builder() - .requestBody("{\"message\":\"a valid message payload\"}") - .headerParams(lollipopHeaderParams) - .build(); - } - - private static LollipopConsumerRequest buildLollipopRequestWithInvalidDigestHeader() { + private static LollipopConsumerRequest buildLollipopRequest(String contentDigest, String encoding, String payload) { HashMap lollipopHeaderParams = new HashMap<>(); - lollipopHeaderParams.put("content-digest", "sha-256=:fadsfeagsdage76ad564=:"); - lollipopHeaderParams.put("content-encoding", ENCODING); - lollipopHeaderParams.put( - "signature-input", - "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" " - + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" - + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); - lollipopHeaderParams.put( - "signature", - "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"); + lollipopHeaderParams.put(CONTENT_DIGEST, contentDigest); + lollipopHeaderParams.put(CONTENT_ENCODING, encoding); + lollipopHeaderParams.put(SIGNATURE_INPUT, SIGNATURE_INPUT_HEADER_VALUE); + lollipopHeaderParams.put(SIGNATURE, SIGNATURE_HEADER_VALUE); return LollipopConsumerRequest.builder() - .requestBody("{\"message\":\"a valid message payload\"}") + .requestBody(payload) .headerParams(lollipopHeaderParams) .build(); } - private static LollipopConsumerRequest buildLollipopRequestWithInvalidContent() { - HashMap lollipopHeaderParams = new HashMap<>(); - lollipopHeaderParams.put("content-digest", "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"); - lollipopHeaderParams.put("content-encoding", ENCODING); - lollipopHeaderParams.put( - "signature-input", - "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" " - + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" - + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); - lollipopHeaderParams.put( - "signature", - "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"); - - return LollipopConsumerRequest.builder() - .requestBody("{\"message\":\"an invalid message payload\"}") - .headerParams(lollipopHeaderParams) - .build(); + private static String buildMessage(CommandResult commandResult, String s) { + return s + commandResult.getResultCode() + " and message " + commandResult.getResultMessage(); } } From bfcc8d9ad25c02fd61f3d8e1f8a4f72b0590d225 Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Thu, 6 Apr 2023 16:53:19 +0200 Subject: [PATCH 047/403] Create build-gradle-project.yml --- .github/workflows/build-gradle-project.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .github/workflows/build-gradle-project.yml diff --git a/.github/workflows/build-gradle-project.yml b/.github/workflows/build-gradle-project.yml new file mode 100644 index 00000000..cccf56d0 --- /dev/null +++ b/.github/workflows/build-gradle-project.yml @@ -0,0 +1,16 @@ +name: Build Gradle project + +on: + push: + pull_request: + +jobs: + build-gradle-project: + runs-on: ubuntu-latest + steps: + - name: Checkout project sources + uses: actions/checkout@v2 + - name: Setup Gradle + uses: gradle/gradle-build-action@v2 + - name: Run build with Gradle Wrapper + run: ./gradlew build From ba63934da7110de8e4abf6967dab36a54f59015f Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Thu, 6 Apr 2023 16:56:10 +0200 Subject: [PATCH 048/403] Update build-gradle-project.yml --- .github/workflows/build-gradle-project.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-gradle-project.yml b/.github/workflows/build-gradle-project.yml index cccf56d0..86794929 100644 --- a/.github/workflows/build-gradle-project.yml +++ b/.github/workflows/build-gradle-project.yml @@ -12,5 +12,7 @@ jobs: uses: actions/checkout@v2 - name: Setup Gradle uses: gradle/gradle-build-action@v2 + - name: Make gradlew executable + run: chmod +x ./gradlew - name: Run build with Gradle Wrapper run: ./gradlew build From 448e739221768410af71db82f1a86b05d0465ff8 Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Thu, 6 Apr 2023 17:06:29 +0200 Subject: [PATCH 049/403] Update build-gradle-project.yml --- .github/workflows/build-gradle-project.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-gradle-project.yml b/.github/workflows/build-gradle-project.yml index 86794929..cee4d34f 100644 --- a/.github/workflows/build-gradle-project.yml +++ b/.github/workflows/build-gradle-project.yml @@ -1,7 +1,6 @@ name: Build Gradle project on: - push: pull_request: jobs: @@ -9,7 +8,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout project sources - uses: actions/checkout@v2 + uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Setup Gradle uses: gradle/gradle-build-action@v2 - name: Make gradlew executable From 68bfd56c084bb8b12349def1336eba54569eee18 Mon Sep 17 00:00:00 2001 From: svariant Date: Thu, 6 Apr 2023 17:44:04 +0200 Subject: [PATCH 050/403] [SLS-19] Generated rest client with openAPI specification for retrieving Identity Provider Cert Data --- gradle/verification-metadata.xml | 456 ++++++++++++++++++ .../build.gradle | 27 ++ .../openapi/openapi-spec.yml | 50 ++ .../client/simple/IdpCertSimpleClient.java | 30 ++ .../simple/IdpCertSimpleClientProvider.java | 19 + .../idp/client/simple/internal/ApiClient.java | 436 +++++++++++++++++ .../client/simple/internal/ApiException.java | 88 ++++ .../client/simple/internal/ApiResponse.java | 47 ++ .../client/simple/internal/Configuration.java | 29 ++ .../idp/client/simple/internal/JSON.java | 246 ++++++++++ .../idp/client/simple/internal/Pair.java | 47 ++ .../simple/internal/RFC3339DateFormat.java | 44 ++ .../simple/internal/ServerConfiguration.java | 65 +++ .../simple/internal/ServerVariable.java | 23 + .../simple/internal/api/DefaultApi.java | 317 ++++++++++++ .../internal/model/AbstractOpenApiSchema.java | 135 ++++++ 16 files changed, 2059 insertions(+) create mode 100644 identity-service-rest-client-native/openapi/openapi-spec.yml create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 9aa9291d..9b818cfb 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -125,6 +125,11 @@ + + + + + @@ -135,6 +140,16 @@ + + + + + + + + + + @@ -145,6 +160,11 @@ + + + + + @@ -157,6 +177,16 @@ + + + + + + + + + + @@ -168,6 +198,11 @@ + + + + + @@ -201,6 +236,14 @@ + + + + + + + + @@ -227,6 +270,14 @@ + + + + + + + + @@ -253,6 +304,14 @@ + + + + + + + + @@ -288,6 +347,19 @@ + + + + + + + + + + + + + @@ -298,11 +370,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -316,6 +422,16 @@ + + + + + + + + + + @@ -347,6 +463,14 @@ + + + + + + + + @@ -357,6 +481,14 @@ + + + + + + + + @@ -437,6 +569,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -745,6 +914,11 @@ + + + + + @@ -835,6 +1009,22 @@ + + + + + + + + + + + + + + + + @@ -885,6 +1075,14 @@ + + + + + + + + @@ -1141,6 +1339,14 @@ + + + + + + + + @@ -1151,6 +1357,14 @@ + + + + + + + + @@ -1161,6 +1375,14 @@ + + + + + + + + @@ -1171,6 +1393,14 @@ + + + + + + + + @@ -1181,6 +1411,14 @@ + + + + + + + + @@ -1191,18 +1429,36 @@ + + + + + + + + + + + + + + + + + + @@ -1213,6 +1469,14 @@ + + + + + + + + @@ -1223,6 +1487,14 @@ + + + + + + + + @@ -1233,6 +1505,11 @@ + + + + + @@ -1249,6 +1526,14 @@ + + + + + + + + @@ -1259,12 +1544,25 @@ + + + + + + + + + + + + + @@ -1275,6 +1573,14 @@ + + + + + + + + @@ -1285,6 +1591,22 @@ + + + + + + + + + + + + + + + + @@ -1305,6 +1627,14 @@ + + + + + + + + @@ -1325,6 +1655,11 @@ + + + + + @@ -1367,6 +1702,14 @@ + + + + + + + + @@ -1377,6 +1720,14 @@ + + + + + + + + @@ -1457,6 +1808,14 @@ + + + + + + + + @@ -1525,6 +1884,11 @@ + + + + + @@ -1609,6 +1973,11 @@ + + + + + @@ -1889,6 +2258,14 @@ + + + + + + + + @@ -1959,6 +2336,19 @@ + + + + + + + + + + + + + @@ -1975,6 +2365,11 @@ + + + + + @@ -2211,6 +2606,9 @@ + + + @@ -2581,6 +2979,11 @@ + + + + + @@ -2591,6 +2994,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2653,6 +3085,14 @@ + + + + + + + + @@ -2671,6 +3111,14 @@ + + + + + + + + @@ -2695,6 +3143,14 @@ + + + + + + + + diff --git a/identity-service-rest-client-native/build.gradle b/identity-service-rest-client-native/build.gradle index 460062f0..d38a7392 100644 --- a/identity-service-rest-client-native/build.gradle +++ b/identity-service-rest-client-native/build.gradle @@ -10,6 +10,7 @@ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' id("io.freefair.lombok") version "8.0.0-rc4" + /*id("org.openapi.generator") version "6.5.0"*/ } group 'it.pagopa.tech' @@ -44,11 +45,37 @@ dependencies { } } implementation project(path: ':core') + + implementation 'javax.annotation:javax.annotation-api:1.3.2' + implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.14.2' + implementation 'org.openapitools:jackson-databind-nullable:0.2.6' + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.2' + implementation 'com.google.code.findbugs:jsr305:3.0.2' + + implementation 'org.mock-server:mockserver-client-java:5.15.0' + implementation 'javax.inject:javax.inject:1' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + testImplementation 'org.assertj:assertj-core:3.24.2' + //Mockserver for testing api + testImplementation 'org.mock-server:mockserver-netty:5.15.0' } tasks.named('test') { // Use JUnit Platform for unit tests. useJUnitPlatform() } + +/*compileJava.dependsOn tasks.openApiGenerate + +openApiGenerate { + generatorName = "java" + inputSpec = "$projectDir/openapi/openapi-spec.yml" + outputDir = "$projectDir/generated" + configOptions = [ + dataLibrary : "java8", + library : "native", + useRuntimeException: "true", + sourceFolder : "build/generated/sources/" + ] +}*/ diff --git a/identity-service-rest-client-native/openapi/openapi-spec.yml b/identity-service-rest-client-native/openapi/openapi-spec.yml new file mode 100644 index 00000000..cb180052 --- /dev/null +++ b/identity-service-rest-client-native/openapi/openapi-spec.yml @@ -0,0 +1,50 @@ +openapi: "3.0.1" +info: + title: "identity-services" + version: "2022-09-06T20:08:39Z" + x-logo: + url: https://io.italia.it/assets/img/io-logo-blue.svg + description: |- + Client used to retrieve the public keys from the identity provider +servers: + - url: "https://api.is.eng.pagopa.it" + x-amazon-apigateway-endpoint-configuration: + disableExecuteApiEndpoint: true +paths: + /idp-keys/spid: + get: + responses: + "200": + description: "200 response" + content: {} + /idp-keys/cie: + get: + responses: + "200": + description: "200 response" + content: {} + /idp-keys/spid/{tag}: + get: + parameters: + - name: "tag" + in: "path" + required: true + schema: + type: "string" + responses: + "200": + description: "200 response" + content: {} + /idp-keys/cie/{tag}: + get: + parameters: + - name: "tag" + in: "path" + required: true + schema: + type: "string" + responses: + "200": + description: "200 response" + content: {} +components: {} \ No newline at end of file diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java new file mode 100644 index 00000000..8eae30a2 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -0,0 +1,30 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple; + +import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.api.DefaultApi; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import javax.inject.Inject; + +public class IdpCertSimpleClient implements IdpCertClient { + + ApiClient apiClient; + DefaultApi defaultApi; + + @Inject + public IdpCertSimpleClient(ApiClient client) { + this.apiClient = client; + this.defaultApi = new DefaultApi(client); + } + + /** + * @param entityId + * @param instant + * @return + */ + @Override + public IdpCertData getCertData(String entityId, String instant) { + return null; + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java new file mode 100644 index 00000000..402136fd --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java @@ -0,0 +1,19 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple; + +import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; +import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; + +public class IdpCertSimpleClientProvider implements IdpCertClientProvider { + + /** + * Provide an instance of {@link IdpCertSimpleClient} + * + * @return {@link IdpCertSimpleClient} + */ + @Override + public IdpCertClient provideClient() { + return new IdpCertSimpleClient(new ApiClient()); + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java new file mode 100644 index 00000000..6405bcf6 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java @@ -0,0 +1,436 @@ +/* (C)2022-2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import java.io.InputStream; +import java.net.URI; +import java.net.URLEncoder; +import java.net.http.HttpClient; +import java.net.http.HttpConnectTimeoutException; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.StringJoiner; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import org.openapitools.jackson.nullable.JsonNullableModule; + +/** + * Configuration and utility class for API clients. + * + *

This class can be constructed and modified, then used to instantiate the various API classes. + * The API classes use the settings in this class to configure themselves, but otherwise do not + * store a link to this class. + * + *

This class is mutable and not synchronized, so it is not thread-safe. The API classes + * generated from this are immutable and thread-safe. + * + *

The setter methods of this class return the current object to facilitate a fluent style of + * configuration. + */ +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +public class ApiClient { + + private HttpClient.Builder builder; + private ObjectMapper mapper; + private String scheme; + private String host; + private int port; + private String basePath; + private Consumer interceptor; + private Consumer> responseInterceptor; + private Consumer> asyncResponseInterceptor; + private Duration readTimeout; + private Duration connectTimeout; + + private static String valueToString(Object value) { + if (value == null) { + return ""; + } + if (value instanceof OffsetDateTime) { + return ((OffsetDateTime) value).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } + return value.toString(); + } + + /** + * URL encode a string in the UTF-8 encoding. + * + * @param s String to encode. + * @return URL-encoded representation of the input string. + */ + public static String urlEncode(String s) { + return URLEncoder.encode(s, UTF_8).replaceAll("\\+", "%20"); + } + + /** + * Convert a URL query name/value parameter to a list of encoded {@link Pair} objects. + * + *

The value can be null, in which case an empty list is returned. + * + * @param name The query name parameter. + * @param value The query value, which may not be a collection but may be null. + * @return A singleton list of the {@link Pair} objects representing the input parameters, which + * is encoded for use in a URL. If the value is null, an empty list is returned. + */ + public static List parameterToPairs(String name, Object value) { + if (name == null || name.isEmpty() || value == null) { + return Collections.emptyList(); + } + return Collections.singletonList( + new Pair(urlEncode(name), urlEncode(valueToString(value)))); + } + + /** + * Convert a URL query name/collection parameter to a list of encoded {@link Pair} objects. + * + * @param collectionFormat The swagger collectionFormat string (csv, tsv, etc). + * @param name The query name parameter. + * @param values A collection of values for the given query name, which may be null. + * @return A list of {@link Pair} objects representing the input parameters, which is encoded + * for use in a URL. If the values collection is null, an empty list is returned. + */ + public static List parameterToPairs( + String collectionFormat, String name, Collection values) { + if (name == null || name.isEmpty() || values == null || values.isEmpty()) { + return Collections.emptyList(); + } + + // get the collection format (default: csv) + String format = + collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat; + + // create the params based on the collection format + if ("multi".equals(format)) { + return values.stream() + .map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value)))) + .collect(Collectors.toList()); + } + + String delimiter; + switch (format) { + case "csv": + delimiter = urlEncode(","); + break; + case "ssv": + delimiter = urlEncode(" "); + break; + case "tsv": + delimiter = urlEncode("\t"); + break; + case "pipes": + delimiter = urlEncode("|"); + break; + default: + throw new IllegalArgumentException( + "Illegal collection format: " + collectionFormat); + } + + StringJoiner joiner = new StringJoiner(delimiter); + for (Object value : values) { + joiner.add(urlEncode(valueToString(value))); + } + + return Collections.singletonList(new Pair(urlEncode(name), joiner.toString())); + } + + /** Create an instance of ApiClient. */ + public ApiClient() { + this.builder = createDefaultHttpClientBuilder(); + this.mapper = createDefaultObjectMapper(); + updateBaseUri(getDefaultBaseUri()); + interceptor = null; + readTimeout = null; + connectTimeout = null; + responseInterceptor = null; + asyncResponseInterceptor = null; + } + + /** + * Create an instance of ApiClient. + * + * @param builder Http client builder. + * @param mapper Object mapper. + * @param baseUri Base URI + */ + public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, String baseUri) { + this.builder = builder; + this.mapper = mapper; + updateBaseUri(baseUri != null ? baseUri : getDefaultBaseUri()); + interceptor = null; + readTimeout = null; + connectTimeout = null; + responseInterceptor = null; + asyncResponseInterceptor = null; + } + + protected ObjectMapper createDefaultObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); + mapper.registerModule(new JavaTimeModule()); + mapper.registerModule(new JsonNullableModule()); + return mapper; + } + + protected String getDefaultBaseUri() { + return "https://api.is.eng.pagopa.it"; + } + + protected HttpClient.Builder createDefaultHttpClientBuilder() { + return HttpClient.newBuilder(); + } + + public void updateBaseUri(String baseUri) { + URI uri = URI.create(baseUri); + scheme = uri.getScheme(); + host = uri.getHost(); + port = uri.getPort(); + basePath = uri.getRawPath(); + } + + /** + * Set a custom {@link HttpClient.Builder} object to use when creating the {@link HttpClient} + * that is used by the API client. + * + * @param builder Custom client builder. + * @return This object. + */ + public ApiClient setHttpClientBuilder(HttpClient.Builder builder) { + this.builder = builder; + return this; + } + + /** + * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}. + * + *

The returned object is immutable and thread-safe. + * + * @return The HTTP client. + */ + public HttpClient getHttpClient() { + return builder.build(); + } + + /** + * Set a custom {@link ObjectMapper} to serialize and deserialize the request and response + * bodies. + * + * @param mapper Custom object mapper. + * @return This object. + */ + public ApiClient setObjectMapper(ObjectMapper mapper) { + this.mapper = mapper; + return this; + } + + /** + * Get a copy of the current {@link ObjectMapper}. + * + * @return A copy of the current object mapper. + */ + public ObjectMapper getObjectMapper() { + return mapper.copy(); + } + + /** + * Set a custom host name for the target service. + * + * @param host The host name of the target service. + * @return This object. + */ + public ApiClient setHost(String host) { + this.host = host; + return this; + } + + /** + * Set a custom port number for the target service. + * + * @param port The port of the target service. Set this to -1 to reset the value to the default + * for the scheme. + * @return This object. + */ + public ApiClient setPort(int port) { + this.port = port; + return this; + } + + /** + * Set a custom base path for the target service, for example '/v2'. + * + * @param basePath The base path against which the rest of the path is resolved. + * @return This object. + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get the base URI to resolve the endpoint paths against. + * + * @return The complete base URI that the rest of the API parameters are resolved against. + */ + public String getBaseUri() { + return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; + } + + /** + * Set a custom scheme for the target service, for example 'https'. + * + * @param scheme The scheme of the target service + * @return This object. + */ + public ApiClient setScheme(String scheme) { + this.scheme = scheme; + return this; + } + + /** + * Set a custom request interceptor. + * + *

A request interceptor is a mechanism for altering each request before it is sent. After + * the request has been fully configured but not yet built, the request builder is passed into + * this function for further modification, after which it is sent out. + * + *

This is useful for altering the requests in a custom manner, such as adding headers. It + * could also be used for logging and monitoring. + * + * @param interceptor A function invoked before creating each request. A value of null resets + * the interceptor to a no-op. + * @return This object. + */ + public ApiClient setRequestInterceptor(Consumer interceptor) { + this.interceptor = interceptor; + return this; + } + + /** + * Get the custom interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer getRequestInterceptor() { + return interceptor; + } + + /** + * Set a custom response interceptor. + * + *

This is useful for logging, monitoring or extraction of header variables + * + * @param interceptor A function invoked before creating each request. A value of null resets + * the interceptor to a no-op. + * @return This object. + */ + public ApiClient setResponseInterceptor(Consumer> interceptor) { + this.responseInterceptor = interceptor; + return this; + } + + /** + * Get the custom response interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getResponseInterceptor() { + return responseInterceptor; + } + + /** + * Set a custom async response interceptor. Use this interceptor when asyncNative is set to + * 'true'. + * + *

This is useful for logging, monitoring or extraction of header variables + * + * @param interceptor A function invoked before creating each request. A value of null resets + * the interceptor to a no-op. + * @return This object. + */ + public ApiClient setAsyncResponseInterceptor(Consumer> interceptor) { + this.asyncResponseInterceptor = interceptor; + return this; + } + + /** + * Get the custom async response interceptor. Use this interceptor when asyncNative is set to + * 'true'. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getAsyncResponseInterceptor() { + return asyncResponseInterceptor; + } + + /** + * Set the read timeout for the http client. + * + *

This is the value used by default for each request, though it can be overridden on a + * per-request basis with a request interceptor. + * + * @param readTimeout The read timeout used by default by the http client. Setting this value to + * null resets the timeout to an effectively infinite value. + * @return This object. + */ + public ApiClient setReadTimeout(Duration readTimeout) { + this.readTimeout = readTimeout; + return this; + } + + /** + * Get the read timeout that was set. + * + * @return The read timeout, or null if no timeout was set. Null represents an infinite wait + * time. + */ + public Duration getReadTimeout() { + return readTimeout; + } + /** + * Sets the connect timeout (in milliseconds) for the http client. + * + *

In the case where a new connection needs to be established, if the connection cannot be + * established within the given {@code duration}, then {@link + * HttpClient#send(HttpRequest,BodyHandler) HttpClient::send} throws an {@link + * HttpConnectTimeoutException}, or {@link HttpClient#sendAsync(HttpRequest,BodyHandler) + * HttpClient::sendAsync} completes exceptionally with an {@code HttpConnectTimeoutException}. + * If a new connection does not need to be established, for example if a connection can be + * reused from a previous request, then this timeout duration has no effect. + * + * @param connectTimeout connection timeout in milliseconds + * @return This object. + */ + public ApiClient setConnectTimeout(Duration connectTimeout) { + this.connectTimeout = connectTimeout; + this.builder.connectTimeout(connectTimeout); + return this; + } + + /** + * Get connection timeout (in milliseconds). + * + * @return Timeout in milliseconds + */ + public Duration getConnectTimeout() { + return connectTimeout; + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java new file mode 100644 index 00000000..5297d641 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java @@ -0,0 +1,88 @@ +/* (C)2022-2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; + +import java.net.http.HttpHeaders; + +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +public class ApiException extends RuntimeException { + private int code = 0; + private HttpHeaders responseHeaders = null; + private String responseBody = null; + + public ApiException() {} + + public ApiException(Throwable throwable) { + super(throwable); + } + + public ApiException(String message) { + super(message); + } + + public ApiException( + String message, + Throwable throwable, + int code, + HttpHeaders responseHeaders, + String responseBody) { + super(message, throwable); + this.code = code; + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + public ApiException( + String message, int code, HttpHeaders responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException( + String message, Throwable throwable, int code, HttpHeaders responseHeaders) { + this(message, throwable, code, responseHeaders, null); + } + + public ApiException(int code, HttpHeaders responseHeaders, String responseBody) { + this((String) null, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(int code, String message) { + super(message); + this.code = code; + } + + public ApiException( + int code, String message, HttpHeaders responseHeaders, String responseBody) { + this(code, message); + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + /** + * Get the HTTP status code. + * + * @return HTTP status code + */ + public int getCode() { + return code; + } + + /** + * Get the HTTP response headers. + * + * @return Headers as an HttpHeaders object + */ + public HttpHeaders getResponseHeaders() { + return responseHeaders; + } + + /** + * Get the HTTP response body. + * + * @return Response body in the form of string + */ + public String getResponseBody() { + return responseBody; + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java new file mode 100644 index 00000000..582e0a4d --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java @@ -0,0 +1,47 @@ +/* (C)2022-2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; + +import java.util.List; +import java.util.Map; + +/** + * API response returned by API call. + * + * @param The type of data that is deserialized from response body + */ +public class ApiResponse { + private final int statusCode; + private final Map> headers; + private final T data; + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + */ + public ApiResponse(int statusCode, Map> headers) { + this(statusCode, headers, null); + } + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + * @param data The object deserialized from response bod + */ + public ApiResponse(int statusCode, Map> headers, T data) { + this.statusCode = statusCode; + this.headers = headers; + this.data = data; + } + + public int getStatusCode() { + return statusCode; + } + + public Map> getHeaders() { + return headers; + } + + public T getData() { + return data; + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java new file mode 100644 index 00000000..cbc956b8 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java @@ -0,0 +1,29 @@ +/* (C)2022-2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; + +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +public class Configuration { + private static ApiClient defaultApiClient = new ApiClient(); + + /** + * Get the default API client, which would be used when creating API instances without providing + * an API client. + * + * @return Default API client + */ + public static ApiClient getDefaultApiClient() { + return defaultApiClient; + } + + /** + * Set the default API client, which would be used when creating API instances without providing + * an API client. + * + * @param apiClient API client + */ + public static void setDefaultApiClient(ApiClient apiClient) { + defaultApiClient = apiClient; + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java new file mode 100644 index 00000000..889ef90a --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java @@ -0,0 +1,246 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import java.text.DateFormat; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import org.openapitools.jackson.nullable.JsonNullableModule; + +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +public class JSON { + private ObjectMapper mapper; + + public JSON() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + mapper.registerModule(new JavaTimeModule()); + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + } + + /** + * Set the date format for JSON (de)serialization with Date properties. + * + * @param dateFormat Date format + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + + /** + * Get the object mapper + * + * @return object mapper + */ + public ObjectMapper getMapper() { + return mapper; + } + + /** + * Returns the target model class that should be used to deserialize the input data. The + * discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param modelClass The class that contains the discriminator mappings. + * @return the target model class. + */ + public static Class getClassForElement(JsonNode node, Class modelClass) { + ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass); + if (cdm != null) { + return cdm.getClassForElement(node, new HashSet>()); + } + return null; + } + + /** Helper class to register the discriminator mappings. */ + private static class ClassDiscriminatorMapping { + // The model class name. + Class modelClass; + // The name of the discriminator property. + String discriminatorName; + // The discriminator mappings for a model class. + Map> discriminatorMappings; + + // Constructs a new class discriminator. + ClassDiscriminatorMapping( + Class cls, String propertyName, Map> mappings) { + modelClass = cls; + discriminatorName = propertyName; + discriminatorMappings = new HashMap>(); + if (mappings != null) { + discriminatorMappings.putAll(mappings); + } + } + + // Return the name of the discriminator property for this model class. + String getDiscriminatorPropertyName() { + return discriminatorName; + } + + // Return the discriminator value or null if the discriminator is not + // present in the payload. + String getDiscriminatorValue(JsonNode node) { + // Determine the value of the discriminator property in the input data. + if (discriminatorName != null) { + // Get the value of the discriminator property, if present in the input payload. + node = node.get(discriminatorName); + if (node != null && node.isValueNode()) { + String discrValue = node.asText(); + if (discrValue != null) { + return discrValue; + } + } + } + return null; + } + + /** + * Returns the target model class that should be used to deserialize the input data. This + * function can be invoked for anyOf/oneOf composed models with discriminator mappings. The + * discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param visitedClasses The set of classes that have already been visited. + * @return the target model class. + */ + Class getClassForElement(JsonNode node, Set> visitedClasses) { + if (visitedClasses.contains(modelClass)) { + // Class has already been visited. + return null; + } + // Determine the value of the discriminator property in the input data. + String discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + return null; + } + Class cls = discriminatorMappings.get(discrValue); + // It may not be sufficient to return this cls directly because that target class + // may itself be a composed schema, possibly with its own discriminator. + visitedClasses.add(modelClass); + for (Class childClass : discriminatorMappings.values()) { + ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass); + if (childCdm == null) { + continue; + } + if (!discriminatorName.equals(childCdm.discriminatorName)) { + discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + continue; + } + } + if (childCdm != null) { + // Recursively traverse the discriminator mappings. + Class childDiscr = childCdm.getClassForElement(node, visitedClasses); + if (childDiscr != null) { + return childDiscr; + } + } + } + return cls; + } + } + + /** + * Returns true if inst is an instance of modelClass in the OpenAPI model hierarchy. + * + *

The Java class hierarchy is not implemented the same way as the OpenAPI model hierarchy, + * so it's not possible to use the instanceof keyword. + * + * @param modelClass A OpenAPI model class. + * @param inst The instance object. + * @param visitedClasses The set of classes that have already been visited. + * @return true if inst is an instance of modelClass in the OpenAPI model hierarchy. + */ + public static boolean isInstanceOf( + Class modelClass, Object inst, Set> visitedClasses) { + if (modelClass.isInstance(inst)) { + // This handles the 'allOf' use case with single parent inheritance. + return true; + } + if (visitedClasses.contains(modelClass)) { + // This is to prevent infinite recursion when the composed schemas have + // a circular dependency. + return false; + } + visitedClasses.add(modelClass); + + // Traverse the oneOf/anyOf composed schemas. + Map> descendants = modelDescendants.get(modelClass); + if (descendants != null) { + for (Class childType : descendants.values()) { + if (isInstanceOf(childType, inst, visitedClasses)) { + return true; + } + } + } + return false; + } + + /** A map of discriminators for all model classes. */ + private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap<>(); + + /** A map of oneOf/anyOf descendants for each model class. */ + private static Map, Map>> modelDescendants = new HashMap<>(); + + /** + * Register a model class discriminator. + * + * @param modelClass the model class + * @param discriminatorPropertyName the name of the discriminator property + * @param mappings a map with the discriminator mappings. + */ + public static void registerDiscriminator( + Class modelClass, String discriminatorPropertyName, Map> mappings) { + ClassDiscriminatorMapping m = + new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings); + modelDiscriminators.put(modelClass, m); + } + + /** + * Register the oneOf/anyOf descendants of the modelClass. + * + * @param modelClass the model class + * @param descendants a map of oneOf/anyOf descendants. + */ + public static void registerDescendants(Class modelClass, Map> descendants) { + modelDescendants.put(modelClass, descendants); + } + + private static JSON json; + + static { + json = new JSON(); + } + + /** + * Get the default JSON instance. + * + * @return the default JSON instance + */ + public static JSON getDefault() { + return json; + } + + /** + * Set the default JSON instance. + * + * @param json JSON instance to be used + */ + public static void setDefault(JSON json) { + JSON.json = json; + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java new file mode 100644 index 00000000..68b71c24 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java @@ -0,0 +1,47 @@ +/* (C)2022-2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; + +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +public class Pair { + private String name = ""; + private String value = ""; + + public Pair(String name, String value) { + setName(name); + setValue(value); + } + + private void setName(String name) { + if (!isValidString(name)) { + return; + } + + this.name = name; + } + + private void setValue(String value) { + if (!isValidString(value)) { + return; + } + + this.value = value; + } + + public String getName() { + return this.name; + } + + public String getValue() { + return this.value; + } + + private boolean isValidString(String arg) { + if (arg == null) { + return false; + } + + return true; + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java new file mode 100644 index 00000000..eb26f968 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java @@ -0,0 +1,44 @@ +/* (C)2022-2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; + +import com.fasterxml.jackson.databind.util.StdDateFormat; +import java.text.DateFormat; +import java.text.DecimalFormat; +import java.text.FieldPosition; +import java.text.ParsePosition; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +public class RFC3339DateFormat extends DateFormat { + private static final long serialVersionUID = 1L; + private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); + + private final StdDateFormat fmt = + new StdDateFormat().withTimeZone(TIMEZONE_Z).withColonInTimeZone(true); + + public RFC3339DateFormat() { + this.calendar = new GregorianCalendar(); + this.numberFormat = new DecimalFormat(); + } + + @Override + public Date parse(String source) { + return parse(source, new ParsePosition(0)); + } + + @Override + public Date parse(String source, ParsePosition pos) { + return fmt.parse(source, pos); + } + + @Override + public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { + return fmt.format(date, toAppendTo, fieldPosition); + } + + @Override + public Object clone() { + return super.clone(); + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java new file mode 100644 index 00000000..747b99ab --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java @@ -0,0 +1,65 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; + +import java.util.Map; + +/** Representing a Server configuration. */ +public class ServerConfiguration { + public String URL; + public String description; + public Map variables; + + /** + * @param URL A URL to the target host. + * @param description A description of the host designated by the URL. + * @param variables A map between a variable name and its value. The value is used for + * substitution in the server's URL template. + */ + public ServerConfiguration( + String URL, String description, Map variables) { + this.URL = URL; + this.description = description; + this.variables = variables; + } + + /** + * Format URL template using given variables. + * + * @param variables A map between a variable name and its value. + * @return Formatted URL. + */ + public String URL(Map variables) { + String url = this.URL; + + // go through variables and replace placeholders + for (Map.Entry variable : this.variables.entrySet()) { + String name = variable.getKey(); + ServerVariable serverVariable = variable.getValue(); + String value = serverVariable.defaultValue; + + if (variables != null && variables.containsKey(name)) { + value = variables.get(name); + if (serverVariable.enumValues.size() > 0 + && !serverVariable.enumValues.contains(value)) { + throw new IllegalArgumentException( + "The variable " + + name + + " in the server URL has invalid value " + + value + + "."); + } + } + url = url.replace("{" + name + "}", value); + } + return url; + } + + /** + * Format URL template using default server variables. + * + * @return Formatted URL. + */ + public String URL() { + return URL(null); + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java new file mode 100644 index 00000000..f0bb418a --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java @@ -0,0 +1,23 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; + +import java.util.HashSet; + +/** Representing a Server Variable for server URL template substitution. */ +public class ServerVariable { + public String description; + public String defaultValue; + public HashSet enumValues = null; + + /** + * @param description A description for the server variable. + * @param defaultValue The default value to use for substitution. + * @param enumValues An enumeration of string values to be used if the substitution options are + * from a limited set. + */ + public ServerVariable(String description, String defaultValue, HashSet enumValues) { + this.description = description; + this.defaultValue = defaultValue; + this.enumValues = enumValues; + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java new file mode 100644 index 00000000..e58deef0 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java @@ -0,0 +1,317 @@ +/* (C)2022-2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.api; + +import com.fasterxml.jackson.databind.ObjectMapper; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiException; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiResponse; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.util.function.Consumer; + +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +public class DefaultApi { + private final HttpClient memberVarHttpClient; + private final ObjectMapper memberVarObjectMapper; + private final String memberVarBaseUri; + private final Consumer memberVarInterceptor; + private final Duration memberVarReadTimeout; + private final Consumer> memberVarResponseInterceptor; + private final Consumer> memberVarAsyncResponseInterceptor; + + public DefaultApi() { + this(new ApiClient()); + } + + public DefaultApi(ApiClient apiClient) { + memberVarHttpClient = apiClient.getHttpClient(); + memberVarObjectMapper = apiClient.getObjectMapper(); + memberVarBaseUri = apiClient.getBaseUri(); + memberVarInterceptor = apiClient.getRequestInterceptor(); + memberVarReadTimeout = apiClient.getReadTimeout(); + memberVarResponseInterceptor = apiClient.getResponseInterceptor(); + memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); + } + + protected ApiException getApiException(String operationId, HttpResponse response) + throws IOException { + String body = response.body() == null ? null : new String(response.body().readAllBytes()); + String message = formatExceptionMessage(operationId, response.statusCode(), body); + return new ApiException(response.statusCode(), message, response.headers(), body); + } + + private String formatExceptionMessage(String operationId, int statusCode, String body) { + if (body == null || body.isEmpty()) { + body = "[no body]"; + } + return operationId + " call failed with: " + statusCode + " - " + body; + } + + /** + * @throws ApiException if fails to make API call + */ + public void idpKeysCieGet() throws ApiException { + idpKeysCieGetWithHttpInfo(); + } + + /** + * @return ApiResponse<Void> + * @throws ApiException if fails to make API call + */ + public ApiResponse idpKeysCieGetWithHttpInfo() throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysCieGetRequestBuilder(); + try { + HttpResponse localVarResponse = + memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode() / 100 != 2) { + throw getApiException("idpKeysCieGet", localVarResponse); + } + return new ApiResponse( + localVarResponse.statusCode(), localVarResponse.headers().map(), null); + } finally { + // Drain the InputStream + while (localVarResponse.body().read() != -1) { + // Ignore + } + localVarResponse.body().close(); + } + } catch (IOException e) { + throw new ApiException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } + + private HttpRequest.Builder idpKeysCieGetRequestBuilder() throws ApiException { + + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + + String localVarPath = "/idp-keys/cie"; + + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + + localVarRequestBuilder.header("Accept", "application/json"); + + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; + } + /** + * @param tag (required) + * @throws ApiException if fails to make API call + */ + public void idpKeysCieTagGet(String tag) throws ApiException { + idpKeysCieTagGetWithHttpInfo(tag); + } + + /** + * @param tag (required) + * @return ApiResponse<Void> + * @throws ApiException if fails to make API call + */ + public ApiResponse idpKeysCieTagGetWithHttpInfo(String tag) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysCieTagGetRequestBuilder(tag); + try { + HttpResponse localVarResponse = + memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode() / 100 != 2) { + throw getApiException("idpKeysCieTagGet", localVarResponse); + } + return new ApiResponse( + localVarResponse.statusCode(), localVarResponse.headers().map(), null); + } finally { + // Drain the InputStream + while (localVarResponse.body().read() != -1) { + // Ignore + } + localVarResponse.body().close(); + } + } catch (IOException e) { + throw new ApiException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } + + private HttpRequest.Builder idpKeysCieTagGetRequestBuilder(String tag) throws ApiException { + // verify the required parameter 'tag' is set + if (tag == null) { + throw new ApiException( + 400, "Missing the required parameter 'tag' when calling idpKeysCieTagGet"); + } + + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + + String localVarPath = + "/idp-keys/cie/{tag}".replace("{tag}", ApiClient.urlEncode(tag.toString())); + + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + + localVarRequestBuilder.header("Accept", "application/json"); + + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; + } + /** + * @throws ApiException if fails to make API call + */ + public void idpKeysSpidGet() throws ApiException { + idpKeysSpidGetWithHttpInfo(); + } + + /** + * @return ApiResponse<Void> + * @throws ApiException if fails to make API call + */ + public ApiResponse idpKeysSpidGetWithHttpInfo() throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysSpidGetRequestBuilder(); + try { + HttpResponse localVarResponse = + memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode() / 100 != 2) { + throw getApiException("idpKeysSpidGet", localVarResponse); + } + return new ApiResponse( + localVarResponse.statusCode(), localVarResponse.headers().map(), null); + } finally { + // Drain the InputStream + while (localVarResponse.body().read() != -1) { + // Ignore + } + localVarResponse.body().close(); + } + } catch (IOException e) { + throw new ApiException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } + + private HttpRequest.Builder idpKeysSpidGetRequestBuilder() throws ApiException { + + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + + String localVarPath = "/idp-keys/spid"; + + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + + localVarRequestBuilder.header("Accept", "application/json"); + + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; + } + /** + * @param tag (required) + * @throws ApiException if fails to make API call + */ + public void idpKeysSpidTagGet(String tag) throws ApiException { + idpKeysSpidTagGetWithHttpInfo(tag); + } + + /** + * @param tag (required) + * @return ApiResponse<Void> + * @throws ApiException if fails to make API call + */ + public ApiResponse idpKeysSpidTagGetWithHttpInfo(String tag) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysSpidTagGetRequestBuilder(tag); + try { + HttpResponse localVarResponse = + memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode() / 100 != 2) { + throw getApiException("idpKeysSpidTagGet", localVarResponse); + } + return new ApiResponse( + localVarResponse.statusCode(), localVarResponse.headers().map(), null); + } finally { + // Drain the InputStream + while (localVarResponse.body().read() != -1) { + // Ignore + } + localVarResponse.body().close(); + } + } catch (IOException e) { + throw new ApiException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } + + private HttpRequest.Builder idpKeysSpidTagGetRequestBuilder(String tag) throws ApiException { + // verify the required parameter 'tag' is set + if (tag == null) { + throw new ApiException( + 400, "Missing the required parameter 'tag' when calling idpKeysSpidTagGet"); + } + + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + + String localVarPath = + "/idp-keys/spid/{tag}".replace("{tag}", ApiClient.urlEncode(tag.toString())); + + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + + localVarRequestBuilder.header("Accept", "application/json"); + + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java new file mode 100644 index 00000000..e5c342aa --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java @@ -0,0 +1,135 @@ +/* (C)2022-2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; + +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Map; +import java.util.Objects; + +/** Abstract class for oneOf,anyOf schemas defined in OpenAPI spec */ +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +public abstract class AbstractOpenApiSchema { + + // store the actual instance of the schema/object + private Object instance; + + // is nullable + private Boolean isNullable; + + // schema type (e.g. oneOf, anyOf) + private final String schemaType; + + public AbstractOpenApiSchema(String schemaType, Boolean isNullable) { + this.schemaType = schemaType; + this.isNullable = isNullable; + } + + /** + * Get the list of oneOf/anyOf composed schemas allowed to be stored in this object + * + * @return an instance of the actual schema/object + */ + public abstract Map> getSchemas(); + + /** + * Get the actual instance + * + * @return an instance of the actual schema/object + */ + @JsonValue + public Object getActualInstance() { + return instance; + } + + /** + * Set the actual instance + * + * @param instance the actual instance of the schema/object + */ + public void setActualInstance(Object instance) { + this.instance = instance; + } + + /** + * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf + * schema as well + * + * @return an instance of the actual schema/object + */ + public Object getActualInstanceRecursively() { + return getActualInstanceRecursively(this); + } + + private Object getActualInstanceRecursively(AbstractOpenApiSchema object) { + if (object.getActualInstance() == null) { + return null; + } else if (object.getActualInstance() instanceof AbstractOpenApiSchema) { + return getActualInstanceRecursively((AbstractOpenApiSchema) object.getActualInstance()); + } else { + return object.getActualInstance(); + } + } + + /** + * Get the schema type (e.g. anyOf, oneOf) + * + * @return the schema type + */ + public String getSchemaType() { + return schemaType; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ").append(getClass()).append(" {\n"); + sb.append(" instance: ").append(toIndentedString(instance)).append("\n"); + sb.append(" isNullable: ").append(toIndentedString(isNullable)).append("\n"); + sb.append(" schemaType: ").append(toIndentedString(schemaType)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first + * line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AbstractOpenApiSchema a = (AbstractOpenApiSchema) o; + return Objects.equals(this.instance, a.instance) + && Objects.equals(this.isNullable, a.isNullable) + && Objects.equals(this.schemaType, a.schemaType); + } + + @Override + public int hashCode() { + return Objects.hash(instance, isNullable, schemaType); + } + + /** + * Is nullable + * + * @return true if it's nullable + */ + public Boolean isNullable() { + if (Boolean.TRUE.equals(isNullable)) { + return Boolean.TRUE; + } else { + return Boolean.FALSE; + } + } +} From d84bbaae3fbb36b78bcc02f0d2d68b7ee9db482c Mon Sep 17 00:00:00 2001 From: svariant Date: Thu, 6 Apr 2023 17:45:05 +0200 Subject: [PATCH 051/403] [SLS-19] Added error for oidc assertion in AssertionSimpleClient - not supported yet --- .../client/simple/AssertionSimpleClient.java | 7 ++++++- .../client/simple/AssertionSimpleClientTest.java | 3 ++- .../assertion/client/AssertionClient.java | 3 ++- .../exception/OidcAssertionNotSupported.java | 15 +++++++++++++++ 4 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/OidcAssertionNotSupported.java diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java index adf568dc..4f437124 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java @@ -7,8 +7,10 @@ import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.api.DefaultApi; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.AssertionRef; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.LCUserInfo; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.OidcUserInfo; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.SamlUserInfo; import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.OidcAssertionNotSupported; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import javax.inject.Inject; @@ -35,7 +37,7 @@ public AssertionSimpleClient(ApiClient client) { */ @Override public SamlAssertion getAssertion(String jwt, String assertionRef) - throws LollipopAssertionNotFoundException { + throws LollipopAssertionNotFoundException, OidcAssertionNotSupported { AssertionRef ref = new AssertionRef(assertionRef); if (jwt.isEmpty() || assertionRef.isEmpty()) { @@ -59,6 +61,9 @@ public SamlAssertion getAssertion(String jwt, String assertionRef) response.setAssertionData(assertionData); return response; } + if (responseAssertion.getActualInstance().getClass().equals(OidcUserInfo.class)) { + throw new OidcAssertionNotSupported("OIDC Claims not supported yet."); + } return null; } diff --git a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java index 291f0516..04d11dee 100644 --- a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java +++ b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java @@ -7,6 +7,7 @@ import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.OidcAssertionNotSupported; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; @@ -159,7 +160,7 @@ public static void startServer() { } @Test - void samlAssertionFound() throws LollipopAssertionNotFoundException { + void samlAssertionFound() throws LollipopAssertionNotFoundException, OidcAssertionNotSupported { // setup String xmlResponse = " Date: Thu, 6 Apr 2023 16:53:19 +0200 Subject: [PATCH 052/403] Create build-gradle-project.yml --- .github/workflows/build-gradle-project.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .github/workflows/build-gradle-project.yml diff --git a/.github/workflows/build-gradle-project.yml b/.github/workflows/build-gradle-project.yml new file mode 100644 index 00000000..cccf56d0 --- /dev/null +++ b/.github/workflows/build-gradle-project.yml @@ -0,0 +1,16 @@ +name: Build Gradle project + +on: + push: + pull_request: + +jobs: + build-gradle-project: + runs-on: ubuntu-latest + steps: + - name: Checkout project sources + uses: actions/checkout@v2 + - name: Setup Gradle + uses: gradle/gradle-build-action@v2 + - name: Run build with Gradle Wrapper + run: ./gradlew build From a17f1e7ec76d77c815a65156a18cf201eec453be Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Thu, 6 Apr 2023 16:56:10 +0200 Subject: [PATCH 053/403] Update build-gradle-project.yml --- .github/workflows/build-gradle-project.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-gradle-project.yml b/.github/workflows/build-gradle-project.yml index cccf56d0..86794929 100644 --- a/.github/workflows/build-gradle-project.yml +++ b/.github/workflows/build-gradle-project.yml @@ -12,5 +12,7 @@ jobs: uses: actions/checkout@v2 - name: Setup Gradle uses: gradle/gradle-build-action@v2 + - name: Make gradlew executable + run: chmod +x ./gradlew - name: Run build with Gradle Wrapper run: ./gradlew build From 0c4fe64a7d10c016c3b43806c5da0e2ffc1452d3 Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Thu, 6 Apr 2023 17:06:29 +0200 Subject: [PATCH 054/403] Update build-gradle-project.yml --- .github/workflows/build-gradle-project.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-gradle-project.yml b/.github/workflows/build-gradle-project.yml index 86794929..cee4d34f 100644 --- a/.github/workflows/build-gradle-project.yml +++ b/.github/workflows/build-gradle-project.yml @@ -1,7 +1,6 @@ name: Build Gradle project on: - push: pull_request: jobs: @@ -9,7 +8,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout project sources - uses: actions/checkout@v2 + uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Setup Gradle uses: gradle/gradle-build-action@v2 - name: Make gradlew executable From c90da245f0ee2989afba7ab507b62b2cbeb17cbd Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 6 Apr 2023 19:46:02 +0200 Subject: [PATCH 055/403] [SLS-31] Updated build.gradle --- build.gradle | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/build.gradle b/build.gradle index 16e65d8c..96c68616 100644 --- a/build.gradle +++ b/build.gradle @@ -20,6 +20,19 @@ allprojects { apply plugin: 'nebula.lint' gradleLint.rules = ['all-dependency'] + configurations { + spotless { + resolutionStrategy { + disableDependencyVerification() + } + } + gradleLint { + resolutionStrategy { + disableDependencyVerification() + } + } + } + spotless { // optional: limit format enforcement to just the files changed by this feature branch ratchetFrom 'origin/main' From a501ee4f929d8118ccdaf97c1d09ebc7f69941d8 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 6 Apr 2023 19:53:56 +0200 Subject: [PATCH 056/403] [SLS-31] Updated verification-metadata.xml --- gradle/verification-metadata.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 9aa9291d..faeef5c9 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2205,12 +2205,19 @@ + + + + + + + From 3561d19422c0b0ded5e2c26749377714c8d12201 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 6 Apr 2023 20:09:37 +0200 Subject: [PATCH 057/403] [SLS-31] Updated build.gradle --- build.gradle | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/build.gradle b/build.gradle index 96c68616..6c079c37 100644 --- a/build.gradle +++ b/build.gradle @@ -4,6 +4,7 @@ plugins { id("com.diffplug.spotless") version "6.17.0" id("nebula.lint") version "18.0.3" id("org.kordamp.gradle.reproducible") version "0.50.0" + id("com.gradle.enterprise") version("3.9") } repositories { @@ -33,6 +34,16 @@ allprojects { } } + gradleEnterprise { + if (System.getenv("CI") != null) { + buildScan { + publishAlways() + termsOfServiceUrl = "https://gradle.com/terms-of-service" + termsOfServiceAgree = "yes" + } + } + } + spotless { // optional: limit format enforcement to just the files changed by this feature branch ratchetFrom 'origin/main' From 0f10a61f9d8ac09f37bd59a92d7a02fe7094735b Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 6 Apr 2023 20:13:22 +0200 Subject: [PATCH 058/403] [SLS-31] Updated build.gradle --- build.gradle | 12 +++--------- gradle/verification-metadata.xml | 13 +++++++++++++ settings.gradle | 14 ++++++++++++++ 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index 6c079c37..08d0913e 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,6 @@ plugins { id("com.diffplug.spotless") version "6.17.0" id("nebula.lint") version "18.0.3" id("org.kordamp.gradle.reproducible") version "0.50.0" - id("com.gradle.enterprise") version("3.9") } repositories { @@ -32,14 +31,9 @@ allprojects { disableDependencyVerification() } } - } - - gradleEnterprise { - if (System.getenv("CI") != null) { - buildScan { - publishAlways() - termsOfServiceUrl = "https://gradle.com/terms-of-service" - termsOfServiceAgree = "yes" + gradleEnterprise { + resolutionStrategy { + disableDependencyVerification() } } } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index faeef5c9..f9956b91 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -639,6 +639,19 @@ + + + + + + + + + + + + + diff --git a/settings.gradle b/settings.gradle index 231c70d5..8e918fab 100644 --- a/settings.gradle +++ b/settings.gradle @@ -14,5 +14,19 @@ pluginManagement { } } +plugins { + id("com.gradle.enterprise") version("3.9") +} + +gradleEnterprise { + if (System.getenv("CI") != null) { + buildScan { + publishAlways() + termsOfServiceUrl = "https://gradle.com/terms-of-service" + termsOfServiceAgree = "yes" + } + } +} + rootProject.name = 'eng-lollipop-consumer-java-sdk' include 'core', 'assertion-rest-client-native', 'http-verifier', 'identity-service-rest-client-native', 'redis-storage' From ee507ad852f0f602e4a85a7bb838640c635f37f0 Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Tue, 11 Apr 2023 11:35:19 +0200 Subject: [PATCH 059/403] Create PULL_REQUEST_TEMPLATE.md --- .github/PULL_REQUEST_TEMPLATE.md | 37 ++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..7086d553 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,37 @@ + + + + + +#### List of Changes + + + +#### Motivation and Context + + + +#### How Has This Been Tested? + + + + + +#### Screenshots (if appropriate): + +#### Types of changes + + + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as + expected) + +#### Checklist: + + + + +- [ ] My change requires a change to the documentation. +- [ ] I have updated the documentation accordingly. From f6173f4b54f7a3b1f93c268eb3a11c67e8da70d6 Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Tue, 11 Apr 2023 11:37:46 +0200 Subject: [PATCH 060/403] Create CODEOWNERS --- CODEOWNERS | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 CODEOWNERS diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 00000000..e514c2f9 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,3 @@ +# see https://help.github.com/en/articles/about-code-owners#example-of-a-codeowners-file + +* @pagopa/pagopa-tech From e926646d0e8c7b9697d2201d84ee316821d53faf Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Tue, 11 Apr 2023 12:00:39 +0200 Subject: [PATCH 061/403] Update and rename build-gradle-project.yml to pr_scan.yml --- .github/workflows/build-gradle-project.yml | 19 ------------ .github/workflows/pr_scan.yml | 36 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 19 deletions(-) delete mode 100644 .github/workflows/build-gradle-project.yml create mode 100644 .github/workflows/pr_scan.yml diff --git a/.github/workflows/build-gradle-project.yml b/.github/workflows/build-gradle-project.yml deleted file mode 100644 index cee4d34f..00000000 --- a/.github/workflows/build-gradle-project.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Build Gradle project - -on: - pull_request: - -jobs: - build-gradle-project: - runs-on: ubuntu-latest - steps: - - name: Checkout project sources - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Setup Gradle - uses: gradle/gradle-build-action@v2 - - name: Make gradlew executable - run: chmod +x ./gradlew - - name: Run build with Gradle Wrapper - run: ./gradlew build diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml new file mode 100644 index 00000000..2351b695 --- /dev/null +++ b/.github/workflows/pr_scan.yml @@ -0,0 +1,36 @@ +name: Build Gradle project + +on: + pull_request: + +env: + DOCKERFILE: Dockerfile + +jobs: + build-gradle-project: + runs-on: ubuntu-latest + steps: + - name: Checkout project sources + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Setup Gradle + uses: gradle/gradle-build-action@v2 + - name: Make gradlew executable + run: chmod +x ./gradlew + - name: Run build with Gradle Wrapper + run: ./gradlew build + - name: Build the Docker image + run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest + - name: Run the Anchore Grype scan action + uses: anchore/scan-action@d5aa5b6cb9414b0c7771438046ff5bcfa2854ed7 + id: scan + with: + image: "localbuild/testimage:latest" + fail-build: true + severity-cutoff: "high" + - name: Upload Anchore Scan Report + uses: github/codeql-action/upload-sarif@v2 + if: always() + with: + sarif_file: ${{ steps.scan.outputs.sarif }} From e83f309e49d72745a70b85e2b009c75fa1bc8967 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 12:10:03 +0200 Subject: [PATCH 062/403] [SLS-31] Updated build.gradle --- .github/workflows/pr_scan.yml | 2 +- Dockerfile.test-only | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 Dockerfile.test-only diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 2351b695..48aa8a97 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -4,7 +4,7 @@ on: pull_request: env: - DOCKERFILE: Dockerfile + DOCKERFILE: Dockerfile.test-only jobs: build-gradle-project: diff --git a/Dockerfile.test-only b/Dockerfile.test-only new file mode 100644 index 00000000..dc962125 --- /dev/null +++ b/Dockerfile.test-only @@ -0,0 +1,5 @@ +FROM openjdk:11-jre-slim + +RUN mkdir /app + +COPY core/build/libs/*.jar /app/core.jar \ No newline at end of file From af297ab137bd49ec36af882ee41463df5c5b853f Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 12:14:30 +0200 Subject: [PATCH 063/403] [SLS-31] Updated build.gradle --- .github/workflows/pr_scan.yml | 2 +- Dockerfile.test-only | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 48aa8a97..ec044da3 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -1,4 +1,4 @@ -name: Build Gradle project +name: Check Build and Anchore on PR on: pull_request: diff --git a/Dockerfile.test-only b/Dockerfile.test-only index dc962125..787f3d15 100644 --- a/Dockerfile.test-only +++ b/Dockerfile.test-only @@ -2,4 +2,4 @@ FROM openjdk:11-jre-slim RUN mkdir /app -COPY core/build/libs/*.jar /app/core.jar \ No newline at end of file +COPY core/build/libs/*.jar /app/ \ No newline at end of file From c41b28e3a2acb25c61acdcedc1578f38ec3575ec Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 12:23:24 +0200 Subject: [PATCH 064/403] [SLS-31] Test inserting dependency with vulnerability --- core/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/build.gradle b/core/build.gradle index a5d2b770..d44be93e 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -43,6 +43,9 @@ dependencies { testImplementation 'org.mockito:mockito-core:5.2.0' testImplementation 'org.mockito:mockito-junit-jupiter:5.2.0' testImplementation 'org.assertj:assertj-core:3.24.2' + // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind + implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4.1' + } tasks.named('test') { From 11fe45ecf6bb33549621c37661e29aa538fa49de Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 12:29:29 +0200 Subject: [PATCH 065/403] [SLS-31] Updated Dockerfile.test-only to use amazoncorretto version of the openjdk --- Dockerfile.test-only | 2 +- gradle/verification-metadata.xml | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Dockerfile.test-only b/Dockerfile.test-only index 787f3d15..6b35a682 100644 --- a/Dockerfile.test-only +++ b/Dockerfile.test-only @@ -1,4 +1,4 @@ -FROM openjdk:11-jre-slim +FROM amazoncorretto:11 RUN mkdir /app diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index f9956b91..4e3c6f42 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -135,6 +135,11 @@ + + + + + @@ -157,6 +162,11 @@ + + + + + @@ -201,6 +211,14 @@ + + + + + + + + @@ -227,6 +245,14 @@ + + + + + + + + @@ -253,6 +279,14 @@ + + + + + + + + From 026d565ca5f8b97d84898e9c8d007de72196501a Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 12:34:04 +0200 Subject: [PATCH 066/403] [SLS-31] Updated build.gradle --- core/build.gradle | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index d44be93e..a5d2b770 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -43,9 +43,6 @@ dependencies { testImplementation 'org.mockito:mockito-core:5.2.0' testImplementation 'org.mockito:mockito-junit-jupiter:5.2.0' testImplementation 'org.assertj:assertj-core:3.24.2' - // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind - implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4.1' - } tasks.named('test') { From 9620feff905f6e41459fab354a76767aff87588d Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 12:39:42 +0200 Subject: [PATCH 067/403] [SLS-31] Updated Dockerfile.test-only --- Dockerfile.test-only | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Dockerfile.test-only b/Dockerfile.test-only index 6b35a682..12491d05 100644 --- a/Dockerfile.test-only +++ b/Dockerfile.test-only @@ -2,4 +2,8 @@ FROM amazoncorretto:11 RUN mkdir /app -COPY core/build/libs/*.jar /app/ \ No newline at end of file +COPY core/build/libs/*.jar /app/ +COPY http-verifier/build/libs/*.jar /app/ +COPY redis-storage/build/libs/*.jar /app/ +COPY identity-service-rest-client-native/build/libs/*.jar /app/ +COPY assertion-rest-client-native/build/libs/*.jar /app/ \ No newline at end of file From 3fe0c3c3c9dc1bb7ac0bfb68846e601fbe26b99d Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 12:59:28 +0200 Subject: [PATCH 068/403] [SLS-31] Updated action file to contain references to the name 'pr_scan' --- .github/workflows/pr_scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index ec044da3..af448973 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -7,7 +7,7 @@ env: DOCKERFILE: Dockerfile.test-only jobs: - build-gradle-project: + pr_scan: runs-on: ubuntu-latest steps: - name: Checkout project sources From 41d74d99118e60f1afea99d59b3f023d7c903869 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 15:46:45 +0200 Subject: [PATCH 069/403] [SLS-31] Introducing config for library release --- .github/workflows/release.yaml | 24 ++++++++++++++++++++++++ build.gradle | 10 ++++++++++ 2 files changed, 34 insertions(+) create mode 100644 .github/workflows/release.yaml diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 00000000..41d5c897 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,24 @@ +name: Publish package to GitHub Packages +on: + release: + types: [created] +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 + with: + java-version: '11' + distribution: 'adopt' + - name: Validate Gradle wrapper + uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b + - name: Publish package + uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 + with: + arguments: publish + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 08d0913e..f7661683 100644 --- a/build.gradle +++ b/build.gradle @@ -120,6 +120,16 @@ subprojects { from components.java } } + repositories { + maven { + name = "GitHubPackages" + url = "https://maven.pkg.github.com/pagopa/eng-lollipop-consumer-java-sdk" + credentials { + username = System.getenv("GITHUB_ACTOR") + password = System.getenv("GITHUB_TOKEN") + } + } + } } } From bf707a3b71df4b7990a01776a5c08933435a6294 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 16:02:01 +0200 Subject: [PATCH 070/403] [SLS-31] Updated release.yaml --- .github/workflows/release.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 41d5c897..a9a6f6ef 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -16,6 +16,8 @@ jobs: distribution: 'adopt' - name: Validate Gradle wrapper uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b + - name: Make gradlew executable + run: chmod +x ./gradlew - name: Publish package uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 with: From 4a002a0da5d693c18b0eac3b694fd52fa3c17fd6 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 11 Apr 2023 16:45:01 +0200 Subject: [PATCH 071/403] [SLS-19] Updated openAPI generated client with response configuration --- .../openapi/openapi-spec.yml | 210 ++++- .../idp/client/simple/internal/ApiClient.java | 802 +++++++++--------- .../client/simple/internal/ApiException.java | 34 +- .../client/simple/internal/ApiResponse.java | 20 +- .../client/simple/internal/Configuration.java | 26 +- .../idp/client/simple/internal/JSON.java | 431 +++++----- .../idp/client/simple/internal/Pair.java | 20 +- .../simple/internal/RFC3339DateFormat.java | 77 +- .../simple/internal/ServerConfiguration.java | 23 +- .../simple/internal/ServerVariable.java | 8 +- .../simple/internal/api/DefaultApi.java | 549 ++++++------ .../internal/model/AbstractOpenApiSchema.java | 54 +- .../simple/internal/model/CIECertData.java | 157 ++++ .../simple/internal/model/CertData.java | 281 ++++++ .../internal/model/EntityDescriptor.java | 145 ++++ .../simple/internal/model/ProblemJson.java | 292 +++++++ .../simple/internal/model/SPIDCertData.java | 143 ++++ .../model/SPIDCertDataEntitiesDescriptor.java | 158 ++++ 18 files changed, 2453 insertions(+), 977 deletions(-) create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/ProblemJson.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertData.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertDataEntitiesDescriptor.java diff --git a/identity-service-rest-client-native/openapi/openapi-spec.yml b/identity-service-rest-client-native/openapi/openapi-spec.yml index cb180052..86a07ede 100644 --- a/identity-service-rest-client-native/openapi/openapi-spec.yml +++ b/identity-service-rest-client-native/openapi/openapi-spec.yml @@ -16,13 +16,67 @@ paths: responses: "200": description: "200 response" - content: {} + content: + application/json: + schema: + $ref: '#/components/schemas/TagList' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' + '410': + description: Assertion gone + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' /idp-keys/cie: get: responses: "200": description: "200 response" - content: {} + content: + application/json: + schema: + $ref: '#/components/schemas/TagList' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' + '410': + description: Assertion gone + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' /idp-keys/spid/{tag}: get: parameters: @@ -34,7 +88,34 @@ paths: responses: "200": description: "200 response" - content: {} + content: + application/xml: + schema: + $ref: '#/components/schemas/CertData' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' + '410': + description: Assertion gone + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' /idp-keys/cie/{tag}: get: parameters: @@ -46,5 +127,124 @@ paths: responses: "200": description: "200 response" - content: {} -components: {} \ No newline at end of file + content: + application/xml: + schema: + $ref: '#/components/schemas/CertData' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' + '410': + description: Assertion gone + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' +components: + schemas: + ProblemJson: + type: object + properties: + type: + type: string + format: uri + description: |- + An absolute URI that identifies the problem type. When dereferenced, + it SHOULD provide human-readable documentation for the problem type + (e.g., using HTML). + default: about:blank + example: https://example.com/problem/constraint-violation + title: + type: string + description: >- + A short, summary of the problem type. Written in english and + readable + + for engineers (usually not suited for non technical stakeholders and + + not localized); example: Service Unavailable + status: + type: integer + format: int32 + description: >- + The HTTP status code generated by the origin server for this + occurrence + + of the problem. + minimum: 100 + maximum: 600 + exclusiveMaximum: true + example: 200 + detail: + type: string + description: |- + A human readable explanation specific to this occurrence of the + problem. + example: There was an error processing the request + instance: + type: string + format: uri + description: >- + An absolute URI that identifies the specific occurrence of the + problem. + + It may or may not yield further information if dereferenced. + TagList: + type: array + items: + type: string + EntityDescriptor: + type: object + properties: + entityID: + type: string + xml: + attribute: true + required: + - entityID + SPIDCertData: + type: object + properties: + entitiesDescriptor: + type: object + properties: + entityDescriptor: + type: array + items: + $ref: '#/components/schemas/EntityDescriptor' + xml: + name: "EntityDescriptor" + prefix: "md" + namespace: "urn:oasis:names:tc:SAML:2.0:metadata" + xml: + name: "EntitiesDescriptor" + prefix: "md" + namespace: "urn:oasis:names:tc:SAML:2.0:metadata" + CIECertData: + type: object + properties: + entityDescriptor: + type: array + items: + $ref: '#/components/schemas/EntityDescriptor' + xml: + name: "EntityDescriptor" + CertData: + oneOf: + - $ref: '#/components/schemas/CIECertData' + - $ref: '#/components/schemas/SPIDCertData' \ No newline at end of file diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java index 6405bcf6..a3fcc124 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java @@ -1,13 +1,24 @@ -/* (C)2022-2023 */ -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ -import static java.nio.charset.StandardCharsets.UTF_8; +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.openapitools.jackson.nullable.JsonNullableModule; + import java.io.InputStream; import java.net.URI; import java.net.URLEncoder; @@ -24,413 +35,422 @@ import java.util.StringJoiner; import java.util.function.Consumer; import java.util.stream.Collectors; -import org.openapitools.jackson.nullable.JsonNullableModule; + +import static java.nio.charset.StandardCharsets.UTF_8; /** * Configuration and utility class for API clients. * - *

This class can be constructed and modified, then used to instantiate the various API classes. - * The API classes use the settings in this class to configure themselves, but otherwise do not - * store a link to this class. + *

This class can be constructed and modified, then used to instantiate the + * various API classes. The API classes use the settings in this class to + * configure themselves, but otherwise do not store a link to this class.

* - *

This class is mutable and not synchronized, so it is not thread-safe. The API classes - * generated from this are immutable and thread-safe. + *

This class is mutable and not synchronized, so it is not thread-safe. + * The API classes generated from this are immutable and thread-safe.

* - *

The setter methods of this class return the current object to facilitate a fluent style of - * configuration. + *

The setter methods of this class return the current object to facilitate + * a fluent style of configuration.

*/ -@javax.annotation.Generated( - value = "org.openapitools.codegen.languages.JavaClientCodegen", - date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class ApiClient { - private HttpClient.Builder builder; - private ObjectMapper mapper; - private String scheme; - private String host; - private int port; - private String basePath; - private Consumer interceptor; - private Consumer> responseInterceptor; - private Consumer> asyncResponseInterceptor; - private Duration readTimeout; - private Duration connectTimeout; - - private static String valueToString(Object value) { - if (value == null) { - return ""; - } - if (value instanceof OffsetDateTime) { - return ((OffsetDateTime) value).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); - } - return value.toString(); - } - - /** - * URL encode a string in the UTF-8 encoding. - * - * @param s String to encode. - * @return URL-encoded representation of the input string. - */ - public static String urlEncode(String s) { - return URLEncoder.encode(s, UTF_8).replaceAll("\\+", "%20"); - } - - /** - * Convert a URL query name/value parameter to a list of encoded {@link Pair} objects. - * - *

The value can be null, in which case an empty list is returned. - * - * @param name The query name parameter. - * @param value The query value, which may not be a collection but may be null. - * @return A singleton list of the {@link Pair} objects representing the input parameters, which - * is encoded for use in a URL. If the value is null, an empty list is returned. - */ - public static List parameterToPairs(String name, Object value) { - if (name == null || name.isEmpty() || value == null) { - return Collections.emptyList(); - } - return Collections.singletonList( - new Pair(urlEncode(name), urlEncode(valueToString(value)))); - } - - /** - * Convert a URL query name/collection parameter to a list of encoded {@link Pair} objects. - * - * @param collectionFormat The swagger collectionFormat string (csv, tsv, etc). - * @param name The query name parameter. - * @param values A collection of values for the given query name, which may be null. - * @return A list of {@link Pair} objects representing the input parameters, which is encoded - * for use in a URL. If the values collection is null, an empty list is returned. - */ - public static List parameterToPairs( - String collectionFormat, String name, Collection values) { - if (name == null || name.isEmpty() || values == null || values.isEmpty()) { - return Collections.emptyList(); - } - - // get the collection format (default: csv) - String format = - collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat; - - // create the params based on the collection format - if ("multi".equals(format)) { - return values.stream() - .map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value)))) - .collect(Collectors.toList()); - } - - String delimiter; - switch (format) { - case "csv": - delimiter = urlEncode(","); - break; - case "ssv": - delimiter = urlEncode(" "); - break; - case "tsv": - delimiter = urlEncode("\t"); - break; - case "pipes": - delimiter = urlEncode("|"); - break; - default: - throw new IllegalArgumentException( - "Illegal collection format: " + collectionFormat); - } - - StringJoiner joiner = new StringJoiner(delimiter); - for (Object value : values) { - joiner.add(urlEncode(valueToString(value))); - } - - return Collections.singletonList(new Pair(urlEncode(name), joiner.toString())); - } - - /** Create an instance of ApiClient. */ - public ApiClient() { - this.builder = createDefaultHttpClientBuilder(); - this.mapper = createDefaultObjectMapper(); - updateBaseUri(getDefaultBaseUri()); - interceptor = null; - readTimeout = null; - connectTimeout = null; - responseInterceptor = null; - asyncResponseInterceptor = null; - } - - /** - * Create an instance of ApiClient. - * - * @param builder Http client builder. - * @param mapper Object mapper. - * @param baseUri Base URI - */ - public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, String baseUri) { - this.builder = builder; - this.mapper = mapper; - updateBaseUri(baseUri != null ? baseUri : getDefaultBaseUri()); - interceptor = null; - readTimeout = null; - connectTimeout = null; - responseInterceptor = null; - asyncResponseInterceptor = null; + private HttpClient.Builder builder; + private ObjectMapper mapper; + private String scheme; + private String host; + private int port; + private String basePath; + private Consumer interceptor; + private Consumer> responseInterceptor; + private Consumer> asyncResponseInterceptor; + private Duration readTimeout; + private Duration connectTimeout; + + private static String valueToString(Object value) { + if (value == null) { + return ""; } - - protected ObjectMapper createDefaultObjectMapper() { - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); - mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); - mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); - mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); - mapper.registerModule(new JavaTimeModule()); - mapper.registerModule(new JsonNullableModule()); - return mapper; + if (value instanceof OffsetDateTime) { + return ((OffsetDateTime) value).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); } - - protected String getDefaultBaseUri() { - return "https://api.is.eng.pagopa.it"; + return value.toString(); + } + + /** + * URL encode a string in the UTF-8 encoding. + * + * @param s String to encode. + * @return URL-encoded representation of the input string. + */ + public static String urlEncode(String s) { + return URLEncoder.encode(s, UTF_8).replaceAll("\\+", "%20"); + } + + /** + * Convert a URL query name/value parameter to a list of encoded {@link Pair} + * objects. + * + *

The value can be null, in which case an empty list is returned.

+ * + * @param name The query name parameter. + * @param value The query value, which may not be a collection but may be + * null. + * @return A singleton list of the {@link Pair} objects representing the input + * parameters, which is encoded for use in a URL. If the value is null, an + * empty list is returned. + */ + public static List parameterToPairs(String name, Object value) { + if (name == null || name.isEmpty() || value == null) { + return Collections.emptyList(); } - - protected HttpClient.Builder createDefaultHttpClientBuilder() { - return HttpClient.newBuilder(); + return Collections.singletonList(new Pair(urlEncode(name), urlEncode(valueToString(value)))); + } + + /** + * Convert a URL query name/collection parameter to a list of encoded + * {@link Pair} objects. + * + * @param collectionFormat The swagger collectionFormat string (csv, tsv, etc). + * @param name The query name parameter. + * @param values A collection of values for the given query name, which may be + * null. + * @return A list of {@link Pair} objects representing the input parameters, + * which is encoded for use in a URL. If the values collection is null, an + * empty list is returned. + */ + public static List parameterToPairs( + String collectionFormat, String name, Collection values) { + if (name == null || name.isEmpty() || values == null || values.isEmpty()) { + return Collections.emptyList(); } - public void updateBaseUri(String baseUri) { - URI uri = URI.create(baseUri); - scheme = uri.getScheme(); - host = uri.getHost(); - port = uri.getPort(); - basePath = uri.getRawPath(); - } + // get the collection format (default: csv) + String format = collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat; - /** - * Set a custom {@link HttpClient.Builder} object to use when creating the {@link HttpClient} - * that is used by the API client. - * - * @param builder Custom client builder. - * @return This object. - */ - public ApiClient setHttpClientBuilder(HttpClient.Builder builder) { - this.builder = builder; - return this; + // create the params based on the collection format + if ("multi".equals(format)) { + return values.stream() + .map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value)))) + .collect(Collectors.toList()); } - /** - * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}. - * - *

The returned object is immutable and thread-safe. - * - * @return The HTTP client. - */ - public HttpClient getHttpClient() { - return builder.build(); + String delimiter; + switch(format) { + case "csv": + delimiter = urlEncode(","); + break; + case "ssv": + delimiter = urlEncode(" "); + break; + case "tsv": + delimiter = urlEncode("\t"); + break; + case "pipes": + delimiter = urlEncode("|"); + break; + default: + throw new IllegalArgumentException("Illegal collection format: " + collectionFormat); } - /** - * Set a custom {@link ObjectMapper} to serialize and deserialize the request and response - * bodies. - * - * @param mapper Custom object mapper. - * @return This object. - */ - public ApiClient setObjectMapper(ObjectMapper mapper) { - this.mapper = mapper; - return this; + StringJoiner joiner = new StringJoiner(delimiter); + for (Object value : values) { + joiner.add(urlEncode(valueToString(value))); } - /** - * Get a copy of the current {@link ObjectMapper}. - * - * @return A copy of the current object mapper. - */ - public ObjectMapper getObjectMapper() { - return mapper.copy(); - } - - /** - * Set a custom host name for the target service. - * - * @param host The host name of the target service. - * @return This object. - */ - public ApiClient setHost(String host) { - this.host = host; - return this; - } - - /** - * Set a custom port number for the target service. - * - * @param port The port of the target service. Set this to -1 to reset the value to the default - * for the scheme. - * @return This object. - */ - public ApiClient setPort(int port) { - this.port = port; - return this; - } - - /** - * Set a custom base path for the target service, for example '/v2'. - * - * @param basePath The base path against which the rest of the path is resolved. - * @return This object. - */ - public ApiClient setBasePath(String basePath) { - this.basePath = basePath; - return this; - } - - /** - * Get the base URI to resolve the endpoint paths against. - * - * @return The complete base URI that the rest of the API parameters are resolved against. - */ - public String getBaseUri() { - return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; - } - - /** - * Set a custom scheme for the target service, for example 'https'. - * - * @param scheme The scheme of the target service - * @return This object. - */ - public ApiClient setScheme(String scheme) { - this.scheme = scheme; - return this; - } - - /** - * Set a custom request interceptor. - * - *

A request interceptor is a mechanism for altering each request before it is sent. After - * the request has been fully configured but not yet built, the request builder is passed into - * this function for further modification, after which it is sent out. - * - *

This is useful for altering the requests in a custom manner, such as adding headers. It - * could also be used for logging and monitoring. - * - * @param interceptor A function invoked before creating each request. A value of null resets - * the interceptor to a no-op. - * @return This object. - */ - public ApiClient setRequestInterceptor(Consumer interceptor) { - this.interceptor = interceptor; - return this; - } - - /** - * Get the custom interceptor. - * - * @return The custom interceptor that was set, or null if there isn't any. - */ - public Consumer getRequestInterceptor() { - return interceptor; - } - - /** - * Set a custom response interceptor. - * - *

This is useful for logging, monitoring or extraction of header variables - * - * @param interceptor A function invoked before creating each request. A value of null resets - * the interceptor to a no-op. - * @return This object. - */ - public ApiClient setResponseInterceptor(Consumer> interceptor) { - this.responseInterceptor = interceptor; - return this; - } - - /** - * Get the custom response interceptor. - * - * @return The custom interceptor that was set, or null if there isn't any. - */ - public Consumer> getResponseInterceptor() { - return responseInterceptor; - } - - /** - * Set a custom async response interceptor. Use this interceptor when asyncNative is set to - * 'true'. - * - *

This is useful for logging, monitoring or extraction of header variables - * - * @param interceptor A function invoked before creating each request. A value of null resets - * the interceptor to a no-op. - * @return This object. - */ - public ApiClient setAsyncResponseInterceptor(Consumer> interceptor) { - this.asyncResponseInterceptor = interceptor; - return this; - } - - /** - * Get the custom async response interceptor. Use this interceptor when asyncNative is set to - * 'true'. - * - * @return The custom interceptor that was set, or null if there isn't any. - */ - public Consumer> getAsyncResponseInterceptor() { - return asyncResponseInterceptor; - } - - /** - * Set the read timeout for the http client. - * - *

This is the value used by default for each request, though it can be overridden on a - * per-request basis with a request interceptor. - * - * @param readTimeout The read timeout used by default by the http client. Setting this value to - * null resets the timeout to an effectively infinite value. - * @return This object. - */ - public ApiClient setReadTimeout(Duration readTimeout) { - this.readTimeout = readTimeout; - return this; - } - - /** - * Get the read timeout that was set. - * - * @return The read timeout, or null if no timeout was set. Null represents an infinite wait - * time. - */ - public Duration getReadTimeout() { - return readTimeout; - } - /** - * Sets the connect timeout (in milliseconds) for the http client. - * - *

In the case where a new connection needs to be established, if the connection cannot be - * established within the given {@code duration}, then {@link - * HttpClient#send(HttpRequest,BodyHandler) HttpClient::send} throws an {@link - * HttpConnectTimeoutException}, or {@link HttpClient#sendAsync(HttpRequest,BodyHandler) - * HttpClient::sendAsync} completes exceptionally with an {@code HttpConnectTimeoutException}. - * If a new connection does not need to be established, for example if a connection can be - * reused from a previous request, then this timeout duration has no effect. - * - * @param connectTimeout connection timeout in milliseconds - * @return This object. - */ - public ApiClient setConnectTimeout(Duration connectTimeout) { - this.connectTimeout = connectTimeout; - this.builder.connectTimeout(connectTimeout); - return this; - } - - /** - * Get connection timeout (in milliseconds). - * - * @return Timeout in milliseconds - */ - public Duration getConnectTimeout() { - return connectTimeout; - } + return Collections.singletonList(new Pair(urlEncode(name), joiner.toString())); + } + + /** + * Create an instance of ApiClient. + */ + public ApiClient() { + this.builder = createDefaultHttpClientBuilder(); + this.mapper = createDefaultObjectMapper(); + updateBaseUri(getDefaultBaseUri()); + interceptor = null; + readTimeout = null; + connectTimeout = null; + responseInterceptor = null; + asyncResponseInterceptor = null; + } + + /** + * Create an instance of ApiClient. + * + * @param builder Http client builder. + * @param mapper Object mapper. + * @param baseUri Base URI + */ + public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, String baseUri) { + this.builder = builder; + this.mapper = mapper; + updateBaseUri(baseUri != null ? baseUri : getDefaultBaseUri()); + interceptor = null; + readTimeout = null; + connectTimeout = null; + responseInterceptor = null; + asyncResponseInterceptor = null; + } + + protected ObjectMapper createDefaultObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); + mapper.registerModule(new JavaTimeModule()); + mapper.registerModule(new JsonNullableModule()); + return mapper; + } + + protected String getDefaultBaseUri() { + return "https://api.is.eng.pagopa.it"; + } + + protected HttpClient.Builder createDefaultHttpClientBuilder() { + return HttpClient.newBuilder(); + } + + public void updateBaseUri(String baseUri) { + URI uri = URI.create(baseUri); + scheme = uri.getScheme(); + host = uri.getHost(); + port = uri.getPort(); + basePath = uri.getRawPath(); + } + + /** + * Set a custom {@link HttpClient.Builder} object to use when creating the + * {@link HttpClient} that is used by the API client. + * + * @param builder Custom client builder. + * @return This object. + */ + public ApiClient setHttpClientBuilder(HttpClient.Builder builder) { + this.builder = builder; + return this; + } + + /** + * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}. + * + *

The returned object is immutable and thread-safe.

+ * + * @return The HTTP client. + */ + public HttpClient getHttpClient() { + return builder.build(); + } + + /** + * Set a custom {@link ObjectMapper} to serialize and deserialize the request + * and response bodies. + * + * @param mapper Custom object mapper. + * @return This object. + */ + public ApiClient setObjectMapper(ObjectMapper mapper) { + this.mapper = mapper; + return this; + } + + /** + * Get a copy of the current {@link ObjectMapper}. + * + * @return A copy of the current object mapper. + */ + public ObjectMapper getObjectMapper() { + return mapper.copy(); + } + + /** + * Set a custom host name for the target service. + * + * @param host The host name of the target service. + * @return This object. + */ + public ApiClient setHost(String host) { + this.host = host; + return this; + } + + /** + * Set a custom port number for the target service. + * + * @param port The port of the target service. Set this to -1 to reset the + * value to the default for the scheme. + * @return This object. + */ + public ApiClient setPort(int port) { + this.port = port; + return this; + } + + /** + * Set a custom base path for the target service, for example '/v2'. + * + * @param basePath The base path against which the rest of the path is + * resolved. + * @return This object. + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get the base URI to resolve the endpoint paths against. + * + * @return The complete base URI that the rest of the API parameters are + * resolved against. + */ + public String getBaseUri() { + return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; + } + + /** + * Set a custom scheme for the target service, for example 'https'. + * + * @param scheme The scheme of the target service + * @return This object. + */ + public ApiClient setScheme(String scheme){ + this.scheme = scheme; + return this; + } + + /** + * Set a custom request interceptor. + * + *

A request interceptor is a mechanism for altering each request before it + * is sent. After the request has been fully configured but not yet built, the + * request builder is passed into this function for further modification, + * after which it is sent out.

+ * + *

This is useful for altering the requests in a custom manner, such as + * adding headers. It could also be used for logging and monitoring.

+ * + * @param interceptor A function invoked before creating each request. A value + * of null resets the interceptor to a no-op. + * @return This object. + */ + public ApiClient setRequestInterceptor(Consumer interceptor) { + this.interceptor = interceptor; + return this; + } + + /** + * Get the custom interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer getRequestInterceptor() { + return interceptor; + } + + /** + * Set a custom response interceptor. + * + *

This is useful for logging, monitoring or extraction of header variables

+ * + * @param interceptor A function invoked before creating each request. A value + * of null resets the interceptor to a no-op. + * @return This object. + */ + public ApiClient setResponseInterceptor(Consumer> interceptor) { + this.responseInterceptor = interceptor; + return this; + } + + /** + * Get the custom response interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getResponseInterceptor() { + return responseInterceptor; + } + + /** + * Set a custom async response interceptor. Use this interceptor when asyncNative is set to 'true'. + * + *

This is useful for logging, monitoring or extraction of header variables

+ * + * @param interceptor A function invoked before creating each request. A value + * of null resets the interceptor to a no-op. + * @return This object. + */ + public ApiClient setAsyncResponseInterceptor(Consumer> interceptor) { + this.asyncResponseInterceptor = interceptor; + return this; + } + + /** + * Get the custom async response interceptor. Use this interceptor when asyncNative is set to 'true'. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getAsyncResponseInterceptor() { + return asyncResponseInterceptor; + } + + /** + * Set the read timeout for the http client. + * + *

This is the value used by default for each request, though it can be + * overridden on a per-request basis with a request interceptor.

+ * + * @param readTimeout The read timeout used by default by the http client. + * Setting this value to null resets the timeout to an + * effectively infinite value. + * @return This object. + */ + public ApiClient setReadTimeout(Duration readTimeout) { + this.readTimeout = readTimeout; + return this; + } + + /** + * Get the read timeout that was set. + * + * @return The read timeout, or null if no timeout was set. Null represents + * an infinite wait time. + */ + public Duration getReadTimeout() { + return readTimeout; + } + /** + * Sets the connect timeout (in milliseconds) for the http client. + * + *

In the case where a new connection needs to be established, if + * the connection cannot be established within the given {@code + * duration}, then {@link HttpClient#send(HttpRequest,BodyHandler) + * HttpClient::send} throws an {@link HttpConnectTimeoutException}, or + * {@link HttpClient#sendAsync(HttpRequest,BodyHandler) + * HttpClient::sendAsync} completes exceptionally with an + * {@code HttpConnectTimeoutException}. If a new connection does not + * need to be established, for example if a connection can be reused + * from a previous request, then this timeout duration has no effect. + * + * @param connectTimeout connection timeout in milliseconds + * + * @return This object. + */ + public ApiClient setConnectTimeout(Duration connectTimeout) { + this.connectTimeout = connectTimeout; + this.builder.connectTimeout(connectTimeout); + return this; + } + + /** + * Get connection timeout (in milliseconds). + * + * @return Timeout in milliseconds + */ + public Duration getConnectTimeout() { + return connectTimeout; + } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java index 5297d641..b4f92de1 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java @@ -1,11 +1,21 @@ -/* (C)2022-2023 */ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; import java.net.http.HttpHeaders; -@javax.annotation.Generated( - value = "org.openapitools.codegen.languages.JavaClientCodegen", - date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class ApiException extends RuntimeException { private int code = 0; private HttpHeaders responseHeaders = null; @@ -21,25 +31,18 @@ public ApiException(String message) { super(message); } - public ApiException( - String message, - Throwable throwable, - int code, - HttpHeaders responseHeaders, - String responseBody) { + public ApiException(String message, Throwable throwable, int code, HttpHeaders responseHeaders, String responseBody) { super(message, throwable); this.code = code; this.responseHeaders = responseHeaders; this.responseBody = responseBody; } - public ApiException( - String message, int code, HttpHeaders responseHeaders, String responseBody) { + public ApiException(String message, int code, HttpHeaders responseHeaders, String responseBody) { this(message, (Throwable) null, code, responseHeaders, responseBody); } - public ApiException( - String message, Throwable throwable, int code, HttpHeaders responseHeaders) { + public ApiException(String message, Throwable throwable, int code, HttpHeaders responseHeaders) { this(message, throwable, code, responseHeaders, null); } @@ -52,8 +55,7 @@ public ApiException(int code, String message) { this.code = code; } - public ApiException( - int code, String message, HttpHeaders responseHeaders, String responseBody) { + public ApiException(int code, String message, HttpHeaders responseHeaders, String responseBody) { this(code, message); this.responseHeaders = responseHeaders; this.responseBody = responseBody; diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java index 582e0a4d..04d5fc8c 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java @@ -1,4 +1,16 @@ -/* (C)2022-2023 */ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; import java.util.List; @@ -10,9 +22,9 @@ * @param The type of data that is deserialized from response body */ public class ApiResponse { - private final int statusCode; - private final Map> headers; - private final T data; + final private int statusCode; + final private Map> headers; + final private T data; /** * @param statusCode The status code of HTTP response diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java index cbc956b8..44af4652 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java @@ -1,15 +1,25 @@ -/* (C)2022-2023 */ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; -@javax.annotation.Generated( - value = "org.openapitools.codegen.languages.JavaClientCodegen", - date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class Configuration { private static ApiClient defaultApiClient = new ApiClient(); /** - * Get the default API client, which would be used when creating API instances without providing - * an API client. + * Get the default API client, which would be used when creating API + * instances without providing an API client. * * @return Default API client */ @@ -18,8 +28,8 @@ public static ApiClient getDefaultApiClient() { } /** - * Set the default API client, which would be used when creating API instances without providing - * an API client. + * Set the default API client, which would be used when creating API + * instances without providing an API client. * * @param apiClient API client */ diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java index 889ef90a..fc1b5610 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java @@ -1,246 +1,247 @@ -/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; -import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.openapitools.jackson.nullable.JsonNullableModule; + import java.text.DateFormat; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import org.openapitools.jackson.nullable.JsonNullableModule; -@javax.annotation.Generated( - value = "org.openapitools.codegen.languages.JavaClientCodegen", - date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class JSON { - private ObjectMapper mapper; - - public JSON() { - mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); - mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); - mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); - mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); - mapper.setDateFormat(new RFC3339DateFormat()); - mapper.registerModule(new JavaTimeModule()); - JsonNullableModule jnm = new JsonNullableModule(); - mapper.registerModule(jnm); + private ObjectMapper mapper; + + public JSON() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + mapper.registerModule(new JavaTimeModule()); + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + } + + /** + * Set the date format for JSON (de)serialization with Date properties. + * + * @param dateFormat Date format + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + + /** + * Get the object mapper + * + * @return object mapper + */ + public ObjectMapper getMapper() { return mapper; } + + /** + * Returns the target model class that should be used to deserialize the input data. + * The discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param modelClass The class that contains the discriminator mappings. + * + * @return the target model class. + */ + public static Class getClassForElement(JsonNode node, Class modelClass) { + ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass); + if (cdm != null) { + return cdm.getClassForElement(node, new HashSet>()); } - - /** - * Set the date format for JSON (de)serialization with Date properties. - * - * @param dateFormat Date format - */ - public void setDateFormat(DateFormat dateFormat) { - mapper.setDateFormat(dateFormat); + return null; + } + + /** + * Helper class to register the discriminator mappings. + */ + private static class ClassDiscriminatorMapping { + // The model class name. + Class modelClass; + // The name of the discriminator property. + String discriminatorName; + // The discriminator mappings for a model class. + Map> discriminatorMappings; + + // Constructs a new class discriminator. + ClassDiscriminatorMapping(Class cls, String propertyName, Map> mappings) { + modelClass = cls; + discriminatorName = propertyName; + discriminatorMappings = new HashMap>(); + if (mappings != null) { + discriminatorMappings.putAll(mappings); + } } - /** - * Get the object mapper - * - * @return object mapper - */ - public ObjectMapper getMapper() { - return mapper; + // Return the name of the discriminator property for this model class. + String getDiscriminatorPropertyName() { + return discriminatorName; } - /** - * Returns the target model class that should be used to deserialize the input data. The - * discriminator mappings are used to determine the target model class. - * - * @param node The input data. - * @param modelClass The class that contains the discriminator mappings. - * @return the target model class. - */ - public static Class getClassForElement(JsonNode node, Class modelClass) { - ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass); - if (cdm != null) { - return cdm.getClassForElement(node, new HashSet>()); - } - return null; - } - - /** Helper class to register the discriminator mappings. */ - private static class ClassDiscriminatorMapping { - // The model class name. - Class modelClass; - // The name of the discriminator property. - String discriminatorName; - // The discriminator mappings for a model class. - Map> discriminatorMappings; - - // Constructs a new class discriminator. - ClassDiscriminatorMapping( - Class cls, String propertyName, Map> mappings) { - modelClass = cls; - discriminatorName = propertyName; - discriminatorMappings = new HashMap>(); - if (mappings != null) { - discriminatorMappings.putAll(mappings); - } - } - - // Return the name of the discriminator property for this model class. - String getDiscriminatorPropertyName() { - return discriminatorName; - } - - // Return the discriminator value or null if the discriminator is not - // present in the payload. - String getDiscriminatorValue(JsonNode node) { - // Determine the value of the discriminator property in the input data. - if (discriminatorName != null) { - // Get the value of the discriminator property, if present in the input payload. - node = node.get(discriminatorName); - if (node != null && node.isValueNode()) { - String discrValue = node.asText(); - if (discrValue != null) { - return discrValue; - } - } - } - return null; - } - - /** - * Returns the target model class that should be used to deserialize the input data. This - * function can be invoked for anyOf/oneOf composed models with discriminator mappings. The - * discriminator mappings are used to determine the target model class. - * - * @param node The input data. - * @param visitedClasses The set of classes that have already been visited. - * @return the target model class. - */ - Class getClassForElement(JsonNode node, Set> visitedClasses) { - if (visitedClasses.contains(modelClass)) { - // Class has already been visited. - return null; - } - // Determine the value of the discriminator property in the input data. - String discrValue = getDiscriminatorValue(node); - if (discrValue == null) { - return null; - } - Class cls = discriminatorMappings.get(discrValue); - // It may not be sufficient to return this cls directly because that target class - // may itself be a composed schema, possibly with its own discriminator. - visitedClasses.add(modelClass); - for (Class childClass : discriminatorMappings.values()) { - ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass); - if (childCdm == null) { - continue; - } - if (!discriminatorName.equals(childCdm.discriminatorName)) { - discrValue = getDiscriminatorValue(node); - if (discrValue == null) { - continue; - } - } - if (childCdm != null) { - // Recursively traverse the discriminator mappings. - Class childDiscr = childCdm.getClassForElement(node, visitedClasses); - if (childDiscr != null) { - return childDiscr; - } - } - } - return cls; + // Return the discriminator value or null if the discriminator is not + // present in the payload. + String getDiscriminatorValue(JsonNode node) { + // Determine the value of the discriminator property in the input data. + if (discriminatorName != null) { + // Get the value of the discriminator property, if present in the input payload. + node = node.get(discriminatorName); + if (node != null && node.isValueNode()) { + String discrValue = node.asText(); + if (discrValue != null) { + return discrValue; + } } + } + return null; } /** - * Returns true if inst is an instance of modelClass in the OpenAPI model hierarchy. - * - *

The Java class hierarchy is not implemented the same way as the OpenAPI model hierarchy, - * so it's not possible to use the instanceof keyword. + * Returns the target model class that should be used to deserialize the input data. + * This function can be invoked for anyOf/oneOf composed models with discriminator mappings. + * The discriminator mappings are used to determine the target model class. * - * @param modelClass A OpenAPI model class. - * @param inst The instance object. + * @param node The input data. * @param visitedClasses The set of classes that have already been visited. - * @return true if inst is an instance of modelClass in the OpenAPI model hierarchy. + * + * @return the target model class. */ - public static boolean isInstanceOf( - Class modelClass, Object inst, Set> visitedClasses) { - if (modelClass.isInstance(inst)) { - // This handles the 'allOf' use case with single parent inheritance. - return true; + Class getClassForElement(JsonNode node, Set> visitedClasses) { + if (visitedClasses.contains(modelClass)) { + // Class has already been visited. + return null; + } + // Determine the value of the discriminator property in the input data. + String discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + return null; + } + Class cls = discriminatorMappings.get(discrValue); + // It may not be sufficient to return this cls directly because that target class + // may itself be a composed schema, possibly with its own discriminator. + visitedClasses.add(modelClass); + for (Class childClass : discriminatorMappings.values()) { + ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass); + if (childCdm == null) { + continue; } - if (visitedClasses.contains(modelClass)) { - // This is to prevent infinite recursion when the composed schemas have - // a circular dependency. - return false; + if (!discriminatorName.equals(childCdm.discriminatorName)) { + discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + continue; + } } - visitedClasses.add(modelClass); - - // Traverse the oneOf/anyOf composed schemas. - Map> descendants = modelDescendants.get(modelClass); - if (descendants != null) { - for (Class childType : descendants.values()) { - if (isInstanceOf(childType, inst, visitedClasses)) { - return true; - } - } + if (childCdm != null) { + // Recursively traverse the discriminator mappings. + Class childDiscr = childCdm.getClassForElement(node, visitedClasses); + if (childDiscr != null) { + return childDiscr; + } } - return false; + } + return cls; } - - /** A map of discriminators for all model classes. */ - private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap<>(); - - /** A map of oneOf/anyOf descendants for each model class. */ - private static Map, Map>> modelDescendants = new HashMap<>(); - - /** - * Register a model class discriminator. - * - * @param modelClass the model class - * @param discriminatorPropertyName the name of the discriminator property - * @param mappings a map with the discriminator mappings. - */ - public static void registerDiscriminator( - Class modelClass, String discriminatorPropertyName, Map> mappings) { - ClassDiscriminatorMapping m = - new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings); - modelDiscriminators.put(modelClass, m); + } + + /** + * Returns true if inst is an instance of modelClass in the OpenAPI model hierarchy. + * + * The Java class hierarchy is not implemented the same way as the OpenAPI model hierarchy, + * so it's not possible to use the instanceof keyword. + * + * @param modelClass A OpenAPI model class. + * @param inst The instance object. + * @param visitedClasses The set of classes that have already been visited. + * + * @return true if inst is an instance of modelClass in the OpenAPI model hierarchy. + */ + public static boolean isInstanceOf(Class modelClass, Object inst, Set> visitedClasses) { + if (modelClass.isInstance(inst)) { + // This handles the 'allOf' use case with single parent inheritance. + return true; } - - /** - * Register the oneOf/anyOf descendants of the modelClass. - * - * @param modelClass the model class - * @param descendants a map of oneOf/anyOf descendants. - */ - public static void registerDescendants(Class modelClass, Map> descendants) { - modelDescendants.put(modelClass, descendants); + if (visitedClasses.contains(modelClass)) { + // This is to prevent infinite recursion when the composed schemas have + // a circular dependency. + return false; } - - private static JSON json; - - static { - json = new JSON(); - } - - /** - * Get the default JSON instance. - * - * @return the default JSON instance - */ - public static JSON getDefault() { - return json; - } - - /** - * Set the default JSON instance. - * - * @param json JSON instance to be used - */ - public static void setDefault(JSON json) { - JSON.json = json; + visitedClasses.add(modelClass); + + // Traverse the oneOf/anyOf composed schemas. + Map> descendants = modelDescendants.get(modelClass); + if (descendants != null) { + for (Class childType : descendants.values()) { + if (isInstanceOf(childType, inst, visitedClasses)) { + return true; + } + } } + return false; + } + + /** + * A map of discriminators for all model classes. + */ + private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap<>(); + + /** + * A map of oneOf/anyOf descendants for each model class. + */ + private static Map, Map>> modelDescendants = new HashMap<>(); + + /** + * Register a model class discriminator. + * + * @param modelClass the model class + * @param discriminatorPropertyName the name of the discriminator property + * @param mappings a map with the discriminator mappings. + */ + public static void registerDiscriminator(Class modelClass, String discriminatorPropertyName, Map> mappings) { + ClassDiscriminatorMapping m = new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings); + modelDiscriminators.put(modelClass, m); + } + + /** + * Register the oneOf/anyOf descendants of the modelClass. + * + * @param modelClass the model class + * @param descendants a map of oneOf/anyOf descendants. + */ + public static void registerDescendants(Class modelClass, Map> descendants) { + modelDescendants.put(modelClass, descendants); + } + + private static JSON json; + + static { + json = new JSON(); + } + + /** + * Get the default JSON instance. + * + * @return the default JSON instance + */ + public static JSON getDefault() { + return json; + } + + /** + * Set the default JSON instance. + * + * @param json JSON instance to be used + */ + public static void setDefault(JSON json) { + JSON.json = json; + } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java index 68b71c24..8d1d80c2 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java @@ -1,14 +1,24 @@ -/* (C)2022-2023 */ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; -@javax.annotation.Generated( - value = "org.openapitools.codegen.languages.JavaClientCodegen", - date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class Pair { private String name = ""; private String value = ""; - public Pair(String name, String value) { + public Pair (String name, String value) { setName(name); setValue(value); } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java index eb26f968..57853d22 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java @@ -1,7 +1,19 @@ -/* (C)2022-2023 */ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; import com.fasterxml.jackson.databind.util.StdDateFormat; + import java.text.DateFormat; import java.text.DecimalFormat; import java.text.FieldPosition; @@ -11,34 +23,35 @@ import java.util.TimeZone; public class RFC3339DateFormat extends DateFormat { - private static final long serialVersionUID = 1L; - private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); - - private final StdDateFormat fmt = - new StdDateFormat().withTimeZone(TIMEZONE_Z).withColonInTimeZone(true); - - public RFC3339DateFormat() { - this.calendar = new GregorianCalendar(); - this.numberFormat = new DecimalFormat(); - } - - @Override - public Date parse(String source) { - return parse(source, new ParsePosition(0)); - } - - @Override - public Date parse(String source, ParsePosition pos) { - return fmt.parse(source, pos); - } - - @Override - public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { - return fmt.format(date, toAppendTo, fieldPosition); - } - - @Override - public Object clone() { - return super.clone(); - } -} + private static final long serialVersionUID = 1L; + private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); + + private final StdDateFormat fmt = new StdDateFormat() + .withTimeZone(TIMEZONE_Z) + .withColonInTimeZone(true); + + public RFC3339DateFormat() { + this.calendar = new GregorianCalendar(); + this.numberFormat = new DecimalFormat(); + } + + @Override + public Date parse(String source) { + return parse(source, new ParsePosition(0)); + } + + @Override + public Date parse(String source, ParsePosition pos) { + return fmt.parse(source, pos); + } + + @Override + public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { + return fmt.format(date, toAppendTo, fieldPosition); + } + + @Override + public Object clone() { + return super.clone(); + } +} \ No newline at end of file diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java index 747b99ab..33501d36 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java @@ -1,9 +1,10 @@ -/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; import java.util.Map; -/** Representing a Server configuration. */ +/** + * Representing a Server configuration. + */ public class ServerConfiguration { public String URL; public String description; @@ -12,11 +13,9 @@ public class ServerConfiguration { /** * @param URL A URL to the target host. * @param description A description of the host designated by the URL. - * @param variables A map between a variable name and its value. The value is used for - * substitution in the server's URL template. + * @param variables A map between a variable name and its value. The value is used for substitution in the server's URL template. */ - public ServerConfiguration( - String URL, String description, Map variables) { + public ServerConfiguration(String URL, String description, Map variables) { this.URL = URL; this.description = description; this.variables = variables; @@ -32,21 +31,15 @@ public String URL(Map variables) { String url = this.URL; // go through variables and replace placeholders - for (Map.Entry variable : this.variables.entrySet()) { + for (Map.Entry variable: this.variables.entrySet()) { String name = variable.getKey(); ServerVariable serverVariable = variable.getValue(); String value = serverVariable.defaultValue; if (variables != null && variables.containsKey(name)) { value = variables.get(name); - if (serverVariable.enumValues.size() > 0 - && !serverVariable.enumValues.contains(value)) { - throw new IllegalArgumentException( - "The variable " - + name - + " in the server URL has invalid value " - + value - + "."); + if (serverVariable.enumValues.size() > 0 && !serverVariable.enumValues.contains(value)) { + throw new IllegalArgumentException("The variable " + name + " in the server URL has invalid value " + value + "."); } } url = url.replace("{" + name + "}", value); diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java index f0bb418a..c06da593 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java @@ -1,9 +1,10 @@ -/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; import java.util.HashSet; -/** Representing a Server Variable for server URL template substitution. */ +/** + * Representing a Server Variable for server URL template substitution. + */ public class ServerVariable { public String description; public String defaultValue; @@ -12,8 +13,7 @@ public class ServerVariable { /** * @param description A description for the server variable. * @param defaultValue The default value to use for substitution. - * @param enumValues An enumeration of string values to be used if the substitution options are - * from a limited set. + * @param enumValues An enumeration of string values to be used if the substitution options are from a limited set. */ public ServerVariable(String description, String defaultValue, HashSet enumValues) { this.description = description; diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java index e58deef0..a061221b 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java @@ -1,317 +1,344 @@ -/* (C)2022-2023 */ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.api; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiResponse; -import java.io.IOException; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.CertData; + import java.io.InputStream; +import java.io.IOException; +import java.net.http.HttpRequest; import java.net.URI; import java.net.http.HttpClient; -import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; + +import java.util.List; import java.util.function.Consumer; -@javax.annotation.Generated( - value = "org.openapitools.codegen.languages.JavaClientCodegen", - date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class DefaultApi { - private final HttpClient memberVarHttpClient; - private final ObjectMapper memberVarObjectMapper; - private final String memberVarBaseUri; - private final Consumer memberVarInterceptor; - private final Duration memberVarReadTimeout; - private final Consumer> memberVarResponseInterceptor; - private final Consumer> memberVarAsyncResponseInterceptor; - - public DefaultApi() { - this(new ApiClient()); - } - - public DefaultApi(ApiClient apiClient) { - memberVarHttpClient = apiClient.getHttpClient(); - memberVarObjectMapper = apiClient.getObjectMapper(); - memberVarBaseUri = apiClient.getBaseUri(); - memberVarInterceptor = apiClient.getRequestInterceptor(); - memberVarReadTimeout = apiClient.getReadTimeout(); - memberVarResponseInterceptor = apiClient.getResponseInterceptor(); - memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); + private final HttpClient memberVarHttpClient; + private final ObjectMapper memberVarObjectMapper; + private final String memberVarBaseUri; + private final Consumer memberVarInterceptor; + private final Duration memberVarReadTimeout; + private final Consumer> memberVarResponseInterceptor; + private final Consumer> memberVarAsyncResponseInterceptor; + + public DefaultApi() { + this(new ApiClient()); + } + + public DefaultApi(ApiClient apiClient) { + memberVarHttpClient = apiClient.getHttpClient(); + memberVarObjectMapper = apiClient.getObjectMapper(); + memberVarBaseUri = apiClient.getBaseUri(); + memberVarInterceptor = apiClient.getRequestInterceptor(); + memberVarReadTimeout = apiClient.getReadTimeout(); + memberVarResponseInterceptor = apiClient.getResponseInterceptor(); + memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); + } + + protected ApiException getApiException(String operationId, HttpResponse response) throws IOException { + String body = response.body() == null ? null : new String(response.body().readAllBytes()); + String message = formatExceptionMessage(operationId, response.statusCode(), body); + return new ApiException(response.statusCode(), message, response.headers(), body); + } + + private String formatExceptionMessage(String operationId, int statusCode, String body) { + if (body == null || body.isEmpty()) { + body = "[no body]"; } - - protected ApiException getApiException(String operationId, HttpResponse response) - throws IOException { - String body = response.body() == null ? null : new String(response.body().readAllBytes()); - String message = formatExceptionMessage(operationId, response.statusCode(), body); - return new ApiException(response.statusCode(), message, response.headers(), body); - } - - private String formatExceptionMessage(String operationId, int statusCode, String body) { - if (body == null || body.isEmpty()) { - body = "[no body]"; + return operationId + " call failed with: " + statusCode + " - " + body; + } + + /** + * + * + * @return List<String> + * @throws ApiException if fails to make API call + */ + public List idpKeysCieGet() throws ApiException { + ApiResponse> localVarResponse = idpKeysCieGetWithHttpInfo(); + return localVarResponse.getData(); + } + + /** + * + * + * @return ApiResponse<List<String>> + * @throws ApiException if fails to make API call + */ + public ApiResponse> idpKeysCieGetWithHttpInfo() throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysCieGetRequestBuilder(); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode()/ 100 != 2) { + throw getApiException("idpKeysCieGet", localVarResponse); } - return operationId + " call failed with: " + statusCode + " - " + body; + return new ApiResponse>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference>() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); } - - /** - * @throws ApiException if fails to make API call - */ - public void idpKeysCieGet() throws ApiException { - idpKeysCieGetWithHttpInfo(); + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); } + } - /** - * @return ApiResponse<Void> - * @throws ApiException if fails to make API call - */ - public ApiResponse idpKeysCieGetWithHttpInfo() throws ApiException { - HttpRequest.Builder localVarRequestBuilder = idpKeysCieGetRequestBuilder(); - try { - HttpResponse localVarResponse = - memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - try { - if (localVarResponse.statusCode() / 100 != 2) { - throw getApiException("idpKeysCieGet", localVarResponse); - } - return new ApiResponse( - localVarResponse.statusCode(), localVarResponse.headers().map(), null); - } finally { - // Drain the InputStream - while (localVarResponse.body().read() != -1) { - // Ignore - } - localVarResponse.body().close(); - } - } catch (IOException e) { - throw new ApiException(e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); - } - } - - private HttpRequest.Builder idpKeysCieGetRequestBuilder() throws ApiException { + private HttpRequest.Builder idpKeysCieGetRequestBuilder() throws ApiException { - HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); - String localVarPath = "/idp-keys/cie"; + String localVarPath = "/idp-keys/cie"; - localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); - localVarRequestBuilder.header("Accept", "application/json"); + localVarRequestBuilder.header("Accept", "application/json"); - localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); - } - return localVarRequestBuilder; + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); } - /** - * @param tag (required) - * @throws ApiException if fails to make API call - */ - public void idpKeysCieTagGet(String tag) throws ApiException { - idpKeysCieTagGetWithHttpInfo(tag); + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); } - - /** - * @param tag (required) - * @return ApiResponse<Void> - * @throws ApiException if fails to make API call - */ - public ApiResponse idpKeysCieTagGetWithHttpInfo(String tag) throws ApiException { - HttpRequest.Builder localVarRequestBuilder = idpKeysCieTagGetRequestBuilder(tag); - try { - HttpResponse localVarResponse = - memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - try { - if (localVarResponse.statusCode() / 100 != 2) { - throw getApiException("idpKeysCieTagGet", localVarResponse); - } - return new ApiResponse( - localVarResponse.statusCode(), localVarResponse.headers().map(), null); - } finally { - // Drain the InputStream - while (localVarResponse.body().read() != -1) { - // Ignore - } - localVarResponse.body().close(); - } - } catch (IOException e) { - throw new ApiException(e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); + return localVarRequestBuilder; + } + /** + * + * + * @param tag (required) + * @return CertData + * @throws ApiException if fails to make API call + */ + public CertData idpKeysCieTagGet(String tag) throws ApiException { + ApiResponse localVarResponse = idpKeysCieTagGetWithHttpInfo(tag); + return localVarResponse.getData(); + } + + /** + * + * + * @param tag (required) + * @return ApiResponse<CertData> + * @throws ApiException if fails to make API call + */ + public ApiResponse idpKeysCieTagGetWithHttpInfo(String tag) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysCieTagGetRequestBuilder(tag); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode()/ 100 != 2) { + throw getApiException("idpKeysCieTagGet", localVarResponse); } + return new ApiResponse( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); } + } - private HttpRequest.Builder idpKeysCieTagGetRequestBuilder(String tag) throws ApiException { - // verify the required parameter 'tag' is set - if (tag == null) { - throw new ApiException( - 400, "Missing the required parameter 'tag' when calling idpKeysCieTagGet"); - } + private HttpRequest.Builder idpKeysCieTagGetRequestBuilder(String tag) throws ApiException { + // verify the required parameter 'tag' is set + if (tag == null) { + throw new ApiException(400, "Missing the required parameter 'tag' when calling idpKeysCieTagGet"); + } - HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); - String localVarPath = - "/idp-keys/cie/{tag}".replace("{tag}", ApiClient.urlEncode(tag.toString())); + String localVarPath = "/idp-keys/cie/{tag}" + .replace("{tag}", ApiClient.urlEncode(tag.toString())); - localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); - localVarRequestBuilder.header("Accept", "application/json"); + localVarRequestBuilder.header("Accept", "application/xml, application/json"); - localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); - } - return localVarRequestBuilder; + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); } - /** - * @throws ApiException if fails to make API call - */ - public void idpKeysSpidGet() throws ApiException { - idpKeysSpidGetWithHttpInfo(); + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); } - - /** - * @return ApiResponse<Void> - * @throws ApiException if fails to make API call - */ - public ApiResponse idpKeysSpidGetWithHttpInfo() throws ApiException { - HttpRequest.Builder localVarRequestBuilder = idpKeysSpidGetRequestBuilder(); - try { - HttpResponse localVarResponse = - memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - try { - if (localVarResponse.statusCode() / 100 != 2) { - throw getApiException("idpKeysSpidGet", localVarResponse); - } - return new ApiResponse( - localVarResponse.statusCode(), localVarResponse.headers().map(), null); - } finally { - // Drain the InputStream - while (localVarResponse.body().read() != -1) { - // Ignore - } - localVarResponse.body().close(); - } - } catch (IOException e) { - throw new ApiException(e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); + return localVarRequestBuilder; + } + /** + * + * + * @return List<String> + * @throws ApiException if fails to make API call + */ + public List idpKeysSpidGet() throws ApiException { + ApiResponse> localVarResponse = idpKeysSpidGetWithHttpInfo(); + return localVarResponse.getData(); + } + + /** + * + * + * @return ApiResponse<List<String>> + * @throws ApiException if fails to make API call + */ + public ApiResponse> idpKeysSpidGetWithHttpInfo() throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysSpidGetRequestBuilder(); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode()/ 100 != 2) { + throw getApiException("idpKeysSpidGet", localVarResponse); } + return new ApiResponse>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference>() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } - private HttpRequest.Builder idpKeysSpidGetRequestBuilder() throws ApiException { + private HttpRequest.Builder idpKeysSpidGetRequestBuilder() throws ApiException { - HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); - String localVarPath = "/idp-keys/spid"; + String localVarPath = "/idp-keys/spid"; - localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); - localVarRequestBuilder.header("Accept", "application/json"); + localVarRequestBuilder.header("Accept", "application/json"); - localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); - } - return localVarRequestBuilder; + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); } - /** - * @param tag (required) - * @throws ApiException if fails to make API call - */ - public void idpKeysSpidTagGet(String tag) throws ApiException { - idpKeysSpidTagGetWithHttpInfo(tag); + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); } - - /** - * @param tag (required) - * @return ApiResponse<Void> - * @throws ApiException if fails to make API call - */ - public ApiResponse idpKeysSpidTagGetWithHttpInfo(String tag) throws ApiException { - HttpRequest.Builder localVarRequestBuilder = idpKeysSpidTagGetRequestBuilder(tag); - try { - HttpResponse localVarResponse = - memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - try { - if (localVarResponse.statusCode() / 100 != 2) { - throw getApiException("idpKeysSpidTagGet", localVarResponse); - } - return new ApiResponse( - localVarResponse.statusCode(), localVarResponse.headers().map(), null); - } finally { - // Drain the InputStream - while (localVarResponse.body().read() != -1) { - // Ignore - } - localVarResponse.body().close(); - } - } catch (IOException e) { - throw new ApiException(e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); + return localVarRequestBuilder; + } + /** + * + * + * @param tag (required) + * @return CertData + * @throws ApiException if fails to make API call + */ + public CertData idpKeysSpidTagGet(String tag) throws ApiException { + ApiResponse localVarResponse = idpKeysSpidTagGetWithHttpInfo(tag); + return localVarResponse.getData(); + } + + /** + * + * + * @param tag (required) + * @return ApiResponse<CertData> + * @throws ApiException if fails to make API call + */ + public ApiResponse idpKeysSpidTagGetWithHttpInfo(String tag) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysSpidTagGetRequestBuilder(tag); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode()/ 100 != 2) { + throw getApiException("idpKeysSpidTagGet", localVarResponse); } + return new ApiResponse( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } - private HttpRequest.Builder idpKeysSpidTagGetRequestBuilder(String tag) throws ApiException { - // verify the required parameter 'tag' is set - if (tag == null) { - throw new ApiException( - 400, "Missing the required parameter 'tag' when calling idpKeysSpidTagGet"); - } + private HttpRequest.Builder idpKeysSpidTagGetRequestBuilder(String tag) throws ApiException { + // verify the required parameter 'tag' is set + if (tag == null) { + throw new ApiException(400, "Missing the required parameter 'tag' when calling idpKeysSpidTagGet"); + } - HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); - String localVarPath = - "/idp-keys/spid/{tag}".replace("{tag}", ApiClient.urlEncode(tag.toString())); + String localVarPath = "/idp-keys/spid/{tag}" + .replace("{tag}", ApiClient.urlEncode(tag.toString())); - localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); - localVarRequestBuilder.header("Accept", "application/json"); + localVarRequestBuilder.header("Accept", "application/xml, application/json"); - localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); - } - return localVarRequestBuilder; + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); } + return localVarRequestBuilder; + } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java index e5c342aa..688511a7 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java @@ -1,14 +1,28 @@ -/* (C)2022-2023 */ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; -import com.fasterxml.jackson.annotation.JsonValue; -import java.util.Map; import java.util.Objects; +import java.lang.reflect.Type; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonValue; -/** Abstract class for oneOf,anyOf schemas defined in OpenAPI spec */ -@javax.annotation.Generated( - value = "org.openapitools.codegen.languages.JavaClientCodegen", - date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +/** + * Abstract class for oneOf,anyOf schemas defined in OpenAPI spec + */ +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public abstract class AbstractOpenApiSchema { // store the actual instance of the schema/object @@ -38,22 +52,17 @@ public AbstractOpenApiSchema(String schemaType, Boolean isNullable) { * @return an instance of the actual schema/object */ @JsonValue - public Object getActualInstance() { - return instance; - } + public Object getActualInstance() {return instance;} /** * Set the actual instance * * @param instance the actual instance of the schema/object */ - public void setActualInstance(Object instance) { - this.instance = instance; - } + public void setActualInstance(Object instance) {this.instance = instance;} /** - * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf - * schema as well + * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf schema as well * * @return an instance of the actual schema/object */ @@ -65,7 +74,7 @@ private Object getActualInstanceRecursively(AbstractOpenApiSchema object) { if (object.getActualInstance() == null) { return null; } else if (object.getActualInstance() instanceof AbstractOpenApiSchema) { - return getActualInstanceRecursively((AbstractOpenApiSchema) object.getActualInstance()); + return getActualInstanceRecursively((AbstractOpenApiSchema)object.getActualInstance()); } else { return object.getActualInstance(); } @@ -92,8 +101,8 @@ public String toString() { } /** - * Convert the given object to string with each line indented by 4 spaces (except the first - * line). + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). */ private String toIndentedString(Object o) { if (o == null) { @@ -110,9 +119,9 @@ public boolean equals(Object o) { return false; } AbstractOpenApiSchema a = (AbstractOpenApiSchema) o; - return Objects.equals(this.instance, a.instance) - && Objects.equals(this.isNullable, a.isNullable) - && Objects.equals(this.schemaType, a.schemaType); + return Objects.equals(this.instance, a.instance) && + Objects.equals(this.isNullable, a.isNullable) && + Objects.equals(this.schemaType, a.schemaType); } @Override @@ -132,4 +141,7 @@ public Boolean isNullable() { return Boolean.FALSE; } } + + + } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java new file mode 100644 index 00000000..6fbeec22 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java @@ -0,0 +1,157 @@ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; + +import java.util.StringJoiner; +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * CIECertData + */ +@JsonPropertyOrder({ + CIECertData.JSON_PROPERTY_ENTITY_DESCRIPTOR +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +public class CIECertData { + public static final String JSON_PROPERTY_ENTITY_DESCRIPTOR = "entityDescriptor"; + private List entityDescriptor; + + public CIECertData() { + } + + public CIECertData entityDescriptor(List entityDescriptor) { + this.entityDescriptor = entityDescriptor; + return this; + } + + public CIECertData addEntityDescriptorItem(EntityDescriptor entityDescriptorItem) { + if (this.entityDescriptor == null) { + this.entityDescriptor = new ArrayList<>(); + } + this.entityDescriptor.add(entityDescriptorItem); + return this; + } + + /** + * Get entityDescriptor + * @return entityDescriptor + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_ENTITY_DESCRIPTOR) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public List getEntityDescriptor() { + return entityDescriptor; + } + + + @JsonProperty(JSON_PROPERTY_ENTITY_DESCRIPTOR) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setEntityDescriptor(List entityDescriptor) { + this.entityDescriptor = entityDescriptor; + } + + + /** + * Return true if this CIECertData object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + CIECertData ciECertData = (CIECertData) o; + return Objects.equals(this.entityDescriptor, ciECertData.entityDescriptor); + } + + @Override + public int hashCode() { + return Objects.hash(entityDescriptor); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class CIECertData {\n"); + sb.append(" entityDescriptor: ").append(toIndentedString(entityDescriptor)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `entityDescriptor` to the URL query string + if (getEntityDescriptor() != null) { + for (int i = 0; i < getEntityDescriptor().size(); i++) { + if (getEntityDescriptor().get(i) != null) { + joiner.add(getEntityDescriptor().get(i).toUrlQueryString(String.format("%sentityDescriptor%s%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); + } + } + } + + return joiner.toString(); + } +} + diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java new file mode 100644 index 00000000..e9c970a5 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java @@ -0,0 +1,281 @@ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; + +import java.util.StringJoiner; +import java.util.Map; +import java.util.HashMap; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.Collections; +import java.util.HashSet; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.JSON; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +@JsonDeserialize(using = CertData.CertDataDeserializer.class) +@JsonSerialize(using = CertData.CertDataSerializer.class) +public class CertData extends AbstractOpenApiSchema { + private static final Logger log = Logger.getLogger(CertData.class.getName()); + + public static class CertDataSerializer extends StdSerializer { + public CertDataSerializer(Class t) { + super(t); + } + + public CertDataSerializer() { + this(null); + } + + @Override + public void serialize(CertData value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + + public static class CertDataDeserializer extends StdDeserializer { + public CertDataDeserializer() { + this(CertData.class); + } + + public CertDataDeserializer(Class vc) { + super(vc); + } + + @Override + public CertData deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + Object deserialized = null; + boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS); + int match = 0; + JsonToken token = tree.traverse(jp.getCodec()).nextToken(); + // deserialize CIECertData + try { + boolean attemptParsing = true; + // ensure that we respect type coercion as set on the client ObjectMapper + if (CIECertData.class.equals(Integer.class) || CIECertData.class.equals(Long.class) || CIECertData.class.equals(Float.class) || CIECertData.class.equals(Double.class) || CIECertData.class.equals(Boolean.class) || CIECertData.class.equals(String.class)) { + attemptParsing = typeCoercion; + if (!attemptParsing) { + attemptParsing |= ((CIECertData.class.equals(Integer.class) || CIECertData.class.equals(Long.class)) && token == JsonToken.VALUE_NUMBER_INT); + attemptParsing |= ((CIECertData.class.equals(Float.class) || CIECertData.class.equals(Double.class)) && token == JsonToken.VALUE_NUMBER_FLOAT); + attemptParsing |= (CIECertData.class.equals(Boolean.class) && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE)); + attemptParsing |= (CIECertData.class.equals(String.class) && token == JsonToken.VALUE_STRING); + } + } + if (attemptParsing) { + deserialized = tree.traverse(jp.getCodec()).readValueAs(CIECertData.class); + // TODO: there is no validation against JSON schema constraints + // (min, max, enum, pattern...), this does not perform a strict JSON + // validation, which means the 'match' count may be higher than it should be. + match++; + log.log(Level.FINER, "Input data matches schema 'CIECertData'"); + } + } catch (Exception e) { + // deserialization failed, continue + log.log(Level.FINER, "Input data does not match schema 'CIECertData'", e); + } + + // deserialize SPIDCertData + try { + boolean attemptParsing = true; + // ensure that we respect type coercion as set on the client ObjectMapper + if (SPIDCertData.class.equals(Integer.class) || SPIDCertData.class.equals(Long.class) || SPIDCertData.class.equals(Float.class) || SPIDCertData.class.equals(Double.class) || SPIDCertData.class.equals(Boolean.class) || SPIDCertData.class.equals(String.class)) { + attemptParsing = typeCoercion; + if (!attemptParsing) { + attemptParsing |= ((SPIDCertData.class.equals(Integer.class) || SPIDCertData.class.equals(Long.class)) && token == JsonToken.VALUE_NUMBER_INT); + attemptParsing |= ((SPIDCertData.class.equals(Float.class) || SPIDCertData.class.equals(Double.class)) && token == JsonToken.VALUE_NUMBER_FLOAT); + attemptParsing |= (SPIDCertData.class.equals(Boolean.class) && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE)); + attemptParsing |= (SPIDCertData.class.equals(String.class) && token == JsonToken.VALUE_STRING); + } + } + if (attemptParsing) { + deserialized = tree.traverse(jp.getCodec()).readValueAs(SPIDCertData.class); + // TODO: there is no validation against JSON schema constraints + // (min, max, enum, pattern...), this does not perform a strict JSON + // validation, which means the 'match' count may be higher than it should be. + match++; + log.log(Level.FINER, "Input data matches schema 'SPIDCertData'"); + } + } catch (Exception e) { + // deserialization failed, continue + log.log(Level.FINER, "Input data does not match schema 'SPIDCertData'", e); + } + + if (match == 1) { + CertData ret = new CertData(); + ret.setActualInstance(deserialized); + return ret; + } + throw new IOException(String.format("Failed deserialization for CertData: %d classes match result, expected 1", match)); + } + + /** + * Handle deserialization of the 'null' value. + */ + @Override + public CertData getNullValue(DeserializationContext ctxt) throws JsonMappingException { + throw new JsonMappingException(ctxt.getParser(), "CertData cannot be null"); + } + } + + // store a list of schema names defined in oneOf + public static final Map> schemas = new HashMap<>(); + + public CertData() { + super("oneOf", Boolean.FALSE); + } + + public CertData(CIECertData o) { + super("oneOf", Boolean.FALSE); + setActualInstance(o); + } + + public CertData(SPIDCertData o) { + super("oneOf", Boolean.FALSE); + setActualInstance(o); + } + + static { + schemas.put("CIECertData", CIECertData.class); + schemas.put("SPIDCertData", SPIDCertData.class); + JSON.registerDescendants(CertData.class, Collections.unmodifiableMap(schemas)); + } + + @Override + public Map> getSchemas() { + return CertData.schemas; + } + + /** + * Set the instance that matches the oneOf child schema, check + * the instance parameter is valid against the oneOf child schemas: + * CIECertData, SPIDCertData + * + * It could be an instance of the 'oneOf' schemas. + * The oneOf child schemas may themselves be a composed schema (allOf, anyOf, oneOf). + */ + @Override + public void setActualInstance(Object instance) { + if (JSON.isInstanceOf(CIECertData.class, instance, new HashSet>())) { + super.setActualInstance(instance); + return; + } + + if (JSON.isInstanceOf(SPIDCertData.class, instance, new HashSet>())) { + super.setActualInstance(instance); + return; + } + + throw new RuntimeException("Invalid instance type. Must be CIECertData, SPIDCertData"); + } + + /** + * Get the actual instance, which can be the following: + * CIECertData, SPIDCertData + * + * @return The actual instance (CIECertData, SPIDCertData) + */ + @Override + public Object getActualInstance() { + return super.getActualInstance(); + } + + /** + * Get the actual instance of `CIECertData`. If the actual instance is not `CIECertData`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `CIECertData` + * @throws ClassCastException if the instance is not `CIECertData` + */ + public CIECertData getCIECertData() throws ClassCastException { + return (CIECertData)super.getActualInstance(); + } + + /** + * Get the actual instance of `SPIDCertData`. If the actual instance is not `SPIDCertData`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `SPIDCertData` + * @throws ClassCastException if the instance is not `SPIDCertData` + */ + public SPIDCertData getSPIDCertData() throws ClassCastException { + return (SPIDCertData)super.getActualInstance(); + } + + + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + if (getActualInstance() instanceof CIECertData) { + if (getActualInstance() != null) { + joiner.add(((CIECertData)getActualInstance()).toUrlQueryString(prefix + "one_of_0" + suffix)); + } + return joiner.toString(); + } + if (getActualInstance() instanceof SPIDCertData) { + if (getActualInstance() != null) { + joiner.add(((SPIDCertData)getActualInstance()).toUrlQueryString(prefix + "one_of_1" + suffix)); + } + return joiner.toString(); + } + return null; + } + +} + diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java new file mode 100644 index 00000000..1c6ef986 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java @@ -0,0 +1,145 @@ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import java.util.StringJoiner; + + +/** + * EntityDescriptor + */ +@JsonPropertyOrder({ + EntityDescriptor.JSON_PROPERTY_ENTITY_I_D +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +public class EntityDescriptor { + public static final String JSON_PROPERTY_ENTITY_I_D = "entityID"; + private String entityID; + + public EntityDescriptor() { + } + + public EntityDescriptor entityID(String entityID) { + this.entityID = entityID; + return this; + } + + /** + * Get entityID + * @return entityID + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_ENTITY_I_D) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + + public String getEntityID() { + return entityID; + } + + + @JsonProperty(JSON_PROPERTY_ENTITY_I_D) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setEntityID(String entityID) { + this.entityID = entityID; + } + + + /** + * Return true if this EntityDescriptor object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + EntityDescriptor entityDescriptor = (EntityDescriptor) o; + return Objects.equals(this.entityID, entityDescriptor.entityID); + } + + @Override + public int hashCode() { + return Objects.hash(entityID); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class EntityDescriptor {\n"); + sb.append(" entityID: ").append(toIndentedString(entityID)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `entityID` to the URL query string + if (getEntityID() != null) { + joiner.add(String.format("%sentityID%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getEntityID()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} + diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/ProblemJson.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/ProblemJson.java new file mode 100644 index 00000000..7fcc4f37 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/ProblemJson.java @@ -0,0 +1,292 @@ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import java.net.URI; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import java.util.StringJoiner; + + +/** + * ProblemJson + */ +@JsonPropertyOrder({ + ProblemJson.JSON_PROPERTY_TYPE, + ProblemJson.JSON_PROPERTY_TITLE, + ProblemJson.JSON_PROPERTY_STATUS, + ProblemJson.JSON_PROPERTY_DETAIL, + ProblemJson.JSON_PROPERTY_INSTANCE +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +public class ProblemJson { + public static final String JSON_PROPERTY_TYPE = "type"; + private URI type = URI.create("about:blank"); + + public static final String JSON_PROPERTY_TITLE = "title"; + private String title; + + public static final String JSON_PROPERTY_STATUS = "status"; + private Integer status; + + public static final String JSON_PROPERTY_DETAIL = "detail"; + private String detail; + + public static final String JSON_PROPERTY_INSTANCE = "instance"; + private URI instance; + + public ProblemJson() { + } + + public ProblemJson type(URI type) { + this.type = type; + return this; + } + + /** + * An absolute URI that identifies the problem type. When dereferenced, it SHOULD provide human-readable documentation for the problem type (e.g., using HTML). + * @return type + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public URI getType() { + return type; + } + + + @JsonProperty(JSON_PROPERTY_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setType(URI type) { + this.type = type; + } + + + public ProblemJson title(String title) { + this.title = title; + return this; + } + + /** + * A short, summary of the problem type. Written in english and readable for engineers (usually not suited for non technical stakeholders and not localized); example: Service Unavailable + * @return title + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_TITLE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getTitle() { + return title; + } + + + @JsonProperty(JSON_PROPERTY_TITLE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setTitle(String title) { + this.title = title; + } + + + public ProblemJson status(Integer status) { + this.status = status; + return this; + } + + /** + * The HTTP status code generated by the origin server for this occurrence of the problem. + * minimum: 100 + * maximum: 600 + * @return status + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Integer getStatus() { + return status; + } + + + @JsonProperty(JSON_PROPERTY_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setStatus(Integer status) { + this.status = status; + } + + + public ProblemJson detail(String detail) { + this.detail = detail; + return this; + } + + /** + * A human readable explanation specific to this occurrence of the problem. + * @return detail + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_DETAIL) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getDetail() { + return detail; + } + + + @JsonProperty(JSON_PROPERTY_DETAIL) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setDetail(String detail) { + this.detail = detail; + } + + + public ProblemJson instance(URI instance) { + this.instance = instance; + return this; + } + + /** + * An absolute URI that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced. + * @return instance + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_INSTANCE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public URI getInstance() { + return instance; + } + + + @JsonProperty(JSON_PROPERTY_INSTANCE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setInstance(URI instance) { + this.instance = instance; + } + + + /** + * Return true if this ProblemJson object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProblemJson problemJson = (ProblemJson) o; + return Objects.equals(this.type, problemJson.type) && + Objects.equals(this.title, problemJson.title) && + Objects.equals(this.status, problemJson.status) && + Objects.equals(this.detail, problemJson.detail) && + Objects.equals(this.instance, problemJson.instance); + } + + @Override + public int hashCode() { + return Objects.hash(type, title, status, detail, instance); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ProblemJson {\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append(" title: ").append(toIndentedString(title)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" detail: ").append(toIndentedString(detail)).append("\n"); + sb.append(" instance: ").append(toIndentedString(instance)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `type` to the URL query string + if (getType() != null) { + joiner.add(String.format("%stype%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getType()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `title` to the URL query string + if (getTitle() != null) { + joiner.add(String.format("%stitle%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getTitle()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `status` to the URL query string + if (getStatus() != null) { + joiner.add(String.format("%sstatus%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getStatus()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `detail` to the URL query string + if (getDetail() != null) { + joiner.add(String.format("%sdetail%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getDetail()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `instance` to the URL query string + if (getInstance() != null) { + joiner.add(String.format("%sinstance%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getInstance()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} + diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertData.java new file mode 100644 index 00000000..572534fe --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertData.java @@ -0,0 +1,143 @@ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import java.util.Objects; +import java.util.StringJoiner; + + +/** + * SPIDCertData + */ +@JsonPropertyOrder({ + SPIDCertData.JSON_PROPERTY_ENTITIES_DESCRIPTOR +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +public class SPIDCertData { + public static final String JSON_PROPERTY_ENTITIES_DESCRIPTOR = "entitiesDescriptor"; + private SPIDCertDataEntitiesDescriptor entitiesDescriptor; + + public SPIDCertData() { + } + + public SPIDCertData entitiesDescriptor(SPIDCertDataEntitiesDescriptor entitiesDescriptor) { + this.entitiesDescriptor = entitiesDescriptor; + return this; + } + + /** + * Get entitiesDescriptor + * @return entitiesDescriptor + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_ENTITIES_DESCRIPTOR) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public SPIDCertDataEntitiesDescriptor getEntitiesDescriptor() { + return entitiesDescriptor; + } + + + @JsonProperty(JSON_PROPERTY_ENTITIES_DESCRIPTOR) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setEntitiesDescriptor(SPIDCertDataEntitiesDescriptor entitiesDescriptor) { + this.entitiesDescriptor = entitiesDescriptor; + } + + + /** + * Return true if this SPIDCertData object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SPIDCertData spIDCertData = (SPIDCertData) o; + return Objects.equals(this.entitiesDescriptor, spIDCertData.entitiesDescriptor); + } + + @Override + public int hashCode() { + return Objects.hash(entitiesDescriptor); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class SPIDCertData {\n"); + sb.append(" entitiesDescriptor: ").append(toIndentedString(entitiesDescriptor)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `entitiesDescriptor` to the URL query string + if (getEntitiesDescriptor() != null) { + joiner.add(getEntitiesDescriptor().toUrlQueryString(prefix + "entitiesDescriptor" + suffix)); + } + + return joiner.toString(); + } +} + diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertDataEntitiesDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertDataEntitiesDescriptor.java new file mode 100644 index 00000000..a4169a63 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertDataEntitiesDescriptor.java @@ -0,0 +1,158 @@ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.StringJoiner; + + +/** + * SPIDCertDataEntitiesDescriptor + */ +@JsonPropertyOrder({ + SPIDCertDataEntitiesDescriptor.JSON_PROPERTY_ENTITY_DESCRIPTOR +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +public class SPIDCertDataEntitiesDescriptor { + public static final String JSON_PROPERTY_ENTITY_DESCRIPTOR = "entityDescriptor"; + private List entityDescriptor; + + public SPIDCertDataEntitiesDescriptor() { + } + + public SPIDCertDataEntitiesDescriptor entityDescriptor(List entityDescriptor) { + this.entityDescriptor = entityDescriptor; + return this; + } + + public SPIDCertDataEntitiesDescriptor addEntityDescriptorItem(EntityDescriptor entityDescriptorItem) { + if (this.entityDescriptor == null) { + this.entityDescriptor = new ArrayList<>(); + } + this.entityDescriptor.add(entityDescriptorItem); + return this; + } + + /** + * Get entityDescriptor + * @return entityDescriptor + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_ENTITY_DESCRIPTOR) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public List getEntityDescriptor() { + return entityDescriptor; + } + + + @JsonProperty(JSON_PROPERTY_ENTITY_DESCRIPTOR) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setEntityDescriptor(List entityDescriptor) { + this.entityDescriptor = entityDescriptor; + } + + + /** + * Return true if this SPIDCertData_entitiesDescriptor object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SPIDCertDataEntitiesDescriptor spIDCertDataEntitiesDescriptor = (SPIDCertDataEntitiesDescriptor) o; + return Objects.equals(this.entityDescriptor, spIDCertDataEntitiesDescriptor.entityDescriptor); + } + + @Override + public int hashCode() { + return Objects.hash(entityDescriptor); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class SPIDCertDataEntitiesDescriptor {\n"); + sb.append(" entityDescriptor: ").append(toIndentedString(entityDescriptor)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `entityDescriptor` to the URL query string + if (getEntityDescriptor() != null) { + for (int i = 0; i < getEntityDescriptor().size(); i++) { + if (getEntityDescriptor().get(i) != null) { + joiner.add(getEntityDescriptor().get(i).toUrlQueryString(String.format("%sentityDescriptor%s%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); + } + } + } + + return joiner.toString(); + } +} + From c7024995c2ec57463695f937c022d7487a0eac95 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 11 Apr 2023 16:46:38 +0200 Subject: [PATCH 072/403] [SLS-19] Defined skeleton getCertData - changed return type to List --- .../consumer/idp/client/IdpCertClient.java | 3 +- .../client/simple/IdpCertSimpleClient.java | 88 ++++++++++++++++++- 2 files changed, 87 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java index 7629f668..50ace9c7 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java @@ -2,8 +2,9 @@ package it.pagopa.tech.lollipop.consumer.idp.client; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import java.util.List; public interface IdpCertClient { - IdpCertData getCertData(String entityId, String instant); + List getCertData(String entityId, String instant); } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 8eae30a2..3c602363 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -1,16 +1,25 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple; +import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.OidcAssertionNotSupported; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; +import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.api.DefaultApi; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.CertData; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; + +import java.util.ArrayList; +import java.util.List; import javax.inject.Inject; public class IdpCertSimpleClient implements IdpCertClient { - ApiClient apiClient; - DefaultApi defaultApi; + private final ApiClient apiClient; + private final DefaultApi defaultApi; @Inject public IdpCertSimpleClient(ApiClient client) { @@ -24,7 +33,80 @@ public IdpCertSimpleClient(ApiClient client) { * @return */ @Override - public IdpCertData getCertData(String entityId, String instant) { + public List getCertData(String entityId, String instant) { + List listCertData = new ArrayList<>(); + + if (entityId.equals("https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO")) { //TODO inserire entityID in config + List tagList = getCIETagList(instant); + for(String tag: tagList){ + IdpCertData certData = getCIECertData(tag); + listCertData.add(certData); + } + } else { + List tagList = getSPIDTagList(instant); + for(String tag: tagList){ + IdpCertData certData = getSPIDCertData(tag, entityId); + listCertData.add(certData); + } + } + return listCertData; + } + + private List getSPIDTagList(String instant) { + List responseAssertion = new ArrayList<>(); + + try { + responseAssertion = this.defaultApi.idpKeysSpidGet(); + } catch (ApiException e) { + /*throw new LollipopAssertionNotFoundException( + "Error retrieving idp cert list: " + e.getMessage(), e);*/ + } + + //TODO gestire filtro tag (prendere quello subito prima e subito dopo rispetto all' "instant") + + return responseAssertion; + } + + private IdpCertData getSPIDCertData(String tag, String entityId) { + CertData responseAssertion; + + try { + responseAssertion = this.defaultApi.idpKeysSpidTagGet(tag); + } catch (ApiException e) { + /*throw new LollipopAssertionNotFoundException( + "Error retrieving assertion: " + e.getMessage(), e);*/ + } + + //TODO gestire filtraggio xml per entityId + + return null; + } + + private List getCIETagList(String instant) { + List responseAssertion = new ArrayList<>(); + + try { + responseAssertion = this.defaultApi.idpKeysCieGet(); + } catch (ApiException e) { + /*throw new LollipopAssertionNotFoundException( + "Error retrieving idp cert list: " + e.getMessage(), e);*/ + } + + //TODO gestire filtro tag (prendere quello subito prima e subito dopo rispetto all' "instant") + + return responseAssertion; + } + + private IdpCertData getCIECertData(String tag) { + CertData responseAssertion; + + try { + responseAssertion = this.defaultApi.idpKeysCieTagGet(tag); + } catch (ApiException e) { + /*throw new LollipopAssertionNotFoundException( + "Error retrieving assertion: " + e.getMessage(), e);*/ + } + return null; } } From a0e4653856d26e6de93d162e7efee1afae683c9b Mon Sep 17 00:00:00 2001 From: giomella Date: Tue, 11 Apr 2023 16:59:52 +0200 Subject: [PATCH 073/403] [SLS-20] implemented AssertionService interface for retrieving the assertion. Do some refactor on AssertionSimpleClient and LollipopConsumerCommandBuilderImpl. --- .../client/simple/AssertionSimpleClient.java | 8 +-- .../simple/AssertionSimpleClientTest.java | 22 ------- .../consumer/assertion/AssertionService.java | 13 +++- .../assertion/AssertionServiceFactory.java | 4 ++ .../impl/AssertionServiceFactoryImpl.java | 33 ++++++++++ .../impl/AssertionServiceFactoryImplStub.java | 17 ----- .../assertion/impl/AssertionServiceImpl.java | 64 +++++++++++++++++++ .../impl/AssertionServiceImplStub.java | 18 ------ .../LollipopConsumerCommandBuilderImpl.java | 2 +- 9 files changed, 115 insertions(+), 66 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImpl.java delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImpl.java delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java index adf568dc..b2f93b42 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java @@ -15,12 +15,10 @@ /** Implementation of the @AssertionClient using generated openAPI REST Client */ public class AssertionSimpleClient implements AssertionClient { - ApiClient apiClient; - DefaultApi defaultApi; + private final DefaultApi defaultApi; @Inject public AssertionSimpleClient(ApiClient client) { - this.apiClient = client; this.defaultApi = new DefaultApi(client); } @@ -38,10 +36,6 @@ public SamlAssertion getAssertion(String jwt, String assertionRef) throws LollipopAssertionNotFoundException { AssertionRef ref = new AssertionRef(assertionRef); - if (jwt.isEmpty() || assertionRef.isEmpty()) { - throw new IllegalArgumentException("Jwt or Assertion Ref missing"); - } - LCUserInfo responseAssertion; try { diff --git a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java index 291f0516..436867bc 100644 --- a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java +++ b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java @@ -304,28 +304,6 @@ void assertionNotFound() { () -> assertionSimpleClient.getAssertion(JWT, WRONG_ASSERTION_REF)); } - @Test - void noJwt() { - // setup - String assertionRef = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; - String jwt = ""; - - Assertions.assertThrows( - IllegalArgumentException.class, - () -> assertionSimpleClient.getAssertion(jwt, assertionRef)); - } - - @Test - void noAssertionRef() { - // setup - String assertionRef = ""; - String jwt = "Bearer aValidJWT"; - - Assertions.assertThrows( - IllegalArgumentException.class, - () -> assertionSimpleClient.getAssertion(jwt, assertionRef)); - } - private void createExpectationAssertionFound() { new MockServerClient("localhost", 2000) .when( diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionService.java index f755062f..d8ef224f 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionService.java @@ -1,9 +1,20 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion; +import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; +/** + * Interface of the assertion service, it defines the methods for managing the assertions + */ public interface AssertionService { - SamlAssertion getAssertion(String jwt, String assertionRef); + /** + * Retrieve a SAML assertion using the provided jwt and the assertion reference + * @param jwt the jwt + * @param assertionRef the assertion reference + * @return the requested SAML assertion or null if the assertion is not supported + * @throws LollipopAssertionNotFoundException if some error occurred retrieving the request + */ + SamlAssertion getAssertion(String jwt, String assertionRef) throws LollipopAssertionNotFoundException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionServiceFactory.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionServiceFactory.java index 0b1bd266..386da2e1 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionServiceFactory.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionServiceFactory.java @@ -1,7 +1,11 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion; +/** Interface for the factory used to create instances of {@link AssertionServiceFactory} */ public interface AssertionServiceFactory { + /** + * @return instance of AssertionService + */ AssertionService create(); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImpl.java new file mode 100644 index 00000000..b6cd8ba4 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImpl.java @@ -0,0 +1,33 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.assertion.impl; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; +import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; +import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClientProvider; +import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorageProvider; + +import javax.inject.Inject; + +/** + * Implementation of {@link AssertionServiceFactory}, used to create instances of {@link + * AssertionServiceImpl} + */ +public class AssertionServiceFactoryImpl implements AssertionServiceFactory { + private AssertionStorageProvider assertionStorageProvider; + private AssertionClientProvider assertionClientProvider; + + @Inject + public AssertionServiceFactoryImpl(AssertionStorageProvider assertionStorageProvider, AssertionClientProvider assertionClientProvider) { + this.assertionStorageProvider = assertionStorageProvider; + this.assertionClientProvider = assertionClientProvider; + } + + /** + * Factory for creating an instance of {@link AssertionServiceImpl} + * @return an instance of {@link AssertionServiceImpl} + */ + @Override + public AssertionService create() { + return new AssertionServiceImpl(assertionStorageProvider.provideStorage(), assertionClientProvider.provideClient()); + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java deleted file mode 100644 index 874c1158..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImplStub.java +++ /dev/null @@ -1,17 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.assertion.impl; - -import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; -import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; -import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClientProvider; -import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorageProvider; - -public class AssertionServiceFactoryImplStub implements AssertionServiceFactory { - private AssertionStorageProvider assertionStorageProvider; - private AssertionClientProvider assertionClientProvider; - - @Override - public AssertionService create() { - return null; - } -} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImpl.java new file mode 100644 index 00000000..a0af5aa3 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImpl.java @@ -0,0 +1,64 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.assertion.impl; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; +import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClient; +import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorage; +import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; + +import javax.inject.Inject; + +/** + * Service for managing the assertion + */ +public class AssertionServiceImpl implements AssertionService { + + private final AssertionStorage assertionStorage; + private final AssertionClient assertionClient; + + @Inject + public AssertionServiceImpl(AssertionStorage assertionStorage, AssertionClient assertionClient) { + this.assertionStorage = assertionStorage; + this.assertionClient = assertionClient; + } + + /** + * {@inheritDoc} + * + * Retrieve the SAML assertion, first looking in the storage if enabled + * ({@link it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig}) and then + * if not found through the client {@link AssertionClient}. + * If the storage is enabled ({@link it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig}) + * and the assertion is retrieved through the client, it store the assertion. + * + * @param jwt the jwt + * @param assertionRef the assertion reference + * @return the SAML assertion or null if the assertion is not supported (not SAML) + * @throws LollipopAssertionNotFoundException if some error occurred retrieving the assertion through the client + */ + @Override + public SamlAssertion getAssertion(String jwt, String assertionRef) throws LollipopAssertionNotFoundException { + + if (jwt == null || jwt.isBlank() || assertionRef == null || assertionRef.isBlank()) { + String errMsg = String.format("Cannot retrieve the assertion, jwt [%s] or assertion reference [%s] missing", jwt, assertionRef); + throw new IllegalArgumentException(errMsg); + } + + SamlAssertion samlAssertion = assertionStorage.getAssertion(assertionRef); + + if (samlAssertion != null) { + return samlAssertion; + } + + samlAssertion = assertionClient.getAssertion(jwt, assertionRef); + + if (samlAssertion == null) { + return null; + } + + assertionStorage.saveAssertion(assertionRef, samlAssertion); + + return samlAssertion; + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java deleted file mode 100644 index a6feea97..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplStub.java +++ /dev/null @@ -1,18 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.assertion.impl; - -import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; -import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClient; -import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorage; -import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; - -public class AssertionServiceImplStub implements AssertionService { - - private AssertionStorage assertionStorage; - private AssertionClient assertionClient; - - @Override - public SamlAssertion getAssertion(String jwt, String assertionRef) { - return null; - } -} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java index 3f4e22e7..95844767 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java @@ -7,7 +7,7 @@ import javax.inject.Inject; /** - * Implementation of {@link LollipopConsumerCommandBuilder}, used to create istances of {@link + * Implementation of {@link LollipopConsumerCommandBuilder}, used to create instances of {@link * LollipopConsumerCommandImpl} */ public class LollipopConsumerCommandBuilderImpl implements LollipopConsumerCommandBuilder { From 3b823c9a37881714a94c2f100a1dbf17bd3c6c0b Mon Sep 17 00:00:00 2001 From: giomella Date: Tue, 11 Apr 2023 17:02:39 +0200 Subject: [PATCH 074/403] [SLS-20] implemented SimpleAssertionStorage for storing the retrieved assertions and added StorageConfig class for the storage configuration. --- .../assertion/storage/AssertionStorage.java | 15 +++- .../storage/AssertionStorageProvider.java | 4 + .../storage/SimpleAssertionStorage.java | 78 +++++++++++++++++++ .../SimpleAssertionStorageProvider.java | 19 +++++ .../assertion/storage/StorageConfig.java | 18 +++++ 5 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorage.java index 5883d6f9..e566d214 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorage.java @@ -3,9 +3,22 @@ import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; +/** + * Interface of the storage used for storing the assertion retrieved for validation + */ public interface AssertionStorage { + /** + * Retrieve the assertion associated with the provided assertion reference + * @param assertionRef the assertion reference + * @return the SAML assertion if found, otherwise null + */ SamlAssertion getAssertion(String assertionRef); - void saveAssertion(SamlAssertion assertion); + /** + * Store the provided assertion + * @param assertionRef the assertion reference + * @param assertion the SAML assertion + */ + void saveAssertion(String assertionRef, SamlAssertion assertion); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorageProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorageProvider.java index abe8bb25..5dd2af1e 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorageProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorageProvider.java @@ -1,7 +1,11 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.storage; +/** Interface for the provider used to create instances of {@link AssertionStorage} */ public interface AssertionStorageProvider { + /** + * @return instance of {@link AssertionStorage} + */ AssertionStorage provideStorage(); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java new file mode 100644 index 00000000..e804a88e --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java @@ -0,0 +1,78 @@ +package it.pagopa.tech.lollipop.consumer.assertion.storage; + +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; + +import javax.inject.Inject; +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; + +/** + * Implementation of the {@link AssertionStorage} interface as a simple in memory storage + */ +public class SimpleAssertionStorage implements AssertionStorage { + + private final Map assertionMap; + private final Map timerMap; + private final StorageConfig storageConfig; + + @Inject + public SimpleAssertionStorage(Map assertionMap, Map timerMap, StorageConfig storageConfig) { + this.assertionMap = assertionMap; + this.timerMap = timerMap; + this.storageConfig = storageConfig; + } + + /** + * Retrieve the assertion associated with the provided assertion reference + * @param assertionRef the assertion reference + * @return the SAML assertion if found, otherwise null + */ + @Override + public SamlAssertion getAssertion(String assertionRef) { + if (!storageConfig.isAssertionStorageEnabled()) { + return null; + } + + SamlAssertion samlAssertion = assertionMap.get(assertionRef); + if (samlAssertion != null) { + delayEviction(assertionRef); + } + return samlAssertion; + } + + /** + * Store the assertion + * @param assertionRef the assertion reference + * @param assertion the SAML assertion + */ + @Override + public void saveAssertion(String assertionRef, SamlAssertion assertion) { + if (!storageConfig.isAssertionStorageEnabled()) { + return; + } + + assertionMap.put(assertionRef, assertion); + scheduleEviction(assertionRef); + + } + + private void scheduleEviction(String assertionRef) { + TimerTask evictionTask = new TimerTask() { + public void run() { + assertionMap.remove(assertionRef); + } + }; + Timer timer = new Timer(); + long delay = 1000L; + timer.schedule(evictionTask, delay); + timerMap.put(assertionRef, timer); + } + + private void delayEviction(String assertionRef) { + Timer timer = timerMap.get(assertionRef); + timer.cancel(); + timerMap.remove(assertionRef); + scheduleEviction(assertionRef); + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java new file mode 100644 index 00000000..9f7e4253 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java @@ -0,0 +1,19 @@ +package it.pagopa.tech.lollipop.consumer.assertion.storage; + +import java.util.HashMap; + +/** + * Implementation of {@link AssertionStorageProvider} interface. It provides an instance of the + */ +public class SimpleAssertionStorageProvider implements AssertionStorageProvider { + + /** + * {@inheritDoc} + * + * @return an instance of {@link SimpleAssertionStorage} + */ + @Override + public AssertionStorage provideStorage() { + return new SimpleAssertionStorage(new HashMap<>(), new HashMap<>(), new StorageConfig(true, 60000L)); + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java new file mode 100644 index 00000000..ba67775b --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java @@ -0,0 +1,18 @@ +package it.pagopa.tech.lollipop.consumer.assertion.storage; + +import lombok.Getter; + +/** + * Configuration class for the assertion storage + */ +@Getter +public class StorageConfig { + + private final boolean assertionStorageEnabled; + private final long storageEvictionDelay; + + public StorageConfig(boolean assertionStorageEnabled, long storageEvictionDelay) { + this.assertionStorageEnabled = assertionStorageEnabled; + this.storageEvictionDelay = storageEvictionDelay; + } +} From dfe220ea20df1039de6a750ba84f5865e0994bb9 Mon Sep 17 00:00:00 2001 From: giomella Date: Tue, 11 Apr 2023 17:03:05 +0200 Subject: [PATCH 075/403] [SLS-20] added unit tests. --- .../impl/AssertionServiceImplTest.java | 116 ++++++++++++++++++ .../storage/SimpleAssertionStorageTest.java | 102 +++++++++++++++ 2 files changed, 218 insertions(+) create mode 100644 core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplTest.java create mode 100644 core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplTest.java new file mode 100644 index 00000000..a8c6a401 --- /dev/null +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplTest.java @@ -0,0 +1,116 @@ +package it.pagopa.tech.lollipop.consumer.assertion.impl; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; +import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClient; +import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorage; +import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +class AssertionServiceImplTest { + + private static AssertionStorage assertionStorageMock; + private static AssertionClient assertionClientMock; + private static AssertionService sut; + + private static final String JWT = "jwt"; + private static final String ASSERTION_REF = "assertionRef"; + + @BeforeEach + void setUp() { + assertionClientMock = mock(AssertionClient.class); + assertionStorageMock = mock(AssertionStorage.class); + sut = new AssertionServiceImpl(assertionStorageMock, assertionClientMock); + } + + @Test + void getAssertionFromStorageWithSuccess() throws LollipopAssertionNotFoundException { + SamlAssertion assertion = new SamlAssertion(); + doReturn(assertion).when(assertionStorageMock).getAssertion(ASSERTION_REF); + + sut.getAssertion(JWT, ASSERTION_REF); + + verify(assertionStorageMock).getAssertion(ASSERTION_REF); + verify(assertionClientMock, never()).getAssertion(JWT, ASSERTION_REF); + verify(assertionStorageMock, never()).saveAssertion(ASSERTION_REF, assertion); + } + + @Test + void getAssertionFromClientWithSuccess() throws LollipopAssertionNotFoundException { + SamlAssertion assertion = new SamlAssertion(); + doReturn(null).when(assertionStorageMock).getAssertion(ASSERTION_REF); + doReturn(assertion).when(assertionClientMock).getAssertion(JWT, ASSERTION_REF); + + sut.getAssertion(JWT, ASSERTION_REF); + + verify(assertionStorageMock).getAssertion(ASSERTION_REF); + verify(assertionClientMock).getAssertion(JWT, ASSERTION_REF); + verify(assertionStorageMock).saveAssertion(ASSERTION_REF, assertion); + } + + @Test + void getUnsupportedAssertionFromClient() throws LollipopAssertionNotFoundException { + doReturn(null).when(assertionStorageMock).getAssertion(ASSERTION_REF); + doReturn(null).when(assertionClientMock).getAssertion(JWT, ASSERTION_REF); + + sut.getAssertion(JWT, ASSERTION_REF); + + verify(assertionStorageMock).getAssertion(ASSERTION_REF); + verify(assertionClientMock).getAssertion(JWT, ASSERTION_REF); + verify(assertionStorageMock, never()).saveAssertion(anyString(), any()); + } + + @Test + void getAssertionFromClientWithLollipopAssertionNotFoundException() throws LollipopAssertionNotFoundException { + doReturn(null).when(assertionStorageMock).getAssertion(ASSERTION_REF); + doThrow(LollipopAssertionNotFoundException.class).when(assertionClientMock).getAssertion(JWT, ASSERTION_REF); + + Assertions.assertThrows(LollipopAssertionNotFoundException.class, () -> sut.getAssertion(JWT, ASSERTION_REF)); + + verify(assertionStorageMock).getAssertion(ASSERTION_REF); + verify(assertionClientMock).getAssertion(JWT, ASSERTION_REF); + verify(assertionStorageMock, never()).saveAssertion(anyString(), any(SamlAssertion.class)); + } + + @Test + void getAssertionWithEmptyJwtParameterFailure() throws LollipopAssertionNotFoundException { + Assertions.assertThrows(IllegalArgumentException.class, () -> sut.getAssertion("", ASSERTION_REF)); + + verify(assertionStorageMock, never()).getAssertion(anyString()); + verify(assertionClientMock, never()).getAssertion(JWT, ASSERTION_REF); + verify(assertionStorageMock, never()).saveAssertion(anyString(), any(SamlAssertion.class)); + } + + @Test + void getAssertionWithNullJwtParameterFailure() throws LollipopAssertionNotFoundException { + Assertions.assertThrows(IllegalArgumentException.class, () -> sut.getAssertion(null, ASSERTION_REF)); + + verify(assertionStorageMock, never()).getAssertion(anyString()); + verify(assertionClientMock, never()).getAssertion(JWT, ASSERTION_REF); + verify(assertionStorageMock, never()).saveAssertion(anyString(), any(SamlAssertion.class)); + } + + @Test + void getAssertionWithEmptyAssertionRefParameterFailure() throws LollipopAssertionNotFoundException { + Assertions.assertThrows(IllegalArgumentException.class, () -> sut.getAssertion(JWT, "")); + + verify(assertionStorageMock, never()).getAssertion(ASSERTION_REF); + verify(assertionClientMock, never()).getAssertion(JWT, ASSERTION_REF); + verify(assertionStorageMock, never()).saveAssertion(anyString(), any(SamlAssertion.class)); + } + + @Test + void getAssertionWithNullAssertionRefParameterFailure() throws LollipopAssertionNotFoundException { + Assertions.assertThrows(IllegalArgumentException.class, () -> sut.getAssertion(JWT, null)); + + verify(assertionStorageMock, never()).getAssertion(ASSERTION_REF); + verify(assertionClientMock, never()).getAssertion(JWT, ASSERTION_REF); + verify(assertionStorageMock, never()).saveAssertion(anyString(), any(SamlAssertion.class)); + } +} \ No newline at end of file diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java new file mode 100644 index 00000000..fb5ad2d7 --- /dev/null +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java @@ -0,0 +1,102 @@ +package it.pagopa.tech.lollipop.consumer.assertion.storage; + +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; +import java.util.Timer; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +class SimpleAssertionStorageTest { + + private static StorageConfig storageConfigMock; + private AssertionStorage sut; + private static final String ASSERTION_REF_1 = "assertionRef1"; + + @BeforeEach + void setUp() { + storageConfigMock = mock(StorageConfig.class); + doReturn(10000L).when(storageConfigMock).getStorageEvictionDelay(); + } + + @Test + void getExistingAssertionAndResetScheduleEvictionWithStorageEnabled() { + doReturn(true).when(storageConfigMock).isAssertionStorageEnabled(); + + Map assertionMap = new HashMap<>(); + SamlAssertion samlAssertion = new SamlAssertion(); + assertionMap.put(ASSERTION_REF_1, samlAssertion); + Map timerMap = new HashMap<>(); + Timer timer = new Timer(); + timerMap.put(ASSERTION_REF_1, timer); + + sut = new SimpleAssertionStorage(assertionMap, timerMap, storageConfigMock); + + SamlAssertion result = sut.getAssertion(ASSERTION_REF_1); + + assertNotNull(result); + assertEquals(samlAssertion, result); + assertEquals(1, timerMap.size()); + assertNotEquals(timer, timerMap.get(ASSERTION_REF_1)); + + } + + @Test + void getNotExistingAssertionWithStorageEnabled() { + doReturn(true).when(storageConfigMock).isAssertionStorageEnabled(); + + sut = new SimpleAssertionStorage(new HashMap<>(), new HashMap<>(), storageConfigMock); + + SamlAssertion result = sut.getAssertion(ASSERTION_REF_1); + + assertNull(result); + } + + @Test + void saveAssertionAndScheduleEvictionWithStorageEnabled() { + doReturn(true).when(storageConfigMock).isAssertionStorageEnabled(); + + Map assertionMap = new HashMap<>(); + Map timerMap = new HashMap<>(); + + sut = new SimpleAssertionStorage(assertionMap, timerMap, storageConfigMock); + SamlAssertion samlAssertion = new SamlAssertion(); + + sut.saveAssertion(ASSERTION_REF_1, samlAssertion); + + assertEquals(1, assertionMap.size()); + assertEquals(1, timerMap.size()); + assertEquals(samlAssertion, assertionMap.get(ASSERTION_REF_1)); + } + + @Test + void getAssertionWithStorageDisabled() { + doReturn(false).when(storageConfigMock).isAssertionStorageEnabled(); + + sut = new SimpleAssertionStorage(new HashMap<>(), new HashMap<>(), storageConfigMock); + + SamlAssertion result = sut.getAssertion(ASSERTION_REF_1); + + assertNull(result); + } + + @Test + void savaAssertionWithStorageDisabled() { + doReturn(false).when(storageConfigMock).isAssertionStorageEnabled(); + + Map assertionMap = new HashMap<>(); + Map timerMap = new HashMap<>(); + + sut = new SimpleAssertionStorage(assertionMap, timerMap, storageConfigMock); + + sut.saveAssertion(ASSERTION_REF_1, new SamlAssertion()); + + assertEquals(0, assertionMap.size()); + assertEquals(0, timerMap.size()); + } +} \ No newline at end of file From d3f4a11715a621f45edf78e5c28e76372b945264 Mon Sep 17 00:00:00 2001 From: giomella Date: Tue, 11 Apr 2023 17:13:26 +0200 Subject: [PATCH 076/403] [SLS-20] applied spotless formatting. --- .../consumer/assertion/AssertionService.java | 8 ++--- .../impl/AssertionServiceFactoryImpl.java | 11 +++--- .../assertion/impl/AssertionServiceImpl.java | 30 +++++++++------- .../assertion/storage/AssertionStorage.java | 6 ++-- .../storage/SimpleAssertionStorage.java | 29 +++++++++------- .../SimpleAssertionStorageProvider.java | 8 ++--- .../assertion/storage/StorageConfig.java | 5 ++- .../impl/AssertionServiceImplTest.java | 34 ++++++++++++------- .../storage/SimpleAssertionStorageTest.java | 17 +++++----- 9 files changed, 83 insertions(+), 65 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionService.java index d8ef224f..ea4c4b12 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/AssertionService.java @@ -4,17 +4,17 @@ import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; -/** - * Interface of the assertion service, it defines the methods for managing the assertions - */ +/** Interface of the assertion service, it defines the methods for managing the assertions */ public interface AssertionService { /** * Retrieve a SAML assertion using the provided jwt and the assertion reference + * * @param jwt the jwt * @param assertionRef the assertion reference * @return the requested SAML assertion or null if the assertion is not supported * @throws LollipopAssertionNotFoundException if some error occurred retrieving the request */ - SamlAssertion getAssertion(String jwt, String assertionRef) throws LollipopAssertionNotFoundException; + SamlAssertion getAssertion(String jwt, String assertionRef) + throws LollipopAssertionNotFoundException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImpl.java index b6cd8ba4..beaada98 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImpl.java @@ -5,29 +5,32 @@ import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClientProvider; import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorageProvider; - import javax.inject.Inject; /** * Implementation of {@link AssertionServiceFactory}, used to create instances of {@link - * AssertionServiceImpl} + * AssertionServiceImpl} */ public class AssertionServiceFactoryImpl implements AssertionServiceFactory { private AssertionStorageProvider assertionStorageProvider; private AssertionClientProvider assertionClientProvider; @Inject - public AssertionServiceFactoryImpl(AssertionStorageProvider assertionStorageProvider, AssertionClientProvider assertionClientProvider) { + public AssertionServiceFactoryImpl( + AssertionStorageProvider assertionStorageProvider, + AssertionClientProvider assertionClientProvider) { this.assertionStorageProvider = assertionStorageProvider; this.assertionClientProvider = assertionClientProvider; } /** * Factory for creating an instance of {@link AssertionServiceImpl} + * * @return an instance of {@link AssertionServiceImpl} */ @Override public AssertionService create() { - return new AssertionServiceImpl(assertionStorageProvider.provideStorage(), assertionClientProvider.provideClient()); + return new AssertionServiceImpl( + assertionStorageProvider.provideStorage(), assertionClientProvider.provideClient()); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImpl.java index a0af5aa3..873552f5 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImpl.java @@ -6,19 +6,17 @@ import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorage; import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; - import javax.inject.Inject; -/** - * Service for managing the assertion - */ +/** Service for managing the assertion */ public class AssertionServiceImpl implements AssertionService { private final AssertionStorage assertionStorage; private final AssertionClient assertionClient; @Inject - public AssertionServiceImpl(AssertionStorage assertionStorage, AssertionClient assertionClient) { + public AssertionServiceImpl( + AssertionStorage assertionStorage, AssertionClient assertionClient) { this.assertionStorage = assertionStorage; this.assertionClient = assertionClient; } @@ -26,22 +24,28 @@ public AssertionServiceImpl(AssertionStorage assertionStorage, AssertionClient a /** * {@inheritDoc} * - * Retrieve the SAML assertion, first looking in the storage if enabled - * ({@link it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig}) and then - * if not found through the client {@link AssertionClient}. - * If the storage is enabled ({@link it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig}) - * and the assertion is retrieved through the client, it store the assertion. + *

Retrieve the SAML assertion, first looking in the storage if enabled ({@link + * it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig}) and then if not found + * through the client {@link AssertionClient}. If the storage is enabled ({@link + * it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig}) and the assertion is + * retrieved through the client, it store the assertion. * * @param jwt the jwt * @param assertionRef the assertion reference * @return the SAML assertion or null if the assertion is not supported (not SAML) - * @throws LollipopAssertionNotFoundException if some error occurred retrieving the assertion through the client + * @throws LollipopAssertionNotFoundException if some error occurred retrieving the assertion + * through the client */ @Override - public SamlAssertion getAssertion(String jwt, String assertionRef) throws LollipopAssertionNotFoundException { + public SamlAssertion getAssertion(String jwt, String assertionRef) + throws LollipopAssertionNotFoundException { if (jwt == null || jwt.isBlank() || assertionRef == null || assertionRef.isBlank()) { - String errMsg = String.format("Cannot retrieve the assertion, jwt [%s] or assertion reference [%s] missing", jwt, assertionRef); + String errMsg = + String.format( + "Cannot retrieve the assertion, jwt [%s] or assertion reference [%s]" + + " missing", + jwt, assertionRef); throw new IllegalArgumentException(errMsg); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorage.java index e566d214..b18f3bf2 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorage.java @@ -3,13 +3,12 @@ import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; -/** - * Interface of the storage used for storing the assertion retrieved for validation - */ +/** Interface of the storage used for storing the assertion retrieved for validation */ public interface AssertionStorage { /** * Retrieve the assertion associated with the provided assertion reference + * * @param assertionRef the assertion reference * @return the SAML assertion if found, otherwise null */ @@ -17,6 +16,7 @@ public interface AssertionStorage { /** * Store the provided assertion + * * @param assertionRef the assertion reference * @param assertion the SAML assertion */ diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java index e804a88e..9753433f 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java @@ -1,15 +1,13 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.storage; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; - -import javax.inject.Inject; import java.util.Map; import java.util.Timer; import java.util.TimerTask; +import javax.inject.Inject; -/** - * Implementation of the {@link AssertionStorage} interface as a simple in memory storage - */ +/** Implementation of the {@link AssertionStorage} interface as a simple in memory storage */ public class SimpleAssertionStorage implements AssertionStorage { private final Map assertionMap; @@ -17,7 +15,10 @@ public class SimpleAssertionStorage implements AssertionStorage { private final StorageConfig storageConfig; @Inject - public SimpleAssertionStorage(Map assertionMap, Map timerMap, StorageConfig storageConfig) { + public SimpleAssertionStorage( + Map assertionMap, + Map timerMap, + StorageConfig storageConfig) { this.assertionMap = assertionMap; this.timerMap = timerMap; this.storageConfig = storageConfig; @@ -25,6 +26,7 @@ public SimpleAssertionStorage(Map assertionMap, Map(), new HashMap<>(), new StorageConfig(true, 60000L)); + return new SimpleAssertionStorage( + new HashMap<>(), new HashMap<>(), new StorageConfig(true, 60000L)); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java index ba67775b..29f557ab 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java @@ -1,10 +1,9 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.storage; import lombok.Getter; -/** - * Configuration class for the assertion storage - */ +/** Configuration class for the assertion storage */ @Getter public class StorageConfig { diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplTest.java index a8c6a401..951a30ca 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceImplTest.java @@ -1,5 +1,10 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.impl; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClient; import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorage; @@ -9,10 +14,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.*; - class AssertionServiceImplTest { private static AssertionStorage assertionStorageMock; @@ -67,11 +68,16 @@ void getUnsupportedAssertionFromClient() throws LollipopAssertionNotFoundExcepti } @Test - void getAssertionFromClientWithLollipopAssertionNotFoundException() throws LollipopAssertionNotFoundException { + void getAssertionFromClientWithLollipopAssertionNotFoundException() + throws LollipopAssertionNotFoundException { doReturn(null).when(assertionStorageMock).getAssertion(ASSERTION_REF); - doThrow(LollipopAssertionNotFoundException.class).when(assertionClientMock).getAssertion(JWT, ASSERTION_REF); + doThrow(LollipopAssertionNotFoundException.class) + .when(assertionClientMock) + .getAssertion(JWT, ASSERTION_REF); - Assertions.assertThrows(LollipopAssertionNotFoundException.class, () -> sut.getAssertion(JWT, ASSERTION_REF)); + Assertions.assertThrows( + LollipopAssertionNotFoundException.class, + () -> sut.getAssertion(JWT, ASSERTION_REF)); verify(assertionStorageMock).getAssertion(ASSERTION_REF); verify(assertionClientMock).getAssertion(JWT, ASSERTION_REF); @@ -80,7 +86,8 @@ void getAssertionFromClientWithLollipopAssertionNotFoundException() throws Lolli @Test void getAssertionWithEmptyJwtParameterFailure() throws LollipopAssertionNotFoundException { - Assertions.assertThrows(IllegalArgumentException.class, () -> sut.getAssertion("", ASSERTION_REF)); + Assertions.assertThrows( + IllegalArgumentException.class, () -> sut.getAssertion("", ASSERTION_REF)); verify(assertionStorageMock, never()).getAssertion(anyString()); verify(assertionClientMock, never()).getAssertion(JWT, ASSERTION_REF); @@ -89,7 +96,8 @@ void getAssertionWithEmptyJwtParameterFailure() throws LollipopAssertionNotFound @Test void getAssertionWithNullJwtParameterFailure() throws LollipopAssertionNotFoundException { - Assertions.assertThrows(IllegalArgumentException.class, () -> sut.getAssertion(null, ASSERTION_REF)); + Assertions.assertThrows( + IllegalArgumentException.class, () -> sut.getAssertion(null, ASSERTION_REF)); verify(assertionStorageMock, never()).getAssertion(anyString()); verify(assertionClientMock, never()).getAssertion(JWT, ASSERTION_REF); @@ -97,7 +105,8 @@ void getAssertionWithNullJwtParameterFailure() throws LollipopAssertionNotFoundE } @Test - void getAssertionWithEmptyAssertionRefParameterFailure() throws LollipopAssertionNotFoundException { + void getAssertionWithEmptyAssertionRefParameterFailure() + throws LollipopAssertionNotFoundException { Assertions.assertThrows(IllegalArgumentException.class, () -> sut.getAssertion(JWT, "")); verify(assertionStorageMock, never()).getAssertion(ASSERTION_REF); @@ -106,11 +115,12 @@ void getAssertionWithEmptyAssertionRefParameterFailure() throws LollipopAssertio } @Test - void getAssertionWithNullAssertionRefParameterFailure() throws LollipopAssertionNotFoundException { + void getAssertionWithNullAssertionRefParameterFailure() + throws LollipopAssertionNotFoundException { Assertions.assertThrows(IllegalArgumentException.class, () -> sut.getAssertion(JWT, null)); verify(assertionStorageMock, never()).getAssertion(ASSERTION_REF); verify(assertionClientMock, never()).getAssertion(JWT, ASSERTION_REF); verify(assertionStorageMock, never()).saveAssertion(anyString(), any(SamlAssertion.class)); } -} \ No newline at end of file +} diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java index fb5ad2d7..67afebec 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java @@ -1,16 +1,16 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.storage; -import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import java.util.HashMap; import java.util.Map; import java.util.Timer; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; class SimpleAssertionStorageTest { @@ -43,7 +43,6 @@ void getExistingAssertionAndResetScheduleEvictionWithStorageEnabled() { assertEquals(samlAssertion, result); assertEquals(1, timerMap.size()); assertNotEquals(timer, timerMap.get(ASSERTION_REF_1)); - } @Test @@ -99,4 +98,4 @@ void savaAssertionWithStorageDisabled() { assertEquals(0, assertionMap.size()); assertEquals(0, timerMap.size()); } -} \ No newline at end of file +} From 885f9ccb3575b3529c9d3a9608f40673c43f5e66 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 17:17:09 +0200 Subject: [PATCH 077/403] [SLS-31] Updated build.gradle --- assertion-rest-client-native/build.gradle | 2 - build.gradle | 2 +- core/build.gradle | 2 - http-verifier/build.gradle | 2 +- .../build.gradle | 2 +- redis-storage/build.gradle | 2 - sample/build.gradle | 6 +- sample/gradlew | 257 +++++++++++------- 8 files changed, 158 insertions(+), 117 deletions(-) diff --git a/assertion-rest-client-native/build.gradle b/assertion-rest-client-native/build.gradle index 55886112..001bdaf1 100644 --- a/assertion-rest-client-native/build.gradle +++ b/assertion-rest-client-native/build.gradle @@ -14,8 +14,6 @@ plugins { /*id("org.openapi.generator") version "6.5.0"*/ } -group 'it.pagopa.commons' - repositories { mavenLocal() mavenCentral() diff --git a/build.gradle b/build.gradle index f7661683..75f4874d 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ repositories { allprojects { version = "1.0.0-SNAPSHOT" - group = 'it.pagopa.tech' + group = 'it.pagopa.tech.lollipop-consumer-java-sdk' sourceCompatibility = '11' targetCompatibility = '11' apply plugin: 'com.diffplug.spotless' diff --git a/core/build.gradle b/core/build.gradle index a5d2b770..f570fbda 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -13,8 +13,6 @@ plugins { id("io.freefair.lombok") version "8.0.0" } -group 'it.pagopa.tech' - repositories { mavenLocal() mavenCentral() diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index dbb59380..cf570018 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -13,7 +13,7 @@ plugins { id("io.freefair.lombok") version "8.0.0" } -group 'it.pagopa.tech' +group 'it.pagopa.tech.lollipop.sdk.impls' repositories { mavenLocal() diff --git a/identity-service-rest-client-native/build.gradle b/identity-service-rest-client-native/build.gradle index 460062f0..ed71e034 100644 --- a/identity-service-rest-client-native/build.gradle +++ b/identity-service-rest-client-native/build.gradle @@ -12,7 +12,7 @@ plugins { id("io.freefair.lombok") version "8.0.0-rc4" } -group 'it.pagopa.tech' +group 'it.pagopa.tech.lollipop.sdk.impls' repositories { mavenLocal() diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle index 86f23568..cad17071 100644 --- a/redis-storage/build.gradle +++ b/redis-storage/build.gradle @@ -13,8 +13,6 @@ plugins { id("io.freefair.lombok") version "8.0.0" } -group 'it.pagopa.tech' - repositories { mavenLocal() mavenCentral() diff --git a/sample/build.gradle b/sample/build.gradle index 9bf6b880..bde45400 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -16,16 +16,14 @@ application { mainClassName = "it.pagopa.tech.sample.LollipopConsumerSample" } -group 'it.pagopa.tech' - repositories { mavenLocal() mavenCentral() } dependencies { - implementation 'it.pagopa.tech:core:1.0.0-SNAPSHOT' - implementation 'it.pagopa.tech:http-verifier:1.0.0-SNAPSHOT' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:core:1.0.0-SNAPSHOT' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:http-verifier:1.0.0-SNAPSHOT' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' } diff --git a/sample/gradlew b/sample/gradlew index 4f906e0c..1b6c7873 100644 --- a/sample/gradlew +++ b/sample/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,101 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" From a04cb5c9020ee993d873a7436d773aefebf81e05 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 11 Apr 2023 18:38:16 +0200 Subject: [PATCH 078/403] [SLS-19] Written basic tests for getCertData --- .../client/simple/IdpCertSimpleClient.java | 10 ++--- .../java/simple/IdpCertSimpleClientTest.java | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 3c602363..bb423fc4 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -1,20 +1,16 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple; -import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.OidcAssertionNotSupported; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; -import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.api.DefaultApi; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.CertData; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; -import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; +import javax.inject.Inject; import java.util.ArrayList; import java.util.List; -import javax.inject.Inject; public class IdpCertSimpleClient implements IdpCertClient { @@ -36,15 +32,17 @@ public IdpCertSimpleClient(ApiClient client) { public List getCertData(String entityId, String instant) { List listCertData = new ArrayList<>(); - if (entityId.equals("https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO")) { //TODO inserire entityID in config + if (entityId.equals("https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO")) { //TODO inserire entityID in classe di configurazione List tagList = getCIETagList(instant); for(String tag: tagList){ + //TODO recupero storage IdpCertData certData = getCIECertData(tag); listCertData.add(certData); } } else { List tagList = getSPIDTagList(instant); for(String tag: tagList){ + //TODO recupero storage IdpCertData certData = getSPIDCertData(tag, entityId); listCertData.add(certData); } diff --git a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java new file mode 100644 index 00000000..65c1ca74 --- /dev/null +++ b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java @@ -0,0 +1,40 @@ +package simple; + + +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClient; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.List; + +class IdpCertSimpleClientTest { + + private static IdpCertSimpleClient idpCertSimpleClient; + + private static final String instant = "1679072970"; + private static final String SPID_ENTITY_ID = "https://posteid.poste.it"; + private static final String CIE_ENTITY_ID = "https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"; + + @BeforeAll + public static void startServer() { + ApiClient client = new ApiClient(); + idpCertSimpleClient = new IdpCertSimpleClient(client); + } + @Test + void getSPIDCertData() { + List response = idpCertSimpleClient.getCertData(SPID_ENTITY_ID, instant); + + Assertions.assertNotNull(response); + } + + @Test + void getCIECertData() { + List response = idpCertSimpleClient.getCertData(CIE_ENTITY_ID, instant); + + Assertions.assertNotNull(response); + } +} \ No newline at end of file From ae5fedf032cbd052374af77193690f838b2be871 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 11 Apr 2023 18:39:49 +0200 Subject: [PATCH 079/403] [SLS-19] Changed InputStream mapper from objectMapper to xmlMapper --- .../idp/client/simple/internal/ApiClient.java | 18 +++++++++++++++++- .../client/simple/internal/api/DefaultApi.java | 7 +++++-- .../client/simple/internal/model/CertData.java | 12 ++++++++---- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java index a3fcc124..5bd7a9d9 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java @@ -16,6 +16,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.openapitools.jackson.nullable.JsonNullableModule; @@ -56,6 +57,7 @@ public class ApiClient { private HttpClient.Builder builder; private ObjectMapper mapper; + private XmlMapper xmlMapper; private String scheme; private String host; private int port; @@ -166,6 +168,7 @@ public static List parameterToPairs( public ApiClient() { this.builder = createDefaultHttpClientBuilder(); this.mapper = createDefaultObjectMapper(); + this.xmlMapper = createDefaultXmlMapper(); updateBaseUri(getDefaultBaseUri()); interceptor = null; readTimeout = null; @@ -181,9 +184,10 @@ public ApiClient() { * @param mapper Object mapper. * @param baseUri Base URI */ - public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, String baseUri) { + public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, XmlMapper xmlMapper, String baseUri) { this.builder = builder; this.mapper = mapper; + this.xmlMapper = xmlMapper; updateBaseUri(baseUri != null ? baseUri : getDefaultBaseUri()); interceptor = null; readTimeout = null; @@ -206,6 +210,11 @@ protected ObjectMapper createDefaultObjectMapper() { return mapper; } + protected XmlMapper createDefaultXmlMapper() { + XmlMapper mapper = new XmlMapper(); + return mapper; + } + protected String getDefaultBaseUri() { return "https://api.is.eng.pagopa.it"; } @@ -266,6 +275,13 @@ public ObjectMapper getObjectMapper() { return mapper.copy(); } + public ApiClient setXmlMapper(XmlMapper mapper) { + this.xmlMapper = mapper; + return this; + } + + public XmlMapper getXmlMapper() { return xmlMapper.copy(); } + /** * Set a custom host name for the target service. * diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java index a061221b..b8ece665 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java @@ -14,6 +14,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiResponse; @@ -34,6 +35,7 @@ public class DefaultApi { private final HttpClient memberVarHttpClient; private final ObjectMapper memberVarObjectMapper; + private final XmlMapper memberVarXMLMapper; private final String memberVarBaseUri; private final Consumer memberVarInterceptor; private final Duration memberVarReadTimeout; @@ -47,6 +49,7 @@ public DefaultApi() { public DefaultApi(ApiClient apiClient) { memberVarHttpClient = apiClient.getHttpClient(); memberVarObjectMapper = apiClient.getObjectMapper(); + memberVarXMLMapper = apiClient.getXmlMapper(); memberVarBaseUri = apiClient.getBaseUri(); memberVarInterceptor = apiClient.getRequestInterceptor(); memberVarReadTimeout = apiClient.getReadTimeout(); @@ -167,7 +170,7 @@ public ApiResponse idpKeysCieTagGetWithHttpInfo(String tag) throws Api return new ApiResponse( localVarResponse.statusCode(), localVarResponse.headers().map(), - localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream + localVarResponse.body() == null ? null : memberVarXMLMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream ); } finally { } @@ -304,7 +307,7 @@ public ApiResponse idpKeysSpidTagGetWithHttpInfo(String tag) throws Ap return new ApiResponse( localVarResponse.statusCode(), localVarResponse.headers().map(), - localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream + localVarResponse.body() == null ? null : memberVarXMLMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream ); } finally { } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java index e9c970a5..baea3633 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java @@ -93,8 +93,10 @@ public CertData deserialize(JsonParser jp, DeserializationContext ctxt) throws I // TODO: there is no validation against JSON schema constraints // (min, max, enum, pattern...), this does not perform a strict JSON // validation, which means the 'match' count may be higher than it should be. - match++; - log.log(Level.FINER, "Input data matches schema 'CIECertData'"); + if (((CIECertData) deserialized).getEntityDescriptor() != null) { + match++; + log.log(Level.FINER, "Input data matches schema 'CIECertData'"); + } } } catch (Exception e) { // deserialization failed, continue @@ -119,8 +121,10 @@ public CertData deserialize(JsonParser jp, DeserializationContext ctxt) throws I // TODO: there is no validation against JSON schema constraints // (min, max, enum, pattern...), this does not perform a strict JSON // validation, which means the 'match' count may be higher than it should be. - match++; - log.log(Level.FINER, "Input data matches schema 'SPIDCertData'"); + if(((SPIDCertData) deserialized).getEntitiesDescriptor() != null){ + match++; + log.log(Level.FINER, "Input data matches schema 'SPIDCertData'"); + } } } catch (Exception e) { // deserialization failed, continue From a2e8ffd25711639d133fc41290777c6fb81a9d22 Mon Sep 17 00:00:00 2001 From: giomella Date: Tue, 11 Apr 2023 19:07:58 +0200 Subject: [PATCH 080/403] [SLS-20] refactor SimpleAssertionStorage eviction logic and StorageConfig initialization. Fixed unit test. --- .../impl/AssertionServiceFactoryImpl.java | 14 ++-- .../storage/AssertionStorageProvider.java | 2 +- .../storage/SimpleAssertionStorage.java | 40 +++++----- .../SimpleAssertionStorageProvider.java | 4 +- .../assertion/storage/StorageConfig.java | 16 ++-- .../helper/LollipopConsumerFactoryHelper.java | 6 +- .../storage/SimpleAssertionStorageTest.java | 74 +++++++++++++------ 7 files changed, 94 insertions(+), 62 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImpl.java index beaada98..108d47cc 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImpl.java @@ -5,6 +5,8 @@ import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClientProvider; import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorageProvider; +import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; + import javax.inject.Inject; /** @@ -12,15 +14,15 @@ * AssertionServiceImpl} */ public class AssertionServiceFactoryImpl implements AssertionServiceFactory { - private AssertionStorageProvider assertionStorageProvider; - private AssertionClientProvider assertionClientProvider; + private final AssertionStorageProvider assertionStorageProvider; + private final AssertionClientProvider assertionClientProvider; + private final StorageConfig storageConfig; @Inject - public AssertionServiceFactoryImpl( - AssertionStorageProvider assertionStorageProvider, - AssertionClientProvider assertionClientProvider) { + public AssertionServiceFactoryImpl(AssertionStorageProvider assertionStorageProvider, AssertionClientProvider assertionClientProvider, StorageConfig storageConfig) { this.assertionStorageProvider = assertionStorageProvider; this.assertionClientProvider = assertionClientProvider; + this.storageConfig = storageConfig; } /** @@ -31,6 +33,6 @@ public AssertionServiceFactoryImpl( @Override public AssertionService create() { return new AssertionServiceImpl( - assertionStorageProvider.provideStorage(), assertionClientProvider.provideClient()); + assertionStorageProvider.provideStorage(storageConfig), assertionClientProvider.provideClient()); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorageProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorageProvider.java index 5dd2af1e..66bde23c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorageProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/AssertionStorageProvider.java @@ -7,5 +7,5 @@ public interface AssertionStorageProvider { /** * @return instance of {@link AssertionStorage} */ - AssertionStorage provideStorage(); + AssertionStorage provideStorage(StorageConfig storageConfig); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java index 9753433f..ad07354a 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java @@ -2,25 +2,27 @@ package it.pagopa.tech.lollipop.consumer.assertion.storage; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; + import javax.inject.Inject; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; /** Implementation of the {@link AssertionStorage} interface as a simple in memory storage */ public class SimpleAssertionStorage implements AssertionStorage { private final Map assertionMap; - private final Map timerMap; + private final Map> scheduledEvictionsMap; private final StorageConfig storageConfig; @Inject public SimpleAssertionStorage( Map assertionMap, - Map timerMap, + Map> scheduledEvictionsMap, StorageConfig storageConfig) { this.assertionMap = assertionMap; - this.timerMap = timerMap; + this.scheduledEvictionsMap = scheduledEvictionsMap; this.storageConfig = storageConfig; } @@ -60,22 +62,22 @@ public void saveAssertion(String assertionRef, SamlAssertion assertion) { } private void scheduleEviction(String assertionRef) { - TimerTask evictionTask = - new TimerTask() { - public void run() { - assertionMap.remove(assertionRef); - } - }; - Timer timer = new Timer(); - long delay = 1000L; - timer.schedule(evictionTask, delay); - timerMap.put(assertionRef, timer); + ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); + ScheduledFuture schedule = executorService.schedule(getEvictionTask(assertionRef), storageConfig.getStorageEvictionDelay(), storageConfig.getStorageEvictionDelayTimeUnit()); + scheduledEvictionsMap.put(assertionRef, schedule); } private void delayEviction(String assertionRef) { - Timer timer = timerMap.get(assertionRef); - timer.cancel(); - timerMap.remove(assertionRef); + ScheduledFuture schedule = scheduledEvictionsMap.get(assertionRef); + schedule.cancel(false); + scheduledEvictionsMap.remove(assertionRef); scheduleEviction(assertionRef); } + + private Runnable getEvictionTask(String assertionRef) { + return () -> { + assertionMap.remove(assertionRef); + scheduledEvictionsMap.remove(assertionRef); + }; + } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java index 409c6237..fa95ad28 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java @@ -12,8 +12,8 @@ public class SimpleAssertionStorageProvider implements AssertionStorageProvider * @return an instance of {@link SimpleAssertionStorage} */ @Override - public AssertionStorage provideStorage() { + public AssertionStorage provideStorage(StorageConfig storageConfig) { return new SimpleAssertionStorage( - new HashMap<>(), new HashMap<>(), new StorageConfig(true, 60000L)); + new HashMap<>(), new HashMap<>(), storageConfig); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java index 29f557ab..19568da1 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java @@ -1,17 +1,15 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.storage; -import lombok.Getter; +import lombok.Data; + +import java.util.concurrent.TimeUnit; /** Configuration class for the assertion storage */ -@Getter +@Data public class StorageConfig { - private final boolean assertionStorageEnabled; - private final long storageEvictionDelay; - - public StorageConfig(boolean assertionStorageEnabled, long storageEvictionDelay) { - this.assertionStorageEnabled = assertionStorageEnabled; - this.storageEvictionDelay = storageEvictionDelay; - } + private boolean assertionStorageEnabled = true; + private long storageEvictionDelay = 1L; + private TimeUnit storageEvictionDelayTimeUnit = TimeUnit.MINUTES; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index 04f28480..6caa8d69 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -14,9 +14,9 @@ /** Helper class for retrieving instances */ public class LollipopConsumerFactoryHelper { - private HttpMessageVerifierFactory httpMessageVerifierFactory; - private IdpCertProviderFactory idpCertProviderFactory; - private AssertionServiceFactory assertionServiceFactory; + private final HttpMessageVerifierFactory httpMessageVerifierFactory; + private final IdpCertProviderFactory idpCertProviderFactory; + private final AssertionServiceFactory assertionServiceFactory; @Inject public LollipopConsumerFactoryHelper( diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java index 67afebec..df797707 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java @@ -1,19 +1,22 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.storage; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; - import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; -import java.util.HashMap; -import java.util.Map; -import java.util.Timer; +import lombok.SneakyThrows; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.*; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + class SimpleAssertionStorageTest { + private static final long EVICTION_DELAY = 5000L; private static StorageConfig storageConfigMock; private AssertionStorage sut; private static final String ASSERTION_REF_1 = "assertionRef1"; @@ -21,28 +24,33 @@ class SimpleAssertionStorageTest { @BeforeEach void setUp() { storageConfigMock = mock(StorageConfig.class); - doReturn(10000L).when(storageConfigMock).getStorageEvictionDelay(); + doReturn(EVICTION_DELAY).when(storageConfigMock).getStorageEvictionDelay(); + doReturn(TimeUnit.MILLISECONDS).when(storageConfigMock).getStorageEvictionDelayTimeUnit(); } @Test - void getExistingAssertionAndResetScheduleEvictionWithStorageEnabled() { + void getExistingAssertionAndResetScheduleEvictionWithStorageEnabled() throws InterruptedException, ExecutionException { doReturn(true).when(storageConfigMock).isAssertionStorageEnabled(); Map assertionMap = new HashMap<>(); SamlAssertion samlAssertion = new SamlAssertion(); assertionMap.put(ASSERTION_REF_1, samlAssertion); - Map timerMap = new HashMap<>(); - Timer timer = new Timer(); - timerMap.put(ASSERTION_REF_1, timer); + Map> scheduledEvictionsMap = new HashMap<>(); + ScheduledFuture scheduledFutureMock = mock(ScheduledFuture.class); + scheduledEvictionsMap.put(ASSERTION_REF_1, scheduledFutureMock); - sut = new SimpleAssertionStorage(assertionMap, timerMap, storageConfigMock); + sut = new SimpleAssertionStorage(assertionMap, scheduledEvictionsMap, storageConfigMock); SamlAssertion result = sut.getAssertion(ASSERTION_REF_1); assertNotNull(result); assertEquals(samlAssertion, result); - assertEquals(1, timerMap.size()); - assertNotEquals(timer, timerMap.get(ASSERTION_REF_1)); + assertEquals(1, scheduledEvictionsMap.size()); + + CompletableFuture future = waitEvictionEnd(scheduledEvictionsMap); + assertEquals(true, future.get()); + assertEquals(0, assertionMap.size()); + assertEquals(0, scheduledEvictionsMap.size()); } @Test @@ -57,20 +65,25 @@ void getNotExistingAssertionWithStorageEnabled() { } @Test - void saveAssertionAndScheduleEvictionWithStorageEnabled() { + void saveAssertionAndScheduleEvictionWithStorageEnabled() throws InterruptedException, ExecutionException { doReturn(true).when(storageConfigMock).isAssertionStorageEnabled(); Map assertionMap = new HashMap<>(); - Map timerMap = new HashMap<>(); + Map> scheduledEvictionsMap = new HashMap<>(); - sut = new SimpleAssertionStorage(assertionMap, timerMap, storageConfigMock); + sut = new SimpleAssertionStorage(assertionMap, scheduledEvictionsMap, storageConfigMock); SamlAssertion samlAssertion = new SamlAssertion(); sut.saveAssertion(ASSERTION_REF_1, samlAssertion); assertEquals(1, assertionMap.size()); - assertEquals(1, timerMap.size()); + assertEquals(1, scheduledEvictionsMap.size()); assertEquals(samlAssertion, assertionMap.get(ASSERTION_REF_1)); + + CompletableFuture future = waitEvictionEnd(scheduledEvictionsMap); + assertEquals(true, future.get()); + assertEquals(0, assertionMap.size()); + assertEquals(0, scheduledEvictionsMap.size()); } @Test @@ -89,13 +102,30 @@ void savaAssertionWithStorageDisabled() { doReturn(false).when(storageConfigMock).isAssertionStorageEnabled(); Map assertionMap = new HashMap<>(); - Map timerMap = new HashMap<>(); + Map> scheduledEvictionsMap = new HashMap<>(); - sut = new SimpleAssertionStorage(assertionMap, timerMap, storageConfigMock); + sut = new SimpleAssertionStorage(assertionMap, scheduledEvictionsMap, storageConfigMock); sut.saveAssertion(ASSERTION_REF_1, new SamlAssertion()); assertEquals(0, assertionMap.size()); - assertEquals(0, timerMap.size()); + assertEquals(0, scheduledEvictionsMap.size()); + } + + private CompletableFuture waitEvictionEnd(Map> scheduledEvictionsMap) { + CompletableFuture future = new CompletableFuture<>(); + ExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); + executorService.submit( + new Runnable() { + @SneakyThrows + @Override + public void run() { + ScheduledFuture scheduledFuture = scheduledEvictionsMap.get(ASSERTION_REF_1); + scheduledFuture.get(); + future.complete(true); + + } + }); + return future; } } From 76d6bf580ccb352eb70a580c6fe36e282a17271f Mon Sep 17 00:00:00 2001 From: giomella Date: Tue, 11 Apr 2023 19:10:07 +0200 Subject: [PATCH 081/403] [SLS-20] applied spotless formatting. --- .../impl/AssertionServiceFactoryImpl.java | 9 ++++-- .../storage/SimpleAssertionStorage.java | 9 ++++-- .../SimpleAssertionStorageProvider.java | 3 +- .../assertion/storage/StorageConfig.java | 3 +- .../storage/SimpleAssertionStorageTest.java | 28 ++++++++++--------- 5 files changed, 29 insertions(+), 23 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImpl.java index 108d47cc..6bf2d5ab 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/impl/AssertionServiceFactoryImpl.java @@ -6,7 +6,6 @@ import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClientProvider; import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorageProvider; import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; - import javax.inject.Inject; /** @@ -19,7 +18,10 @@ public class AssertionServiceFactoryImpl implements AssertionServiceFactory { private final StorageConfig storageConfig; @Inject - public AssertionServiceFactoryImpl(AssertionStorageProvider assertionStorageProvider, AssertionClientProvider assertionClientProvider, StorageConfig storageConfig) { + public AssertionServiceFactoryImpl( + AssertionStorageProvider assertionStorageProvider, + AssertionClientProvider assertionClientProvider, + StorageConfig storageConfig) { this.assertionStorageProvider = assertionStorageProvider; this.assertionClientProvider = assertionClientProvider; this.storageConfig = storageConfig; @@ -33,6 +35,7 @@ public AssertionServiceFactoryImpl(AssertionStorageProvider assertionStorageProv @Override public AssertionService create() { return new AssertionServiceImpl( - assertionStorageProvider.provideStorage(storageConfig), assertionClientProvider.provideClient()); + assertionStorageProvider.provideStorage(storageConfig), + assertionClientProvider.provideClient()); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java index ad07354a..c3445df8 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java @@ -2,12 +2,11 @@ package it.pagopa.tech.lollipop.consumer.assertion.storage; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; - -import javax.inject.Inject; import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; +import javax.inject.Inject; /** Implementation of the {@link AssertionStorage} interface as a simple in memory storage */ public class SimpleAssertionStorage implements AssertionStorage { @@ -63,7 +62,11 @@ public void saveAssertion(String assertionRef, SamlAssertion assertion) { private void scheduleEviction(String assertionRef) { ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); - ScheduledFuture schedule = executorService.schedule(getEvictionTask(assertionRef), storageConfig.getStorageEvictionDelay(), storageConfig.getStorageEvictionDelayTimeUnit()); + ScheduledFuture schedule = + executorService.schedule( + getEvictionTask(assertionRef), + storageConfig.getStorageEvictionDelay(), + storageConfig.getStorageEvictionDelayTimeUnit()); scheduledEvictionsMap.put(assertionRef, schedule); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java index fa95ad28..222554bd 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java @@ -13,7 +13,6 @@ public class SimpleAssertionStorageProvider implements AssertionStorageProvider */ @Override public AssertionStorage provideStorage(StorageConfig storageConfig) { - return new SimpleAssertionStorage( - new HashMap<>(), new HashMap<>(), storageConfig); + return new SimpleAssertionStorage(new HashMap<>(), new HashMap<>(), storageConfig); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java index 19568da1..683df9a8 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java @@ -1,9 +1,8 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.storage; -import lombok.Data; - import java.util.concurrent.TimeUnit; +import lombok.Data; /** Configuration class for the assertion storage */ @Data diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java index df797707..21998598 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java @@ -1,18 +1,17 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.storage; -import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; -import lombok.SneakyThrows; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import java.util.HashMap; import java.util.Map; import java.util.concurrent.*; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; +import lombok.SneakyThrows; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; class SimpleAssertionStorageTest { @@ -29,7 +28,8 @@ void setUp() { } @Test - void getExistingAssertionAndResetScheduleEvictionWithStorageEnabled() throws InterruptedException, ExecutionException { + void getExistingAssertionAndResetScheduleEvictionWithStorageEnabled() + throws InterruptedException, ExecutionException { doReturn(true).when(storageConfigMock).isAssertionStorageEnabled(); Map assertionMap = new HashMap<>(); @@ -65,7 +65,8 @@ void getNotExistingAssertionWithStorageEnabled() { } @Test - void saveAssertionAndScheduleEvictionWithStorageEnabled() throws InterruptedException, ExecutionException { + void saveAssertionAndScheduleEvictionWithStorageEnabled() + throws InterruptedException, ExecutionException { doReturn(true).when(storageConfigMock).isAssertionStorageEnabled(); Map assertionMap = new HashMap<>(); @@ -112,7 +113,8 @@ void savaAssertionWithStorageDisabled() { assertEquals(0, scheduledEvictionsMap.size()); } - private CompletableFuture waitEvictionEnd(Map> scheduledEvictionsMap) { + private CompletableFuture waitEvictionEnd( + Map> scheduledEvictionsMap) { CompletableFuture future = new CompletableFuture<>(); ExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); executorService.submit( @@ -120,10 +122,10 @@ private CompletableFuture waitEvictionEnd(Map scheduledFuture = scheduledEvictionsMap.get(ASSERTION_REF_1); + ScheduledFuture scheduledFuture = + scheduledEvictionsMap.get(ASSERTION_REF_1); scheduledFuture.get(); future.complete(true); - } }); return future; From 149ece25ca2fedf655bcc9ca9c375586df5ded28 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 12 Apr 2023 09:34:44 +0200 Subject: [PATCH 082/403] [SLS-31] Test that does not build if test fails --- .../http_verifier/visma/VismaHttpMessageVerifierTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java index 157ec82e..3dd30bf2 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java @@ -15,7 +15,7 @@ public class VismaHttpMessageVerifierTest { @Test public void correctDigestIsVerified() { // setup - var content = new String(new byte[] {1, 2, 4}); + var content = new String(new byte[] {1, 2, 123}); var header = "md5=:V9tg6T+1JldSH4+Zy8c5jw==:,sha-256=:1LKaloxAFzY43tjRdMhpV6+iEb5HnO4CDbpd/hJ9kco=:"; From f671db90d774aba11fa98ec29870bf52638efee3 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 12 Apr 2023 09:38:40 +0200 Subject: [PATCH 083/403] [SLS-31] Test that does not build if missing dependencies --- http-verifier/build.gradle | 2 +- .../http_verifier/visma/VismaHttpMessageVerifierTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index cf570018..4963adcb 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -48,7 +48,7 @@ dependencies { // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.assertj:assertj-core:3.24.2' - implementation project(':core') + //implementation project(':core') } tasks.named('test') { diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java index 3dd30bf2..157ec82e 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java @@ -15,7 +15,7 @@ public class VismaHttpMessageVerifierTest { @Test public void correctDigestIsVerified() { // setup - var content = new String(new byte[] {1, 2, 123}); + var content = new String(new byte[] {1, 2, 4}); var header = "md5=:V9tg6T+1JldSH4+Zy8c5jw==:,sha-256=:1LKaloxAFzY43tjRdMhpV6+iEb5HnO4CDbpd/hJ9kco=:"; From 6db236e88d078518d5c9d749c0a33ee1642f1798 Mon Sep 17 00:00:00 2001 From: giomella Date: Wed, 12 Apr 2023 09:42:11 +0200 Subject: [PATCH 084/403] [SLS-20] updated javadoc. --- .../storage/SimpleAssertionStorage.java | 25 ++++++++++++++++--- .../SimpleAssertionStorageProvider.java | 1 + 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java index c3445df8..4bf39fb9 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java @@ -8,7 +8,15 @@ import java.util.concurrent.ScheduledFuture; import javax.inject.Inject; -/** Implementation of the {@link AssertionStorage} interface as a simple in memory storage */ +/** + * Implementation of the {@link AssertionStorage} interface as a simple in memory storage. + * + *

The storage can be configured via the {@link StorageConfig} configuration class. + * + *

It store in a in memory {@link java.util.HashMap} the assertions and the associated scheduled + * eviction operations, every time an assertion is accessed the associated eviction operation is + * rescheduled. + */ public class SimpleAssertionStorage implements AssertionStorage { private final Map assertionMap; @@ -26,10 +34,15 @@ public SimpleAssertionStorage( } /** - * Retrieve the assertion associated with the provided assertion reference + * Retrieve the assertion associated with the provided assertion reference if the storage is + * enabled {@link StorageConfig}, otherwise no operation is performed. + * + *

Before the assertion is returned the associated eviction operation is rescheduled with the + * delay configured via {@link StorageConfig} * * @param assertionRef the assertion reference - * @return the SAML assertion if found, otherwise null + * @return the SAML assertion if found, null if the assertion is not present in the storage or + * the storage is disabled */ @Override public SamlAssertion getAssertion(String assertionRef) { @@ -45,7 +58,11 @@ public SamlAssertion getAssertion(String assertionRef) { } /** - * Store the assertion + * Store the assertion if the storage is enabled {@link StorageConfig}, otherwise no operation + * is performed. + * + *

Once the assertion is stored an eviction operation is scheduled with a delay configured + * via {@link StorageConfig} * * @param assertionRef the assertion reference * @param assertion the SAML assertion diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java index 222554bd..d74c27b5 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java @@ -9,6 +9,7 @@ public class SimpleAssertionStorageProvider implements AssertionStorageProvider /** * {@inheritDoc} * + * @param storageConfig the storage configuration * @return an instance of {@link SimpleAssertionStorage} */ @Override From fefb11d543ec2815f788eb8c15dabd8ca5cb8b69 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 12 Apr 2023 09:52:55 +0200 Subject: [PATCH 085/403] [SLS-31] Test that does not build if checksum fails --- http-verifier/build.gradle | 2 +- redis-storage/build.gradle | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index 4963adcb..cf570018 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -48,7 +48,7 @@ dependencies { // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.assertj:assertj-core:3.24.2' - //implementation project(':core') + implementation project(':core') } tasks.named('test') { diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle index cad17071..43a68fac 100644 --- a/redis-storage/build.gradle +++ b/redis-storage/build.gradle @@ -45,6 +45,7 @@ dependencies { implementation project(path: ':core') // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.7.0' } tasks.named('test') { From 0c9585767a799fdbd7d2c30a48aeaf8e3a09e602 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 12 Apr 2023 10:04:06 +0200 Subject: [PATCH 086/403] [SLS-31] Removed wrong dependencies --- redis-storage/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle index 43a68fac..cad17071 100644 --- a/redis-storage/build.gradle +++ b/redis-storage/build.gradle @@ -45,7 +45,6 @@ dependencies { implementation project(path: ':core') // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.7.0' } tasks.named('test') { From adde94ae75ce1da64b15494d3724b39ec0a6a2e7 Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Thu, 6 Apr 2023 16:53:19 +0200 Subject: [PATCH 087/403] Create build-gradle-project.yml --- .github/workflows/build-gradle-project.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .github/workflows/build-gradle-project.yml diff --git a/.github/workflows/build-gradle-project.yml b/.github/workflows/build-gradle-project.yml new file mode 100644 index 00000000..cccf56d0 --- /dev/null +++ b/.github/workflows/build-gradle-project.yml @@ -0,0 +1,16 @@ +name: Build Gradle project + +on: + push: + pull_request: + +jobs: + build-gradle-project: + runs-on: ubuntu-latest + steps: + - name: Checkout project sources + uses: actions/checkout@v2 + - name: Setup Gradle + uses: gradle/gradle-build-action@v2 + - name: Run build with Gradle Wrapper + run: ./gradlew build From df7f139fc6548512ee67ae05a05d1e6e6d02288f Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Thu, 6 Apr 2023 16:56:10 +0200 Subject: [PATCH 088/403] Update build-gradle-project.yml --- .github/workflows/build-gradle-project.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-gradle-project.yml b/.github/workflows/build-gradle-project.yml index cccf56d0..86794929 100644 --- a/.github/workflows/build-gradle-project.yml +++ b/.github/workflows/build-gradle-project.yml @@ -12,5 +12,7 @@ jobs: uses: actions/checkout@v2 - name: Setup Gradle uses: gradle/gradle-build-action@v2 + - name: Make gradlew executable + run: chmod +x ./gradlew - name: Run build with Gradle Wrapper run: ./gradlew build From 56368f5f5dbdcc2080951d15a7379635a274557f Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Thu, 6 Apr 2023 17:06:29 +0200 Subject: [PATCH 089/403] Update build-gradle-project.yml --- .github/workflows/build-gradle-project.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-gradle-project.yml b/.github/workflows/build-gradle-project.yml index 86794929..cee4d34f 100644 --- a/.github/workflows/build-gradle-project.yml +++ b/.github/workflows/build-gradle-project.yml @@ -1,7 +1,6 @@ name: Build Gradle project on: - push: pull_request: jobs: @@ -9,7 +8,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout project sources - uses: actions/checkout@v2 + uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Setup Gradle uses: gradle/gradle-build-action@v2 - name: Make gradlew executable From e0b4acc1ce8897dd375aa03b781e4c855d73ad21 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 6 Apr 2023 19:46:02 +0200 Subject: [PATCH 090/403] [SLS-31] Updated build.gradle --- build.gradle | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/build.gradle b/build.gradle index 16e65d8c..96c68616 100644 --- a/build.gradle +++ b/build.gradle @@ -20,6 +20,19 @@ allprojects { apply plugin: 'nebula.lint' gradleLint.rules = ['all-dependency'] + configurations { + spotless { + resolutionStrategy { + disableDependencyVerification() + } + } + gradleLint { + resolutionStrategy { + disableDependencyVerification() + } + } + } + spotless { // optional: limit format enforcement to just the files changed by this feature branch ratchetFrom 'origin/main' From b85b2f344ecb3c784d293e32fb7b92fdf79489cf Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Thu, 6 Apr 2023 16:53:19 +0200 Subject: [PATCH 091/403] Create build-gradle-project.yml --- .github/workflows/build-gradle-project.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-gradle-project.yml b/.github/workflows/build-gradle-project.yml index cee4d34f..0bddc39b 100644 --- a/.github/workflows/build-gradle-project.yml +++ b/.github/workflows/build-gradle-project.yml @@ -1,6 +1,7 @@ name: Build Gradle project on: + push: pull_request: jobs: @@ -8,12 +9,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout project sources + uses: actions/checkout@v2 + - name: Setup Gradle + uses: gradle/gradle-build-action@v2 uses: actions/checkout@v3 with: - fetch-depth: 0 + fetch-depth: 0 - name: Setup Gradle uses: gradle/gradle-build-action@v2 - name: Make gradlew executable - run: chmod +x ./gradlew + run: chmod +x ./gradlew - name: Run build with Gradle Wrapper run: ./gradlew build From 22d1a9b81f3fb543164b03051ab01c051b77094a Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Thu, 6 Apr 2023 17:06:29 +0200 Subject: [PATCH 092/403] Update build-gradle-project.yml --- .github/workflows/build-gradle-project.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-gradle-project.yml b/.github/workflows/build-gradle-project.yml index 0bddc39b..4d3fc326 100644 --- a/.github/workflows/build-gradle-project.yml +++ b/.github/workflows/build-gradle-project.yml @@ -1,7 +1,6 @@ name: Build Gradle project on: - push: pull_request: jobs: @@ -9,7 +8,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout project sources - uses: actions/checkout@v2 + uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Setup Gradle uses: gradle/gradle-build-action@v2 uses: actions/checkout@v3 From d9561d069f8f29295546f9e69af2463eeaa5a5aa Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 6 Apr 2023 19:53:56 +0200 Subject: [PATCH 093/403] [SLS-31] Updated verification-metadata.xml --- gradle/verification-metadata.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 9aa9291d..faeef5c9 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2205,12 +2205,19 @@ + + + + + + + From cc6874af5d9f2a368a2c55833b1c62781c300665 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 6 Apr 2023 20:09:37 +0200 Subject: [PATCH 094/403] [SLS-31] Updated build.gradle --- build.gradle | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/build.gradle b/build.gradle index 96c68616..6c079c37 100644 --- a/build.gradle +++ b/build.gradle @@ -4,6 +4,7 @@ plugins { id("com.diffplug.spotless") version "6.17.0" id("nebula.lint") version "18.0.3" id("org.kordamp.gradle.reproducible") version "0.50.0" + id("com.gradle.enterprise") version("3.9") } repositories { @@ -33,6 +34,16 @@ allprojects { } } + gradleEnterprise { + if (System.getenv("CI") != null) { + buildScan { + publishAlways() + termsOfServiceUrl = "https://gradle.com/terms-of-service" + termsOfServiceAgree = "yes" + } + } + } + spotless { // optional: limit format enforcement to just the files changed by this feature branch ratchetFrom 'origin/main' From d7fe5f5762506848deb99ebe84dd9aba22de1de4 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 6 Apr 2023 20:13:22 +0200 Subject: [PATCH 095/403] [SLS-31] Updated build.gradle --- build.gradle | 12 +++--------- gradle/verification-metadata.xml | 13 +++++++++++++ settings.gradle | 14 ++++++++++++++ 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index 6c079c37..08d0913e 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,6 @@ plugins { id("com.diffplug.spotless") version "6.17.0" id("nebula.lint") version "18.0.3" id("org.kordamp.gradle.reproducible") version "0.50.0" - id("com.gradle.enterprise") version("3.9") } repositories { @@ -32,14 +31,9 @@ allprojects { disableDependencyVerification() } } - } - - gradleEnterprise { - if (System.getenv("CI") != null) { - buildScan { - publishAlways() - termsOfServiceUrl = "https://gradle.com/terms-of-service" - termsOfServiceAgree = "yes" + gradleEnterprise { + resolutionStrategy { + disableDependencyVerification() } } } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index faeef5c9..f9956b91 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -639,6 +639,19 @@ + + + + + + + + + + + + + diff --git a/settings.gradle b/settings.gradle index 231c70d5..8e918fab 100644 --- a/settings.gradle +++ b/settings.gradle @@ -14,5 +14,19 @@ pluginManagement { } } +plugins { + id("com.gradle.enterprise") version("3.9") +} + +gradleEnterprise { + if (System.getenv("CI") != null) { + buildScan { + publishAlways() + termsOfServiceUrl = "https://gradle.com/terms-of-service" + termsOfServiceAgree = "yes" + } + } +} + rootProject.name = 'eng-lollipop-consumer-java-sdk' include 'core', 'assertion-rest-client-native', 'http-verifier', 'identity-service-rest-client-native', 'redis-storage' From 13fd213357af9641678183db976a1660e20c765c Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Tue, 11 Apr 2023 11:35:19 +0200 Subject: [PATCH 096/403] Create PULL_REQUEST_TEMPLATE.md --- .github/PULL_REQUEST_TEMPLATE.md | 37 ++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..7086d553 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,37 @@ + + + + + +#### List of Changes + + + +#### Motivation and Context + + + +#### How Has This Been Tested? + + + + + +#### Screenshots (if appropriate): + +#### Types of changes + + + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as + expected) + +#### Checklist: + + + + +- [ ] My change requires a change to the documentation. +- [ ] I have updated the documentation accordingly. From 17fed18f2c3e252722c9bc3ffc7fd8f98e78223b Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Tue, 11 Apr 2023 11:37:46 +0200 Subject: [PATCH 097/403] Create CODEOWNERS --- CODEOWNERS | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 CODEOWNERS diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 00000000..e514c2f9 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,3 @@ +# see https://help.github.com/en/articles/about-code-owners#example-of-a-codeowners-file + +* @pagopa/pagopa-tech From f2596f432f3a59144dca50e840731c3c7b7864c4 Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Tue, 11 Apr 2023 12:00:39 +0200 Subject: [PATCH 098/403] Update and rename build-gradle-project.yml to pr_scan.yml --- .github/workflows/build-gradle-project.yml | 24 --------------- .github/workflows/pr_scan.yml | 36 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 24 deletions(-) delete mode 100644 .github/workflows/build-gradle-project.yml create mode 100644 .github/workflows/pr_scan.yml diff --git a/.github/workflows/build-gradle-project.yml b/.github/workflows/build-gradle-project.yml deleted file mode 100644 index 4d3fc326..00000000 --- a/.github/workflows/build-gradle-project.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Build Gradle project - -on: - pull_request: - -jobs: - build-gradle-project: - runs-on: ubuntu-latest - steps: - - name: Checkout project sources - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Setup Gradle - uses: gradle/gradle-build-action@v2 - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Setup Gradle - uses: gradle/gradle-build-action@v2 - - name: Make gradlew executable - run: chmod +x ./gradlew - - name: Run build with Gradle Wrapper - run: ./gradlew build diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml new file mode 100644 index 00000000..2351b695 --- /dev/null +++ b/.github/workflows/pr_scan.yml @@ -0,0 +1,36 @@ +name: Build Gradle project + +on: + pull_request: + +env: + DOCKERFILE: Dockerfile + +jobs: + build-gradle-project: + runs-on: ubuntu-latest + steps: + - name: Checkout project sources + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Setup Gradle + uses: gradle/gradle-build-action@v2 + - name: Make gradlew executable + run: chmod +x ./gradlew + - name: Run build with Gradle Wrapper + run: ./gradlew build + - name: Build the Docker image + run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest + - name: Run the Anchore Grype scan action + uses: anchore/scan-action@d5aa5b6cb9414b0c7771438046ff5bcfa2854ed7 + id: scan + with: + image: "localbuild/testimage:latest" + fail-build: true + severity-cutoff: "high" + - name: Upload Anchore Scan Report + uses: github/codeql-action/upload-sarif@v2 + if: always() + with: + sarif_file: ${{ steps.scan.outputs.sarif }} From fe46dc4385c764687e1455aa79e2c151b359c4c3 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 12:10:03 +0200 Subject: [PATCH 099/403] [SLS-31] Updated build.gradle --- .github/workflows/pr_scan.yml | 2 +- Dockerfile.test-only | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 Dockerfile.test-only diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 2351b695..48aa8a97 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -4,7 +4,7 @@ on: pull_request: env: - DOCKERFILE: Dockerfile + DOCKERFILE: Dockerfile.test-only jobs: build-gradle-project: diff --git a/Dockerfile.test-only b/Dockerfile.test-only new file mode 100644 index 00000000..dc962125 --- /dev/null +++ b/Dockerfile.test-only @@ -0,0 +1,5 @@ +FROM openjdk:11-jre-slim + +RUN mkdir /app + +COPY core/build/libs/*.jar /app/core.jar \ No newline at end of file From 63f14861cad2e83b57f34539dc94286ab80894f6 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 12:14:30 +0200 Subject: [PATCH 100/403] [SLS-31] Updated build.gradle --- .github/workflows/pr_scan.yml | 2 +- Dockerfile.test-only | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 48aa8a97..ec044da3 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -1,4 +1,4 @@ -name: Build Gradle project +name: Check Build and Anchore on PR on: pull_request: diff --git a/Dockerfile.test-only b/Dockerfile.test-only index dc962125..787f3d15 100644 --- a/Dockerfile.test-only +++ b/Dockerfile.test-only @@ -2,4 +2,4 @@ FROM openjdk:11-jre-slim RUN mkdir /app -COPY core/build/libs/*.jar /app/core.jar \ No newline at end of file +COPY core/build/libs/*.jar /app/ \ No newline at end of file From 11284420c950e36df3742a2685be829a2da949bd Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 12:23:24 +0200 Subject: [PATCH 101/403] [SLS-31] Test inserting dependency with vulnerability --- core/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/build.gradle b/core/build.gradle index a5d2b770..d44be93e 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -43,6 +43,9 @@ dependencies { testImplementation 'org.mockito:mockito-core:5.2.0' testImplementation 'org.mockito:mockito-junit-jupiter:5.2.0' testImplementation 'org.assertj:assertj-core:3.24.2' + // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind + implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4.1' + } tasks.named('test') { From 8ba57e117ab9cdb590305f922cbaeb42c88346c5 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 12:29:29 +0200 Subject: [PATCH 102/403] [SLS-31] Updated Dockerfile.test-only to use amazoncorretto version of the openjdk --- Dockerfile.test-only | 2 +- gradle/verification-metadata.xml | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Dockerfile.test-only b/Dockerfile.test-only index 787f3d15..6b35a682 100644 --- a/Dockerfile.test-only +++ b/Dockerfile.test-only @@ -1,4 +1,4 @@ -FROM openjdk:11-jre-slim +FROM amazoncorretto:11 RUN mkdir /app diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index f9956b91..4e3c6f42 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -135,6 +135,11 @@ + + + + + @@ -157,6 +162,11 @@ + + + + + @@ -201,6 +211,14 @@ + + + + + + + + @@ -227,6 +245,14 @@ + + + + + + + + @@ -253,6 +279,14 @@ + + + + + + + + From c555f1b40369ca5904be80fff9223b2cf61a4551 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 12:34:04 +0200 Subject: [PATCH 103/403] [SLS-31] Updated build.gradle --- core/build.gradle | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index d44be93e..a5d2b770 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -43,9 +43,6 @@ dependencies { testImplementation 'org.mockito:mockito-core:5.2.0' testImplementation 'org.mockito:mockito-junit-jupiter:5.2.0' testImplementation 'org.assertj:assertj-core:3.24.2' - // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind - implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4.1' - } tasks.named('test') { From 248e4489cce74236001d498d28c42fbd87bad914 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 12:39:42 +0200 Subject: [PATCH 104/403] [SLS-31] Updated Dockerfile.test-only --- Dockerfile.test-only | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Dockerfile.test-only b/Dockerfile.test-only index 6b35a682..12491d05 100644 --- a/Dockerfile.test-only +++ b/Dockerfile.test-only @@ -2,4 +2,8 @@ FROM amazoncorretto:11 RUN mkdir /app -COPY core/build/libs/*.jar /app/ \ No newline at end of file +COPY core/build/libs/*.jar /app/ +COPY http-verifier/build/libs/*.jar /app/ +COPY redis-storage/build/libs/*.jar /app/ +COPY identity-service-rest-client-native/build/libs/*.jar /app/ +COPY assertion-rest-client-native/build/libs/*.jar /app/ \ No newline at end of file From 4a1d653b34fbe7ea5b2eabeda50dc177bdd27bcd Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 12:59:28 +0200 Subject: [PATCH 105/403] [SLS-31] Updated action file to contain references to the name 'pr_scan' --- .github/workflows/pr_scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index ec044da3..af448973 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -7,7 +7,7 @@ env: DOCKERFILE: Dockerfile.test-only jobs: - build-gradle-project: + pr_scan: runs-on: ubuntu-latest steps: - name: Checkout project sources From 9a417a5ed4e3d803ca2e566d67455503f7de50f0 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 15:46:45 +0200 Subject: [PATCH 106/403] [SLS-31] Introducing config for library release --- .github/workflows/release.yaml | 24 ++++++++++++++++++++++++ build.gradle | 10 ++++++++++ 2 files changed, 34 insertions(+) create mode 100644 .github/workflows/release.yaml diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 00000000..41d5c897 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,24 @@ +name: Publish package to GitHub Packages +on: + release: + types: [created] +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 + with: + java-version: '11' + distribution: 'adopt' + - name: Validate Gradle wrapper + uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b + - name: Publish package + uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 + with: + arguments: publish + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 08d0913e..f7661683 100644 --- a/build.gradle +++ b/build.gradle @@ -120,6 +120,16 @@ subprojects { from components.java } } + repositories { + maven { + name = "GitHubPackages" + url = "https://maven.pkg.github.com/pagopa/eng-lollipop-consumer-java-sdk" + credentials { + username = System.getenv("GITHUB_ACTOR") + password = System.getenv("GITHUB_TOKEN") + } + } + } } } From 5e74a2865849229ae9c3771cc07ee753520171fb Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 16:02:01 +0200 Subject: [PATCH 107/403] [SLS-31] Updated release.yaml --- .github/workflows/release.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 41d5c897..a9a6f6ef 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -16,6 +16,8 @@ jobs: distribution: 'adopt' - name: Validate Gradle wrapper uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b + - name: Make gradlew executable + run: chmod +x ./gradlew - name: Publish package uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 with: From 0f0aea353a099ca38c0791a74cdfe0f86bc12bb2 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 11 Apr 2023 17:17:09 +0200 Subject: [PATCH 108/403] [SLS-31] Updated build.gradle --- assertion-rest-client-native/build.gradle | 2 - build.gradle | 2 +- core/build.gradle | 2 - http-verifier/build.gradle | 2 +- .../build.gradle | 2 +- redis-storage/build.gradle | 2 - sample/build.gradle | 6 +- sample/gradlew | 257 +++++++++++------- 8 files changed, 158 insertions(+), 117 deletions(-) diff --git a/assertion-rest-client-native/build.gradle b/assertion-rest-client-native/build.gradle index 55886112..001bdaf1 100644 --- a/assertion-rest-client-native/build.gradle +++ b/assertion-rest-client-native/build.gradle @@ -14,8 +14,6 @@ plugins { /*id("org.openapi.generator") version "6.5.0"*/ } -group 'it.pagopa.commons' - repositories { mavenLocal() mavenCentral() diff --git a/build.gradle b/build.gradle index f7661683..75f4874d 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ repositories { allprojects { version = "1.0.0-SNAPSHOT" - group = 'it.pagopa.tech' + group = 'it.pagopa.tech.lollipop-consumer-java-sdk' sourceCompatibility = '11' targetCompatibility = '11' apply plugin: 'com.diffplug.spotless' diff --git a/core/build.gradle b/core/build.gradle index a5d2b770..f570fbda 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -13,8 +13,6 @@ plugins { id("io.freefair.lombok") version "8.0.0" } -group 'it.pagopa.tech' - repositories { mavenLocal() mavenCentral() diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index dbb59380..cf570018 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -13,7 +13,7 @@ plugins { id("io.freefair.lombok") version "8.0.0" } -group 'it.pagopa.tech' +group 'it.pagopa.tech.lollipop.sdk.impls' repositories { mavenLocal() diff --git a/identity-service-rest-client-native/build.gradle b/identity-service-rest-client-native/build.gradle index 460062f0..ed71e034 100644 --- a/identity-service-rest-client-native/build.gradle +++ b/identity-service-rest-client-native/build.gradle @@ -12,7 +12,7 @@ plugins { id("io.freefair.lombok") version "8.0.0-rc4" } -group 'it.pagopa.tech' +group 'it.pagopa.tech.lollipop.sdk.impls' repositories { mavenLocal() diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle index 86f23568..cad17071 100644 --- a/redis-storage/build.gradle +++ b/redis-storage/build.gradle @@ -13,8 +13,6 @@ plugins { id("io.freefair.lombok") version "8.0.0" } -group 'it.pagopa.tech' - repositories { mavenLocal() mavenCentral() diff --git a/sample/build.gradle b/sample/build.gradle index 9bf6b880..bde45400 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -16,16 +16,14 @@ application { mainClassName = "it.pagopa.tech.sample.LollipopConsumerSample" } -group 'it.pagopa.tech' - repositories { mavenLocal() mavenCentral() } dependencies { - implementation 'it.pagopa.tech:core:1.0.0-SNAPSHOT' - implementation 'it.pagopa.tech:http-verifier:1.0.0-SNAPSHOT' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:core:1.0.0-SNAPSHOT' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:http-verifier:1.0.0-SNAPSHOT' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' } diff --git a/sample/gradlew b/sample/gradlew index 4f906e0c..1b6c7873 100644 --- a/sample/gradlew +++ b/sample/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,101 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" From d9614e6b24b75c80a94520e6b4782a7787b2cd93 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 12 Apr 2023 09:34:44 +0200 Subject: [PATCH 109/403] [SLS-31] Test that does not build if test fails --- .../http_verifier/visma/VismaHttpMessageVerifierTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java index 157ec82e..3dd30bf2 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java @@ -15,7 +15,7 @@ public class VismaHttpMessageVerifierTest { @Test public void correctDigestIsVerified() { // setup - var content = new String(new byte[] {1, 2, 4}); + var content = new String(new byte[] {1, 2, 123}); var header = "md5=:V9tg6T+1JldSH4+Zy8c5jw==:,sha-256=:1LKaloxAFzY43tjRdMhpV6+iEb5HnO4CDbpd/hJ9kco=:"; From f9448abdc99698830b1c08e0e62867280800fde5 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 12 Apr 2023 09:38:40 +0200 Subject: [PATCH 110/403] [SLS-31] Test that does not build if missing dependencies --- http-verifier/build.gradle | 2 +- .../http_verifier/visma/VismaHttpMessageVerifierTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index cf570018..4963adcb 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -48,7 +48,7 @@ dependencies { // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.assertj:assertj-core:3.24.2' - implementation project(':core') + //implementation project(':core') } tasks.named('test') { diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java index 3dd30bf2..157ec82e 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java @@ -15,7 +15,7 @@ public class VismaHttpMessageVerifierTest { @Test public void correctDigestIsVerified() { // setup - var content = new String(new byte[] {1, 2, 123}); + var content = new String(new byte[] {1, 2, 4}); var header = "md5=:V9tg6T+1JldSH4+Zy8c5jw==:,sha-256=:1LKaloxAFzY43tjRdMhpV6+iEb5HnO4CDbpd/hJ9kco=:"; From 8b8970205d899f83689b827047d7293dea97d197 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 12 Apr 2023 09:52:55 +0200 Subject: [PATCH 111/403] [SLS-31] Test that does not build if checksum fails --- http-verifier/build.gradle | 2 +- redis-storage/build.gradle | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index 4963adcb..cf570018 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -48,7 +48,7 @@ dependencies { // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.assertj:assertj-core:3.24.2' - //implementation project(':core') + implementation project(':core') } tasks.named('test') { diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle index cad17071..43a68fac 100644 --- a/redis-storage/build.gradle +++ b/redis-storage/build.gradle @@ -45,6 +45,7 @@ dependencies { implementation project(path: ':core') // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.7.0' } tasks.named('test') { From d6042286be52e07868158d56709db7e15fb37760 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 12 Apr 2023 10:04:06 +0200 Subject: [PATCH 112/403] [SLS-31] Removed wrong dependencies --- redis-storage/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle index 43a68fac..cad17071 100644 --- a/redis-storage/build.gradle +++ b/redis-storage/build.gradle @@ -45,7 +45,6 @@ dependencies { implementation project(path: ':core') // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.7.0' } tasks.named('test') { From 4defcd1d08e216c6c69201e548e5e8f957edd067 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 12:03:10 +0200 Subject: [PATCH 113/403] [SLS-19] Handled entities filtering by entityId - added exceptions --- .../exception/CertDataNotFoundException.java | 13 ++ .../CertDataTagListNotFoundException.java | 13 ++ .../exception/EntityIdNotFoundException.java | 13 ++ .../TagListSearchOutOfBoundException.java | 13 ++ .../consumer/idp/client/IdpCertClient.java | 4 +- .../client/simple/IdpCertSimpleClient.java | 162 ++++++++++---- .../simple/internal/model/CIECertData.java | 3 + .../simple/internal/model/CertData.java | 206 +++--------------- .../internal/model/EntitiesDescriptor.java | 37 ++++ .../internal/model/EntityDescriptor.java | 2 + .../simple/internal/model/SPIDCertData.java | 143 ------------ .../model/SPIDCertDataEntitiesDescriptor.java | 158 -------------- .../java/simple/IdpCertSimpleClientTest.java | 6 +- 13 files changed, 246 insertions(+), 527 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataNotFoundException.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/EntityIdNotFoundException.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/TagListSearchOutOfBoundException.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java delete mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertData.java delete mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertDataEntitiesDescriptor.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataNotFoundException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataNotFoundException.java new file mode 100644 index 00000000..95030acb --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataNotFoundException.java @@ -0,0 +1,13 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +public class CertDataNotFoundException extends Exception{ + /** + * Constructs new exception with provided message and cause + * + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public CertDataNotFoundException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java new file mode 100644 index 00000000..fe00adfb --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java @@ -0,0 +1,13 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +public class CertDataTagListNotFoundException extends Exception{ + /** + * Constructs new exception with provided message and cause + * + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public CertDataTagListNotFoundException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/EntityIdNotFoundException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/EntityIdNotFoundException.java new file mode 100644 index 00000000..7b5b35ce --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/EntityIdNotFoundException.java @@ -0,0 +1,13 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +public class EntityIdNotFoundException extends Exception{ + + /** + * Constructs new exception with provided messag + * + * @param message Detail message + */ + public EntityIdNotFoundException(String message) { + super(message); + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/TagListSearchOutOfBoundException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/TagListSearchOutOfBoundException.java new file mode 100644 index 00000000..638ca4a2 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/TagListSearchOutOfBoundException.java @@ -0,0 +1,13 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +public class TagListSearchOutOfBoundException extends Exception{ + + /** + * Constructs new exception with provided message + * + * @param message Detail message + */ + public TagListSearchOutOfBoundException(String message) { + super(message); + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java index 50ace9c7..98c03c2b 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java @@ -1,10 +1,12 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client; +import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import java.util.List; public interface IdpCertClient { - List getCertData(String entityId, String instant); + List getCertData(String entityId, String instant) throws CertDataNotFoundException, CertDataTagListNotFoundException; } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index bb423fc4..a091e120 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -1,11 +1,17 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple; +import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.EntityIdNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.TagListSearchOutOfBoundException; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.api.DefaultApi; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.CertData; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.EntitiesDescriptor; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.EntityDescriptor; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import javax.inject.Inject; @@ -17,6 +23,8 @@ public class IdpCertSimpleClient implements IdpCertClient { private final ApiClient apiClient; private final DefaultApi defaultApi; + private static final List CIE_ENTITY_IDS = new ArrayList<>(List.of("https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO")); + @Inject public IdpCertSimpleClient(ApiClient client) { this.apiClient = client; @@ -29,82 +37,140 @@ public IdpCertSimpleClient(ApiClient client) { * @return */ @Override - public List getCertData(String entityId, String instant) { + public List getCertData(String entityId, String instant) throws CertDataNotFoundException, CertDataTagListNotFoundException { List listCertData = new ArrayList<>(); + List tagList; + + if (entityId == null || instant == null || entityId.isBlank() || instant.isBlank()) { + throw new IllegalArgumentException("EntityID or Assertion Issue Instant missing"); + } - if (entityId.equals("https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO")) { //TODO inserire entityID in classe di configurazione - List tagList = getCIETagList(instant); - for(String tag: tagList){ + if (CIE_ENTITY_IDS.contains(entityId)) { //TODO inserire entityID in classe di configurazione + + try { + tagList = getCIETagList(instant); + } catch (ApiException | TagListSearchOutOfBoundException e) { + throw new CertDataTagListNotFoundException("Error retrieving certificate's tag list: " + e.getMessage(), e); + } + + for (String tag : tagList) { //TODO recupero storage - IdpCertData certData = getCIECertData(tag); - listCertData.add(certData); + try { + IdpCertData certData = getCIECertData(tag, entityId); + + if(certData != null){ + listCertData.add(certData); + } + } catch (ApiException | EntityIdNotFoundException e) { + throw new CertDataNotFoundException("Error retrieving certificate data for tag" + tag + ": " + e.getMessage(), e); + } + } } else { - List tagList = getSPIDTagList(instant); - for(String tag: tagList){ + try { + tagList = getSPIDTagList(instant); + } catch (ApiException | TagListSearchOutOfBoundException e) { + throw new CertDataTagListNotFoundException("Error retrieving certificate's tag list: " + e.getMessage(), e); + } + + for (String tag : tagList) { //TODO recupero storage - IdpCertData certData = getSPIDCertData(tag, entityId); - listCertData.add(certData); + try { + IdpCertData certData = getSPIDCertData(tag, entityId); + + if(certData != null){ + listCertData.add(certData); + } + } catch (ApiException | EntityIdNotFoundException e) { + throw new CertDataNotFoundException("Error retrieving certificate data for tag" + tag + ": " + e.getMessage(), e); + } + } } return listCertData; } - private List getSPIDTagList(String instant) { - List responseAssertion = new ArrayList<>(); + private List getSPIDTagList(String instant) throws TagListSearchOutOfBoundException { + List responseAssertion; - try { - responseAssertion = this.defaultApi.idpKeysSpidGet(); - } catch (ApiException e) { - /*throw new LollipopAssertionNotFoundException( - "Error retrieving idp cert list: " + e.getMessage(), e);*/ - } + responseAssertion = this.defaultApi.idpKeysSpidGet(); - //TODO gestire filtro tag (prendere quello subito prima e subito dopo rispetto all' "instant") + return getTagsFromInstant(responseAssertion, instant); + } + + private IdpCertData getSPIDCertData(String tag, String entityId) throws EntityIdNotFoundException { + CertData responseAssertion = null; - return responseAssertion; + responseAssertion = this.defaultApi.idpKeysSpidTagGet(tag); + + return getEntityData(((EntitiesDescriptor)responseAssertion.getActualInstance()), tag, entityId); } - private IdpCertData getSPIDCertData(String tag, String entityId) { - CertData responseAssertion; + private List getCIETagList(String instant) throws TagListSearchOutOfBoundException { + List responseAssertion; - try { - responseAssertion = this.defaultApi.idpKeysSpidTagGet(tag); - } catch (ApiException e) { - /*throw new LollipopAssertionNotFoundException( - "Error retrieving assertion: " + e.getMessage(), e);*/ - } + responseAssertion = this.defaultApi.idpKeysCieGet(); + + return getTagsFromInstant(responseAssertion, instant); + } + + private IdpCertData getCIECertData(String tag, String entityId) throws EntityIdNotFoundException { + CertData responseAssertion; - //TODO gestire filtraggio xml per entityId + responseAssertion = this.defaultApi.idpKeysCieTagGet(tag); - return null; + return getEntityData(((EntitiesDescriptor)responseAssertion.getActualInstance()), tag, entityId); } - private List getCIETagList(String instant) { - List responseAssertion = new ArrayList<>(); + private IdpCertData getEntityData(EntitiesDescriptor data, String tag, String entityId) throws EntityIdNotFoundException { + IdpCertData newData = new IdpCertData(); - try { - responseAssertion = this.defaultApi.idpKeysCieGet(); - } catch (ApiException e) { - /*throw new LollipopAssertionNotFoundException( - "Error retrieving idp cert list: " + e.getMessage(), e);*/ - } + for (EntityDescriptor entity : data.getEntityList()) { + if (entity.getEntityID().equals(entityId)){ + newData.setEntityId(entityId); + newData.setTag(tag); + newData.setCertData("test"); - //TODO gestire filtro tag (prendere quello subito prima e subito dopo rispetto all' "instant") + return newData; + } + } - return responseAssertion; + throw new EntityIdNotFoundException("Cert for entityID" + entityId + " not found"); } - private IdpCertData getCIECertData(String tag) { - CertData responseAssertion; + private List getTagsFromInstant(List tagList, String instant) throws TagListSearchOutOfBoundException { + List newTagList = new ArrayList<>(); + + if (tagList.size() <= 2) { + return tagList; + } + + int index = tagList.size() / 2; + + //TODO ordinamento tag + boolean notFound = true; + while (notFound) { + String upperTag = tagList.get(index); + String lowerTag = tagList.get(index + 1); + if (Long.valueOf(instant) <= Long.valueOf(upperTag) || upperTag.equals("latest")) { + if (Long.valueOf(instant) >= Long.valueOf(lowerTag)) { + notFound = false; + newTagList.add(upperTag); + newTagList.add(lowerTag); + } else { + index += 1; + } + } else { + index -= 1; + } + + if (index < 0 || index >= tagList.size()) { + throw new TagListSearchOutOfBoundException("Error finding the tags relative to assertion instant" + instant); + } - try { - responseAssertion = this.defaultApi.idpKeysCieTagGet(tag); - } catch (ApiException e) { - /*throw new LollipopAssertionNotFoundException( - "Error retrieving assertion: " + e.getMessage(), e);*/ } - return null; + + return newTagList; } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java index 6fbeec22..7611bcb4 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java @@ -15,6 +15,8 @@ import java.util.StringJoiner; import java.util.Objects; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; @@ -28,6 +30,7 @@ @JsonPropertyOrder({ CIECertData.JSON_PROPERTY_ENTITY_DESCRIPTOR }) +@JsonIgnoreProperties(ignoreUnknown = true) @javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class CIECertData { public static final String JSON_PROPERTY_ENTITY_DESCRIPTOR = "entityDescriptor"; diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java index baea3633..8b256dc3 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java @@ -3,7 +3,7 @@ * Client used to retrieve the public keys from the identity provider * * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech @@ -13,15 +13,11 @@ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; -import java.util.StringJoiner; -import java.util.Map; -import java.util.HashMap; +import java.util.*; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.Collections; -import java.util.HashSet; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; @@ -37,10 +33,14 @@ import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.JSON; +import lombok.Getter; +import lombok.Setter; @javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") @JsonDeserialize(using = CertData.CertDataDeserializer.class) @JsonSerialize(using = CertData.CertDataSerializer.class) +@Getter +@Setter public class CertData extends AbstractOpenApiSchema { private static final Logger log = Logger.getLogger(CertData.class.getName()); @@ -75,65 +75,42 @@ public CertData deserialize(JsonParser jp, DeserializationContext ctxt) throws I boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS); int match = 0; JsonToken token = tree.traverse(jp.getCodec()).nextToken(); + EntitiesDescriptor entitiesDescriptor = new EntitiesDescriptor(); // deserialize CIECertData try { - boolean attemptParsing = true; - // ensure that we respect type coercion as set on the client ObjectMapper - if (CIECertData.class.equals(Integer.class) || CIECertData.class.equals(Long.class) || CIECertData.class.equals(Float.class) || CIECertData.class.equals(Double.class) || CIECertData.class.equals(Boolean.class) || CIECertData.class.equals(String.class)) { - attemptParsing = typeCoercion; - if (!attemptParsing) { - attemptParsing |= ((CIECertData.class.equals(Integer.class) || CIECertData.class.equals(Long.class)) && token == JsonToken.VALUE_NUMBER_INT); - attemptParsing |= ((CIECertData.class.equals(Float.class) || CIECertData.class.equals(Double.class)) && token == JsonToken.VALUE_NUMBER_FLOAT); - attemptParsing |= (CIECertData.class.equals(Boolean.class) && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE)); - attemptParsing |= (CIECertData.class.equals(String.class) && token == JsonToken.VALUE_STRING); - } - } - if (attemptParsing) { - deserialized = tree.traverse(jp.getCodec()).readValueAs(CIECertData.class); - // TODO: there is no validation against JSON schema constraints - // (min, max, enum, pattern...), this does not perform a strict JSON - // validation, which means the 'match' count may be higher than it should be. - if (((CIECertData) deserialized).getEntityDescriptor() != null) { - match++; - log.log(Level.FINER, "Input data matches schema 'CIECertData'"); - } - } - } catch (Exception e) { - // deserialization failed, continue - log.log(Level.FINER, "Input data does not match schema 'CIECertData'", e); - } + deserialized = tree.traverse(jp.getCodec()).readValueAs(EntityDescriptor.class); - // deserialize SPIDCertData - try { - boolean attemptParsing = true; - // ensure that we respect type coercion as set on the client ObjectMapper - if (SPIDCertData.class.equals(Integer.class) || SPIDCertData.class.equals(Long.class) || SPIDCertData.class.equals(Float.class) || SPIDCertData.class.equals(Double.class) || SPIDCertData.class.equals(Boolean.class) || SPIDCertData.class.equals(String.class)) { - attemptParsing = typeCoercion; - if (!attemptParsing) { - attemptParsing |= ((SPIDCertData.class.equals(Integer.class) || SPIDCertData.class.equals(Long.class)) && token == JsonToken.VALUE_NUMBER_INT); - attemptParsing |= ((SPIDCertData.class.equals(Float.class) || SPIDCertData.class.equals(Double.class)) && token == JsonToken.VALUE_NUMBER_FLOAT); - attemptParsing |= (SPIDCertData.class.equals(Boolean.class) && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE)); - attemptParsing |= (SPIDCertData.class.equals(String.class) && token == JsonToken.VALUE_STRING); - } - } - if (attemptParsing) { - deserialized = tree.traverse(jp.getCodec()).readValueAs(SPIDCertData.class); - // TODO: there is no validation against JSON schema constraints - // (min, max, enum, pattern...), this does not perform a strict JSON - // validation, which means the 'match' count may be higher than it should be. - if(((SPIDCertData) deserialized).getEntitiesDescriptor() != null){ - match++; - log.log(Level.FINER, "Input data matches schema 'SPIDCertData'"); + + + if (((EntityDescriptor) deserialized).getEntityID() != null) { + List entityList = Arrays.asList(((EntityDescriptor)deserialized)); + entitiesDescriptor.setEntityList(entityList); + log.log(Level.FINER, "Input data matches schema 'EntityDescriptor'"); + + match++; + } else { + try{ + deserialized = tree.traverse(jp.getCodec()).readValueAs(EntitiesDescriptor.class); + + if (((EntitiesDescriptor) deserialized).getEntityList() != null) { + entitiesDescriptor.setEntityList(((EntitiesDescriptor) deserialized).getEntityList()); + log.log(Level.FINER, "Input data matches schema 'Entities Descriptor'"); + + match++; + } + } catch (Exception e){ + // deserialization failed, continue + log.log(Level.FINER, "Input data does not match schema 'Entities Descriptor'", e); } } } catch (Exception e) { // deserialization failed, continue - log.log(Level.FINER, "Input data does not match schema 'SPIDCertData'", e); + log.log(Level.FINER, "Input data does not match schema 'EntityDescriptor'", e); } if (match == 1) { CertData ret = new CertData(); - ret.setActualInstance(deserialized); + ret.setActualInstance(entitiesDescriptor); return ret; } throw new IOException(String.format("Failed deserialization for CertData: %d classes match result, expected 1", match)); @@ -155,131 +132,10 @@ public CertData() { super("oneOf", Boolean.FALSE); } - public CertData(CIECertData o) { - super("oneOf", Boolean.FALSE); - setActualInstance(o); - } - - public CertData(SPIDCertData o) { - super("oneOf", Boolean.FALSE); - setActualInstance(o); - } - - static { - schemas.put("CIECertData", CIECertData.class); - schemas.put("SPIDCertData", SPIDCertData.class); - JSON.registerDescendants(CertData.class, Collections.unmodifiableMap(schemas)); - } - @Override public Map> getSchemas() { return CertData.schemas; } - /** - * Set the instance that matches the oneOf child schema, check - * the instance parameter is valid against the oneOf child schemas: - * CIECertData, SPIDCertData - * - * It could be an instance of the 'oneOf' schemas. - * The oneOf child schemas may themselves be a composed schema (allOf, anyOf, oneOf). - */ - @Override - public void setActualInstance(Object instance) { - if (JSON.isInstanceOf(CIECertData.class, instance, new HashSet>())) { - super.setActualInstance(instance); - return; - } - - if (JSON.isInstanceOf(SPIDCertData.class, instance, new HashSet>())) { - super.setActualInstance(instance); - return; - } - - throw new RuntimeException("Invalid instance type. Must be CIECertData, SPIDCertData"); - } - - /** - * Get the actual instance, which can be the following: - * CIECertData, SPIDCertData - * - * @return The actual instance (CIECertData, SPIDCertData) - */ - @Override - public Object getActualInstance() { - return super.getActualInstance(); - } - - /** - * Get the actual instance of `CIECertData`. If the actual instance is not `CIECertData`, - * the ClassCastException will be thrown. - * - * @return The actual instance of `CIECertData` - * @throws ClassCastException if the instance is not `CIECertData` - */ - public CIECertData getCIECertData() throws ClassCastException { - return (CIECertData)super.getActualInstance(); - } - - /** - * Get the actual instance of `SPIDCertData`. If the actual instance is not `SPIDCertData`, - * the ClassCastException will be thrown. - * - * @return The actual instance of `SPIDCertData` - * @throws ClassCastException if the instance is not `SPIDCertData` - */ - public SPIDCertData getSPIDCertData() throws ClassCastException { - return (SPIDCertData)super.getActualInstance(); - } - - - - /** - * Convert the instance into URL query string. - * - * @return URL query string - */ - public String toUrlQueryString() { - return toUrlQueryString(null); - } - - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - String suffix = ""; - String containerSuffix = ""; - String containerPrefix = ""; - if (prefix == null) { - // style=form, explode=true, e.g. /pet?name=cat&type=manx - prefix = ""; - } else { - // deepObject style e.g. /pet?id[name]=cat&id[type]=manx - prefix = prefix + "["; - suffix = "]"; - containerSuffix = "]"; - containerPrefix = "["; - } - - StringJoiner joiner = new StringJoiner("&"); - - if (getActualInstance() instanceof CIECertData) { - if (getActualInstance() != null) { - joiner.add(((CIECertData)getActualInstance()).toUrlQueryString(prefix + "one_of_0" + suffix)); - } - return joiner.toString(); - } - if (getActualInstance() instanceof SPIDCertData) { - if (getActualInstance() != null) { - joiner.add(((SPIDCertData)getActualInstance()).toUrlQueryString(prefix + "one_of_1" + suffix)); - } - return joiner.toString(); - } - return null; - } - } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java new file mode 100644 index 00000000..95dffbb6 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java @@ -0,0 +1,37 @@ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + + +/** + * EntitiesDescriptor + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@Getter +@Setter +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +public class EntitiesDescriptor { + + @JsonProperty("EntityDescriptor") + private List entityList; + +} + diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java index 1c6ef986..f822b9dc 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java @@ -13,6 +13,7 @@ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; @@ -29,6 +30,7 @@ @JsonPropertyOrder({ EntityDescriptor.JSON_PROPERTY_ENTITY_I_D }) +@JsonIgnoreProperties(ignoreUnknown = true) @javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class EntityDescriptor { public static final String JSON_PROPERTY_ENTITY_I_D = "entityID"; diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertData.java deleted file mode 100644 index 572534fe..00000000 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertData.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; - -import java.util.Objects; -import java.util.StringJoiner; - - -/** - * SPIDCertData - */ -@JsonPropertyOrder({ - SPIDCertData.JSON_PROPERTY_ENTITIES_DESCRIPTOR -}) -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") -public class SPIDCertData { - public static final String JSON_PROPERTY_ENTITIES_DESCRIPTOR = "entitiesDescriptor"; - private SPIDCertDataEntitiesDescriptor entitiesDescriptor; - - public SPIDCertData() { - } - - public SPIDCertData entitiesDescriptor(SPIDCertDataEntitiesDescriptor entitiesDescriptor) { - this.entitiesDescriptor = entitiesDescriptor; - return this; - } - - /** - * Get entitiesDescriptor - * @return entitiesDescriptor - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_ENTITIES_DESCRIPTOR) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public SPIDCertDataEntitiesDescriptor getEntitiesDescriptor() { - return entitiesDescriptor; - } - - - @JsonProperty(JSON_PROPERTY_ENTITIES_DESCRIPTOR) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setEntitiesDescriptor(SPIDCertDataEntitiesDescriptor entitiesDescriptor) { - this.entitiesDescriptor = entitiesDescriptor; - } - - - /** - * Return true if this SPIDCertData object is equal to o. - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - SPIDCertData spIDCertData = (SPIDCertData) o; - return Objects.equals(this.entitiesDescriptor, spIDCertData.entitiesDescriptor); - } - - @Override - public int hashCode() { - return Objects.hash(entitiesDescriptor); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class SPIDCertData {\n"); - sb.append(" entitiesDescriptor: ").append(toIndentedString(entitiesDescriptor)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } - - /** - * Convert the instance into URL query string. - * - * @return URL query string - */ - public String toUrlQueryString() { - return toUrlQueryString(null); - } - - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - String suffix = ""; - String containerSuffix = ""; - String containerPrefix = ""; - if (prefix == null) { - // style=form, explode=true, e.g. /pet?name=cat&type=manx - prefix = ""; - } else { - // deepObject style e.g. /pet?id[name]=cat&id[type]=manx - prefix = prefix + "["; - suffix = "]"; - containerSuffix = "]"; - containerPrefix = "["; - } - - StringJoiner joiner = new StringJoiner("&"); - - // add `entitiesDescriptor` to the URL query string - if (getEntitiesDescriptor() != null) { - joiner.add(getEntitiesDescriptor().toUrlQueryString(prefix + "entitiesDescriptor" + suffix)); - } - - return joiner.toString(); - } -} - diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertDataEntitiesDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertDataEntitiesDescriptor.java deleted file mode 100644 index a4169a63..00000000 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertDataEntitiesDescriptor.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.StringJoiner; - - -/** - * SPIDCertDataEntitiesDescriptor - */ -@JsonPropertyOrder({ - SPIDCertDataEntitiesDescriptor.JSON_PROPERTY_ENTITY_DESCRIPTOR -}) -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") -public class SPIDCertDataEntitiesDescriptor { - public static final String JSON_PROPERTY_ENTITY_DESCRIPTOR = "entityDescriptor"; - private List entityDescriptor; - - public SPIDCertDataEntitiesDescriptor() { - } - - public SPIDCertDataEntitiesDescriptor entityDescriptor(List entityDescriptor) { - this.entityDescriptor = entityDescriptor; - return this; - } - - public SPIDCertDataEntitiesDescriptor addEntityDescriptorItem(EntityDescriptor entityDescriptorItem) { - if (this.entityDescriptor == null) { - this.entityDescriptor = new ArrayList<>(); - } - this.entityDescriptor.add(entityDescriptorItem); - return this; - } - - /** - * Get entityDescriptor - * @return entityDescriptor - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_ENTITY_DESCRIPTOR) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public List getEntityDescriptor() { - return entityDescriptor; - } - - - @JsonProperty(JSON_PROPERTY_ENTITY_DESCRIPTOR) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setEntityDescriptor(List entityDescriptor) { - this.entityDescriptor = entityDescriptor; - } - - - /** - * Return true if this SPIDCertData_entitiesDescriptor object is equal to o. - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - SPIDCertDataEntitiesDescriptor spIDCertDataEntitiesDescriptor = (SPIDCertDataEntitiesDescriptor) o; - return Objects.equals(this.entityDescriptor, spIDCertDataEntitiesDescriptor.entityDescriptor); - } - - @Override - public int hashCode() { - return Objects.hash(entityDescriptor); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class SPIDCertDataEntitiesDescriptor {\n"); - sb.append(" entityDescriptor: ").append(toIndentedString(entityDescriptor)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } - - /** - * Convert the instance into URL query string. - * - * @return URL query string - */ - public String toUrlQueryString() { - return toUrlQueryString(null); - } - - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - String suffix = ""; - String containerSuffix = ""; - String containerPrefix = ""; - if (prefix == null) { - // style=form, explode=true, e.g. /pet?name=cat&type=manx - prefix = ""; - } else { - // deepObject style e.g. /pet?id[name]=cat&id[type]=manx - prefix = prefix + "["; - suffix = "]"; - containerSuffix = "]"; - containerPrefix = "["; - } - - StringJoiner joiner = new StringJoiner("&"); - - // add `entityDescriptor` to the URL query string - if (getEntityDescriptor() != null) { - for (int i = 0; i < getEntityDescriptor().size(); i++) { - if (getEntityDescriptor().get(i) != null) { - joiner.add(getEntityDescriptor().get(i).toUrlQueryString(String.format("%sentityDescriptor%s%s", prefix, suffix, - "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); - } - } - } - - return joiner.toString(); - } -} - diff --git a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java index 65c1ca74..bb1acd60 100644 --- a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java @@ -1,6 +1,8 @@ package simple; +import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; @@ -25,14 +27,14 @@ public static void startServer() { idpCertSimpleClient = new IdpCertSimpleClient(client); } @Test - void getSPIDCertData() { + void getSPIDCertData() throws CertDataTagListNotFoundException, CertDataNotFoundException { List response = idpCertSimpleClient.getCertData(SPID_ENTITY_ID, instant); Assertions.assertNotNull(response); } @Test - void getCIECertData() { + void getCIECertData() throws CertDataTagListNotFoundException, CertDataNotFoundException { List response = idpCertSimpleClient.getCertData(CIE_ENTITY_ID, instant); Assertions.assertNotNull(response); From 24c25522ee9d1cbf497e812f8ca01db10bd87506 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 12:04:05 +0200 Subject: [PATCH 114/403] [SLS-19] Moved constant outside test method --- .../simple/AssertionSimpleClientTest.java | 250 +++++++++--------- 1 file changed, 124 insertions(+), 126 deletions(-) diff --git a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java index 04d11dee..f82fdd02 100644 --- a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java +++ b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java @@ -21,6 +21,129 @@ class AssertionSimpleClientTest { private static AssertionSimpleClient assertionSimpleClient; private static ClientAndServer mockServer; + private static final String XML_STRING = " https://posteid.poste.it" + + " " + + " " + + " " + + " " + + " " + + " " + + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" + + " " + + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" + + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" + + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" + + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" + + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " + + " " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " " + + " " + + " https://posteid.poste.it " + + " " + + " " + + " " + + " " + + " " + + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" + + " " + + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" + + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" + + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" + + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" + + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " + + " " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + " " + + " " + + " " + + " https://app-backend.io.italia.it" + + " " + + " https://www.spid.gov.it/SpidL2" + + " " + + " " + + " TINIT-AAAAAA89S20I111X" + + " " + + " "; private static final String RESPONSE_STRING = "{\"response_xml\": \" https://posteid.poste.it" - + " " - + " " - + " " - + " " - + " " - + " " - + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" - + " " - + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" - + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" - + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" - + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" - + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " - + " " - + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" - + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" - + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" - + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" - + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" - + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" - + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" - + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" - + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" - + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" - + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" - + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" - + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" - + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" - + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" - + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" - + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" - + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" - + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" - + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" - + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" - + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" - + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" - + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" - + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" - + " " - + " " - + " https://posteid.poste.it " - + " " - + " " - + " " - + " " - + " " - + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" - + " " - + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" - + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" - + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" - + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" - + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " - + " " - + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" - + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" - + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" - + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" - + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" - + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" - + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" - + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" - + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" - + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" - + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" - + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" - + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" - + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" - + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" - + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" - + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" - + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" - + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" - + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" - + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" - + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" - + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" - + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" - + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" - + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" - + " " - + " " - + " " - + " https://app-backend.io.italia.it" - + " " - + " https://www.spid.gov.it/SpidL2" - + " " - + " " - + " TINIT-AAAAAA89S20I111X" - + " " - + " "; createExpectationAssertionFound(); SamlAssertion response = assertionSimpleClient.getAssertion(JWT, ASSERTION_REF); @@ -293,7 +291,7 @@ void samlAssertionFound() throws LollipopAssertionNotFoundException, OidcAsserti Assertions.assertNotNull(response.getAssertionRef()); Assertions.assertNotNull(response.getAssertionData()); Assertions.assertEquals(ASSERTION_REF, response.getAssertionRef()); - Assertions.assertEquals(xmlResponse, response.getAssertionData()); + Assertions.assertEquals(XML_STRING, response.getAssertionData()); } @Test From 85985e2ff6c6fa01b1983445d9ec48d9c5211694 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 12:29:10 +0200 Subject: [PATCH 115/403] [SLS-19] Fixed tag list sorting --- .../client/simple/IdpCertSimpleClient.java | 43 +++++++++++-------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index a091e120..a7a1c9e9 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -16,6 +16,7 @@ import javax.inject.Inject; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class IdpCertSimpleClient implements IdpCertClient { @@ -62,7 +63,7 @@ public List getCertData(String entityId, String instant) throws Cer listCertData.add(certData); } } catch (ApiException | EntityIdNotFoundException e) { - throw new CertDataNotFoundException("Error retrieving certificate data for tag" + tag + ": " + e.getMessage(), e); + throw new CertDataNotFoundException("Error retrieving certificate data for tag " + tag + ": " + e.getMessage(), e); } } @@ -82,7 +83,7 @@ public List getCertData(String entityId, String instant) throws Cer listCertData.add(certData); } } catch (ApiException | EntityIdNotFoundException e) { - throw new CertDataNotFoundException("Error retrieving certificate data for tag" + tag + ": " + e.getMessage(), e); + throw new CertDataNotFoundException("Error retrieving certificate data for tag " + tag + ": " + e.getMessage(), e); } } @@ -135,7 +136,7 @@ private IdpCertData getEntityData(EntitiesDescriptor data, String tag, String en } } - throw new EntityIdNotFoundException("Cert for entityID" + entityId + " not found"); + throw new EntityIdNotFoundException("Cert for entityID " + entityId + " not found"); } private List getTagsFromInstant(List tagList, String instant) throws TagListSearchOutOfBoundException { @@ -146,31 +147,35 @@ private List getTagsFromInstant(List tagList, String instant) th } int index = tagList.size() / 2; + boolean latestRemoved = tagList.remove("latest"); + + Collections.sort(tagList); + + if(latestRemoved){ + tagList.add(0, "latest"); + } - //TODO ordinamento tag boolean notFound = true; while (notFound) { - String upperTag = tagList.get(index); - String lowerTag = tagList.get(index + 1); - if (Long.valueOf(instant) <= Long.valueOf(upperTag) || upperTag.equals("latest")) { - if (Long.valueOf(instant) >= Long.valueOf(lowerTag)) { - notFound = false; - newTagList.add(upperTag); - newTagList.add(lowerTag); + try{ + String upperTag = tagList.get(index); + String lowerTag = tagList.get(index - 1); + if (Long.valueOf(instant) <= Long.valueOf(upperTag) || upperTag.equals("latest")) { + if (Long.valueOf(instant) >= Long.valueOf(lowerTag)) { + notFound = false; + newTagList.add(upperTag); + newTagList.add(lowerTag); + } else { + index -= 1; + } } else { index += 1; } - } else { - index -= 1; + } catch (Exception e){ + throw new TagListSearchOutOfBoundException("Error finding the tags relative to assertion instant " + instant); } - - if (index < 0 || index >= tagList.size()) { - throw new TagListSearchOutOfBoundException("Error finding the tags relative to assertion instant" + instant); - } - } - return newTagList; } } From 5ecda83de4a96b3608f5b369c270476af74750e9 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 12:29:23 +0200 Subject: [PATCH 116/403] [SLS-19] Deleted unused class --- .../simple/internal/model/CIECertData.java | 160 ------------------ 1 file changed, 160 deletions(-) delete mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java deleted file mode 100644 index 7611bcb4..00000000 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; - -import java.util.StringJoiner; -import java.util.Objects; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.ArrayList; -import java.util.List; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; - - -/** - * CIECertData - */ -@JsonPropertyOrder({ - CIECertData.JSON_PROPERTY_ENTITY_DESCRIPTOR -}) -@JsonIgnoreProperties(ignoreUnknown = true) -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") -public class CIECertData { - public static final String JSON_PROPERTY_ENTITY_DESCRIPTOR = "entityDescriptor"; - private List entityDescriptor; - - public CIECertData() { - } - - public CIECertData entityDescriptor(List entityDescriptor) { - this.entityDescriptor = entityDescriptor; - return this; - } - - public CIECertData addEntityDescriptorItem(EntityDescriptor entityDescriptorItem) { - if (this.entityDescriptor == null) { - this.entityDescriptor = new ArrayList<>(); - } - this.entityDescriptor.add(entityDescriptorItem); - return this; - } - - /** - * Get entityDescriptor - * @return entityDescriptor - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_ENTITY_DESCRIPTOR) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public List getEntityDescriptor() { - return entityDescriptor; - } - - - @JsonProperty(JSON_PROPERTY_ENTITY_DESCRIPTOR) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setEntityDescriptor(List entityDescriptor) { - this.entityDescriptor = entityDescriptor; - } - - - /** - * Return true if this CIECertData object is equal to o. - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - CIECertData ciECertData = (CIECertData) o; - return Objects.equals(this.entityDescriptor, ciECertData.entityDescriptor); - } - - @Override - public int hashCode() { - return Objects.hash(entityDescriptor); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class CIECertData {\n"); - sb.append(" entityDescriptor: ").append(toIndentedString(entityDescriptor)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } - - /** - * Convert the instance into URL query string. - * - * @return URL query string - */ - public String toUrlQueryString() { - return toUrlQueryString(null); - } - - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - String suffix = ""; - String containerSuffix = ""; - String containerPrefix = ""; - if (prefix == null) { - // style=form, explode=true, e.g. /pet?name=cat&type=manx - prefix = ""; - } else { - // deepObject style e.g. /pet?id[name]=cat&id[type]=manx - prefix = prefix + "["; - suffix = "]"; - containerSuffix = "]"; - containerPrefix = "["; - } - - StringJoiner joiner = new StringJoiner("&"); - - // add `entityDescriptor` to the URL query string - if (getEntityDescriptor() != null) { - for (int i = 0; i < getEntityDescriptor().size(); i++) { - if (getEntityDescriptor().get(i) != null) { - joiner.add(getEntityDescriptor().get(i).toUrlQueryString(String.format("%sentityDescriptor%s%s", prefix, suffix, - "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); - } - } - } - - return joiner.toString(); - } -} - From ed6b20c5f0d0b85c0324c118e3955be42122deba Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 12:30:16 +0200 Subject: [PATCH 117/403] [SLS-19] Test covered all IdpCertSimpleClient class methods --- .../java/simple/IdpCertSimpleClientTest.java | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java index bb1acd60..7972a073 100644 --- a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java @@ -3,6 +3,8 @@ import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.EntityIdNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.TagListSearchOutOfBoundException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; @@ -17,26 +19,40 @@ class IdpCertSimpleClientTest { private static IdpCertSimpleClient idpCertSimpleClient; - private static final String instant = "1679072970"; + private static final String INSTANT = "1679072970"; private static final String SPID_ENTITY_ID = "https://posteid.poste.it"; private static final String CIE_ENTITY_ID = "https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"; + private static final String WRONG_ENTITY_ID = "https://wrongEntityID.it"; + private static final String WRONG_INSTANT = "xxxxxx"; + @BeforeAll public static void startServer() { ApiClient client = new ApiClient(); idpCertSimpleClient = new IdpCertSimpleClient(client); } @Test - void getSPIDCertData() throws CertDataTagListNotFoundException, CertDataNotFoundException { - List response = idpCertSimpleClient.getCertData(SPID_ENTITY_ID, instant); + void certSPIDDataFound() throws CertDataTagListNotFoundException, CertDataNotFoundException { + List response = idpCertSimpleClient.getCertData(SPID_ENTITY_ID, INSTANT); Assertions.assertNotNull(response); } @Test - void getCIECertData() throws CertDataTagListNotFoundException, CertDataNotFoundException { - List response = idpCertSimpleClient.getCertData(CIE_ENTITY_ID, instant); + void certCIEDataFound() throws CertDataTagListNotFoundException, CertDataNotFoundException { + List response = idpCertSimpleClient.getCertData(CIE_ENTITY_ID, INSTANT); Assertions.assertNotNull(response); } + + @Test + void getCertDataWrongEntityID() throws CertDataTagListNotFoundException, CertDataNotFoundException { + Assertions.assertThrows(CertDataNotFoundException.class, () -> idpCertSimpleClient.getCertData(WRONG_ENTITY_ID, INSTANT)); + } + + @Test + void getCertDataWrongInstant() throws CertDataTagListNotFoundException, CertDataNotFoundException { + Assertions.assertThrows(CertDataTagListNotFoundException.class, () -> idpCertSimpleClient.getCertData(SPID_ENTITY_ID, WRONG_INSTANT)); + } + } \ No newline at end of file From 8444619d69addc014c2d50e4f72713de7662873e Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 14:09:10 +0200 Subject: [PATCH 118/403] [SLS-19] Removed TODOs --- .../consumer/idp/client/simple/IdpCertSimpleClient.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index a7a1c9e9..5e24a158 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -55,7 +55,6 @@ public List getCertData(String entityId, String instant) throws Cer } for (String tag : tagList) { - //TODO recupero storage try { IdpCertData certData = getCIECertData(tag, entityId); @@ -75,7 +74,6 @@ public List getCertData(String entityId, String instant) throws Cer } for (String tag : tagList) { - //TODO recupero storage try { IdpCertData certData = getSPIDCertData(tag, entityId); From 5c08fba1d760a901d3b547e8a9c08b08876c00b4 Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Wed, 12 Apr 2023 14:11:56 +0200 Subject: [PATCH 119/403] Update release.yaml --- .github/workflows/release.yaml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a9a6f6ef..d39039b6 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -9,11 +9,18 @@ jobs: contents: read packages: write steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + # jdkfile version hash was locally computed and checked against https://github.com/paketo-buildpacks/adoptium/releases + - run: | + echo "4a29efda1d702b8ff38e554cf932051f40ec70006caed5c4857a8cbc7a0b7db7 ${{ runner.temp }}/jdkfile" >> ${{ runner.temp }}/jdkfile.sha256 + echo {{ runner.temp }}/jdkfile.sha256 + curl -L "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.18%2B10/OpenJDK11U-jdk_x64_linux_hotspot_11.0.18_10.tar.gz" -o "${{ runner.temp }}/jdkfile" + sha256sum --check --status "${{ runner.temp }}/jdkfile.sha256" - uses: actions/setup-java@v3 with: - java-version: '11' - distribution: 'adopt' + distribution: "jdkfile" + jdkFile: "${{ runner.temp }}/jdkfile" + java-version: "11" - name: Validate Gradle wrapper uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b - name: Make gradlew executable @@ -23,4 +30,4 @@ jobs: with: arguments: publish env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 065d8e4495cb9ef9a92e4d89258d033145c53b37 Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Wed, 12 Apr 2023 14:24:11 +0200 Subject: [PATCH 120/403] Update release.yaml --- .github/workflows/release.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index d39039b6..550b0239 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -12,14 +12,14 @@ jobs: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # jdkfile version hash was locally computed and checked against https://github.com/paketo-buildpacks/adoptium/releases - run: | - echo "4a29efda1d702b8ff38e554cf932051f40ec70006caed5c4857a8cbc7a0b7db7 ${{ runner.temp }}/jdkfile" >> ${{ runner.temp }}/jdkfile.sha256 + echo "4a29efda1d702b8ff38e554cf932051f40ec70006caed5c4857a8cbc7a0b7db7 ${{ runner.temp }}/jdkfile.tar.gz" >> ${{ runner.temp }}/jdkfile.sha256 echo {{ runner.temp }}/jdkfile.sha256 - curl -L "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.18%2B10/OpenJDK11U-jdk_x64_linux_hotspot_11.0.18_10.tar.gz" -o "${{ runner.temp }}/jdkfile" + curl -L "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.18%2B10/OpenJDK11U-jdk_x64_linux_hotspot_11.0.18_10.tar.gz" -o "${{ runner.temp }}/jdkfile.tar.gz" sha256sum --check --status "${{ runner.temp }}/jdkfile.sha256" - uses: actions/setup-java@v3 with: distribution: "jdkfile" - jdkFile: "${{ runner.temp }}/jdkfile" + jdkFile: "${{ runner.temp }}/jdkfile.tar.gz" java-version: "11" - name: Validate Gradle wrapper uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b From fc4243406288baaf03aee11a542d82e902c68a8f Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Wed, 12 Apr 2023 14:34:00 +0200 Subject: [PATCH 121/403] Update release.yaml --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 550b0239..a3553112 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -16,7 +16,7 @@ jobs: echo {{ runner.temp }}/jdkfile.sha256 curl -L "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.18%2B10/OpenJDK11U-jdk_x64_linux_hotspot_11.0.18_10.tar.gz" -o "${{ runner.temp }}/jdkfile.tar.gz" sha256sum --check --status "${{ runner.temp }}/jdkfile.sha256" - - uses: actions/setup-java@v3 + - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 with: distribution: "jdkfile" jdkFile: "${{ runner.temp }}/jdkfile.tar.gz" From ef0e4240e64015ffda81de1ac81ac198121fdcec Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Wed, 12 Apr 2023 14:44:07 +0200 Subject: [PATCH 122/403] Update pr_scan.yml --- .github/workflows/pr_scan.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index af448973..d89481d3 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -11,11 +11,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout project sources - uses: actions/checkout@v3 + uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 with: fetch-depth: 0 - name: Setup Gradle - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 - name: Make gradlew executable run: chmod +x ./gradlew - name: Run build with Gradle Wrapper @@ -30,7 +30,7 @@ jobs: fail-build: true severity-cutoff: "high" - name: Upload Anchore Scan Report - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@9885f86fab4879632b7e44514f19148225dfbdcd if: always() with: sarif_file: ${{ steps.scan.outputs.sarif }} From 27ca9191a709ee4134d6658bbfb033a66c0cfa0c Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 14:56:49 +0200 Subject: [PATCH 123/403] [SLS-19] Completed signature retrieving from idp certification - added comments & cleaned models --- .../client/simple/AssertionSimpleClient.java | 1 + .../client/simple/IdpCertSimpleClient.java | 29 ++-- .../simple/IdpCertSimpleClientProvider.java | 1 + .../simple/internal/model/CertData.java | 3 +- .../internal/model/EntitiesDescriptor.java | 2 - .../internal/model/EntityDescriptor.java | 131 ++---------------- 6 files changed, 33 insertions(+), 134 deletions(-) diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java index 4f437124..b8d82fca 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java @@ -34,6 +34,7 @@ public AssertionSimpleClient(ApiClient client) { * @param assertionRef Assertion unique identification * @return the retrieved assertion or null if the assertion is not supported (not SAML) * @throws LollipopAssertionNotFoundException if some error occurred in the request + * @throws OidcAssertionNotSupported if the assertion retrieved is a OIDC token */ @Override public SamlAssertion getAssertion(String jwt, String assertionRef) diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 5e24a158..251ba97d 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -33,9 +33,14 @@ public IdpCertSimpleClient(ApiClient client) { } /** - * @param entityId - * @param instant - * @return + * Retrieve the certification data of the given entityId issued + * in the same timeframe as the issue instant of the SAML assertion + * + * @param entityId Identity Provider ID + * @param instant Assertion Issue Instant + * @return the certifications issued before and after the timestamp instant + * @throws CertDataTagListNotFoundException if an error occurred retrieving the list of tags or filtering the tags with the instant + * @throws CertDataNotFoundException if an error occurred retrieving the certification XML or if data for the given entityId were not found */ @Override public List getCertData(String entityId, String instant) throws CertDataNotFoundException, CertDataTagListNotFoundException { @@ -58,7 +63,7 @@ public List getCertData(String entityId, String instant) throws Cer try { IdpCertData certData = getCIECertData(tag, entityId); - if(certData != null){ + if (certData != null) { listCertData.add(certData); } } catch (ApiException | EntityIdNotFoundException e) { @@ -77,7 +82,7 @@ public List getCertData(String entityId, String instant) throws Cer try { IdpCertData certData = getSPIDCertData(tag, entityId); - if(certData != null){ + if (certData != null) { listCertData.add(certData); } } catch (ApiException | EntityIdNotFoundException e) { @@ -102,7 +107,7 @@ private IdpCertData getSPIDCertData(String tag, String entityId) throws EntityId responseAssertion = this.defaultApi.idpKeysSpidTagGet(tag); - return getEntityData(((EntitiesDescriptor)responseAssertion.getActualInstance()), tag, entityId); + return getEntityData(((EntitiesDescriptor) responseAssertion.getActualInstance()), tag, entityId); } private List getCIETagList(String instant) throws TagListSearchOutOfBoundException { @@ -118,17 +123,17 @@ private IdpCertData getCIECertData(String tag, String entityId) throws EntityIdN responseAssertion = this.defaultApi.idpKeysCieTagGet(tag); - return getEntityData(((EntitiesDescriptor)responseAssertion.getActualInstance()), tag, entityId); + return getEntityData(((EntitiesDescriptor) responseAssertion.getActualInstance()), tag, entityId); } private IdpCertData getEntityData(EntitiesDescriptor data, String tag, String entityId) throws EntityIdNotFoundException { IdpCertData newData = new IdpCertData(); for (EntityDescriptor entity : data.getEntityList()) { - if (entity.getEntityID().equals(entityId)){ + if (entity.getEntityID().equals(entityId)) { newData.setEntityId(entityId); newData.setTag(tag); - newData.setCertData("test"); + newData.setCertData(entity.getSignature()); return newData; } @@ -149,13 +154,13 @@ private List getTagsFromInstant(List tagList, String instant) th Collections.sort(tagList); - if(latestRemoved){ + if (latestRemoved) { tagList.add(0, "latest"); } boolean notFound = true; while (notFound) { - try{ + try { String upperTag = tagList.get(index); String lowerTag = tagList.get(index - 1); if (Long.valueOf(instant) <= Long.valueOf(upperTag) || upperTag.equals("latest")) { @@ -169,7 +174,7 @@ private List getTagsFromInstant(List tagList, String instant) th } else { index += 1; } - } catch (Exception e){ + } catch (Exception e) { throw new TagListSearchOutOfBoundException("Error finding the tags relative to assertion instant " + instant); } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java index 402136fd..68a756f1 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java @@ -5,6 +5,7 @@ import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; +/** Provider class for retrieving an instance of {@link IdpCertSimpleClient} */ public class IdpCertSimpleClientProvider implements IdpCertClientProvider { /** diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java index 8b256dc3..c3580595 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java @@ -78,9 +78,8 @@ public CertData deserialize(JsonParser jp, DeserializationContext ctxt) throws I EntitiesDescriptor entitiesDescriptor = new EntitiesDescriptor(); // deserialize CIECertData try { - deserialized = tree.traverse(jp.getCodec()).readValueAs(EntityDescriptor.class); - + deserialized = tree.traverse(jp.getCodec()).readValueAs(EntityDescriptor.class); if (((EntityDescriptor) deserialized).getEntityID() != null) { List entityList = Arrays.asList(((EntityDescriptor)deserialized)); diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java index 95dffbb6..9e5ace68 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java @@ -20,14 +20,12 @@ import java.util.List; - /** * EntitiesDescriptor */ @JsonIgnoreProperties(ignoreUnknown = true) @Getter @Setter -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class EntitiesDescriptor { @JsonProperty("EntityDescriptor") diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java index f822b9dc..6b602241 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java @@ -3,145 +3,40 @@ * Client used to retrieve the public keys from the identity provider * * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech * Do not edit the class manually. */ - package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Getter; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.Objects; -import java.util.StringJoiner; +import java.util.Map; /** * EntityDescriptor */ -@JsonPropertyOrder({ - EntityDescriptor.JSON_PROPERTY_ENTITY_I_D -}) @JsonIgnoreProperties(ignoreUnknown = true) -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +@Getter public class EntityDescriptor { - public static final String JSON_PROPERTY_ENTITY_I_D = "entityID"; - private String entityID; - - public EntityDescriptor() { - } - - public EntityDescriptor entityID(String entityID) { - this.entityID = entityID; - return this; - } - - /** - * Get entityID - * @return entityID - **/ - @javax.annotation.Nonnull - @JsonProperty(JSON_PROPERTY_ENTITY_I_D) - @JsonInclude(value = JsonInclude.Include.ALWAYS) - - public String getEntityID() { - return entityID; - } - - - @JsonProperty(JSON_PROPERTY_ENTITY_I_D) - @JsonInclude(value = JsonInclude.Include.ALWAYS) - public void setEntityID(String entityID) { - this.entityID = entityID; - } - - - /** - * Return true if this EntityDescriptor object is equal to o. - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - EntityDescriptor entityDescriptor = (EntityDescriptor) o; - return Objects.equals(this.entityID, entityDescriptor.entityID); - } - - @Override - public int hashCode() { - return Objects.hash(entityID); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class EntityDescriptor {\n"); - sb.append(" entityID: ").append(toIndentedString(entityID)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } - - /** - * Convert the instance into URL query string. - * - * @return URL query string - */ - public String toUrlQueryString() { - return toUrlQueryString(null); - } - - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - String suffix = ""; - String containerSuffix = ""; - String containerPrefix = ""; - if (prefix == null) { - // style=form, explode=true, e.g. /pet?name=cat&type=manx - prefix = ""; - } else { - // deepObject style e.g. /pet?id[name]=cat&id[type]=manx - prefix = prefix + "["; - suffix = "]"; - containerSuffix = "]"; - containerPrefix = "["; - } + @JsonProperty("entityID") + private String entityID; - StringJoiner joiner = new StringJoiner("&"); + private String signature; - // add `entityID` to the URL query string - if (getEntityID() != null) { - joiner.add(String.format("%sentityID%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getEntityID()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + @SuppressWarnings("unchecked") + @JsonProperty("Signature") + private void unpackNestedSignature(Map signature) { + Map keyInfo = (Map) signature.get("KeyInfo"); + Map x509Data = (Map) keyInfo.get("X509Data"); + this.signature = (String) x509Data.get("X509Certificate"); } - return joiner.toString(); - } } From 90002ce4b516a1cb7d7b0456c7b7a185d2566cdb Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 15:06:52 +0200 Subject: [PATCH 124/403] [SLS-19] Improved test constant instant - fixed tag list filtering --- .../consumer/idp/client/simple/IdpCertSimpleClient.java | 4 ++-- .../src/test/java/simple/IdpCertSimpleClientTest.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 251ba97d..64a0b9d9 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -155,7 +155,7 @@ private List getTagsFromInstant(List tagList, String instant) th Collections.sort(tagList); if (latestRemoved) { - tagList.add(0, "latest"); + tagList.add("latest"); } boolean notFound = true; @@ -163,7 +163,7 @@ private List getTagsFromInstant(List tagList, String instant) th try { String upperTag = tagList.get(index); String lowerTag = tagList.get(index - 1); - if (Long.valueOf(instant) <= Long.valueOf(upperTag) || upperTag.equals("latest")) { + if (upperTag.equals("latest") || Long.valueOf(instant) <= Long.valueOf(upperTag)) { if (Long.valueOf(instant) >= Long.valueOf(lowerTag)) { notFound = false; newTagList.add(upperTag); diff --git a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java index 7972a073..951748e9 100644 --- a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java @@ -13,13 +13,14 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import java.time.Instant; import java.util.List; class IdpCertSimpleClientTest { private static IdpCertSimpleClient idpCertSimpleClient; - private static final String INSTANT = "1679072970"; + private static final String INSTANT = String.valueOf(Instant.now().getEpochSecond()); private static final String SPID_ENTITY_ID = "https://posteid.poste.it"; private static final String CIE_ENTITY_ID = "https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"; From 79dddbc18437ef69adedbca8e54702190340c1c2 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 16:04:37 +0200 Subject: [PATCH 125/403] [SLS-19] Improved tag list filtering - added test & configuration for valid CIE entity id --- .../exception/CertDataNotFoundException.java | 1 + .../CertDataTagListNotFoundException.java | 1 + .../exception/EntityIdNotFoundException.java | 3 +- .../InvalidInstantFormatException.java | 14 +++++ .../build.gradle | 3 + .../client/simple/IdpCertSimpleClient.java | 58 ++++++++++--------- .../simple/IdpCertSimpleClientConfig.java | 15 +++++ .../simple/IdpCertSimpleClientProvider.java | 10 +++- .../simple/internal/model/CertData.java | 2 +- .../java/simple/IdpCertSimpleClientTest.java | 17 ++++-- 10 files changed, 90 insertions(+), 34 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/InvalidInstantFormatException.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataNotFoundException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataNotFoundException.java index 95030acb..7665e698 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataNotFoundException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataNotFoundException.java @@ -1,5 +1,6 @@ package it.pagopa.tech.lollipop.consumer.exception; +/** Thrown in case of problems retrieving idp certification data */ public class CertDataNotFoundException extends Exception{ /** * Constructs new exception with provided message and cause diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java index fe00adfb..4355873e 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java @@ -1,5 +1,6 @@ package it.pagopa.tech.lollipop.consumer.exception; +/** Thrown in case of problems retrieving idp certification tag list */ public class CertDataTagListNotFoundException extends Exception{ /** * Constructs new exception with provided message and cause diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/EntityIdNotFoundException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/EntityIdNotFoundException.java index 7b5b35ce..0932b69c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/EntityIdNotFoundException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/EntityIdNotFoundException.java @@ -1,9 +1,10 @@ package it.pagopa.tech.lollipop.consumer.exception; +/** Thrown in case of problems finding the right data for the given entityId */ public class EntityIdNotFoundException extends Exception{ /** - * Constructs new exception with provided messag + * Constructs new exception with provided message * * @param message Detail message */ diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/InvalidInstantFormatException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/InvalidInstantFormatException.java new file mode 100644 index 00000000..3640b348 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/InvalidInstantFormatException.java @@ -0,0 +1,14 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +/** Thrown when the given instant is not a valid timestamp */ +public class InvalidInstantFormatException extends Exception { + + /** + * Constructs new exception with provided message + * + * @param message Detail message + */ + public InvalidInstantFormatException(String message) { + super(message); + } +} diff --git a/identity-service-rest-client-native/build.gradle b/identity-service-rest-client-native/build.gradle index d38a7392..3ae67e50 100644 --- a/identity-service-rest-client-native/build.gradle +++ b/identity-service-rest-client-native/build.gradle @@ -57,6 +57,9 @@ dependencies { // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.assertj:assertj-core:3.24.2' + + testImplementation 'org.mockito:mockito-core:5.2.0' + testImplementation 'org.mockito:mockito-junit-jupiter:5.2.0' //Mockserver for testing api testImplementation 'org.mock-server:mockserver-netty:5.15.0' } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 64a0b9d9..6b773812 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -1,10 +1,7 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple; -import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.EntityIdNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.TagListSearchOutOfBoundException; +import it.pagopa.tech.lollipop.consumer.exception.*; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiException; @@ -24,12 +21,14 @@ public class IdpCertSimpleClient implements IdpCertClient { private final ApiClient apiClient; private final DefaultApi defaultApi; - private static final List CIE_ENTITY_IDS = new ArrayList<>(List.of("https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO")); + private final IdpCertSimpleClientConfig entityConfig; + @Inject - public IdpCertSimpleClient(ApiClient client) { + public IdpCertSimpleClient(ApiClient client, IdpCertSimpleClientConfig entityConfig) { this.apiClient = client; this.defaultApi = new DefaultApi(client); + this.entityConfig = entityConfig; } /** @@ -51,11 +50,10 @@ public List getCertData(String entityId, String instant) throws Cer throw new IllegalArgumentException("EntityID or Assertion Issue Instant missing"); } - if (CIE_ENTITY_IDS.contains(entityId)) { //TODO inserire entityID in classe di configurazione - + if (entityConfig.getCieEntityId().contains(entityId)) { try { tagList = getCIETagList(instant); - } catch (ApiException | TagListSearchOutOfBoundException e) { + } catch (ApiException | TagListSearchOutOfBoundException | InvalidInstantFormatException e) { throw new CertDataTagListNotFoundException("Error retrieving certificate's tag list: " + e.getMessage(), e); } @@ -63,9 +61,7 @@ public List getCertData(String entityId, String instant) throws Cer try { IdpCertData certData = getCIECertData(tag, entityId); - if (certData != null) { - listCertData.add(certData); - } + listCertData.add(certData); } catch (ApiException | EntityIdNotFoundException e) { throw new CertDataNotFoundException("Error retrieving certificate data for tag " + tag + ": " + e.getMessage(), e); } @@ -74,7 +70,7 @@ public List getCertData(String entityId, String instant) throws Cer } else { try { tagList = getSPIDTagList(instant); - } catch (ApiException | TagListSearchOutOfBoundException e) { + } catch (ApiException | TagListSearchOutOfBoundException | InvalidInstantFormatException e) { throw new CertDataTagListNotFoundException("Error retrieving certificate's tag list: " + e.getMessage(), e); } @@ -82,9 +78,7 @@ public List getCertData(String entityId, String instant) throws Cer try { IdpCertData certData = getSPIDCertData(tag, entityId); - if (certData != null) { - listCertData.add(certData); - } + listCertData.add(certData); } catch (ApiException | EntityIdNotFoundException e) { throw new CertDataNotFoundException("Error retrieving certificate data for tag " + tag + ": " + e.getMessage(), e); } @@ -94,7 +88,7 @@ public List getCertData(String entityId, String instant) throws Cer return listCertData; } - private List getSPIDTagList(String instant) throws TagListSearchOutOfBoundException { + private List getSPIDTagList(String instant) throws TagListSearchOutOfBoundException, InvalidInstantFormatException { List responseAssertion; responseAssertion = this.defaultApi.idpKeysSpidGet(); @@ -110,7 +104,7 @@ private IdpCertData getSPIDCertData(String tag, String entityId) throws EntityId return getEntityData(((EntitiesDescriptor) responseAssertion.getActualInstance()), tag, entityId); } - private List getCIETagList(String instant) throws TagListSearchOutOfBoundException { + private List getCIETagList(String instant) throws TagListSearchOutOfBoundException, InvalidInstantFormatException { List responseAssertion; responseAssertion = this.defaultApi.idpKeysCieGet(); @@ -142,29 +136,41 @@ private IdpCertData getEntityData(EntitiesDescriptor data, String tag, String en throw new EntityIdNotFoundException("Cert for entityID " + entityId + " not found"); } - private List getTagsFromInstant(List tagList, String instant) throws TagListSearchOutOfBoundException { + private List getTagsFromInstant(List tagList, String instant) throws TagListSearchOutOfBoundException, InvalidInstantFormatException { List newTagList = new ArrayList<>(); + String latest = "latest"; + long longInstant; - if (tagList.size() <= 2) { - return tagList; + try { + longInstant = Long.parseLong(instant); + } catch (Exception e) { + throw new InvalidInstantFormatException("The given insant " + instant + " is not a valid timestamp"); } - int index = tagList.size() / 2; - boolean latestRemoved = tagList.remove("latest"); + boolean latestRemoved = tagList.remove(latest); Collections.sort(tagList); if (latestRemoved) { - tagList.add("latest"); + tagList.add(latest); } + int index = tagList.size() / 2; + boolean notFound = true; while (notFound) { try { + if (tagList.size() <= 2) { + String firstTimestamp = tagList.get(0); + if (firstTimestamp.equals(latest) || Long.parseLong(firstTimestamp) <= longInstant) { + return tagList; + } + } + String upperTag = tagList.get(index); String lowerTag = tagList.get(index - 1); - if (upperTag.equals("latest") || Long.valueOf(instant) <= Long.valueOf(upperTag)) { - if (Long.valueOf(instant) >= Long.valueOf(lowerTag)) { + if (upperTag.equals(latest) || longInstant <= Long.parseLong(upperTag)) { + if (longInstant >= Long.parseLong(lowerTag)) { notFound = false; newTagList.add(upperTag); newTagList.add(lowerTag); diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java new file mode 100644 index 00000000..8f0f0eab --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java @@ -0,0 +1,15 @@ +package it.pagopa.tech.lollipop.consumer.idp.client.simple; + +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +@Data +@Builder +public class IdpCertSimpleClientConfig { + + @Builder.Default + private List cieEntityId = List.of("https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"); + +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java index 68a756f1..997c923a 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java @@ -5,9 +5,17 @@ import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; +import javax.inject.Inject; + /** Provider class for retrieving an instance of {@link IdpCertSimpleClient} */ public class IdpCertSimpleClientProvider implements IdpCertClientProvider { + private final IdpCertSimpleClientConfig entityConfig; + + @Inject + public IdpCertSimpleClientProvider(IdpCertSimpleClientConfig entityConfig){ + this.entityConfig = entityConfig; + } /** * Provide an instance of {@link IdpCertSimpleClient} * @@ -15,6 +23,6 @@ public class IdpCertSimpleClientProvider implements IdpCertClientProvider { */ @Override public IdpCertClient provideClient() { - return new IdpCertSimpleClient(new ApiClient()); + return new IdpCertSimpleClient(new ApiClient(), this.entityConfig); } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java index c3580595..ace38068 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java @@ -76,7 +76,7 @@ public CertData deserialize(JsonParser jp, DeserializationContext ctxt) throws I int match = 0; JsonToken token = tree.traverse(jp.getCodec()).nextToken(); EntitiesDescriptor entitiesDescriptor = new EntitiesDescriptor(); - // deserialize CIECertData + try { deserialized = tree.traverse(jp.getCodec()).readValueAs(EntityDescriptor.class); diff --git a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java index 951748e9..866f7d24 100644 --- a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java @@ -3,15 +3,14 @@ import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.EntityIdNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.TagListSearchOutOfBoundException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClient; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; -import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; import java.time.Instant; import java.util.List; @@ -19,6 +18,7 @@ class IdpCertSimpleClientTest { private static IdpCertSimpleClient idpCertSimpleClient; + private static IdpCertSimpleClientConfig entityConfig; private static final String INSTANT = String.valueOf(Instant.now().getEpochSecond()); private static final String SPID_ENTITY_ID = "https://posteid.poste.it"; @@ -30,8 +30,10 @@ class IdpCertSimpleClientTest { @BeforeAll public static void startServer() { ApiClient client = new ApiClient(); - idpCertSimpleClient = new IdpCertSimpleClient(client); + entityConfig = Mockito.spy(IdpCertSimpleClientConfig.builder().build()); + idpCertSimpleClient = new IdpCertSimpleClient(client, entityConfig); } + @Test void certSPIDDataFound() throws CertDataTagListNotFoundException, CertDataNotFoundException { List response = idpCertSimpleClient.getCertData(SPID_ENTITY_ID, INSTANT); @@ -52,8 +54,13 @@ void getCertDataWrongEntityID() throws CertDataTagListNotFoundException, CertDat } @Test - void getCertDataWrongInstant() throws CertDataTagListNotFoundException, CertDataNotFoundException { + void getSPIDCertDataWrongInstant() throws CertDataTagListNotFoundException, CertDataNotFoundException { Assertions.assertThrows(CertDataTagListNotFoundException.class, () -> idpCertSimpleClient.getCertData(SPID_ENTITY_ID, WRONG_INSTANT)); } + @Test + void getCIECertDataWrongInstant() throws CertDataTagListNotFoundException, CertDataNotFoundException { + Assertions.assertThrows(CertDataTagListNotFoundException.class, () -> idpCertSimpleClient.getCertData(CIE_ENTITY_ID, WRONG_INSTANT)); + } + } \ No newline at end of file From 8cd1bbd8ff912aab30e77129406ca1c0c91b818b Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 16:58:00 +0200 Subject: [PATCH 126/403] [SLS-19] Added configuration for api client for baseUri and endpoints - applied spotless --- .../simple/AssertionSimpleClientTest.java | 241 ++++---- .../exception/CertDataNotFoundException.java | 3 +- .../CertDataTagListNotFoundException.java | 3 +- .../exception/EntityIdNotFoundException.java | 3 +- .../InvalidInstantFormatException.java | 1 + .../TagListSearchOutOfBoundException.java | 3 +- .../consumer/idp/client/IdpCertClient.java | 3 +- .../client/simple/IdpCertSimpleClient.java | 84 ++- .../simple/IdpCertSimpleClientConfig.java | 12 +- .../simple/IdpCertSimpleClientProvider.java | 9 +- .../idp/client/simple/internal/ApiClient.java | 567 +++++------------ .../client/simple/internal/ApiException.java | 34 +- .../client/simple/internal/ApiResponse.java | 20 +- .../simple/internal/api/DefaultApi.java | 571 +++++++++--------- .../internal/model/AbstractOpenApiSchema.java | 54 +- .../simple/internal/model/CertData.java | 65 +- .../internal/model/EntitiesDescriptor.java | 27 +- .../internal/model/EntityDescriptor.java | 23 +- .../simple/internal/model/ProblemJson.java | 515 ++++++++-------- .../java/simple/IdpCertSimpleClientTest.java | 33 +- 20 files changed, 974 insertions(+), 1297 deletions(-) diff --git a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java index f82fdd02..6345060d 100644 --- a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java +++ b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java @@ -21,129 +21,124 @@ class AssertionSimpleClientTest { private static AssertionSimpleClient assertionSimpleClient; private static ClientAndServer mockServer; - private static final String XML_STRING = " https://posteid.poste.it" - + " " - + " " - + " " - + " " - + " " - + " " - + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" - + " " - + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" - + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" - + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" - + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" - + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " - + " " - + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" - + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" - + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" - + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" - + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" - + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" - + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" - + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" - + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" - + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" - + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" - + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" - + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" - + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" - + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" - + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" - + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" - + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" - + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" - + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" - + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" - + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" - + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" - + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" - + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" - + " " - + " " - + " https://posteid.poste.it " - + " " - + " " - + " " - + " " - + " " - + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" - + " " - + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" - + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" - + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" - + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" - + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " - + " " - + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" - + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" - + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" - + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" - + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" - + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" - + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" - + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" - + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" - + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" - + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" - + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" - + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" - + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" - + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" - + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" - + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" - + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" - + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" - + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" - + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" - + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" - + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" - + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" - + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" - + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" - + " " - + " " - + " " - + " https://app-backend.io.italia.it" - + " " - + " https://www.spid.gov.it/SpidL2" - + " " - + " " - + " TINIT-AAAAAA89S20I111X" - + " " - + " "; + private static final String XML_STRING = + " https://posteid.poste.it" + + " " + + " " + + " " + + " " + + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" + + " " + + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" + + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" + + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" + + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" + + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " " + + " " + + " https://posteid.poste.it " + + " " + + " " + + " " + + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" + + " " + + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" + + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" + + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" + + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" + + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + " " + + " " + + " " + + " https://app-backend.io.italia.it" + + " " + + " https://www.spid.gov.it/SpidL2" + + " " + + " " + + " " + + " TINIT-AAAAAA89S20I111X " + + " "; private static final String RESPONSE_STRING = "{\"response_xml\": \" getCertData(String entityId, String instant) throws CertDataNotFoundException, CertDataTagListNotFoundException; + List getCertData(String entityId, String instant) + throws CertDataNotFoundException, CertDataTagListNotFoundException; } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 6b773812..1b62a68c 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -10,39 +10,38 @@ import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.EntitiesDescriptor; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.EntityDescriptor; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; - -import javax.inject.Inject; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import javax.inject.Inject; public class IdpCertSimpleClient implements IdpCertClient { - private final ApiClient apiClient; private final DefaultApi defaultApi; private final IdpCertSimpleClientConfig entityConfig; - @Inject public IdpCertSimpleClient(ApiClient client, IdpCertSimpleClientConfig entityConfig) { - this.apiClient = client; this.defaultApi = new DefaultApi(client); this.entityConfig = entityConfig; } /** - * Retrieve the certification data of the given entityId issued - * in the same timeframe as the issue instant of the SAML assertion + * Retrieve the certification data of the given entityId issued in the same timeframe as the + * issue instant of the SAML assertion * * @param entityId Identity Provider ID - * @param instant Assertion Issue Instant + * @param instant Assertion Issue Instant * @return the certifications issued before and after the timestamp instant - * @throws CertDataTagListNotFoundException if an error occurred retrieving the list of tags or filtering the tags with the instant - * @throws CertDataNotFoundException if an error occurred retrieving the certification XML or if data for the given entityId were not found + * @throws CertDataTagListNotFoundException if an error occurred retrieving the list of tags or + * filtering the tags with the instant + * @throws CertDataNotFoundException if an error occurred retrieving the certification XML or if + * data for the given entityId were not found */ @Override - public List getCertData(String entityId, String instant) throws CertDataNotFoundException, CertDataTagListNotFoundException { + public List getCertData(String entityId, String instant) + throws CertDataNotFoundException, CertDataTagListNotFoundException { List listCertData = new ArrayList<>(); List tagList; @@ -53,8 +52,11 @@ public List getCertData(String entityId, String instant) throws Cer if (entityConfig.getCieEntityId().contains(entityId)) { try { tagList = getCIETagList(instant); - } catch (ApiException | TagListSearchOutOfBoundException | InvalidInstantFormatException e) { - throw new CertDataTagListNotFoundException("Error retrieving certificate's tag list: " + e.getMessage(), e); + } catch (ApiException + | TagListSearchOutOfBoundException + | InvalidInstantFormatException e) { + throw new CertDataTagListNotFoundException( + "Error retrieving certificate's tag list: " + e.getMessage(), e); } for (String tag : tagList) { @@ -63,15 +65,22 @@ public List getCertData(String entityId, String instant) throws Cer listCertData.add(certData); } catch (ApiException | EntityIdNotFoundException e) { - throw new CertDataNotFoundException("Error retrieving certificate data for tag " + tag + ": " + e.getMessage(), e); + throw new CertDataNotFoundException( + "Error retrieving certificate data for tag " + + tag + + ": " + + e.getMessage(), + e); } - } } else { try { tagList = getSPIDTagList(instant); - } catch (ApiException | TagListSearchOutOfBoundException | InvalidInstantFormatException e) { - throw new CertDataTagListNotFoundException("Error retrieving certificate's tag list: " + e.getMessage(), e); + } catch (ApiException + | TagListSearchOutOfBoundException + | InvalidInstantFormatException e) { + throw new CertDataTagListNotFoundException( + "Error retrieving certificate's tag list: " + e.getMessage(), e); } for (String tag : tagList) { @@ -80,15 +89,20 @@ public List getCertData(String entityId, String instant) throws Cer listCertData.add(certData); } catch (ApiException | EntityIdNotFoundException e) { - throw new CertDataNotFoundException("Error retrieving certificate data for tag " + tag + ": " + e.getMessage(), e); + throw new CertDataNotFoundException( + "Error retrieving certificate data for tag " + + tag + + ": " + + e.getMessage(), + e); } - } } return listCertData; } - private List getSPIDTagList(String instant) throws TagListSearchOutOfBoundException, InvalidInstantFormatException { + private List getSPIDTagList(String instant) + throws TagListSearchOutOfBoundException, InvalidInstantFormatException { List responseAssertion; responseAssertion = this.defaultApi.idpKeysSpidGet(); @@ -96,15 +110,18 @@ private List getSPIDTagList(String instant) throws TagListSearchOutOfBou return getTagsFromInstant(responseAssertion, instant); } - private IdpCertData getSPIDCertData(String tag, String entityId) throws EntityIdNotFoundException { + private IdpCertData getSPIDCertData(String tag, String entityId) + throws EntityIdNotFoundException { CertData responseAssertion = null; responseAssertion = this.defaultApi.idpKeysSpidTagGet(tag); - return getEntityData(((EntitiesDescriptor) responseAssertion.getActualInstance()), tag, entityId); + return getEntityData( + ((EntitiesDescriptor) responseAssertion.getActualInstance()), tag, entityId); } - private List getCIETagList(String instant) throws TagListSearchOutOfBoundException, InvalidInstantFormatException { + private List getCIETagList(String instant) + throws TagListSearchOutOfBoundException, InvalidInstantFormatException { List responseAssertion; responseAssertion = this.defaultApi.idpKeysCieGet(); @@ -112,15 +129,18 @@ private List getCIETagList(String instant) throws TagListSearchOutOfBoun return getTagsFromInstant(responseAssertion, instant); } - private IdpCertData getCIECertData(String tag, String entityId) throws EntityIdNotFoundException { + private IdpCertData getCIECertData(String tag, String entityId) + throws EntityIdNotFoundException { CertData responseAssertion; responseAssertion = this.defaultApi.idpKeysCieTagGet(tag); - return getEntityData(((EntitiesDescriptor) responseAssertion.getActualInstance()), tag, entityId); + return getEntityData( + ((EntitiesDescriptor) responseAssertion.getActualInstance()), tag, entityId); } - private IdpCertData getEntityData(EntitiesDescriptor data, String tag, String entityId) throws EntityIdNotFoundException { + private IdpCertData getEntityData(EntitiesDescriptor data, String tag, String entityId) + throws EntityIdNotFoundException { IdpCertData newData = new IdpCertData(); for (EntityDescriptor entity : data.getEntityList()) { @@ -136,7 +156,8 @@ private IdpCertData getEntityData(EntitiesDescriptor data, String tag, String en throw new EntityIdNotFoundException("Cert for entityID " + entityId + " not found"); } - private List getTagsFromInstant(List tagList, String instant) throws TagListSearchOutOfBoundException, InvalidInstantFormatException { + private List getTagsFromInstant(List tagList, String instant) + throws TagListSearchOutOfBoundException, InvalidInstantFormatException { List newTagList = new ArrayList<>(); String latest = "latest"; long longInstant; @@ -144,7 +165,8 @@ private List getTagsFromInstant(List tagList, String instant) th try { longInstant = Long.parseLong(instant); } catch (Exception e) { - throw new InvalidInstantFormatException("The given insant " + instant + " is not a valid timestamp"); + throw new InvalidInstantFormatException( + "The given insant " + instant + " is not a valid timestamp"); } boolean latestRemoved = tagList.remove(latest); @@ -162,7 +184,8 @@ private List getTagsFromInstant(List tagList, String instant) th try { if (tagList.size() <= 2) { String firstTimestamp = tagList.get(0); - if (firstTimestamp.equals(latest) || Long.parseLong(firstTimestamp) <= longInstant) { + if (firstTimestamp.equals(latest) + || Long.parseLong(firstTimestamp) <= longInstant) { return tagList; } } @@ -181,7 +204,8 @@ private List getTagsFromInstant(List tagList, String instant) th index += 1; } } catch (Exception e) { - throw new TagListSearchOutOfBoundException("Error finding the tags relative to assertion instant " + instant); + throw new TagListSearchOutOfBoundException( + "Error finding the tags relative to assertion instant " + instant); } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java index 8f0f0eab..d744001b 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java @@ -1,15 +1,21 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple; +import java.util.List; import lombok.Builder; import lombok.Data; -import java.util.List; - @Data @Builder public class IdpCertSimpleClientConfig { @Builder.Default - private List cieEntityId = List.of("https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"); + private List cieEntityId = + List.of("https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"); + + @Builder.Default private String baseUri = "https://api.is.eng.pagopa.it"; + + @Builder.Default private String idpKeysCieEndpoint = "/idp-keys/cie"; + @Builder.Default private String idpKeysSpidEndpoint = "/idp-keys/spid"; } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java index 997c923a..6a292a71 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java @@ -4,17 +4,16 @@ import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; - import javax.inject.Inject; /** Provider class for retrieving an instance of {@link IdpCertSimpleClient} */ public class IdpCertSimpleClientProvider implements IdpCertClientProvider { - private final IdpCertSimpleClientConfig entityConfig; + private final IdpCertSimpleClientConfig idpClientConfig; @Inject - public IdpCertSimpleClientProvider(IdpCertSimpleClientConfig entityConfig){ - this.entityConfig = entityConfig; + public IdpCertSimpleClientProvider(IdpCertSimpleClientConfig config) { + this.idpClientConfig = config; } /** * Provide an instance of {@link IdpCertSimpleClient} @@ -23,6 +22,6 @@ public IdpCertSimpleClientProvider(IdpCertSimpleClientConfig entityConfig){ */ @Override public IdpCertClient provideClient() { - return new IdpCertSimpleClient(new ApiClient(), this.entityConfig); + return new IdpCertSimpleClient(new ApiClient(this.idpClientConfig), this.idpClientConfig); } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java index 5bd7a9d9..b1c57be6 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java @@ -1,472 +1,185 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import org.openapitools.jackson.nullable.JsonNullableModule; - +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; import java.io.InputStream; import java.net.URI; import java.net.URLEncoder; import java.net.http.HttpClient; -import java.net.http.HttpConnectTimeoutException; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; -import java.time.OffsetDateTime; -import java.time.format.DateTimeFormatter; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.StringJoiner; import java.util.function.Consumer; -import java.util.stream.Collectors; - -import static java.nio.charset.StandardCharsets.UTF_8; +import lombok.Getter; +import org.openapitools.jackson.nullable.JsonNullableModule; /** * Configuration and utility class for API clients. * - *

This class can be constructed and modified, then used to instantiate the - * various API classes. The API classes use the settings in this class to - * configure themselves, but otherwise do not store a link to this class.

+ *

This class can be constructed and modified, then used to instantiate the various API classes. + * The API classes use the settings in this class to configure themselves, but otherwise do not + * store a link to this class. * - *

This class is mutable and not synchronized, so it is not thread-safe. - * The API classes generated from this are immutable and thread-safe.

+ *

This class is mutable and not synchronized, so it is not thread-safe. The API classes + * generated from this are immutable and thread-safe. * - *

The setter methods of this class return the current object to facilitate - * a fluent style of configuration.

+ *

The setter methods of this class return the current object to facilitate a fluent style of + * configuration. */ -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +@Getter +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class ApiClient { - private HttpClient.Builder builder; - private ObjectMapper mapper; - private XmlMapper xmlMapper; - private String scheme; - private String host; - private int port; - private String basePath; - private Consumer interceptor; - private Consumer> responseInterceptor; - private Consumer> asyncResponseInterceptor; - private Duration readTimeout; - private Duration connectTimeout; - - private static String valueToString(Object value) { - if (value == null) { - return ""; - } - if (value instanceof OffsetDateTime) { - return ((OffsetDateTime) value).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + private HttpClient.Builder builder; + private ObjectMapper mapper; + private XmlMapper xmlMapper; + private String scheme; + private String host; + private int port; + private String basePath; + private Consumer interceptor; + private Consumer> responseInterceptor; + private Consumer> asyncResponseInterceptor; + private Duration readTimeout; + private Duration connectTimeout; + private String idpKeysCieEndpoint; + private String idpKeysSpidEndpoint; + + /** + * URL encode a string in the UTF-8 encoding. + * + * @param s String to encode. + * @return URL-encoded representation of the input string. + */ + public static String urlEncode(String s) { + return URLEncoder.encode(s, UTF_8).replaceAll("\\+", "%20"); } - return value.toString(); - } - - /** - * URL encode a string in the UTF-8 encoding. - * - * @param s String to encode. - * @return URL-encoded representation of the input string. - */ - public static String urlEncode(String s) { - return URLEncoder.encode(s, UTF_8).replaceAll("\\+", "%20"); - } - /** - * Convert a URL query name/value parameter to a list of encoded {@link Pair} - * objects. - * - *

The value can be null, in which case an empty list is returned.

- * - * @param name The query name parameter. - * @param value The query value, which may not be a collection but may be - * null. - * @return A singleton list of the {@link Pair} objects representing the input - * parameters, which is encoded for use in a URL. If the value is null, an - * empty list is returned. - */ - public static List parameterToPairs(String name, Object value) { - if (name == null || name.isEmpty() || value == null) { - return Collections.emptyList(); + /** Create an instance of ApiClient. */ + public ApiClient(IdpCertSimpleClientConfig config) { + this.builder = createDefaultHttpClientBuilder(); + this.mapper = createDefaultObjectMapper(); + this.xmlMapper = createDefaultXmlMapper(); + updateBaseUri(config.getBaseUri()); + interceptor = null; + readTimeout = null; + connectTimeout = null; + responseInterceptor = null; + asyncResponseInterceptor = null; + this.idpKeysCieEndpoint = config.getIdpKeysCieEndpoint(); + this.idpKeysSpidEndpoint = config.getIdpKeysSpidEndpoint(); } - return Collections.singletonList(new Pair(urlEncode(name), urlEncode(valueToString(value)))); - } - /** - * Convert a URL query name/collection parameter to a list of encoded - * {@link Pair} objects. - * - * @param collectionFormat The swagger collectionFormat string (csv, tsv, etc). - * @param name The query name parameter. - * @param values A collection of values for the given query name, which may be - * null. - * @return A list of {@link Pair} objects representing the input parameters, - * which is encoded for use in a URL. If the values collection is null, an - * empty list is returned. - */ - public static List parameterToPairs( - String collectionFormat, String name, Collection values) { - if (name == null || name.isEmpty() || values == null || values.isEmpty()) { - return Collections.emptyList(); + protected ObjectMapper createDefaultObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); + mapper.registerModule(new JavaTimeModule()); + mapper.registerModule(new JsonNullableModule()); + return mapper; } - // get the collection format (default: csv) - String format = collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat; - - // create the params based on the collection format - if ("multi".equals(format)) { - return values.stream() - .map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value)))) - .collect(Collectors.toList()); + protected XmlMapper createDefaultXmlMapper() { + XmlMapper mapper = new XmlMapper(); + return mapper; } - String delimiter; - switch(format) { - case "csv": - delimiter = urlEncode(","); - break; - case "ssv": - delimiter = urlEncode(" "); - break; - case "tsv": - delimiter = urlEncode("\t"); - break; - case "pipes": - delimiter = urlEncode("|"); - break; - default: - throw new IllegalArgumentException("Illegal collection format: " + collectionFormat); + protected HttpClient.Builder createDefaultHttpClientBuilder() { + return HttpClient.newBuilder(); } - StringJoiner joiner = new StringJoiner(delimiter); - for (Object value : values) { - joiner.add(urlEncode(valueToString(value))); + public void updateBaseUri(String baseUri) { + URI uri = URI.create(baseUri); + scheme = uri.getScheme(); + host = uri.getHost(); + port = uri.getPort(); + basePath = uri.getRawPath(); } - return Collections.singletonList(new Pair(urlEncode(name), joiner.toString())); - } - - /** - * Create an instance of ApiClient. - */ - public ApiClient() { - this.builder = createDefaultHttpClientBuilder(); - this.mapper = createDefaultObjectMapper(); - this.xmlMapper = createDefaultXmlMapper(); - updateBaseUri(getDefaultBaseUri()); - interceptor = null; - readTimeout = null; - connectTimeout = null; - responseInterceptor = null; - asyncResponseInterceptor = null; - } - - /** - * Create an instance of ApiClient. - * - * @param builder Http client builder. - * @param mapper Object mapper. - * @param baseUri Base URI - */ - public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, XmlMapper xmlMapper, String baseUri) { - this.builder = builder; - this.mapper = mapper; - this.xmlMapper = xmlMapper; - updateBaseUri(baseUri != null ? baseUri : getDefaultBaseUri()); - interceptor = null; - readTimeout = null; - connectTimeout = null; - responseInterceptor = null; - asyncResponseInterceptor = null; - } - - protected ObjectMapper createDefaultObjectMapper() { - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); - mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); - mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); - mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); - mapper.registerModule(new JavaTimeModule()); - mapper.registerModule(new JsonNullableModule()); - return mapper; - } - - protected XmlMapper createDefaultXmlMapper() { - XmlMapper mapper = new XmlMapper(); - return mapper; - } - - protected String getDefaultBaseUri() { - return "https://api.is.eng.pagopa.it"; - } - - protected HttpClient.Builder createDefaultHttpClientBuilder() { - return HttpClient.newBuilder(); - } - - public void updateBaseUri(String baseUri) { - URI uri = URI.create(baseUri); - scheme = uri.getScheme(); - host = uri.getHost(); - port = uri.getPort(); - basePath = uri.getRawPath(); - } - - /** - * Set a custom {@link HttpClient.Builder} object to use when creating the - * {@link HttpClient} that is used by the API client. - * - * @param builder Custom client builder. - * @return This object. - */ - public ApiClient setHttpClientBuilder(HttpClient.Builder builder) { - this.builder = builder; - return this; - } - - /** - * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}. - * - *

The returned object is immutable and thread-safe.

- * - * @return The HTTP client. - */ - public HttpClient getHttpClient() { - return builder.build(); - } - - /** - * Set a custom {@link ObjectMapper} to serialize and deserialize the request - * and response bodies. - * - * @param mapper Custom object mapper. - * @return This object. - */ - public ApiClient setObjectMapper(ObjectMapper mapper) { - this.mapper = mapper; - return this; - } - - /** - * Get a copy of the current {@link ObjectMapper}. - * - * @return A copy of the current object mapper. - */ - public ObjectMapper getObjectMapper() { - return mapper.copy(); - } - - public ApiClient setXmlMapper(XmlMapper mapper) { - this.xmlMapper = mapper; - return this; - } - - public XmlMapper getXmlMapper() { return xmlMapper.copy(); } - - /** - * Set a custom host name for the target service. - * - * @param host The host name of the target service. - * @return This object. - */ - public ApiClient setHost(String host) { - this.host = host; - return this; - } - - /** - * Set a custom port number for the target service. - * - * @param port The port of the target service. Set this to -1 to reset the - * value to the default for the scheme. - * @return This object. - */ - public ApiClient setPort(int port) { - this.port = port; - return this; - } - - /** - * Set a custom base path for the target service, for example '/v2'. - * - * @param basePath The base path against which the rest of the path is - * resolved. - * @return This object. - */ - public ApiClient setBasePath(String basePath) { - this.basePath = basePath; - return this; - } - - /** - * Get the base URI to resolve the endpoint paths against. - * - * @return The complete base URI that the rest of the API parameters are - * resolved against. - */ - public String getBaseUri() { - return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; - } - - /** - * Set a custom scheme for the target service, for example 'https'. - * - * @param scheme The scheme of the target service - * @return This object. - */ - public ApiClient setScheme(String scheme){ - this.scheme = scheme; - return this; - } - - /** - * Set a custom request interceptor. - * - *

A request interceptor is a mechanism for altering each request before it - * is sent. After the request has been fully configured but not yet built, the - * request builder is passed into this function for further modification, - * after which it is sent out.

- * - *

This is useful for altering the requests in a custom manner, such as - * adding headers. It could also be used for logging and monitoring.

- * - * @param interceptor A function invoked before creating each request. A value - * of null resets the interceptor to a no-op. - * @return This object. - */ - public ApiClient setRequestInterceptor(Consumer interceptor) { - this.interceptor = interceptor; - return this; - } - - /** - * Get the custom interceptor. - * - * @return The custom interceptor that was set, or null if there isn't any. - */ - public Consumer getRequestInterceptor() { - return interceptor; - } + /** + * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}. + * + *

The returned object is immutable and thread-safe. + * + * @return The HTTP client. + */ + public HttpClient getHttpClient() { + return builder.build(); + } - /** - * Set a custom response interceptor. - * - *

This is useful for logging, monitoring or extraction of header variables

- * - * @param interceptor A function invoked before creating each request. A value - * of null resets the interceptor to a no-op. - * @return This object. - */ - public ApiClient setResponseInterceptor(Consumer> interceptor) { - this.responseInterceptor = interceptor; - return this; - } + /** + * Get a copy of the current {@link ObjectMapper}. + * + * @return A copy of the current object mapper. + */ + public ObjectMapper getObjectMapper() { + return mapper.copy(); + } - /** - * Get the custom response interceptor. - * - * @return The custom interceptor that was set, or null if there isn't any. - */ - public Consumer> getResponseInterceptor() { - return responseInterceptor; - } + public ApiClient setXmlMapper(XmlMapper mapper) { + this.xmlMapper = mapper; + return this; + } - /** - * Set a custom async response interceptor. Use this interceptor when asyncNative is set to 'true'. - * - *

This is useful for logging, monitoring or extraction of header variables

- * - * @param interceptor A function invoked before creating each request. A value - * of null resets the interceptor to a no-op. - * @return This object. - */ - public ApiClient setAsyncResponseInterceptor(Consumer> interceptor) { - this.asyncResponseInterceptor = interceptor; - return this; - } + /** + * Get the base URI to resolve the endpoint paths against. + * + * @return The complete base URI that the rest of the API parameters are resolved against. + */ + public String getBaseUri() { + return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; + } - /** - * Get the custom async response interceptor. Use this interceptor when asyncNative is set to 'true'. - * - * @return The custom interceptor that was set, or null if there isn't any. - */ - public Consumer> getAsyncResponseInterceptor() { - return asyncResponseInterceptor; - } + /** + * Get the custom interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer getRequestInterceptor() { + return interceptor; + } - /** - * Set the read timeout for the http client. - * - *

This is the value used by default for each request, though it can be - * overridden on a per-request basis with a request interceptor.

- * - * @param readTimeout The read timeout used by default by the http client. - * Setting this value to null resets the timeout to an - * effectively infinite value. - * @return This object. - */ - public ApiClient setReadTimeout(Duration readTimeout) { - this.readTimeout = readTimeout; - return this; - } + /** + * Get the custom response interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getResponseInterceptor() { + return responseInterceptor; + } - /** - * Get the read timeout that was set. - * - * @return The read timeout, or null if no timeout was set. Null represents - * an infinite wait time. - */ - public Duration getReadTimeout() { - return readTimeout; - } - /** - * Sets the connect timeout (in milliseconds) for the http client. - * - *

In the case where a new connection needs to be established, if - * the connection cannot be established within the given {@code - * duration}, then {@link HttpClient#send(HttpRequest,BodyHandler) - * HttpClient::send} throws an {@link HttpConnectTimeoutException}, or - * {@link HttpClient#sendAsync(HttpRequest,BodyHandler) - * HttpClient::sendAsync} completes exceptionally with an - * {@code HttpConnectTimeoutException}. If a new connection does not - * need to be established, for example if a connection can be reused - * from a previous request, then this timeout duration has no effect. - * - * @param connectTimeout connection timeout in milliseconds - * - * @return This object. - */ - public ApiClient setConnectTimeout(Duration connectTimeout) { - this.connectTimeout = connectTimeout; - this.builder.connectTimeout(connectTimeout); - return this; - } + /** + * Get the custom async response interceptor. Use this interceptor when asyncNative is set to + * 'true'. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getAsyncResponseInterceptor() { + return asyncResponseInterceptor; + } - /** - * Get connection timeout (in milliseconds). - * - * @return Timeout in milliseconds - */ - public Duration getConnectTimeout() { - return connectTimeout; - } + /** + * Get the read timeout that was set. + * + * @return The read timeout, or null if no timeout was set. Null represents an infinite wait + * time. + */ + public Duration getReadTimeout() { + return readTimeout; + } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java index b4f92de1..701b2acf 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java @@ -1,21 +1,11 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; import java.net.http.HttpHeaders; -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class ApiException extends RuntimeException { private int code = 0; private HttpHeaders responseHeaders = null; @@ -31,18 +21,25 @@ public ApiException(String message) { super(message); } - public ApiException(String message, Throwable throwable, int code, HttpHeaders responseHeaders, String responseBody) { + public ApiException( + String message, + Throwable throwable, + int code, + HttpHeaders responseHeaders, + String responseBody) { super(message, throwable); this.code = code; this.responseHeaders = responseHeaders; this.responseBody = responseBody; } - public ApiException(String message, int code, HttpHeaders responseHeaders, String responseBody) { + public ApiException( + String message, int code, HttpHeaders responseHeaders, String responseBody) { this(message, (Throwable) null, code, responseHeaders, responseBody); } - public ApiException(String message, Throwable throwable, int code, HttpHeaders responseHeaders) { + public ApiException( + String message, Throwable throwable, int code, HttpHeaders responseHeaders) { this(message, throwable, code, responseHeaders, null); } @@ -55,7 +52,8 @@ public ApiException(int code, String message) { this.code = code; } - public ApiException(int code, String message, HttpHeaders responseHeaders, String responseBody) { + public ApiException( + int code, String message, HttpHeaders responseHeaders, String responseBody) { this(code, message); this.responseHeaders = responseHeaders; this.responseBody = responseBody; diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java index 04d5fc8c..582e0a4d 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java @@ -1,16 +1,4 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; import java.util.List; @@ -22,9 +10,9 @@ * @param The type of data that is deserialized from response body */ public class ApiResponse { - final private int statusCode; - final private Map> headers; - final private T data; + private final int statusCode; + private final Map> headers; + private final T data; /** * @param statusCode The status code of HTTP response diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java index b8ece665..6bf55bac 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java @@ -1,15 +1,4 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.api; import com.fasterxml.jackson.core.type.TypeReference; @@ -19,329 +8,335 @@ import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiResponse; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.CertData; - -import java.io.InputStream; import java.io.IOException; -import java.net.http.HttpRequest; +import java.io.InputStream; import java.net.URI; import java.net.http.HttpClient; +import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; - import java.util.List; import java.util.function.Consumer; -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class DefaultApi { - private final HttpClient memberVarHttpClient; - private final ObjectMapper memberVarObjectMapper; - private final XmlMapper memberVarXMLMapper; - private final String memberVarBaseUri; - private final Consumer memberVarInterceptor; - private final Duration memberVarReadTimeout; - private final Consumer> memberVarResponseInterceptor; - private final Consumer> memberVarAsyncResponseInterceptor; - - public DefaultApi() { - this(new ApiClient()); - } - - public DefaultApi(ApiClient apiClient) { - memberVarHttpClient = apiClient.getHttpClient(); - memberVarObjectMapper = apiClient.getObjectMapper(); - memberVarXMLMapper = apiClient.getXmlMapper(); - memberVarBaseUri = apiClient.getBaseUri(); - memberVarInterceptor = apiClient.getRequestInterceptor(); - memberVarReadTimeout = apiClient.getReadTimeout(); - memberVarResponseInterceptor = apiClient.getResponseInterceptor(); - memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); - } - - protected ApiException getApiException(String operationId, HttpResponse response) throws IOException { - String body = response.body() == null ? null : new String(response.body().readAllBytes()); - String message = formatExceptionMessage(operationId, response.statusCode(), body); - return new ApiException(response.statusCode(), message, response.headers(), body); - } - - private String formatExceptionMessage(String operationId, int statusCode, String body) { - if (body == null || body.isEmpty()) { - body = "[no body]"; + private final HttpClient memberVarHttpClient; + private final ObjectMapper memberVarObjectMapper; + private final XmlMapper memberVarXMLMapper; + private final String memberVarBaseUri; + private final Consumer memberVarInterceptor; + private final Duration memberVarReadTimeout; + private final Consumer> memberVarResponseInterceptor; + private final Consumer> memberVarAsyncResponseInterceptor; + private final String memberIdpKeysCieEndpoint; + private final String memberIdpKeysSpidEndpoint; + + public DefaultApi(ApiClient apiClient) { + memberVarHttpClient = apiClient.getHttpClient(); + memberVarObjectMapper = apiClient.getObjectMapper(); + memberVarXMLMapper = apiClient.getXmlMapper(); + memberVarBaseUri = apiClient.getBaseUri(); + memberVarInterceptor = apiClient.getRequestInterceptor(); + memberVarReadTimeout = apiClient.getReadTimeout(); + memberVarResponseInterceptor = apiClient.getResponseInterceptor(); + memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); + memberIdpKeysCieEndpoint = apiClient.getIdpKeysCieEndpoint(); + memberIdpKeysSpidEndpoint = apiClient.getIdpKeysSpidEndpoint(); + } + + protected ApiException getApiException(String operationId, HttpResponse response) + throws IOException { + String body = response.body() == null ? null : new String(response.body().readAllBytes()); + String message = formatExceptionMessage(operationId, response.statusCode(), body); + return new ApiException(response.statusCode(), message, response.headers(), body); } - return operationId + " call failed with: " + statusCode + " - " + body; - } - - /** - * - * - * @return List<String> - * @throws ApiException if fails to make API call - */ - public List idpKeysCieGet() throws ApiException { - ApiResponse> localVarResponse = idpKeysCieGetWithHttpInfo(); - return localVarResponse.getData(); - } - - /** - * - * - * @return ApiResponse<List<String>> - * @throws ApiException if fails to make API call - */ - public ApiResponse> idpKeysCieGetWithHttpInfo() throws ApiException { - HttpRequest.Builder localVarRequestBuilder = idpKeysCieGetRequestBuilder(); - try { - HttpResponse localVarResponse = memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - try { - if (localVarResponse.statusCode()/ 100 != 2) { - throw getApiException("idpKeysCieGet", localVarResponse); + + private String formatExceptionMessage(String operationId, int statusCode, String body) { + if (body == null || body.isEmpty()) { + body = "[no body]"; } - return new ApiResponse>( - localVarResponse.statusCode(), - localVarResponse.headers().map(), - localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference>() {}) // closes the InputStream - ); - } finally { - } - } catch (IOException e) { - throw new ApiException(e); + return operationId + " call failed with: " + statusCode + " - " + body; } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); + + /** + * @return List<String> + * @throws ApiException if fails to make API call + */ + public List idpKeysCieGet() throws ApiException { + ApiResponse> localVarResponse = idpKeysCieGetWithHttpInfo(); + return localVarResponse.getData(); } - } - private HttpRequest.Builder idpKeysCieGetRequestBuilder() throws ApiException { + /** + * @return ApiResponse<List<String>> + * @throws ApiException if fails to make API call + */ + public ApiResponse> idpKeysCieGetWithHttpInfo() throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysCieGetRequestBuilder(); + try { + HttpResponse localVarResponse = + memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode() / 100 != 2) { + throw getApiException("idpKeysCieGet", localVarResponse); + } + return new ApiResponse>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null + ? null + : memberVarObjectMapper.readValue( + localVarResponse.body(), + new TypeReference< + List>() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } - HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + private HttpRequest.Builder idpKeysCieGetRequestBuilder() throws ApiException { - String localVarPath = "/idp-keys/cie"; + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); - localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + memberIdpKeysCieEndpoint)); - localVarRequestBuilder.header("Accept", "application/json"); + localVarRequestBuilder.header("Accept", "application/json"); - localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); - } - return localVarRequestBuilder; - } - /** - * - * - * @param tag (required) - * @return CertData - * @throws ApiException if fails to make API call - */ - public CertData idpKeysCieTagGet(String tag) throws ApiException { - ApiResponse localVarResponse = idpKeysCieTagGetWithHttpInfo(tag); - return localVarResponse.getData(); - } - - /** - * - * - * @param tag (required) - * @return ApiResponse<CertData> - * @throws ApiException if fails to make API call - */ - public ApiResponse idpKeysCieTagGetWithHttpInfo(String tag) throws ApiException { - HttpRequest.Builder localVarRequestBuilder = idpKeysCieTagGetRequestBuilder(tag); - try { - HttpResponse localVarResponse = memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - try { - if (localVarResponse.statusCode()/ 100 != 2) { - throw getApiException("idpKeysCieTagGet", localVarResponse); + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); } - return new ApiResponse( - localVarResponse.statusCode(), - localVarResponse.headers().map(), - localVarResponse.body() == null ? null : memberVarXMLMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream - ); - } finally { - } - } catch (IOException e) { - throw new ApiException(e); + return localVarRequestBuilder; } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); + + /** + * @param tag (required) + * @return CertData + * @throws ApiException if fails to make API call + */ + public CertData idpKeysCieTagGet(String tag) throws ApiException { + ApiResponse localVarResponse = idpKeysCieTagGetWithHttpInfo(tag); + return localVarResponse.getData(); } - } - private HttpRequest.Builder idpKeysCieTagGetRequestBuilder(String tag) throws ApiException { - // verify the required parameter 'tag' is set - if (tag == null) { - throw new ApiException(400, "Missing the required parameter 'tag' when calling idpKeysCieTagGet"); + /** + * @param tag (required) + * @return ApiResponse<CertData> + * @throws ApiException if fails to make API call + */ + public ApiResponse idpKeysCieTagGetWithHttpInfo(String tag) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysCieTagGetRequestBuilder(tag); + try { + HttpResponse localVarResponse = + memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode() / 100 != 2) { + throw getApiException("idpKeysCieTagGet", localVarResponse); + } + return new ApiResponse( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null + ? null + : memberVarXMLMapper.readValue( + localVarResponse.body(), + new TypeReference() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } } - HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + private HttpRequest.Builder idpKeysCieTagGetRequestBuilder(String tag) throws ApiException { + // verify the required parameter 'tag' is set + if (tag == null) { + throw new ApiException( + 400, "Missing the required parameter 'tag' when calling idpKeysCieTagGet"); + } - String localVarPath = "/idp-keys/cie/{tag}" - .replace("{tag}", ApiClient.urlEncode(tag.toString())); + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); - localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + String localVarPath = + memberIdpKeysCieEndpoint + + "/{tag}".replace("{tag}", ApiClient.urlEncode(tag.toString())); - localVarRequestBuilder.header("Accept", "application/xml, application/json"); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); - localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); - } - return localVarRequestBuilder; - } - /** - * - * - * @return List<String> - * @throws ApiException if fails to make API call - */ - public List idpKeysSpidGet() throws ApiException { - ApiResponse> localVarResponse = idpKeysSpidGetWithHttpInfo(); - return localVarResponse.getData(); - } - - /** - * - * - * @return ApiResponse<List<String>> - * @throws ApiException if fails to make API call - */ - public ApiResponse> idpKeysSpidGetWithHttpInfo() throws ApiException { - HttpRequest.Builder localVarRequestBuilder = idpKeysSpidGetRequestBuilder(); - try { - HttpResponse localVarResponse = memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - try { - if (localVarResponse.statusCode()/ 100 != 2) { - throw getApiException("idpKeysSpidGet", localVarResponse); + localVarRequestBuilder.header("Accept", "application/xml, application/json"); + + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); } - return new ApiResponse>( - localVarResponse.statusCode(), - localVarResponse.headers().map(), - localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference>() {}) // closes the InputStream - ); - } finally { - } - } catch (IOException e) { - throw new ApiException(e); + return localVarRequestBuilder; } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); + + /** + * @return List<String> + * @throws ApiException if fails to make API call + */ + public List idpKeysSpidGet() throws ApiException { + ApiResponse> localVarResponse = idpKeysSpidGetWithHttpInfo(); + return localVarResponse.getData(); } - } - private HttpRequest.Builder idpKeysSpidGetRequestBuilder() throws ApiException { + /** + * @return ApiResponse<List<String>> + * @throws ApiException if fails to make API call + */ + public ApiResponse> idpKeysSpidGetWithHttpInfo() throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysSpidGetRequestBuilder(); + try { + HttpResponse localVarResponse = + memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode() / 100 != 2) { + throw getApiException("idpKeysSpidGet", localVarResponse); + } + return new ApiResponse>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null + ? null + : memberVarObjectMapper.readValue( + localVarResponse.body(), + new TypeReference< + List>() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } - HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + private HttpRequest.Builder idpKeysSpidGetRequestBuilder() throws ApiException { - String localVarPath = "/idp-keys/spid"; + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); - localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + memberIdpKeysSpidEndpoint)); - localVarRequestBuilder.header("Accept", "application/json"); + localVarRequestBuilder.header("Accept", "application/json"); - localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); - } - return localVarRequestBuilder; - } - /** - * - * - * @param tag (required) - * @return CertData - * @throws ApiException if fails to make API call - */ - public CertData idpKeysSpidTagGet(String tag) throws ApiException { - ApiResponse localVarResponse = idpKeysSpidTagGetWithHttpInfo(tag); - return localVarResponse.getData(); - } - - /** - * - * - * @param tag (required) - * @return ApiResponse<CertData> - * @throws ApiException if fails to make API call - */ - public ApiResponse idpKeysSpidTagGetWithHttpInfo(String tag) throws ApiException { - HttpRequest.Builder localVarRequestBuilder = idpKeysSpidTagGetRequestBuilder(tag); - try { - HttpResponse localVarResponse = memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - try { - if (localVarResponse.statusCode()/ 100 != 2) { - throw getApiException("idpKeysSpidTagGet", localVarResponse); + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); } - return new ApiResponse( - localVarResponse.statusCode(), - localVarResponse.headers().map(), - localVarResponse.body() == null ? null : memberVarXMLMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream - ); - } finally { - } - } catch (IOException e) { - throw new ApiException(e); + return localVarRequestBuilder; } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); + + /** + * @param tag (required) + * @return CertData + * @throws ApiException if fails to make API call + */ + public CertData idpKeysSpidTagGet(String tag) throws ApiException { + ApiResponse localVarResponse = idpKeysSpidTagGetWithHttpInfo(tag); + return localVarResponse.getData(); } - } - private HttpRequest.Builder idpKeysSpidTagGetRequestBuilder(String tag) throws ApiException { - // verify the required parameter 'tag' is set - if (tag == null) { - throw new ApiException(400, "Missing the required parameter 'tag' when calling idpKeysSpidTagGet"); + /** + * @param tag (required) + * @return ApiResponse<CertData> + * @throws ApiException if fails to make API call + */ + public ApiResponse idpKeysSpidTagGetWithHttpInfo(String tag) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysSpidTagGetRequestBuilder(tag); + try { + HttpResponse localVarResponse = + memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode() / 100 != 2) { + throw getApiException("idpKeysSpidTagGet", localVarResponse); + } + return new ApiResponse( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null + ? null + : memberVarXMLMapper.readValue( + localVarResponse.body(), + new TypeReference() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } } - HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + private HttpRequest.Builder idpKeysSpidTagGetRequestBuilder(String tag) throws ApiException { + // verify the required parameter 'tag' is set + if (tag == null) { + throw new ApiException( + 400, "Missing the required parameter 'tag' when calling idpKeysSpidTagGet"); + } - String localVarPath = "/idp-keys/spid/{tag}" - .replace("{tag}", ApiClient.urlEncode(tag.toString())); + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); - localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + String localVarPath = + memberIdpKeysSpidEndpoint + + "/{tag}".replace("{tag}", ApiClient.urlEncode(tag.toString())); - localVarRequestBuilder.header("Accept", "application/xml, application/json"); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); - localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + localVarRequestBuilder.header("Accept", "application/xml, application/json"); + + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; } - return localVarRequestBuilder; - } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java index 688511a7..698fe790 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java @@ -1,28 +1,14 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; -import java.util.Objects; -import java.lang.reflect.Type; -import java.util.Map; - import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Map; +import java.util.Objects; -/** - * Abstract class for oneOf,anyOf schemas defined in OpenAPI spec - */ -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +/** Abstract class for oneOf,anyOf schemas defined in OpenAPI spec */ +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public abstract class AbstractOpenApiSchema { // store the actual instance of the schema/object @@ -52,17 +38,22 @@ public AbstractOpenApiSchema(String schemaType, Boolean isNullable) { * @return an instance of the actual schema/object */ @JsonValue - public Object getActualInstance() {return instance;} + public Object getActualInstance() { + return instance; + } /** * Set the actual instance * * @param instance the actual instance of the schema/object */ - public void setActualInstance(Object instance) {this.instance = instance;} + public void setActualInstance(Object instance) { + this.instance = instance; + } /** - * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf schema as well + * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf + * schema as well * * @return an instance of the actual schema/object */ @@ -74,7 +65,7 @@ private Object getActualInstanceRecursively(AbstractOpenApiSchema object) { if (object.getActualInstance() == null) { return null; } else if (object.getActualInstance() instanceof AbstractOpenApiSchema) { - return getActualInstanceRecursively((AbstractOpenApiSchema)object.getActualInstance()); + return getActualInstanceRecursively((AbstractOpenApiSchema) object.getActualInstance()); } else { return object.getActualInstance(); } @@ -101,8 +92,8 @@ public String toString() { } /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). + * Convert the given object to string with each line indented by 4 spaces (except the first + * line). */ private String toIndentedString(Object o) { if (o == null) { @@ -119,9 +110,9 @@ public boolean equals(Object o) { return false; } AbstractOpenApiSchema a = (AbstractOpenApiSchema) o; - return Objects.equals(this.instance, a.instance) && - Objects.equals(this.isNullable, a.isNullable) && - Objects.equals(this.schemaType, a.schemaType); + return Objects.equals(this.instance, a.instance) + && Objects.equals(this.isNullable, a.isNullable) + && Objects.equals(this.schemaType, a.schemaType); } @Override @@ -141,7 +132,4 @@ public Boolean isNullable() { return Boolean.FALSE; } } - - - } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java index ace38068..3ff33c7c 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java @@ -1,24 +1,6 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; -import java.util.*; - -import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; - import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; @@ -32,11 +14,16 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.ser.std.StdSerializer; -import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.JSON; +import java.io.IOException; +import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; import lombok.Getter; import lombok.Setter; -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") @JsonDeserialize(using = CertData.CertDataDeserializer.class) @JsonSerialize(using = CertData.CertDataSerializer.class) @Getter @@ -54,7 +41,8 @@ public CertDataSerializer() { } @Override - public void serialize(CertData value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + public void serialize(CertData value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException { jgen.writeObject(value.getActualInstance()); } } @@ -69,7 +57,8 @@ public CertDataDeserializer(Class vc) { } @Override - public CertData deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + public CertData deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException { JsonNode tree = jp.readValueAsTree(); Object deserialized = null; boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS); @@ -82,24 +71,30 @@ public CertData deserialize(JsonParser jp, DeserializationContext ctxt) throws I deserialized = tree.traverse(jp.getCodec()).readValueAs(EntityDescriptor.class); if (((EntityDescriptor) deserialized).getEntityID() != null) { - List entityList = Arrays.asList(((EntityDescriptor)deserialized)); + List entityList = + Arrays.asList(((EntityDescriptor) deserialized)); entitiesDescriptor.setEntityList(entityList); log.log(Level.FINER, "Input data matches schema 'EntityDescriptor'"); match++; } else { - try{ - deserialized = tree.traverse(jp.getCodec()).readValueAs(EntitiesDescriptor.class); + try { + deserialized = + tree.traverse(jp.getCodec()).readValueAs(EntitiesDescriptor.class); if (((EntitiesDescriptor) deserialized).getEntityList() != null) { - entitiesDescriptor.setEntityList(((EntitiesDescriptor) deserialized).getEntityList()); + entitiesDescriptor.setEntityList( + ((EntitiesDescriptor) deserialized).getEntityList()); log.log(Level.FINER, "Input data matches schema 'Entities Descriptor'"); match++; } - } catch (Exception e){ + } catch (Exception e) { // deserialization failed, continue - log.log(Level.FINER, "Input data does not match schema 'Entities Descriptor'", e); + log.log( + Level.FINER, + "Input data does not match schema 'Entities Descriptor'", + e); } } } catch (Exception e) { @@ -112,12 +107,14 @@ public CertData deserialize(JsonParser jp, DeserializationContext ctxt) throws I ret.setActualInstance(entitiesDescriptor); return ret; } - throw new IOException(String.format("Failed deserialization for CertData: %d classes match result, expected 1", match)); + throw new IOException( + String.format( + "Failed deserialization for CertData: %d classes match result, expected" + + " 1", + match)); } - /** - * Handle deserialization of the 'null' value. - */ + /** Handle deserialization of the 'null' value. */ @Override public CertData getNullValue(DeserializationContext ctxt) throws JsonMappingException { throw new JsonMappingException(ctxt.getParser(), "CertData cannot be null"); @@ -135,6 +132,4 @@ public CertData() { public Map> getSchemas() { return CertData.schemas; } - } - diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java index 9e5ace68..54e95d5b 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java @@ -1,35 +1,18 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; import lombok.Getter; import lombok.Setter; -import java.util.List; - -/** - * EntitiesDescriptor - */ +/** EntitiesDescriptor */ @JsonIgnoreProperties(ignoreUnknown = true) @Getter @Setter public class EntitiesDescriptor { - @JsonProperty("EntityDescriptor") - private List entityList; - + @JsonProperty("EntityDescriptor") + private List entityList; } - diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java index 6b602241..81788328 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java @@ -1,27 +1,12 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Getter; - import java.util.Map; +import lombok.Getter; - -/** - * EntityDescriptor - */ +/** EntityDescriptor */ @JsonIgnoreProperties(ignoreUnknown = true) @Getter public class EntityDescriptor { @@ -37,6 +22,4 @@ private void unpackNestedSignature(Map signature) { Map x509Data = (Map) keyInfo.get("X509Data"); this.signature = (String) x509Data.get("X509Certificate"); } - } - diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/ProblemJson.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/ProblemJson.java index 7fcc4f37..6ca6fd6b 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/ProblemJson.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/ProblemJson.java @@ -1,292 +1,291 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; - import java.net.URI; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Objects; import java.util.StringJoiner; - -/** - * ProblemJson - */ +/** ProblemJson */ @JsonPropertyOrder({ - ProblemJson.JSON_PROPERTY_TYPE, - ProblemJson.JSON_PROPERTY_TITLE, - ProblemJson.JSON_PROPERTY_STATUS, - ProblemJson.JSON_PROPERTY_DETAIL, - ProblemJson.JSON_PROPERTY_INSTANCE + ProblemJson.JSON_PROPERTY_TYPE, + ProblemJson.JSON_PROPERTY_TITLE, + ProblemJson.JSON_PROPERTY_STATUS, + ProblemJson.JSON_PROPERTY_DETAIL, + ProblemJson.JSON_PROPERTY_INSTANCE }) -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class ProblemJson { - public static final String JSON_PROPERTY_TYPE = "type"; - private URI type = URI.create("about:blank"); + public static final String JSON_PROPERTY_TYPE = "type"; + private URI type = URI.create("about:blank"); + + public static final String JSON_PROPERTY_TITLE = "title"; + private String title; - public static final String JSON_PROPERTY_TITLE = "title"; - private String title; - - public static final String JSON_PROPERTY_STATUS = "status"; - private Integer status; - - public static final String JSON_PROPERTY_DETAIL = "detail"; - private String detail; - - public static final String JSON_PROPERTY_INSTANCE = "instance"; - private URI instance; + public static final String JSON_PROPERTY_STATUS = "status"; + private Integer status; - public ProblemJson() { - } - - public ProblemJson type(URI type) { - this.type = type; - return this; - } + public static final String JSON_PROPERTY_DETAIL = "detail"; + private String detail; - /** - * An absolute URI that identifies the problem type. When dereferenced, it SHOULD provide human-readable documentation for the problem type (e.g., using HTML). - * @return type - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_TYPE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public URI getType() { - return type; - } - - - @JsonProperty(JSON_PROPERTY_TYPE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setType(URI type) { - this.type = type; - } - - - public ProblemJson title(String title) { - this.title = title; - return this; - } - - /** - * A short, summary of the problem type. Written in english and readable for engineers (usually not suited for non technical stakeholders and not localized); example: Service Unavailable - * @return title - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_TITLE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public String getTitle() { - return title; - } - - - @JsonProperty(JSON_PROPERTY_TITLE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setTitle(String title) { - this.title = title; - } - - - public ProblemJson status(Integer status) { - this.status = status; - return this; - } - - /** - * The HTTP status code generated by the origin server for this occurrence of the problem. - * minimum: 100 - * maximum: 600 - * @return status - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_STATUS) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public Integer getStatus() { - return status; - } - - - @JsonProperty(JSON_PROPERTY_STATUS) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setStatus(Integer status) { - this.status = status; - } - - - public ProblemJson detail(String detail) { - this.detail = detail; - return this; - } - - /** - * A human readable explanation specific to this occurrence of the problem. - * @return detail - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_DETAIL) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public String getDetail() { - return detail; - } - - - @JsonProperty(JSON_PROPERTY_DETAIL) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setDetail(String detail) { - this.detail = detail; - } - - - public ProblemJson instance(URI instance) { - this.instance = instance; - return this; - } - - /** - * An absolute URI that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced. - * @return instance - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_INSTANCE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public URI getInstance() { - return instance; - } - - - @JsonProperty(JSON_PROPERTY_INSTANCE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setInstance(URI instance) { - this.instance = instance; - } - - - /** - * Return true if this ProblemJson object is equal to o. - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public static final String JSON_PROPERTY_INSTANCE = "instance"; + private URI instance; + + public ProblemJson() {} + + public ProblemJson type(URI type) { + this.type = type; + return this; } - if (o == null || getClass() != o.getClass()) { - return false; + + /** + * An absolute URI that identifies the problem type. When dereferenced, it SHOULD provide + * human-readable documentation for the problem type (e.g., using HTML). + * + * @return type + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public URI getType() { + return type; } - ProblemJson problemJson = (ProblemJson) o; - return Objects.equals(this.type, problemJson.type) && - Objects.equals(this.title, problemJson.title) && - Objects.equals(this.status, problemJson.status) && - Objects.equals(this.detail, problemJson.detail) && - Objects.equals(this.instance, problemJson.instance); - } - - @Override - public int hashCode() { - return Objects.hash(type, title, status, detail, instance); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class ProblemJson {\n"); - sb.append(" type: ").append(toIndentedString(type)).append("\n"); - sb.append(" title: ").append(toIndentedString(title)).append("\n"); - sb.append(" status: ").append(toIndentedString(status)).append("\n"); - sb.append(" detail: ").append(toIndentedString(detail)).append("\n"); - sb.append(" instance: ").append(toIndentedString(instance)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; + + @JsonProperty(JSON_PROPERTY_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setType(URI type) { + this.type = type; } - return o.toString().replace("\n", "\n "); - } - - /** - * Convert the instance into URL query string. - * - * @return URL query string - */ - public String toUrlQueryString() { - return toUrlQueryString(null); - } - - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - String suffix = ""; - String containerSuffix = ""; - String containerPrefix = ""; - if (prefix == null) { - // style=form, explode=true, e.g. /pet?name=cat&type=manx - prefix = ""; - } else { - // deepObject style e.g. /pet?id[name]=cat&id[type]=manx - prefix = prefix + "["; - suffix = "]"; - containerSuffix = "]"; - containerPrefix = "["; + + public ProblemJson title(String title) { + this.title = title; + return this; } - StringJoiner joiner = new StringJoiner("&"); + /** + * A short, summary of the problem type. Written in english and readable for engineers (usually + * not suited for non technical stakeholders and not localized); example: Service Unavailable + * + * @return title + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_TITLE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public String getTitle() { + return title; + } - // add `type` to the URL query string - if (getType() != null) { - joiner.add(String.format("%stype%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getType()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + @JsonProperty(JSON_PROPERTY_TITLE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setTitle(String title) { + this.title = title; } - // add `title` to the URL query string - if (getTitle() != null) { - joiner.add(String.format("%stitle%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getTitle()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + public ProblemJson status(Integer status) { + this.status = status; + return this; } - // add `status` to the URL query string - if (getStatus() != null) { - joiner.add(String.format("%sstatus%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getStatus()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + /** + * The HTTP status code generated by the origin server for this occurrence of the problem. + * minimum: 100 maximum: 600 + * + * @return status + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public Integer getStatus() { + return status; } - // add `detail` to the URL query string - if (getDetail() != null) { - joiner.add(String.format("%sdetail%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getDetail()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + @JsonProperty(JSON_PROPERTY_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setStatus(Integer status) { + this.status = status; } - // add `instance` to the URL query string - if (getInstance() != null) { - joiner.add(String.format("%sinstance%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getInstance()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + public ProblemJson detail(String detail) { + this.detail = detail; + return this; } - return joiner.toString(); - } -} + /** + * A human readable explanation specific to this occurrence of the problem. + * + * @return detail + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_DETAIL) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public String getDetail() { + return detail; + } + + @JsonProperty(JSON_PROPERTY_DETAIL) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setDetail(String detail) { + this.detail = detail; + } + + public ProblemJson instance(URI instance) { + this.instance = instance; + return this; + } + /** + * An absolute URI that identifies the specific occurrence of the problem. It may or may not + * yield further information if dereferenced. + * + * @return instance + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_INSTANCE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public URI getInstance() { + return instance; + } + + @JsonProperty(JSON_PROPERTY_INSTANCE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setInstance(URI instance) { + this.instance = instance; + } + + /** Return true if this ProblemJson object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProblemJson problemJson = (ProblemJson) o; + return Objects.equals(this.type, problemJson.type) + && Objects.equals(this.title, problemJson.title) + && Objects.equals(this.status, problemJson.status) + && Objects.equals(this.detail, problemJson.detail) + && Objects.equals(this.instance, problemJson.instance); + } + + @Override + public int hashCode() { + return Objects.hash(type, title, status, detail, instance); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ProblemJson {\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append(" title: ").append(toIndentedString(title)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" detail: ").append(toIndentedString(detail)).append("\n"); + sb.append(" instance: ").append(toIndentedString(instance)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first + * line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `type` to the URL query string + if (getType() != null) { + joiner.add( + String.format( + "%stype%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getType()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `title` to the URL query string + if (getTitle() != null) { + joiner.add( + String.format( + "%stitle%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getTitle()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `status` to the URL query string + if (getStatus() != null) { + joiner.add( + String.format( + "%sstatus%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getStatus()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `detail` to the URL query string + if (getDetail() != null) { + joiner.add( + String.format( + "%sdetail%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getDetail()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `instance` to the URL query string + if (getInstance() != null) { + joiner.add( + String.format( + "%sinstance%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getInstance()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} diff --git a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java index 866f7d24..20a12462 100644 --- a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java @@ -1,20 +1,19 @@ +/* (C)2023 */ package simple; - import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import java.time.Instant; +import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.mockito.Mockito; -import java.time.Instant; -import java.util.List; - class IdpCertSimpleClientTest { private static IdpCertSimpleClient idpCertSimpleClient; @@ -22,15 +21,16 @@ class IdpCertSimpleClientTest { private static final String INSTANT = String.valueOf(Instant.now().getEpochSecond()); private static final String SPID_ENTITY_ID = "https://posteid.poste.it"; - private static final String CIE_ENTITY_ID = "https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"; + private static final String CIE_ENTITY_ID = + "https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"; private static final String WRONG_ENTITY_ID = "https://wrongEntityID.it"; private static final String WRONG_INSTANT = "xxxxxx"; @BeforeAll public static void startServer() { - ApiClient client = new ApiClient(); entityConfig = Mockito.spy(IdpCertSimpleClientConfig.builder().build()); + ApiClient client = new ApiClient(entityConfig); idpCertSimpleClient = new IdpCertSimpleClient(client, entityConfig); } @@ -49,18 +49,23 @@ void certCIEDataFound() throws CertDataTagListNotFoundException, CertDataNotFoun } @Test - void getCertDataWrongEntityID() throws CertDataTagListNotFoundException, CertDataNotFoundException { - Assertions.assertThrows(CertDataNotFoundException.class, () -> idpCertSimpleClient.getCertData(WRONG_ENTITY_ID, INSTANT)); + void getCertDataWrongEntityID() { + Assertions.assertThrows( + CertDataNotFoundException.class, + () -> idpCertSimpleClient.getCertData(WRONG_ENTITY_ID, INSTANT)); } @Test - void getSPIDCertDataWrongInstant() throws CertDataTagListNotFoundException, CertDataNotFoundException { - Assertions.assertThrows(CertDataTagListNotFoundException.class, () -> idpCertSimpleClient.getCertData(SPID_ENTITY_ID, WRONG_INSTANT)); + void getSPIDCertDataWrongInstant() { + Assertions.assertThrows( + CertDataTagListNotFoundException.class, + () -> idpCertSimpleClient.getCertData(SPID_ENTITY_ID, WRONG_INSTANT)); } @Test - void getCIECertDataWrongInstant() throws CertDataTagListNotFoundException, CertDataNotFoundException { - Assertions.assertThrows(CertDataTagListNotFoundException.class, () -> idpCertSimpleClient.getCertData(CIE_ENTITY_ID, WRONG_INSTANT)); + void getCIECertDataWrongInstant() { + Assertions.assertThrows( + CertDataTagListNotFoundException.class, + () -> idpCertSimpleClient.getCertData(CIE_ENTITY_ID, WRONG_INSTANT)); } - -} \ No newline at end of file +} From d7c7239366d1a1c8429e233530400999eea0a9e4 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 16:58:14 +0200 Subject: [PATCH 127/403] [SLS-19] Removed unused classes --- .../client/simple/internal/Configuration.java | 39 --- .../idp/client/simple/internal/JSON.java | 247 ------------------ .../idp/client/simple/internal/Pair.java | 57 ---- .../simple/internal/RFC3339DateFormat.java | 57 ---- .../simple/internal/ServerConfiguration.java | 58 ---- .../simple/internal/ServerVariable.java | 23 -- 6 files changed, 481 deletions(-) delete mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java delete mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java delete mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java delete mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java delete mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java delete mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java deleted file mode 100644 index 44af4652..00000000 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; - -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") -public class Configuration { - private static ApiClient defaultApiClient = new ApiClient(); - - /** - * Get the default API client, which would be used when creating API - * instances without providing an API client. - * - * @return Default API client - */ - public static ApiClient getDefaultApiClient() { - return defaultApiClient; - } - - /** - * Set the default API client, which would be used when creating API - * instances without providing an API client. - * - * @param apiClient API client - */ - public static void setDefaultApiClient(ApiClient apiClient) { - defaultApiClient = apiClient; - } -} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java deleted file mode 100644 index fc1b5610..00000000 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java +++ /dev/null @@ -1,247 +0,0 @@ -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.*; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import org.openapitools.jackson.nullable.JsonNullableModule; - -import java.text.DateFormat; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") -public class JSON { - private ObjectMapper mapper; - - public JSON() { - mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); - mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); - mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); - mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); - mapper.setDateFormat(new RFC3339DateFormat()); - mapper.registerModule(new JavaTimeModule()); - JsonNullableModule jnm = new JsonNullableModule(); - mapper.registerModule(jnm); - } - - /** - * Set the date format for JSON (de)serialization with Date properties. - * - * @param dateFormat Date format - */ - public void setDateFormat(DateFormat dateFormat) { - mapper.setDateFormat(dateFormat); - } - - /** - * Get the object mapper - * - * @return object mapper - */ - public ObjectMapper getMapper() { return mapper; } - - /** - * Returns the target model class that should be used to deserialize the input data. - * The discriminator mappings are used to determine the target model class. - * - * @param node The input data. - * @param modelClass The class that contains the discriminator mappings. - * - * @return the target model class. - */ - public static Class getClassForElement(JsonNode node, Class modelClass) { - ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass); - if (cdm != null) { - return cdm.getClassForElement(node, new HashSet>()); - } - return null; - } - - /** - * Helper class to register the discriminator mappings. - */ - private static class ClassDiscriminatorMapping { - // The model class name. - Class modelClass; - // The name of the discriminator property. - String discriminatorName; - // The discriminator mappings for a model class. - Map> discriminatorMappings; - - // Constructs a new class discriminator. - ClassDiscriminatorMapping(Class cls, String propertyName, Map> mappings) { - modelClass = cls; - discriminatorName = propertyName; - discriminatorMappings = new HashMap>(); - if (mappings != null) { - discriminatorMappings.putAll(mappings); - } - } - - // Return the name of the discriminator property for this model class. - String getDiscriminatorPropertyName() { - return discriminatorName; - } - - // Return the discriminator value or null if the discriminator is not - // present in the payload. - String getDiscriminatorValue(JsonNode node) { - // Determine the value of the discriminator property in the input data. - if (discriminatorName != null) { - // Get the value of the discriminator property, if present in the input payload. - node = node.get(discriminatorName); - if (node != null && node.isValueNode()) { - String discrValue = node.asText(); - if (discrValue != null) { - return discrValue; - } - } - } - return null; - } - - /** - * Returns the target model class that should be used to deserialize the input data. - * This function can be invoked for anyOf/oneOf composed models with discriminator mappings. - * The discriminator mappings are used to determine the target model class. - * - * @param node The input data. - * @param visitedClasses The set of classes that have already been visited. - * - * @return the target model class. - */ - Class getClassForElement(JsonNode node, Set> visitedClasses) { - if (visitedClasses.contains(modelClass)) { - // Class has already been visited. - return null; - } - // Determine the value of the discriminator property in the input data. - String discrValue = getDiscriminatorValue(node); - if (discrValue == null) { - return null; - } - Class cls = discriminatorMappings.get(discrValue); - // It may not be sufficient to return this cls directly because that target class - // may itself be a composed schema, possibly with its own discriminator. - visitedClasses.add(modelClass); - for (Class childClass : discriminatorMappings.values()) { - ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass); - if (childCdm == null) { - continue; - } - if (!discriminatorName.equals(childCdm.discriminatorName)) { - discrValue = getDiscriminatorValue(node); - if (discrValue == null) { - continue; - } - } - if (childCdm != null) { - // Recursively traverse the discriminator mappings. - Class childDiscr = childCdm.getClassForElement(node, visitedClasses); - if (childDiscr != null) { - return childDiscr; - } - } - } - return cls; - } - } - - /** - * Returns true if inst is an instance of modelClass in the OpenAPI model hierarchy. - * - * The Java class hierarchy is not implemented the same way as the OpenAPI model hierarchy, - * so it's not possible to use the instanceof keyword. - * - * @param modelClass A OpenAPI model class. - * @param inst The instance object. - * @param visitedClasses The set of classes that have already been visited. - * - * @return true if inst is an instance of modelClass in the OpenAPI model hierarchy. - */ - public static boolean isInstanceOf(Class modelClass, Object inst, Set> visitedClasses) { - if (modelClass.isInstance(inst)) { - // This handles the 'allOf' use case with single parent inheritance. - return true; - } - if (visitedClasses.contains(modelClass)) { - // This is to prevent infinite recursion when the composed schemas have - // a circular dependency. - return false; - } - visitedClasses.add(modelClass); - - // Traverse the oneOf/anyOf composed schemas. - Map> descendants = modelDescendants.get(modelClass); - if (descendants != null) { - for (Class childType : descendants.values()) { - if (isInstanceOf(childType, inst, visitedClasses)) { - return true; - } - } - } - return false; - } - - /** - * A map of discriminators for all model classes. - */ - private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap<>(); - - /** - * A map of oneOf/anyOf descendants for each model class. - */ - private static Map, Map>> modelDescendants = new HashMap<>(); - - /** - * Register a model class discriminator. - * - * @param modelClass the model class - * @param discriminatorPropertyName the name of the discriminator property - * @param mappings a map with the discriminator mappings. - */ - public static void registerDiscriminator(Class modelClass, String discriminatorPropertyName, Map> mappings) { - ClassDiscriminatorMapping m = new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings); - modelDiscriminators.put(modelClass, m); - } - - /** - * Register the oneOf/anyOf descendants of the modelClass. - * - * @param modelClass the model class - * @param descendants a map of oneOf/anyOf descendants. - */ - public static void registerDescendants(Class modelClass, Map> descendants) { - modelDescendants.put(modelClass, descendants); - } - - private static JSON json; - - static { - json = new JSON(); - } - - /** - * Get the default JSON instance. - * - * @return the default JSON instance - */ - public static JSON getDefault() { - return json; - } - - /** - * Set the default JSON instance. - * - * @param json JSON instance to be used - */ - public static void setDefault(JSON json) { - JSON.json = json; - } -} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java deleted file mode 100644 index 8d1d80c2..00000000 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; - -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") -public class Pair { - private String name = ""; - private String value = ""; - - public Pair (String name, String value) { - setName(name); - setValue(value); - } - - private void setName(String name) { - if (!isValidString(name)) { - return; - } - - this.name = name; - } - - private void setValue(String value) { - if (!isValidString(value)) { - return; - } - - this.value = value; - } - - public String getName() { - return this.name; - } - - public String getValue() { - return this.value; - } - - private boolean isValidString(String arg) { - if (arg == null) { - return false; - } - - return true; - } -} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java deleted file mode 100644 index 57853d22..00000000 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; - -import com.fasterxml.jackson.databind.util.StdDateFormat; - -import java.text.DateFormat; -import java.text.DecimalFormat; -import java.text.FieldPosition; -import java.text.ParsePosition; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.TimeZone; - -public class RFC3339DateFormat extends DateFormat { - private static final long serialVersionUID = 1L; - private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); - - private final StdDateFormat fmt = new StdDateFormat() - .withTimeZone(TIMEZONE_Z) - .withColonInTimeZone(true); - - public RFC3339DateFormat() { - this.calendar = new GregorianCalendar(); - this.numberFormat = new DecimalFormat(); - } - - @Override - public Date parse(String source) { - return parse(source, new ParsePosition(0)); - } - - @Override - public Date parse(String source, ParsePosition pos) { - return fmt.parse(source, pos); - } - - @Override - public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { - return fmt.format(date, toAppendTo, fieldPosition); - } - - @Override - public Object clone() { - return super.clone(); - } -} \ No newline at end of file diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java deleted file mode 100644 index 33501d36..00000000 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java +++ /dev/null @@ -1,58 +0,0 @@ -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; - -import java.util.Map; - -/** - * Representing a Server configuration. - */ -public class ServerConfiguration { - public String URL; - public String description; - public Map variables; - - /** - * @param URL A URL to the target host. - * @param description A description of the host designated by the URL. - * @param variables A map between a variable name and its value. The value is used for substitution in the server's URL template. - */ - public ServerConfiguration(String URL, String description, Map variables) { - this.URL = URL; - this.description = description; - this.variables = variables; - } - - /** - * Format URL template using given variables. - * - * @param variables A map between a variable name and its value. - * @return Formatted URL. - */ - public String URL(Map variables) { - String url = this.URL; - - // go through variables and replace placeholders - for (Map.Entry variable: this.variables.entrySet()) { - String name = variable.getKey(); - ServerVariable serverVariable = variable.getValue(); - String value = serverVariable.defaultValue; - - if (variables != null && variables.containsKey(name)) { - value = variables.get(name); - if (serverVariable.enumValues.size() > 0 && !serverVariable.enumValues.contains(value)) { - throw new IllegalArgumentException("The variable " + name + " in the server URL has invalid value " + value + "."); - } - } - url = url.replace("{" + name + "}", value); - } - return url; - } - - /** - * Format URL template using default server variables. - * - * @return Formatted URL. - */ - public String URL() { - return URL(null); - } -} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java deleted file mode 100644 index c06da593..00000000 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java +++ /dev/null @@ -1,23 +0,0 @@ -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; - -import java.util.HashSet; - -/** - * Representing a Server Variable for server URL template substitution. - */ -public class ServerVariable { - public String description; - public String defaultValue; - public HashSet enumValues = null; - - /** - * @param description A description for the server variable. - * @param defaultValue The default value to use for substitution. - * @param enumValues An enumeration of string values to be used if the substitution options are from a limited set. - */ - public ServerVariable(String description, String defaultValue, HashSet enumValues) { - this.description = description; - this.defaultValue = defaultValue; - this.enumValues = enumValues; - } -} From 5b9c8cfbc7dec93dd7b3d273b2a2e1fc1d2473fb Mon Sep 17 00:00:00 2001 From: svariant Date: Thu, 6 Apr 2023 17:44:04 +0200 Subject: [PATCH 128/403] [SLS-19] Generated rest client with openAPI specification for retrieving Identity Provider Cert Data --- gradle/verification-metadata.xml | 456 ++++++++++++++++++ .../build.gradle | 27 ++ .../openapi/openapi-spec.yml | 50 ++ .../client/simple/IdpCertSimpleClient.java | 30 ++ .../simple/IdpCertSimpleClientProvider.java | 19 + .../idp/client/simple/internal/ApiClient.java | 436 +++++++++++++++++ .../client/simple/internal/ApiException.java | 88 ++++ .../client/simple/internal/ApiResponse.java | 47 ++ .../client/simple/internal/Configuration.java | 29 ++ .../idp/client/simple/internal/JSON.java | 246 ++++++++++ .../idp/client/simple/internal/Pair.java | 47 ++ .../simple/internal/RFC3339DateFormat.java | 44 ++ .../simple/internal/ServerConfiguration.java | 65 +++ .../simple/internal/ServerVariable.java | 23 + .../simple/internal/api/DefaultApi.java | 317 ++++++++++++ .../internal/model/AbstractOpenApiSchema.java | 135 ++++++ 16 files changed, 2059 insertions(+) create mode 100644 identity-service-rest-client-native/openapi/openapi-spec.yml create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 9aa9291d..9b818cfb 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -125,6 +125,11 @@ + + + + + @@ -135,6 +140,16 @@ + + + + + + + + + + @@ -145,6 +160,11 @@ + + + + + @@ -157,6 +177,16 @@ + + + + + + + + + + @@ -168,6 +198,11 @@ + + + + + @@ -201,6 +236,14 @@ + + + + + + + + @@ -227,6 +270,14 @@ + + + + + + + + @@ -253,6 +304,14 @@ + + + + + + + + @@ -288,6 +347,19 @@ + + + + + + + + + + + + + @@ -298,11 +370,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -316,6 +422,16 @@ + + + + + + + + + + @@ -347,6 +463,14 @@ + + + + + + + + @@ -357,6 +481,14 @@ + + + + + + + + @@ -437,6 +569,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -745,6 +914,11 @@ + + + + + @@ -835,6 +1009,22 @@ + + + + + + + + + + + + + + + + @@ -885,6 +1075,14 @@ + + + + + + + + @@ -1141,6 +1339,14 @@ + + + + + + + + @@ -1151,6 +1357,14 @@ + + + + + + + + @@ -1161,6 +1375,14 @@ + + + + + + + + @@ -1171,6 +1393,14 @@ + + + + + + + + @@ -1181,6 +1411,14 @@ + + + + + + + + @@ -1191,18 +1429,36 @@ + + + + + + + + + + + + + + + + + + @@ -1213,6 +1469,14 @@ + + + + + + + + @@ -1223,6 +1487,14 @@ + + + + + + + + @@ -1233,6 +1505,11 @@ + + + + + @@ -1249,6 +1526,14 @@ + + + + + + + + @@ -1259,12 +1544,25 @@ + + + + + + + + + + + + + @@ -1275,6 +1573,14 @@ + + + + + + + + @@ -1285,6 +1591,22 @@ + + + + + + + + + + + + + + + + @@ -1305,6 +1627,14 @@ + + + + + + + + @@ -1325,6 +1655,11 @@ + + + + + @@ -1367,6 +1702,14 @@ + + + + + + + + @@ -1377,6 +1720,14 @@ + + + + + + + + @@ -1457,6 +1808,14 @@ + + + + + + + + @@ -1525,6 +1884,11 @@ + + + + + @@ -1609,6 +1973,11 @@ + + + + + @@ -1889,6 +2258,14 @@ + + + + + + + + @@ -1959,6 +2336,19 @@ + + + + + + + + + + + + + @@ -1975,6 +2365,11 @@ + + + + + @@ -2211,6 +2606,9 @@ + + + @@ -2581,6 +2979,11 @@ + + + + + @@ -2591,6 +2994,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2653,6 +3085,14 @@ + + + + + + + + @@ -2671,6 +3111,14 @@ + + + + + + + + @@ -2695,6 +3143,14 @@ + + + + + + + + diff --git a/identity-service-rest-client-native/build.gradle b/identity-service-rest-client-native/build.gradle index 460062f0..d38a7392 100644 --- a/identity-service-rest-client-native/build.gradle +++ b/identity-service-rest-client-native/build.gradle @@ -10,6 +10,7 @@ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' id("io.freefair.lombok") version "8.0.0-rc4" + /*id("org.openapi.generator") version "6.5.0"*/ } group 'it.pagopa.tech' @@ -44,11 +45,37 @@ dependencies { } } implementation project(path: ':core') + + implementation 'javax.annotation:javax.annotation-api:1.3.2' + implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.14.2' + implementation 'org.openapitools:jackson-databind-nullable:0.2.6' + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.2' + implementation 'com.google.code.findbugs:jsr305:3.0.2' + + implementation 'org.mock-server:mockserver-client-java:5.15.0' + implementation 'javax.inject:javax.inject:1' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + testImplementation 'org.assertj:assertj-core:3.24.2' + //Mockserver for testing api + testImplementation 'org.mock-server:mockserver-netty:5.15.0' } tasks.named('test') { // Use JUnit Platform for unit tests. useJUnitPlatform() } + +/*compileJava.dependsOn tasks.openApiGenerate + +openApiGenerate { + generatorName = "java" + inputSpec = "$projectDir/openapi/openapi-spec.yml" + outputDir = "$projectDir/generated" + configOptions = [ + dataLibrary : "java8", + library : "native", + useRuntimeException: "true", + sourceFolder : "build/generated/sources/" + ] +}*/ diff --git a/identity-service-rest-client-native/openapi/openapi-spec.yml b/identity-service-rest-client-native/openapi/openapi-spec.yml new file mode 100644 index 00000000..cb180052 --- /dev/null +++ b/identity-service-rest-client-native/openapi/openapi-spec.yml @@ -0,0 +1,50 @@ +openapi: "3.0.1" +info: + title: "identity-services" + version: "2022-09-06T20:08:39Z" + x-logo: + url: https://io.italia.it/assets/img/io-logo-blue.svg + description: |- + Client used to retrieve the public keys from the identity provider +servers: + - url: "https://api.is.eng.pagopa.it" + x-amazon-apigateway-endpoint-configuration: + disableExecuteApiEndpoint: true +paths: + /idp-keys/spid: + get: + responses: + "200": + description: "200 response" + content: {} + /idp-keys/cie: + get: + responses: + "200": + description: "200 response" + content: {} + /idp-keys/spid/{tag}: + get: + parameters: + - name: "tag" + in: "path" + required: true + schema: + type: "string" + responses: + "200": + description: "200 response" + content: {} + /idp-keys/cie/{tag}: + get: + parameters: + - name: "tag" + in: "path" + required: true + schema: + type: "string" + responses: + "200": + description: "200 response" + content: {} +components: {} \ No newline at end of file diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java new file mode 100644 index 00000000..8eae30a2 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -0,0 +1,30 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple; + +import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.api.DefaultApi; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import javax.inject.Inject; + +public class IdpCertSimpleClient implements IdpCertClient { + + ApiClient apiClient; + DefaultApi defaultApi; + + @Inject + public IdpCertSimpleClient(ApiClient client) { + this.apiClient = client; + this.defaultApi = new DefaultApi(client); + } + + /** + * @param entityId + * @param instant + * @return + */ + @Override + public IdpCertData getCertData(String entityId, String instant) { + return null; + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java new file mode 100644 index 00000000..402136fd --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java @@ -0,0 +1,19 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple; + +import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; +import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; + +public class IdpCertSimpleClientProvider implements IdpCertClientProvider { + + /** + * Provide an instance of {@link IdpCertSimpleClient} + * + * @return {@link IdpCertSimpleClient} + */ + @Override + public IdpCertClient provideClient() { + return new IdpCertSimpleClient(new ApiClient()); + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java new file mode 100644 index 00000000..6405bcf6 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java @@ -0,0 +1,436 @@ +/* (C)2022-2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import java.io.InputStream; +import java.net.URI; +import java.net.URLEncoder; +import java.net.http.HttpClient; +import java.net.http.HttpConnectTimeoutException; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.StringJoiner; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import org.openapitools.jackson.nullable.JsonNullableModule; + +/** + * Configuration and utility class for API clients. + * + *

This class can be constructed and modified, then used to instantiate the various API classes. + * The API classes use the settings in this class to configure themselves, but otherwise do not + * store a link to this class. + * + *

This class is mutable and not synchronized, so it is not thread-safe. The API classes + * generated from this are immutable and thread-safe. + * + *

The setter methods of this class return the current object to facilitate a fluent style of + * configuration. + */ +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +public class ApiClient { + + private HttpClient.Builder builder; + private ObjectMapper mapper; + private String scheme; + private String host; + private int port; + private String basePath; + private Consumer interceptor; + private Consumer> responseInterceptor; + private Consumer> asyncResponseInterceptor; + private Duration readTimeout; + private Duration connectTimeout; + + private static String valueToString(Object value) { + if (value == null) { + return ""; + } + if (value instanceof OffsetDateTime) { + return ((OffsetDateTime) value).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } + return value.toString(); + } + + /** + * URL encode a string in the UTF-8 encoding. + * + * @param s String to encode. + * @return URL-encoded representation of the input string. + */ + public static String urlEncode(String s) { + return URLEncoder.encode(s, UTF_8).replaceAll("\\+", "%20"); + } + + /** + * Convert a URL query name/value parameter to a list of encoded {@link Pair} objects. + * + *

The value can be null, in which case an empty list is returned. + * + * @param name The query name parameter. + * @param value The query value, which may not be a collection but may be null. + * @return A singleton list of the {@link Pair} objects representing the input parameters, which + * is encoded for use in a URL. If the value is null, an empty list is returned. + */ + public static List parameterToPairs(String name, Object value) { + if (name == null || name.isEmpty() || value == null) { + return Collections.emptyList(); + } + return Collections.singletonList( + new Pair(urlEncode(name), urlEncode(valueToString(value)))); + } + + /** + * Convert a URL query name/collection parameter to a list of encoded {@link Pair} objects. + * + * @param collectionFormat The swagger collectionFormat string (csv, tsv, etc). + * @param name The query name parameter. + * @param values A collection of values for the given query name, which may be null. + * @return A list of {@link Pair} objects representing the input parameters, which is encoded + * for use in a URL. If the values collection is null, an empty list is returned. + */ + public static List parameterToPairs( + String collectionFormat, String name, Collection values) { + if (name == null || name.isEmpty() || values == null || values.isEmpty()) { + return Collections.emptyList(); + } + + // get the collection format (default: csv) + String format = + collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat; + + // create the params based on the collection format + if ("multi".equals(format)) { + return values.stream() + .map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value)))) + .collect(Collectors.toList()); + } + + String delimiter; + switch (format) { + case "csv": + delimiter = urlEncode(","); + break; + case "ssv": + delimiter = urlEncode(" "); + break; + case "tsv": + delimiter = urlEncode("\t"); + break; + case "pipes": + delimiter = urlEncode("|"); + break; + default: + throw new IllegalArgumentException( + "Illegal collection format: " + collectionFormat); + } + + StringJoiner joiner = new StringJoiner(delimiter); + for (Object value : values) { + joiner.add(urlEncode(valueToString(value))); + } + + return Collections.singletonList(new Pair(urlEncode(name), joiner.toString())); + } + + /** Create an instance of ApiClient. */ + public ApiClient() { + this.builder = createDefaultHttpClientBuilder(); + this.mapper = createDefaultObjectMapper(); + updateBaseUri(getDefaultBaseUri()); + interceptor = null; + readTimeout = null; + connectTimeout = null; + responseInterceptor = null; + asyncResponseInterceptor = null; + } + + /** + * Create an instance of ApiClient. + * + * @param builder Http client builder. + * @param mapper Object mapper. + * @param baseUri Base URI + */ + public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, String baseUri) { + this.builder = builder; + this.mapper = mapper; + updateBaseUri(baseUri != null ? baseUri : getDefaultBaseUri()); + interceptor = null; + readTimeout = null; + connectTimeout = null; + responseInterceptor = null; + asyncResponseInterceptor = null; + } + + protected ObjectMapper createDefaultObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); + mapper.registerModule(new JavaTimeModule()); + mapper.registerModule(new JsonNullableModule()); + return mapper; + } + + protected String getDefaultBaseUri() { + return "https://api.is.eng.pagopa.it"; + } + + protected HttpClient.Builder createDefaultHttpClientBuilder() { + return HttpClient.newBuilder(); + } + + public void updateBaseUri(String baseUri) { + URI uri = URI.create(baseUri); + scheme = uri.getScheme(); + host = uri.getHost(); + port = uri.getPort(); + basePath = uri.getRawPath(); + } + + /** + * Set a custom {@link HttpClient.Builder} object to use when creating the {@link HttpClient} + * that is used by the API client. + * + * @param builder Custom client builder. + * @return This object. + */ + public ApiClient setHttpClientBuilder(HttpClient.Builder builder) { + this.builder = builder; + return this; + } + + /** + * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}. + * + *

The returned object is immutable and thread-safe. + * + * @return The HTTP client. + */ + public HttpClient getHttpClient() { + return builder.build(); + } + + /** + * Set a custom {@link ObjectMapper} to serialize and deserialize the request and response + * bodies. + * + * @param mapper Custom object mapper. + * @return This object. + */ + public ApiClient setObjectMapper(ObjectMapper mapper) { + this.mapper = mapper; + return this; + } + + /** + * Get a copy of the current {@link ObjectMapper}. + * + * @return A copy of the current object mapper. + */ + public ObjectMapper getObjectMapper() { + return mapper.copy(); + } + + /** + * Set a custom host name for the target service. + * + * @param host The host name of the target service. + * @return This object. + */ + public ApiClient setHost(String host) { + this.host = host; + return this; + } + + /** + * Set a custom port number for the target service. + * + * @param port The port of the target service. Set this to -1 to reset the value to the default + * for the scheme. + * @return This object. + */ + public ApiClient setPort(int port) { + this.port = port; + return this; + } + + /** + * Set a custom base path for the target service, for example '/v2'. + * + * @param basePath The base path against which the rest of the path is resolved. + * @return This object. + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get the base URI to resolve the endpoint paths against. + * + * @return The complete base URI that the rest of the API parameters are resolved against. + */ + public String getBaseUri() { + return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; + } + + /** + * Set a custom scheme for the target service, for example 'https'. + * + * @param scheme The scheme of the target service + * @return This object. + */ + public ApiClient setScheme(String scheme) { + this.scheme = scheme; + return this; + } + + /** + * Set a custom request interceptor. + * + *

A request interceptor is a mechanism for altering each request before it is sent. After + * the request has been fully configured but not yet built, the request builder is passed into + * this function for further modification, after which it is sent out. + * + *

This is useful for altering the requests in a custom manner, such as adding headers. It + * could also be used for logging and monitoring. + * + * @param interceptor A function invoked before creating each request. A value of null resets + * the interceptor to a no-op. + * @return This object. + */ + public ApiClient setRequestInterceptor(Consumer interceptor) { + this.interceptor = interceptor; + return this; + } + + /** + * Get the custom interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer getRequestInterceptor() { + return interceptor; + } + + /** + * Set a custom response interceptor. + * + *

This is useful for logging, monitoring or extraction of header variables + * + * @param interceptor A function invoked before creating each request. A value of null resets + * the interceptor to a no-op. + * @return This object. + */ + public ApiClient setResponseInterceptor(Consumer> interceptor) { + this.responseInterceptor = interceptor; + return this; + } + + /** + * Get the custom response interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getResponseInterceptor() { + return responseInterceptor; + } + + /** + * Set a custom async response interceptor. Use this interceptor when asyncNative is set to + * 'true'. + * + *

This is useful for logging, monitoring or extraction of header variables + * + * @param interceptor A function invoked before creating each request. A value of null resets + * the interceptor to a no-op. + * @return This object. + */ + public ApiClient setAsyncResponseInterceptor(Consumer> interceptor) { + this.asyncResponseInterceptor = interceptor; + return this; + } + + /** + * Get the custom async response interceptor. Use this interceptor when asyncNative is set to + * 'true'. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getAsyncResponseInterceptor() { + return asyncResponseInterceptor; + } + + /** + * Set the read timeout for the http client. + * + *

This is the value used by default for each request, though it can be overridden on a + * per-request basis with a request interceptor. + * + * @param readTimeout The read timeout used by default by the http client. Setting this value to + * null resets the timeout to an effectively infinite value. + * @return This object. + */ + public ApiClient setReadTimeout(Duration readTimeout) { + this.readTimeout = readTimeout; + return this; + } + + /** + * Get the read timeout that was set. + * + * @return The read timeout, or null if no timeout was set. Null represents an infinite wait + * time. + */ + public Duration getReadTimeout() { + return readTimeout; + } + /** + * Sets the connect timeout (in milliseconds) for the http client. + * + *

In the case where a new connection needs to be established, if the connection cannot be + * established within the given {@code duration}, then {@link + * HttpClient#send(HttpRequest,BodyHandler) HttpClient::send} throws an {@link + * HttpConnectTimeoutException}, or {@link HttpClient#sendAsync(HttpRequest,BodyHandler) + * HttpClient::sendAsync} completes exceptionally with an {@code HttpConnectTimeoutException}. + * If a new connection does not need to be established, for example if a connection can be + * reused from a previous request, then this timeout duration has no effect. + * + * @param connectTimeout connection timeout in milliseconds + * @return This object. + */ + public ApiClient setConnectTimeout(Duration connectTimeout) { + this.connectTimeout = connectTimeout; + this.builder.connectTimeout(connectTimeout); + return this; + } + + /** + * Get connection timeout (in milliseconds). + * + * @return Timeout in milliseconds + */ + public Duration getConnectTimeout() { + return connectTimeout; + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java new file mode 100644 index 00000000..5297d641 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java @@ -0,0 +1,88 @@ +/* (C)2022-2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; + +import java.net.http.HttpHeaders; + +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +public class ApiException extends RuntimeException { + private int code = 0; + private HttpHeaders responseHeaders = null; + private String responseBody = null; + + public ApiException() {} + + public ApiException(Throwable throwable) { + super(throwable); + } + + public ApiException(String message) { + super(message); + } + + public ApiException( + String message, + Throwable throwable, + int code, + HttpHeaders responseHeaders, + String responseBody) { + super(message, throwable); + this.code = code; + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + public ApiException( + String message, int code, HttpHeaders responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException( + String message, Throwable throwable, int code, HttpHeaders responseHeaders) { + this(message, throwable, code, responseHeaders, null); + } + + public ApiException(int code, HttpHeaders responseHeaders, String responseBody) { + this((String) null, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(int code, String message) { + super(message); + this.code = code; + } + + public ApiException( + int code, String message, HttpHeaders responseHeaders, String responseBody) { + this(code, message); + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + /** + * Get the HTTP status code. + * + * @return HTTP status code + */ + public int getCode() { + return code; + } + + /** + * Get the HTTP response headers. + * + * @return Headers as an HttpHeaders object + */ + public HttpHeaders getResponseHeaders() { + return responseHeaders; + } + + /** + * Get the HTTP response body. + * + * @return Response body in the form of string + */ + public String getResponseBody() { + return responseBody; + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java new file mode 100644 index 00000000..582e0a4d --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java @@ -0,0 +1,47 @@ +/* (C)2022-2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; + +import java.util.List; +import java.util.Map; + +/** + * API response returned by API call. + * + * @param The type of data that is deserialized from response body + */ +public class ApiResponse { + private final int statusCode; + private final Map> headers; + private final T data; + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + */ + public ApiResponse(int statusCode, Map> headers) { + this(statusCode, headers, null); + } + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + * @param data The object deserialized from response bod + */ + public ApiResponse(int statusCode, Map> headers, T data) { + this.statusCode = statusCode; + this.headers = headers; + this.data = data; + } + + public int getStatusCode() { + return statusCode; + } + + public Map> getHeaders() { + return headers; + } + + public T getData() { + return data; + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java new file mode 100644 index 00000000..cbc956b8 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java @@ -0,0 +1,29 @@ +/* (C)2022-2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; + +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +public class Configuration { + private static ApiClient defaultApiClient = new ApiClient(); + + /** + * Get the default API client, which would be used when creating API instances without providing + * an API client. + * + * @return Default API client + */ + public static ApiClient getDefaultApiClient() { + return defaultApiClient; + } + + /** + * Set the default API client, which would be used when creating API instances without providing + * an API client. + * + * @param apiClient API client + */ + public static void setDefaultApiClient(ApiClient apiClient) { + defaultApiClient = apiClient; + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java new file mode 100644 index 00000000..889ef90a --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java @@ -0,0 +1,246 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import java.text.DateFormat; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import org.openapitools.jackson.nullable.JsonNullableModule; + +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +public class JSON { + private ObjectMapper mapper; + + public JSON() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + mapper.registerModule(new JavaTimeModule()); + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + } + + /** + * Set the date format for JSON (de)serialization with Date properties. + * + * @param dateFormat Date format + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + + /** + * Get the object mapper + * + * @return object mapper + */ + public ObjectMapper getMapper() { + return mapper; + } + + /** + * Returns the target model class that should be used to deserialize the input data. The + * discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param modelClass The class that contains the discriminator mappings. + * @return the target model class. + */ + public static Class getClassForElement(JsonNode node, Class modelClass) { + ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass); + if (cdm != null) { + return cdm.getClassForElement(node, new HashSet>()); + } + return null; + } + + /** Helper class to register the discriminator mappings. */ + private static class ClassDiscriminatorMapping { + // The model class name. + Class modelClass; + // The name of the discriminator property. + String discriminatorName; + // The discriminator mappings for a model class. + Map> discriminatorMappings; + + // Constructs a new class discriminator. + ClassDiscriminatorMapping( + Class cls, String propertyName, Map> mappings) { + modelClass = cls; + discriminatorName = propertyName; + discriminatorMappings = new HashMap>(); + if (mappings != null) { + discriminatorMappings.putAll(mappings); + } + } + + // Return the name of the discriminator property for this model class. + String getDiscriminatorPropertyName() { + return discriminatorName; + } + + // Return the discriminator value or null if the discriminator is not + // present in the payload. + String getDiscriminatorValue(JsonNode node) { + // Determine the value of the discriminator property in the input data. + if (discriminatorName != null) { + // Get the value of the discriminator property, if present in the input payload. + node = node.get(discriminatorName); + if (node != null && node.isValueNode()) { + String discrValue = node.asText(); + if (discrValue != null) { + return discrValue; + } + } + } + return null; + } + + /** + * Returns the target model class that should be used to deserialize the input data. This + * function can be invoked for anyOf/oneOf composed models with discriminator mappings. The + * discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param visitedClasses The set of classes that have already been visited. + * @return the target model class. + */ + Class getClassForElement(JsonNode node, Set> visitedClasses) { + if (visitedClasses.contains(modelClass)) { + // Class has already been visited. + return null; + } + // Determine the value of the discriminator property in the input data. + String discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + return null; + } + Class cls = discriminatorMappings.get(discrValue); + // It may not be sufficient to return this cls directly because that target class + // may itself be a composed schema, possibly with its own discriminator. + visitedClasses.add(modelClass); + for (Class childClass : discriminatorMappings.values()) { + ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass); + if (childCdm == null) { + continue; + } + if (!discriminatorName.equals(childCdm.discriminatorName)) { + discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + continue; + } + } + if (childCdm != null) { + // Recursively traverse the discriminator mappings. + Class childDiscr = childCdm.getClassForElement(node, visitedClasses); + if (childDiscr != null) { + return childDiscr; + } + } + } + return cls; + } + } + + /** + * Returns true if inst is an instance of modelClass in the OpenAPI model hierarchy. + * + *

The Java class hierarchy is not implemented the same way as the OpenAPI model hierarchy, + * so it's not possible to use the instanceof keyword. + * + * @param modelClass A OpenAPI model class. + * @param inst The instance object. + * @param visitedClasses The set of classes that have already been visited. + * @return true if inst is an instance of modelClass in the OpenAPI model hierarchy. + */ + public static boolean isInstanceOf( + Class modelClass, Object inst, Set> visitedClasses) { + if (modelClass.isInstance(inst)) { + // This handles the 'allOf' use case with single parent inheritance. + return true; + } + if (visitedClasses.contains(modelClass)) { + // This is to prevent infinite recursion when the composed schemas have + // a circular dependency. + return false; + } + visitedClasses.add(modelClass); + + // Traverse the oneOf/anyOf composed schemas. + Map> descendants = modelDescendants.get(modelClass); + if (descendants != null) { + for (Class childType : descendants.values()) { + if (isInstanceOf(childType, inst, visitedClasses)) { + return true; + } + } + } + return false; + } + + /** A map of discriminators for all model classes. */ + private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap<>(); + + /** A map of oneOf/anyOf descendants for each model class. */ + private static Map, Map>> modelDescendants = new HashMap<>(); + + /** + * Register a model class discriminator. + * + * @param modelClass the model class + * @param discriminatorPropertyName the name of the discriminator property + * @param mappings a map with the discriminator mappings. + */ + public static void registerDiscriminator( + Class modelClass, String discriminatorPropertyName, Map> mappings) { + ClassDiscriminatorMapping m = + new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings); + modelDiscriminators.put(modelClass, m); + } + + /** + * Register the oneOf/anyOf descendants of the modelClass. + * + * @param modelClass the model class + * @param descendants a map of oneOf/anyOf descendants. + */ + public static void registerDescendants(Class modelClass, Map> descendants) { + modelDescendants.put(modelClass, descendants); + } + + private static JSON json; + + static { + json = new JSON(); + } + + /** + * Get the default JSON instance. + * + * @return the default JSON instance + */ + public static JSON getDefault() { + return json; + } + + /** + * Set the default JSON instance. + * + * @param json JSON instance to be used + */ + public static void setDefault(JSON json) { + JSON.json = json; + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java new file mode 100644 index 00000000..68b71c24 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java @@ -0,0 +1,47 @@ +/* (C)2022-2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; + +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +public class Pair { + private String name = ""; + private String value = ""; + + public Pair(String name, String value) { + setName(name); + setValue(value); + } + + private void setName(String name) { + if (!isValidString(name)) { + return; + } + + this.name = name; + } + + private void setValue(String value) { + if (!isValidString(value)) { + return; + } + + this.value = value; + } + + public String getName() { + return this.name; + } + + public String getValue() { + return this.value; + } + + private boolean isValidString(String arg) { + if (arg == null) { + return false; + } + + return true; + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java new file mode 100644 index 00000000..eb26f968 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java @@ -0,0 +1,44 @@ +/* (C)2022-2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; + +import com.fasterxml.jackson.databind.util.StdDateFormat; +import java.text.DateFormat; +import java.text.DecimalFormat; +import java.text.FieldPosition; +import java.text.ParsePosition; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +public class RFC3339DateFormat extends DateFormat { + private static final long serialVersionUID = 1L; + private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); + + private final StdDateFormat fmt = + new StdDateFormat().withTimeZone(TIMEZONE_Z).withColonInTimeZone(true); + + public RFC3339DateFormat() { + this.calendar = new GregorianCalendar(); + this.numberFormat = new DecimalFormat(); + } + + @Override + public Date parse(String source) { + return parse(source, new ParsePosition(0)); + } + + @Override + public Date parse(String source, ParsePosition pos) { + return fmt.parse(source, pos); + } + + @Override + public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { + return fmt.format(date, toAppendTo, fieldPosition); + } + + @Override + public Object clone() { + return super.clone(); + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java new file mode 100644 index 00000000..747b99ab --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java @@ -0,0 +1,65 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; + +import java.util.Map; + +/** Representing a Server configuration. */ +public class ServerConfiguration { + public String URL; + public String description; + public Map variables; + + /** + * @param URL A URL to the target host. + * @param description A description of the host designated by the URL. + * @param variables A map between a variable name and its value. The value is used for + * substitution in the server's URL template. + */ + public ServerConfiguration( + String URL, String description, Map variables) { + this.URL = URL; + this.description = description; + this.variables = variables; + } + + /** + * Format URL template using given variables. + * + * @param variables A map between a variable name and its value. + * @return Formatted URL. + */ + public String URL(Map variables) { + String url = this.URL; + + // go through variables and replace placeholders + for (Map.Entry variable : this.variables.entrySet()) { + String name = variable.getKey(); + ServerVariable serverVariable = variable.getValue(); + String value = serverVariable.defaultValue; + + if (variables != null && variables.containsKey(name)) { + value = variables.get(name); + if (serverVariable.enumValues.size() > 0 + && !serverVariable.enumValues.contains(value)) { + throw new IllegalArgumentException( + "The variable " + + name + + " in the server URL has invalid value " + + value + + "."); + } + } + url = url.replace("{" + name + "}", value); + } + return url; + } + + /** + * Format URL template using default server variables. + * + * @return Formatted URL. + */ + public String URL() { + return URL(null); + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java new file mode 100644 index 00000000..f0bb418a --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java @@ -0,0 +1,23 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; + +import java.util.HashSet; + +/** Representing a Server Variable for server URL template substitution. */ +public class ServerVariable { + public String description; + public String defaultValue; + public HashSet enumValues = null; + + /** + * @param description A description for the server variable. + * @param defaultValue The default value to use for substitution. + * @param enumValues An enumeration of string values to be used if the substitution options are + * from a limited set. + */ + public ServerVariable(String description, String defaultValue, HashSet enumValues) { + this.description = description; + this.defaultValue = defaultValue; + this.enumValues = enumValues; + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java new file mode 100644 index 00000000..e58deef0 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java @@ -0,0 +1,317 @@ +/* (C)2022-2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.api; + +import com.fasterxml.jackson.databind.ObjectMapper; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiException; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiResponse; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.util.function.Consumer; + +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +public class DefaultApi { + private final HttpClient memberVarHttpClient; + private final ObjectMapper memberVarObjectMapper; + private final String memberVarBaseUri; + private final Consumer memberVarInterceptor; + private final Duration memberVarReadTimeout; + private final Consumer> memberVarResponseInterceptor; + private final Consumer> memberVarAsyncResponseInterceptor; + + public DefaultApi() { + this(new ApiClient()); + } + + public DefaultApi(ApiClient apiClient) { + memberVarHttpClient = apiClient.getHttpClient(); + memberVarObjectMapper = apiClient.getObjectMapper(); + memberVarBaseUri = apiClient.getBaseUri(); + memberVarInterceptor = apiClient.getRequestInterceptor(); + memberVarReadTimeout = apiClient.getReadTimeout(); + memberVarResponseInterceptor = apiClient.getResponseInterceptor(); + memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); + } + + protected ApiException getApiException(String operationId, HttpResponse response) + throws IOException { + String body = response.body() == null ? null : new String(response.body().readAllBytes()); + String message = formatExceptionMessage(operationId, response.statusCode(), body); + return new ApiException(response.statusCode(), message, response.headers(), body); + } + + private String formatExceptionMessage(String operationId, int statusCode, String body) { + if (body == null || body.isEmpty()) { + body = "[no body]"; + } + return operationId + " call failed with: " + statusCode + " - " + body; + } + + /** + * @throws ApiException if fails to make API call + */ + public void idpKeysCieGet() throws ApiException { + idpKeysCieGetWithHttpInfo(); + } + + /** + * @return ApiResponse<Void> + * @throws ApiException if fails to make API call + */ + public ApiResponse idpKeysCieGetWithHttpInfo() throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysCieGetRequestBuilder(); + try { + HttpResponse localVarResponse = + memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode() / 100 != 2) { + throw getApiException("idpKeysCieGet", localVarResponse); + } + return new ApiResponse( + localVarResponse.statusCode(), localVarResponse.headers().map(), null); + } finally { + // Drain the InputStream + while (localVarResponse.body().read() != -1) { + // Ignore + } + localVarResponse.body().close(); + } + } catch (IOException e) { + throw new ApiException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } + + private HttpRequest.Builder idpKeysCieGetRequestBuilder() throws ApiException { + + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + + String localVarPath = "/idp-keys/cie"; + + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + + localVarRequestBuilder.header("Accept", "application/json"); + + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; + } + /** + * @param tag (required) + * @throws ApiException if fails to make API call + */ + public void idpKeysCieTagGet(String tag) throws ApiException { + idpKeysCieTagGetWithHttpInfo(tag); + } + + /** + * @param tag (required) + * @return ApiResponse<Void> + * @throws ApiException if fails to make API call + */ + public ApiResponse idpKeysCieTagGetWithHttpInfo(String tag) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysCieTagGetRequestBuilder(tag); + try { + HttpResponse localVarResponse = + memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode() / 100 != 2) { + throw getApiException("idpKeysCieTagGet", localVarResponse); + } + return new ApiResponse( + localVarResponse.statusCode(), localVarResponse.headers().map(), null); + } finally { + // Drain the InputStream + while (localVarResponse.body().read() != -1) { + // Ignore + } + localVarResponse.body().close(); + } + } catch (IOException e) { + throw new ApiException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } + + private HttpRequest.Builder idpKeysCieTagGetRequestBuilder(String tag) throws ApiException { + // verify the required parameter 'tag' is set + if (tag == null) { + throw new ApiException( + 400, "Missing the required parameter 'tag' when calling idpKeysCieTagGet"); + } + + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + + String localVarPath = + "/idp-keys/cie/{tag}".replace("{tag}", ApiClient.urlEncode(tag.toString())); + + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + + localVarRequestBuilder.header("Accept", "application/json"); + + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; + } + /** + * @throws ApiException if fails to make API call + */ + public void idpKeysSpidGet() throws ApiException { + idpKeysSpidGetWithHttpInfo(); + } + + /** + * @return ApiResponse<Void> + * @throws ApiException if fails to make API call + */ + public ApiResponse idpKeysSpidGetWithHttpInfo() throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysSpidGetRequestBuilder(); + try { + HttpResponse localVarResponse = + memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode() / 100 != 2) { + throw getApiException("idpKeysSpidGet", localVarResponse); + } + return new ApiResponse( + localVarResponse.statusCode(), localVarResponse.headers().map(), null); + } finally { + // Drain the InputStream + while (localVarResponse.body().read() != -1) { + // Ignore + } + localVarResponse.body().close(); + } + } catch (IOException e) { + throw new ApiException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } + + private HttpRequest.Builder idpKeysSpidGetRequestBuilder() throws ApiException { + + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + + String localVarPath = "/idp-keys/spid"; + + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + + localVarRequestBuilder.header("Accept", "application/json"); + + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; + } + /** + * @param tag (required) + * @throws ApiException if fails to make API call + */ + public void idpKeysSpidTagGet(String tag) throws ApiException { + idpKeysSpidTagGetWithHttpInfo(tag); + } + + /** + * @param tag (required) + * @return ApiResponse<Void> + * @throws ApiException if fails to make API call + */ + public ApiResponse idpKeysSpidTagGetWithHttpInfo(String tag) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysSpidTagGetRequestBuilder(tag); + try { + HttpResponse localVarResponse = + memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode() / 100 != 2) { + throw getApiException("idpKeysSpidTagGet", localVarResponse); + } + return new ApiResponse( + localVarResponse.statusCode(), localVarResponse.headers().map(), null); + } finally { + // Drain the InputStream + while (localVarResponse.body().read() != -1) { + // Ignore + } + localVarResponse.body().close(); + } + } catch (IOException e) { + throw new ApiException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } + + private HttpRequest.Builder idpKeysSpidTagGetRequestBuilder(String tag) throws ApiException { + // verify the required parameter 'tag' is set + if (tag == null) { + throw new ApiException( + 400, "Missing the required parameter 'tag' when calling idpKeysSpidTagGet"); + } + + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + + String localVarPath = + "/idp-keys/spid/{tag}".replace("{tag}", ApiClient.urlEncode(tag.toString())); + + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + + localVarRequestBuilder.header("Accept", "application/json"); + + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; + } +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java new file mode 100644 index 00000000..e5c342aa --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java @@ -0,0 +1,135 @@ +/* (C)2022-2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; + +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Map; +import java.util.Objects; + +/** Abstract class for oneOf,anyOf schemas defined in OpenAPI spec */ +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +public abstract class AbstractOpenApiSchema { + + // store the actual instance of the schema/object + private Object instance; + + // is nullable + private Boolean isNullable; + + // schema type (e.g. oneOf, anyOf) + private final String schemaType; + + public AbstractOpenApiSchema(String schemaType, Boolean isNullable) { + this.schemaType = schemaType; + this.isNullable = isNullable; + } + + /** + * Get the list of oneOf/anyOf composed schemas allowed to be stored in this object + * + * @return an instance of the actual schema/object + */ + public abstract Map> getSchemas(); + + /** + * Get the actual instance + * + * @return an instance of the actual schema/object + */ + @JsonValue + public Object getActualInstance() { + return instance; + } + + /** + * Set the actual instance + * + * @param instance the actual instance of the schema/object + */ + public void setActualInstance(Object instance) { + this.instance = instance; + } + + /** + * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf + * schema as well + * + * @return an instance of the actual schema/object + */ + public Object getActualInstanceRecursively() { + return getActualInstanceRecursively(this); + } + + private Object getActualInstanceRecursively(AbstractOpenApiSchema object) { + if (object.getActualInstance() == null) { + return null; + } else if (object.getActualInstance() instanceof AbstractOpenApiSchema) { + return getActualInstanceRecursively((AbstractOpenApiSchema) object.getActualInstance()); + } else { + return object.getActualInstance(); + } + } + + /** + * Get the schema type (e.g. anyOf, oneOf) + * + * @return the schema type + */ + public String getSchemaType() { + return schemaType; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ").append(getClass()).append(" {\n"); + sb.append(" instance: ").append(toIndentedString(instance)).append("\n"); + sb.append(" isNullable: ").append(toIndentedString(isNullable)).append("\n"); + sb.append(" schemaType: ").append(toIndentedString(schemaType)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first + * line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AbstractOpenApiSchema a = (AbstractOpenApiSchema) o; + return Objects.equals(this.instance, a.instance) + && Objects.equals(this.isNullable, a.isNullable) + && Objects.equals(this.schemaType, a.schemaType); + } + + @Override + public int hashCode() { + return Objects.hash(instance, isNullable, schemaType); + } + + /** + * Is nullable + * + * @return true if it's nullable + */ + public Boolean isNullable() { + if (Boolean.TRUE.equals(isNullable)) { + return Boolean.TRUE; + } else { + return Boolean.FALSE; + } + } +} From 541bd8326248645f92cacb0b8f8cdd89caec48b0 Mon Sep 17 00:00:00 2001 From: svariant Date: Thu, 6 Apr 2023 17:45:05 +0200 Subject: [PATCH 129/403] [SLS-19] Added error for oidc assertion in AssertionSimpleClient - not supported yet --- .../client/simple/AssertionSimpleClient.java | 7 ++++++- .../client/simple/AssertionSimpleClientTest.java | 3 ++- .../assertion/client/AssertionClient.java | 3 ++- .../exception/OidcAssertionNotSupported.java | 15 +++++++++++++++ 4 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/OidcAssertionNotSupported.java diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java index b2f93b42..49ae014e 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java @@ -7,8 +7,10 @@ import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.api.DefaultApi; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.AssertionRef; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.LCUserInfo; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.OidcUserInfo; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.SamlUserInfo; import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.OidcAssertionNotSupported; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import javax.inject.Inject; @@ -33,7 +35,7 @@ public AssertionSimpleClient(ApiClient client) { */ @Override public SamlAssertion getAssertion(String jwt, String assertionRef) - throws LollipopAssertionNotFoundException { + throws LollipopAssertionNotFoundException, OidcAssertionNotSupported { AssertionRef ref = new AssertionRef(assertionRef); LCUserInfo responseAssertion; @@ -53,6 +55,9 @@ public SamlAssertion getAssertion(String jwt, String assertionRef) response.setAssertionData(assertionData); return response; } + if (responseAssertion.getActualInstance().getClass().equals(OidcUserInfo.class)) { + throw new OidcAssertionNotSupported("OIDC Claims not supported yet."); + } return null; } diff --git a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java index 436867bc..8a444578 100644 --- a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java +++ b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java @@ -7,6 +7,7 @@ import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.OidcAssertionNotSupported; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; @@ -159,7 +160,7 @@ public static void startServer() { } @Test - void samlAssertionFound() throws LollipopAssertionNotFoundException { + void samlAssertionFound() throws LollipopAssertionNotFoundException, OidcAssertionNotSupported { // setup String xmlResponse = " Date: Tue, 11 Apr 2023 16:45:01 +0200 Subject: [PATCH 130/403] [SLS-19] Updated openAPI generated client with response configuration --- .../openapi/openapi-spec.yml | 210 ++++- .../idp/client/simple/internal/ApiClient.java | 802 +++++++++--------- .../client/simple/internal/ApiException.java | 34 +- .../client/simple/internal/ApiResponse.java | 20 +- .../client/simple/internal/Configuration.java | 26 +- .../idp/client/simple/internal/JSON.java | 431 +++++----- .../idp/client/simple/internal/Pair.java | 20 +- .../simple/internal/RFC3339DateFormat.java | 77 +- .../simple/internal/ServerConfiguration.java | 23 +- .../simple/internal/ServerVariable.java | 8 +- .../simple/internal/api/DefaultApi.java | 549 ++++++------ .../internal/model/AbstractOpenApiSchema.java | 54 +- .../simple/internal/model/CIECertData.java | 157 ++++ .../simple/internal/model/CertData.java | 281 ++++++ .../internal/model/EntityDescriptor.java | 145 ++++ .../simple/internal/model/ProblemJson.java | 292 +++++++ .../simple/internal/model/SPIDCertData.java | 143 ++++ .../model/SPIDCertDataEntitiesDescriptor.java | 158 ++++ 18 files changed, 2453 insertions(+), 977 deletions(-) create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/ProblemJson.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertData.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertDataEntitiesDescriptor.java diff --git a/identity-service-rest-client-native/openapi/openapi-spec.yml b/identity-service-rest-client-native/openapi/openapi-spec.yml index cb180052..86a07ede 100644 --- a/identity-service-rest-client-native/openapi/openapi-spec.yml +++ b/identity-service-rest-client-native/openapi/openapi-spec.yml @@ -16,13 +16,67 @@ paths: responses: "200": description: "200 response" - content: {} + content: + application/json: + schema: + $ref: '#/components/schemas/TagList' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' + '410': + description: Assertion gone + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' /idp-keys/cie: get: responses: "200": description: "200 response" - content: {} + content: + application/json: + schema: + $ref: '#/components/schemas/TagList' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' + '410': + description: Assertion gone + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' /idp-keys/spid/{tag}: get: parameters: @@ -34,7 +88,34 @@ paths: responses: "200": description: "200 response" - content: {} + content: + application/xml: + schema: + $ref: '#/components/schemas/CertData' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' + '410': + description: Assertion gone + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' /idp-keys/cie/{tag}: get: parameters: @@ -46,5 +127,124 @@ paths: responses: "200": description: "200 response" - content: {} -components: {} \ No newline at end of file + content: + application/xml: + schema: + $ref: '#/components/schemas/CertData' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' + '410': + description: Assertion gone + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemJson' +components: + schemas: + ProblemJson: + type: object + properties: + type: + type: string + format: uri + description: |- + An absolute URI that identifies the problem type. When dereferenced, + it SHOULD provide human-readable documentation for the problem type + (e.g., using HTML). + default: about:blank + example: https://example.com/problem/constraint-violation + title: + type: string + description: >- + A short, summary of the problem type. Written in english and + readable + + for engineers (usually not suited for non technical stakeholders and + + not localized); example: Service Unavailable + status: + type: integer + format: int32 + description: >- + The HTTP status code generated by the origin server for this + occurrence + + of the problem. + minimum: 100 + maximum: 600 + exclusiveMaximum: true + example: 200 + detail: + type: string + description: |- + A human readable explanation specific to this occurrence of the + problem. + example: There was an error processing the request + instance: + type: string + format: uri + description: >- + An absolute URI that identifies the specific occurrence of the + problem. + + It may or may not yield further information if dereferenced. + TagList: + type: array + items: + type: string + EntityDescriptor: + type: object + properties: + entityID: + type: string + xml: + attribute: true + required: + - entityID + SPIDCertData: + type: object + properties: + entitiesDescriptor: + type: object + properties: + entityDescriptor: + type: array + items: + $ref: '#/components/schemas/EntityDescriptor' + xml: + name: "EntityDescriptor" + prefix: "md" + namespace: "urn:oasis:names:tc:SAML:2.0:metadata" + xml: + name: "EntitiesDescriptor" + prefix: "md" + namespace: "urn:oasis:names:tc:SAML:2.0:metadata" + CIECertData: + type: object + properties: + entityDescriptor: + type: array + items: + $ref: '#/components/schemas/EntityDescriptor' + xml: + name: "EntityDescriptor" + CertData: + oneOf: + - $ref: '#/components/schemas/CIECertData' + - $ref: '#/components/schemas/SPIDCertData' \ No newline at end of file diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java index 6405bcf6..a3fcc124 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java @@ -1,13 +1,24 @@ -/* (C)2022-2023 */ -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ -import static java.nio.charset.StandardCharsets.UTF_8; +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.openapitools.jackson.nullable.JsonNullableModule; + import java.io.InputStream; import java.net.URI; import java.net.URLEncoder; @@ -24,413 +35,422 @@ import java.util.StringJoiner; import java.util.function.Consumer; import java.util.stream.Collectors; -import org.openapitools.jackson.nullable.JsonNullableModule; + +import static java.nio.charset.StandardCharsets.UTF_8; /** * Configuration and utility class for API clients. * - *

This class can be constructed and modified, then used to instantiate the various API classes. - * The API classes use the settings in this class to configure themselves, but otherwise do not - * store a link to this class. + *

This class can be constructed and modified, then used to instantiate the + * various API classes. The API classes use the settings in this class to + * configure themselves, but otherwise do not store a link to this class.

* - *

This class is mutable and not synchronized, so it is not thread-safe. The API classes - * generated from this are immutable and thread-safe. + *

This class is mutable and not synchronized, so it is not thread-safe. + * The API classes generated from this are immutable and thread-safe.

* - *

The setter methods of this class return the current object to facilitate a fluent style of - * configuration. + *

The setter methods of this class return the current object to facilitate + * a fluent style of configuration.

*/ -@javax.annotation.Generated( - value = "org.openapitools.codegen.languages.JavaClientCodegen", - date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class ApiClient { - private HttpClient.Builder builder; - private ObjectMapper mapper; - private String scheme; - private String host; - private int port; - private String basePath; - private Consumer interceptor; - private Consumer> responseInterceptor; - private Consumer> asyncResponseInterceptor; - private Duration readTimeout; - private Duration connectTimeout; - - private static String valueToString(Object value) { - if (value == null) { - return ""; - } - if (value instanceof OffsetDateTime) { - return ((OffsetDateTime) value).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); - } - return value.toString(); - } - - /** - * URL encode a string in the UTF-8 encoding. - * - * @param s String to encode. - * @return URL-encoded representation of the input string. - */ - public static String urlEncode(String s) { - return URLEncoder.encode(s, UTF_8).replaceAll("\\+", "%20"); - } - - /** - * Convert a URL query name/value parameter to a list of encoded {@link Pair} objects. - * - *

The value can be null, in which case an empty list is returned. - * - * @param name The query name parameter. - * @param value The query value, which may not be a collection but may be null. - * @return A singleton list of the {@link Pair} objects representing the input parameters, which - * is encoded for use in a URL. If the value is null, an empty list is returned. - */ - public static List parameterToPairs(String name, Object value) { - if (name == null || name.isEmpty() || value == null) { - return Collections.emptyList(); - } - return Collections.singletonList( - new Pair(urlEncode(name), urlEncode(valueToString(value)))); - } - - /** - * Convert a URL query name/collection parameter to a list of encoded {@link Pair} objects. - * - * @param collectionFormat The swagger collectionFormat string (csv, tsv, etc). - * @param name The query name parameter. - * @param values A collection of values for the given query name, which may be null. - * @return A list of {@link Pair} objects representing the input parameters, which is encoded - * for use in a URL. If the values collection is null, an empty list is returned. - */ - public static List parameterToPairs( - String collectionFormat, String name, Collection values) { - if (name == null || name.isEmpty() || values == null || values.isEmpty()) { - return Collections.emptyList(); - } - - // get the collection format (default: csv) - String format = - collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat; - - // create the params based on the collection format - if ("multi".equals(format)) { - return values.stream() - .map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value)))) - .collect(Collectors.toList()); - } - - String delimiter; - switch (format) { - case "csv": - delimiter = urlEncode(","); - break; - case "ssv": - delimiter = urlEncode(" "); - break; - case "tsv": - delimiter = urlEncode("\t"); - break; - case "pipes": - delimiter = urlEncode("|"); - break; - default: - throw new IllegalArgumentException( - "Illegal collection format: " + collectionFormat); - } - - StringJoiner joiner = new StringJoiner(delimiter); - for (Object value : values) { - joiner.add(urlEncode(valueToString(value))); - } - - return Collections.singletonList(new Pair(urlEncode(name), joiner.toString())); - } - - /** Create an instance of ApiClient. */ - public ApiClient() { - this.builder = createDefaultHttpClientBuilder(); - this.mapper = createDefaultObjectMapper(); - updateBaseUri(getDefaultBaseUri()); - interceptor = null; - readTimeout = null; - connectTimeout = null; - responseInterceptor = null; - asyncResponseInterceptor = null; - } - - /** - * Create an instance of ApiClient. - * - * @param builder Http client builder. - * @param mapper Object mapper. - * @param baseUri Base URI - */ - public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, String baseUri) { - this.builder = builder; - this.mapper = mapper; - updateBaseUri(baseUri != null ? baseUri : getDefaultBaseUri()); - interceptor = null; - readTimeout = null; - connectTimeout = null; - responseInterceptor = null; - asyncResponseInterceptor = null; + private HttpClient.Builder builder; + private ObjectMapper mapper; + private String scheme; + private String host; + private int port; + private String basePath; + private Consumer interceptor; + private Consumer> responseInterceptor; + private Consumer> asyncResponseInterceptor; + private Duration readTimeout; + private Duration connectTimeout; + + private static String valueToString(Object value) { + if (value == null) { + return ""; } - - protected ObjectMapper createDefaultObjectMapper() { - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); - mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); - mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); - mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); - mapper.registerModule(new JavaTimeModule()); - mapper.registerModule(new JsonNullableModule()); - return mapper; + if (value instanceof OffsetDateTime) { + return ((OffsetDateTime) value).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); } - - protected String getDefaultBaseUri() { - return "https://api.is.eng.pagopa.it"; + return value.toString(); + } + + /** + * URL encode a string in the UTF-8 encoding. + * + * @param s String to encode. + * @return URL-encoded representation of the input string. + */ + public static String urlEncode(String s) { + return URLEncoder.encode(s, UTF_8).replaceAll("\\+", "%20"); + } + + /** + * Convert a URL query name/value parameter to a list of encoded {@link Pair} + * objects. + * + *

The value can be null, in which case an empty list is returned.

+ * + * @param name The query name parameter. + * @param value The query value, which may not be a collection but may be + * null. + * @return A singleton list of the {@link Pair} objects representing the input + * parameters, which is encoded for use in a URL. If the value is null, an + * empty list is returned. + */ + public static List parameterToPairs(String name, Object value) { + if (name == null || name.isEmpty() || value == null) { + return Collections.emptyList(); } - - protected HttpClient.Builder createDefaultHttpClientBuilder() { - return HttpClient.newBuilder(); + return Collections.singletonList(new Pair(urlEncode(name), urlEncode(valueToString(value)))); + } + + /** + * Convert a URL query name/collection parameter to a list of encoded + * {@link Pair} objects. + * + * @param collectionFormat The swagger collectionFormat string (csv, tsv, etc). + * @param name The query name parameter. + * @param values A collection of values for the given query name, which may be + * null. + * @return A list of {@link Pair} objects representing the input parameters, + * which is encoded for use in a URL. If the values collection is null, an + * empty list is returned. + */ + public static List parameterToPairs( + String collectionFormat, String name, Collection values) { + if (name == null || name.isEmpty() || values == null || values.isEmpty()) { + return Collections.emptyList(); } - public void updateBaseUri(String baseUri) { - URI uri = URI.create(baseUri); - scheme = uri.getScheme(); - host = uri.getHost(); - port = uri.getPort(); - basePath = uri.getRawPath(); - } + // get the collection format (default: csv) + String format = collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat; - /** - * Set a custom {@link HttpClient.Builder} object to use when creating the {@link HttpClient} - * that is used by the API client. - * - * @param builder Custom client builder. - * @return This object. - */ - public ApiClient setHttpClientBuilder(HttpClient.Builder builder) { - this.builder = builder; - return this; + // create the params based on the collection format + if ("multi".equals(format)) { + return values.stream() + .map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value)))) + .collect(Collectors.toList()); } - /** - * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}. - * - *

The returned object is immutable and thread-safe. - * - * @return The HTTP client. - */ - public HttpClient getHttpClient() { - return builder.build(); + String delimiter; + switch(format) { + case "csv": + delimiter = urlEncode(","); + break; + case "ssv": + delimiter = urlEncode(" "); + break; + case "tsv": + delimiter = urlEncode("\t"); + break; + case "pipes": + delimiter = urlEncode("|"); + break; + default: + throw new IllegalArgumentException("Illegal collection format: " + collectionFormat); } - /** - * Set a custom {@link ObjectMapper} to serialize and deserialize the request and response - * bodies. - * - * @param mapper Custom object mapper. - * @return This object. - */ - public ApiClient setObjectMapper(ObjectMapper mapper) { - this.mapper = mapper; - return this; + StringJoiner joiner = new StringJoiner(delimiter); + for (Object value : values) { + joiner.add(urlEncode(valueToString(value))); } - /** - * Get a copy of the current {@link ObjectMapper}. - * - * @return A copy of the current object mapper. - */ - public ObjectMapper getObjectMapper() { - return mapper.copy(); - } - - /** - * Set a custom host name for the target service. - * - * @param host The host name of the target service. - * @return This object. - */ - public ApiClient setHost(String host) { - this.host = host; - return this; - } - - /** - * Set a custom port number for the target service. - * - * @param port The port of the target service. Set this to -1 to reset the value to the default - * for the scheme. - * @return This object. - */ - public ApiClient setPort(int port) { - this.port = port; - return this; - } - - /** - * Set a custom base path for the target service, for example '/v2'. - * - * @param basePath The base path against which the rest of the path is resolved. - * @return This object. - */ - public ApiClient setBasePath(String basePath) { - this.basePath = basePath; - return this; - } - - /** - * Get the base URI to resolve the endpoint paths against. - * - * @return The complete base URI that the rest of the API parameters are resolved against. - */ - public String getBaseUri() { - return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; - } - - /** - * Set a custom scheme for the target service, for example 'https'. - * - * @param scheme The scheme of the target service - * @return This object. - */ - public ApiClient setScheme(String scheme) { - this.scheme = scheme; - return this; - } - - /** - * Set a custom request interceptor. - * - *

A request interceptor is a mechanism for altering each request before it is sent. After - * the request has been fully configured but not yet built, the request builder is passed into - * this function for further modification, after which it is sent out. - * - *

This is useful for altering the requests in a custom manner, such as adding headers. It - * could also be used for logging and monitoring. - * - * @param interceptor A function invoked before creating each request. A value of null resets - * the interceptor to a no-op. - * @return This object. - */ - public ApiClient setRequestInterceptor(Consumer interceptor) { - this.interceptor = interceptor; - return this; - } - - /** - * Get the custom interceptor. - * - * @return The custom interceptor that was set, or null if there isn't any. - */ - public Consumer getRequestInterceptor() { - return interceptor; - } - - /** - * Set a custom response interceptor. - * - *

This is useful for logging, monitoring or extraction of header variables - * - * @param interceptor A function invoked before creating each request. A value of null resets - * the interceptor to a no-op. - * @return This object. - */ - public ApiClient setResponseInterceptor(Consumer> interceptor) { - this.responseInterceptor = interceptor; - return this; - } - - /** - * Get the custom response interceptor. - * - * @return The custom interceptor that was set, or null if there isn't any. - */ - public Consumer> getResponseInterceptor() { - return responseInterceptor; - } - - /** - * Set a custom async response interceptor. Use this interceptor when asyncNative is set to - * 'true'. - * - *

This is useful for logging, monitoring or extraction of header variables - * - * @param interceptor A function invoked before creating each request. A value of null resets - * the interceptor to a no-op. - * @return This object. - */ - public ApiClient setAsyncResponseInterceptor(Consumer> interceptor) { - this.asyncResponseInterceptor = interceptor; - return this; - } - - /** - * Get the custom async response interceptor. Use this interceptor when asyncNative is set to - * 'true'. - * - * @return The custom interceptor that was set, or null if there isn't any. - */ - public Consumer> getAsyncResponseInterceptor() { - return asyncResponseInterceptor; - } - - /** - * Set the read timeout for the http client. - * - *

This is the value used by default for each request, though it can be overridden on a - * per-request basis with a request interceptor. - * - * @param readTimeout The read timeout used by default by the http client. Setting this value to - * null resets the timeout to an effectively infinite value. - * @return This object. - */ - public ApiClient setReadTimeout(Duration readTimeout) { - this.readTimeout = readTimeout; - return this; - } - - /** - * Get the read timeout that was set. - * - * @return The read timeout, or null if no timeout was set. Null represents an infinite wait - * time. - */ - public Duration getReadTimeout() { - return readTimeout; - } - /** - * Sets the connect timeout (in milliseconds) for the http client. - * - *

In the case where a new connection needs to be established, if the connection cannot be - * established within the given {@code duration}, then {@link - * HttpClient#send(HttpRequest,BodyHandler) HttpClient::send} throws an {@link - * HttpConnectTimeoutException}, or {@link HttpClient#sendAsync(HttpRequest,BodyHandler) - * HttpClient::sendAsync} completes exceptionally with an {@code HttpConnectTimeoutException}. - * If a new connection does not need to be established, for example if a connection can be - * reused from a previous request, then this timeout duration has no effect. - * - * @param connectTimeout connection timeout in milliseconds - * @return This object. - */ - public ApiClient setConnectTimeout(Duration connectTimeout) { - this.connectTimeout = connectTimeout; - this.builder.connectTimeout(connectTimeout); - return this; - } - - /** - * Get connection timeout (in milliseconds). - * - * @return Timeout in milliseconds - */ - public Duration getConnectTimeout() { - return connectTimeout; - } + return Collections.singletonList(new Pair(urlEncode(name), joiner.toString())); + } + + /** + * Create an instance of ApiClient. + */ + public ApiClient() { + this.builder = createDefaultHttpClientBuilder(); + this.mapper = createDefaultObjectMapper(); + updateBaseUri(getDefaultBaseUri()); + interceptor = null; + readTimeout = null; + connectTimeout = null; + responseInterceptor = null; + asyncResponseInterceptor = null; + } + + /** + * Create an instance of ApiClient. + * + * @param builder Http client builder. + * @param mapper Object mapper. + * @param baseUri Base URI + */ + public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, String baseUri) { + this.builder = builder; + this.mapper = mapper; + updateBaseUri(baseUri != null ? baseUri : getDefaultBaseUri()); + interceptor = null; + readTimeout = null; + connectTimeout = null; + responseInterceptor = null; + asyncResponseInterceptor = null; + } + + protected ObjectMapper createDefaultObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); + mapper.registerModule(new JavaTimeModule()); + mapper.registerModule(new JsonNullableModule()); + return mapper; + } + + protected String getDefaultBaseUri() { + return "https://api.is.eng.pagopa.it"; + } + + protected HttpClient.Builder createDefaultHttpClientBuilder() { + return HttpClient.newBuilder(); + } + + public void updateBaseUri(String baseUri) { + URI uri = URI.create(baseUri); + scheme = uri.getScheme(); + host = uri.getHost(); + port = uri.getPort(); + basePath = uri.getRawPath(); + } + + /** + * Set a custom {@link HttpClient.Builder} object to use when creating the + * {@link HttpClient} that is used by the API client. + * + * @param builder Custom client builder. + * @return This object. + */ + public ApiClient setHttpClientBuilder(HttpClient.Builder builder) { + this.builder = builder; + return this; + } + + /** + * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}. + * + *

The returned object is immutable and thread-safe.

+ * + * @return The HTTP client. + */ + public HttpClient getHttpClient() { + return builder.build(); + } + + /** + * Set a custom {@link ObjectMapper} to serialize and deserialize the request + * and response bodies. + * + * @param mapper Custom object mapper. + * @return This object. + */ + public ApiClient setObjectMapper(ObjectMapper mapper) { + this.mapper = mapper; + return this; + } + + /** + * Get a copy of the current {@link ObjectMapper}. + * + * @return A copy of the current object mapper. + */ + public ObjectMapper getObjectMapper() { + return mapper.copy(); + } + + /** + * Set a custom host name for the target service. + * + * @param host The host name of the target service. + * @return This object. + */ + public ApiClient setHost(String host) { + this.host = host; + return this; + } + + /** + * Set a custom port number for the target service. + * + * @param port The port of the target service. Set this to -1 to reset the + * value to the default for the scheme. + * @return This object. + */ + public ApiClient setPort(int port) { + this.port = port; + return this; + } + + /** + * Set a custom base path for the target service, for example '/v2'. + * + * @param basePath The base path against which the rest of the path is + * resolved. + * @return This object. + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get the base URI to resolve the endpoint paths against. + * + * @return The complete base URI that the rest of the API parameters are + * resolved against. + */ + public String getBaseUri() { + return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; + } + + /** + * Set a custom scheme for the target service, for example 'https'. + * + * @param scheme The scheme of the target service + * @return This object. + */ + public ApiClient setScheme(String scheme){ + this.scheme = scheme; + return this; + } + + /** + * Set a custom request interceptor. + * + *

A request interceptor is a mechanism for altering each request before it + * is sent. After the request has been fully configured but not yet built, the + * request builder is passed into this function for further modification, + * after which it is sent out.

+ * + *

This is useful for altering the requests in a custom manner, such as + * adding headers. It could also be used for logging and monitoring.

+ * + * @param interceptor A function invoked before creating each request. A value + * of null resets the interceptor to a no-op. + * @return This object. + */ + public ApiClient setRequestInterceptor(Consumer interceptor) { + this.interceptor = interceptor; + return this; + } + + /** + * Get the custom interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer getRequestInterceptor() { + return interceptor; + } + + /** + * Set a custom response interceptor. + * + *

This is useful for logging, monitoring or extraction of header variables

+ * + * @param interceptor A function invoked before creating each request. A value + * of null resets the interceptor to a no-op. + * @return This object. + */ + public ApiClient setResponseInterceptor(Consumer> interceptor) { + this.responseInterceptor = interceptor; + return this; + } + + /** + * Get the custom response interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getResponseInterceptor() { + return responseInterceptor; + } + + /** + * Set a custom async response interceptor. Use this interceptor when asyncNative is set to 'true'. + * + *

This is useful for logging, monitoring or extraction of header variables

+ * + * @param interceptor A function invoked before creating each request. A value + * of null resets the interceptor to a no-op. + * @return This object. + */ + public ApiClient setAsyncResponseInterceptor(Consumer> interceptor) { + this.asyncResponseInterceptor = interceptor; + return this; + } + + /** + * Get the custom async response interceptor. Use this interceptor when asyncNative is set to 'true'. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getAsyncResponseInterceptor() { + return asyncResponseInterceptor; + } + + /** + * Set the read timeout for the http client. + * + *

This is the value used by default for each request, though it can be + * overridden on a per-request basis with a request interceptor.

+ * + * @param readTimeout The read timeout used by default by the http client. + * Setting this value to null resets the timeout to an + * effectively infinite value. + * @return This object. + */ + public ApiClient setReadTimeout(Duration readTimeout) { + this.readTimeout = readTimeout; + return this; + } + + /** + * Get the read timeout that was set. + * + * @return The read timeout, or null if no timeout was set. Null represents + * an infinite wait time. + */ + public Duration getReadTimeout() { + return readTimeout; + } + /** + * Sets the connect timeout (in milliseconds) for the http client. + * + *

In the case where a new connection needs to be established, if + * the connection cannot be established within the given {@code + * duration}, then {@link HttpClient#send(HttpRequest,BodyHandler) + * HttpClient::send} throws an {@link HttpConnectTimeoutException}, or + * {@link HttpClient#sendAsync(HttpRequest,BodyHandler) + * HttpClient::sendAsync} completes exceptionally with an + * {@code HttpConnectTimeoutException}. If a new connection does not + * need to be established, for example if a connection can be reused + * from a previous request, then this timeout duration has no effect. + * + * @param connectTimeout connection timeout in milliseconds + * + * @return This object. + */ + public ApiClient setConnectTimeout(Duration connectTimeout) { + this.connectTimeout = connectTimeout; + this.builder.connectTimeout(connectTimeout); + return this; + } + + /** + * Get connection timeout (in milliseconds). + * + * @return Timeout in milliseconds + */ + public Duration getConnectTimeout() { + return connectTimeout; + } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java index 5297d641..b4f92de1 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java @@ -1,11 +1,21 @@ -/* (C)2022-2023 */ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; import java.net.http.HttpHeaders; -@javax.annotation.Generated( - value = "org.openapitools.codegen.languages.JavaClientCodegen", - date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class ApiException extends RuntimeException { private int code = 0; private HttpHeaders responseHeaders = null; @@ -21,25 +31,18 @@ public ApiException(String message) { super(message); } - public ApiException( - String message, - Throwable throwable, - int code, - HttpHeaders responseHeaders, - String responseBody) { + public ApiException(String message, Throwable throwable, int code, HttpHeaders responseHeaders, String responseBody) { super(message, throwable); this.code = code; this.responseHeaders = responseHeaders; this.responseBody = responseBody; } - public ApiException( - String message, int code, HttpHeaders responseHeaders, String responseBody) { + public ApiException(String message, int code, HttpHeaders responseHeaders, String responseBody) { this(message, (Throwable) null, code, responseHeaders, responseBody); } - public ApiException( - String message, Throwable throwable, int code, HttpHeaders responseHeaders) { + public ApiException(String message, Throwable throwable, int code, HttpHeaders responseHeaders) { this(message, throwable, code, responseHeaders, null); } @@ -52,8 +55,7 @@ public ApiException(int code, String message) { this.code = code; } - public ApiException( - int code, String message, HttpHeaders responseHeaders, String responseBody) { + public ApiException(int code, String message, HttpHeaders responseHeaders, String responseBody) { this(code, message); this.responseHeaders = responseHeaders; this.responseBody = responseBody; diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java index 582e0a4d..04d5fc8c 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java @@ -1,4 +1,16 @@ -/* (C)2022-2023 */ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; import java.util.List; @@ -10,9 +22,9 @@ * @param The type of data that is deserialized from response body */ public class ApiResponse { - private final int statusCode; - private final Map> headers; - private final T data; + final private int statusCode; + final private Map> headers; + final private T data; /** * @param statusCode The status code of HTTP response diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java index cbc956b8..44af4652 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java @@ -1,15 +1,25 @@ -/* (C)2022-2023 */ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; -@javax.annotation.Generated( - value = "org.openapitools.codegen.languages.JavaClientCodegen", - date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class Configuration { private static ApiClient defaultApiClient = new ApiClient(); /** - * Get the default API client, which would be used when creating API instances without providing - * an API client. + * Get the default API client, which would be used when creating API + * instances without providing an API client. * * @return Default API client */ @@ -18,8 +28,8 @@ public static ApiClient getDefaultApiClient() { } /** - * Set the default API client, which would be used when creating API instances without providing - * an API client. + * Set the default API client, which would be used when creating API + * instances without providing an API client. * * @param apiClient API client */ diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java index 889ef90a..fc1b5610 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java @@ -1,246 +1,247 @@ -/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; -import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.openapitools.jackson.nullable.JsonNullableModule; + import java.text.DateFormat; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import org.openapitools.jackson.nullable.JsonNullableModule; -@javax.annotation.Generated( - value = "org.openapitools.codegen.languages.JavaClientCodegen", - date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class JSON { - private ObjectMapper mapper; - - public JSON() { - mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); - mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); - mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); - mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); - mapper.setDateFormat(new RFC3339DateFormat()); - mapper.registerModule(new JavaTimeModule()); - JsonNullableModule jnm = new JsonNullableModule(); - mapper.registerModule(jnm); + private ObjectMapper mapper; + + public JSON() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + mapper.registerModule(new JavaTimeModule()); + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + } + + /** + * Set the date format for JSON (de)serialization with Date properties. + * + * @param dateFormat Date format + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + + /** + * Get the object mapper + * + * @return object mapper + */ + public ObjectMapper getMapper() { return mapper; } + + /** + * Returns the target model class that should be used to deserialize the input data. + * The discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param modelClass The class that contains the discriminator mappings. + * + * @return the target model class. + */ + public static Class getClassForElement(JsonNode node, Class modelClass) { + ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass); + if (cdm != null) { + return cdm.getClassForElement(node, new HashSet>()); } - - /** - * Set the date format for JSON (de)serialization with Date properties. - * - * @param dateFormat Date format - */ - public void setDateFormat(DateFormat dateFormat) { - mapper.setDateFormat(dateFormat); + return null; + } + + /** + * Helper class to register the discriminator mappings. + */ + private static class ClassDiscriminatorMapping { + // The model class name. + Class modelClass; + // The name of the discriminator property. + String discriminatorName; + // The discriminator mappings for a model class. + Map> discriminatorMappings; + + // Constructs a new class discriminator. + ClassDiscriminatorMapping(Class cls, String propertyName, Map> mappings) { + modelClass = cls; + discriminatorName = propertyName; + discriminatorMappings = new HashMap>(); + if (mappings != null) { + discriminatorMappings.putAll(mappings); + } } - /** - * Get the object mapper - * - * @return object mapper - */ - public ObjectMapper getMapper() { - return mapper; + // Return the name of the discriminator property for this model class. + String getDiscriminatorPropertyName() { + return discriminatorName; } - /** - * Returns the target model class that should be used to deserialize the input data. The - * discriminator mappings are used to determine the target model class. - * - * @param node The input data. - * @param modelClass The class that contains the discriminator mappings. - * @return the target model class. - */ - public static Class getClassForElement(JsonNode node, Class modelClass) { - ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass); - if (cdm != null) { - return cdm.getClassForElement(node, new HashSet>()); - } - return null; - } - - /** Helper class to register the discriminator mappings. */ - private static class ClassDiscriminatorMapping { - // The model class name. - Class modelClass; - // The name of the discriminator property. - String discriminatorName; - // The discriminator mappings for a model class. - Map> discriminatorMappings; - - // Constructs a new class discriminator. - ClassDiscriminatorMapping( - Class cls, String propertyName, Map> mappings) { - modelClass = cls; - discriminatorName = propertyName; - discriminatorMappings = new HashMap>(); - if (mappings != null) { - discriminatorMappings.putAll(mappings); - } - } - - // Return the name of the discriminator property for this model class. - String getDiscriminatorPropertyName() { - return discriminatorName; - } - - // Return the discriminator value or null if the discriminator is not - // present in the payload. - String getDiscriminatorValue(JsonNode node) { - // Determine the value of the discriminator property in the input data. - if (discriminatorName != null) { - // Get the value of the discriminator property, if present in the input payload. - node = node.get(discriminatorName); - if (node != null && node.isValueNode()) { - String discrValue = node.asText(); - if (discrValue != null) { - return discrValue; - } - } - } - return null; - } - - /** - * Returns the target model class that should be used to deserialize the input data. This - * function can be invoked for anyOf/oneOf composed models with discriminator mappings. The - * discriminator mappings are used to determine the target model class. - * - * @param node The input data. - * @param visitedClasses The set of classes that have already been visited. - * @return the target model class. - */ - Class getClassForElement(JsonNode node, Set> visitedClasses) { - if (visitedClasses.contains(modelClass)) { - // Class has already been visited. - return null; - } - // Determine the value of the discriminator property in the input data. - String discrValue = getDiscriminatorValue(node); - if (discrValue == null) { - return null; - } - Class cls = discriminatorMappings.get(discrValue); - // It may not be sufficient to return this cls directly because that target class - // may itself be a composed schema, possibly with its own discriminator. - visitedClasses.add(modelClass); - for (Class childClass : discriminatorMappings.values()) { - ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass); - if (childCdm == null) { - continue; - } - if (!discriminatorName.equals(childCdm.discriminatorName)) { - discrValue = getDiscriminatorValue(node); - if (discrValue == null) { - continue; - } - } - if (childCdm != null) { - // Recursively traverse the discriminator mappings. - Class childDiscr = childCdm.getClassForElement(node, visitedClasses); - if (childDiscr != null) { - return childDiscr; - } - } - } - return cls; + // Return the discriminator value or null if the discriminator is not + // present in the payload. + String getDiscriminatorValue(JsonNode node) { + // Determine the value of the discriminator property in the input data. + if (discriminatorName != null) { + // Get the value of the discriminator property, if present in the input payload. + node = node.get(discriminatorName); + if (node != null && node.isValueNode()) { + String discrValue = node.asText(); + if (discrValue != null) { + return discrValue; + } } + } + return null; } /** - * Returns true if inst is an instance of modelClass in the OpenAPI model hierarchy. - * - *

The Java class hierarchy is not implemented the same way as the OpenAPI model hierarchy, - * so it's not possible to use the instanceof keyword. + * Returns the target model class that should be used to deserialize the input data. + * This function can be invoked for anyOf/oneOf composed models with discriminator mappings. + * The discriminator mappings are used to determine the target model class. * - * @param modelClass A OpenAPI model class. - * @param inst The instance object. + * @param node The input data. * @param visitedClasses The set of classes that have already been visited. - * @return true if inst is an instance of modelClass in the OpenAPI model hierarchy. + * + * @return the target model class. */ - public static boolean isInstanceOf( - Class modelClass, Object inst, Set> visitedClasses) { - if (modelClass.isInstance(inst)) { - // This handles the 'allOf' use case with single parent inheritance. - return true; + Class getClassForElement(JsonNode node, Set> visitedClasses) { + if (visitedClasses.contains(modelClass)) { + // Class has already been visited. + return null; + } + // Determine the value of the discriminator property in the input data. + String discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + return null; + } + Class cls = discriminatorMappings.get(discrValue); + // It may not be sufficient to return this cls directly because that target class + // may itself be a composed schema, possibly with its own discriminator. + visitedClasses.add(modelClass); + for (Class childClass : discriminatorMappings.values()) { + ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass); + if (childCdm == null) { + continue; } - if (visitedClasses.contains(modelClass)) { - // This is to prevent infinite recursion when the composed schemas have - // a circular dependency. - return false; + if (!discriminatorName.equals(childCdm.discriminatorName)) { + discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + continue; + } } - visitedClasses.add(modelClass); - - // Traverse the oneOf/anyOf composed schemas. - Map> descendants = modelDescendants.get(modelClass); - if (descendants != null) { - for (Class childType : descendants.values()) { - if (isInstanceOf(childType, inst, visitedClasses)) { - return true; - } - } + if (childCdm != null) { + // Recursively traverse the discriminator mappings. + Class childDiscr = childCdm.getClassForElement(node, visitedClasses); + if (childDiscr != null) { + return childDiscr; + } } - return false; + } + return cls; } - - /** A map of discriminators for all model classes. */ - private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap<>(); - - /** A map of oneOf/anyOf descendants for each model class. */ - private static Map, Map>> modelDescendants = new HashMap<>(); - - /** - * Register a model class discriminator. - * - * @param modelClass the model class - * @param discriminatorPropertyName the name of the discriminator property - * @param mappings a map with the discriminator mappings. - */ - public static void registerDiscriminator( - Class modelClass, String discriminatorPropertyName, Map> mappings) { - ClassDiscriminatorMapping m = - new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings); - modelDiscriminators.put(modelClass, m); + } + + /** + * Returns true if inst is an instance of modelClass in the OpenAPI model hierarchy. + * + * The Java class hierarchy is not implemented the same way as the OpenAPI model hierarchy, + * so it's not possible to use the instanceof keyword. + * + * @param modelClass A OpenAPI model class. + * @param inst The instance object. + * @param visitedClasses The set of classes that have already been visited. + * + * @return true if inst is an instance of modelClass in the OpenAPI model hierarchy. + */ + public static boolean isInstanceOf(Class modelClass, Object inst, Set> visitedClasses) { + if (modelClass.isInstance(inst)) { + // This handles the 'allOf' use case with single parent inheritance. + return true; } - - /** - * Register the oneOf/anyOf descendants of the modelClass. - * - * @param modelClass the model class - * @param descendants a map of oneOf/anyOf descendants. - */ - public static void registerDescendants(Class modelClass, Map> descendants) { - modelDescendants.put(modelClass, descendants); + if (visitedClasses.contains(modelClass)) { + // This is to prevent infinite recursion when the composed schemas have + // a circular dependency. + return false; } - - private static JSON json; - - static { - json = new JSON(); - } - - /** - * Get the default JSON instance. - * - * @return the default JSON instance - */ - public static JSON getDefault() { - return json; - } - - /** - * Set the default JSON instance. - * - * @param json JSON instance to be used - */ - public static void setDefault(JSON json) { - JSON.json = json; + visitedClasses.add(modelClass); + + // Traverse the oneOf/anyOf composed schemas. + Map> descendants = modelDescendants.get(modelClass); + if (descendants != null) { + for (Class childType : descendants.values()) { + if (isInstanceOf(childType, inst, visitedClasses)) { + return true; + } + } } + return false; + } + + /** + * A map of discriminators for all model classes. + */ + private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap<>(); + + /** + * A map of oneOf/anyOf descendants for each model class. + */ + private static Map, Map>> modelDescendants = new HashMap<>(); + + /** + * Register a model class discriminator. + * + * @param modelClass the model class + * @param discriminatorPropertyName the name of the discriminator property + * @param mappings a map with the discriminator mappings. + */ + public static void registerDiscriminator(Class modelClass, String discriminatorPropertyName, Map> mappings) { + ClassDiscriminatorMapping m = new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings); + modelDiscriminators.put(modelClass, m); + } + + /** + * Register the oneOf/anyOf descendants of the modelClass. + * + * @param modelClass the model class + * @param descendants a map of oneOf/anyOf descendants. + */ + public static void registerDescendants(Class modelClass, Map> descendants) { + modelDescendants.put(modelClass, descendants); + } + + private static JSON json; + + static { + json = new JSON(); + } + + /** + * Get the default JSON instance. + * + * @return the default JSON instance + */ + public static JSON getDefault() { + return json; + } + + /** + * Set the default JSON instance. + * + * @param json JSON instance to be used + */ + public static void setDefault(JSON json) { + JSON.json = json; + } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java index 68b71c24..8d1d80c2 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java @@ -1,14 +1,24 @@ -/* (C)2022-2023 */ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; -@javax.annotation.Generated( - value = "org.openapitools.codegen.languages.JavaClientCodegen", - date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class Pair { private String name = ""; private String value = ""; - public Pair(String name, String value) { + public Pair (String name, String value) { setName(name); setValue(value); } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java index eb26f968..57853d22 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java @@ -1,7 +1,19 @@ -/* (C)2022-2023 */ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; import com.fasterxml.jackson.databind.util.StdDateFormat; + import java.text.DateFormat; import java.text.DecimalFormat; import java.text.FieldPosition; @@ -11,34 +23,35 @@ import java.util.TimeZone; public class RFC3339DateFormat extends DateFormat { - private static final long serialVersionUID = 1L; - private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); - - private final StdDateFormat fmt = - new StdDateFormat().withTimeZone(TIMEZONE_Z).withColonInTimeZone(true); - - public RFC3339DateFormat() { - this.calendar = new GregorianCalendar(); - this.numberFormat = new DecimalFormat(); - } - - @Override - public Date parse(String source) { - return parse(source, new ParsePosition(0)); - } - - @Override - public Date parse(String source, ParsePosition pos) { - return fmt.parse(source, pos); - } - - @Override - public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { - return fmt.format(date, toAppendTo, fieldPosition); - } - - @Override - public Object clone() { - return super.clone(); - } -} + private static final long serialVersionUID = 1L; + private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); + + private final StdDateFormat fmt = new StdDateFormat() + .withTimeZone(TIMEZONE_Z) + .withColonInTimeZone(true); + + public RFC3339DateFormat() { + this.calendar = new GregorianCalendar(); + this.numberFormat = new DecimalFormat(); + } + + @Override + public Date parse(String source) { + return parse(source, new ParsePosition(0)); + } + + @Override + public Date parse(String source, ParsePosition pos) { + return fmt.parse(source, pos); + } + + @Override + public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { + return fmt.format(date, toAppendTo, fieldPosition); + } + + @Override + public Object clone() { + return super.clone(); + } +} \ No newline at end of file diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java index 747b99ab..33501d36 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java @@ -1,9 +1,10 @@ -/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; import java.util.Map; -/** Representing a Server configuration. */ +/** + * Representing a Server configuration. + */ public class ServerConfiguration { public String URL; public String description; @@ -12,11 +13,9 @@ public class ServerConfiguration { /** * @param URL A URL to the target host. * @param description A description of the host designated by the URL. - * @param variables A map between a variable name and its value. The value is used for - * substitution in the server's URL template. + * @param variables A map between a variable name and its value. The value is used for substitution in the server's URL template. */ - public ServerConfiguration( - String URL, String description, Map variables) { + public ServerConfiguration(String URL, String description, Map variables) { this.URL = URL; this.description = description; this.variables = variables; @@ -32,21 +31,15 @@ public String URL(Map variables) { String url = this.URL; // go through variables and replace placeholders - for (Map.Entry variable : this.variables.entrySet()) { + for (Map.Entry variable: this.variables.entrySet()) { String name = variable.getKey(); ServerVariable serverVariable = variable.getValue(); String value = serverVariable.defaultValue; if (variables != null && variables.containsKey(name)) { value = variables.get(name); - if (serverVariable.enumValues.size() > 0 - && !serverVariable.enumValues.contains(value)) { - throw new IllegalArgumentException( - "The variable " - + name - + " in the server URL has invalid value " - + value - + "."); + if (serverVariable.enumValues.size() > 0 && !serverVariable.enumValues.contains(value)) { + throw new IllegalArgumentException("The variable " + name + " in the server URL has invalid value " + value + "."); } } url = url.replace("{" + name + "}", value); diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java index f0bb418a..c06da593 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java @@ -1,9 +1,10 @@ -/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; import java.util.HashSet; -/** Representing a Server Variable for server URL template substitution. */ +/** + * Representing a Server Variable for server URL template substitution. + */ public class ServerVariable { public String description; public String defaultValue; @@ -12,8 +13,7 @@ public class ServerVariable { /** * @param description A description for the server variable. * @param defaultValue The default value to use for substitution. - * @param enumValues An enumeration of string values to be used if the substitution options are - * from a limited set. + * @param enumValues An enumeration of string values to be used if the substitution options are from a limited set. */ public ServerVariable(String description, String defaultValue, HashSet enumValues) { this.description = description; diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java index e58deef0..a061221b 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java @@ -1,317 +1,344 @@ -/* (C)2022-2023 */ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.api; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiResponse; -import java.io.IOException; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.CertData; + import java.io.InputStream; +import java.io.IOException; +import java.net.http.HttpRequest; import java.net.URI; import java.net.http.HttpClient; -import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; + +import java.util.List; import java.util.function.Consumer; -@javax.annotation.Generated( - value = "org.openapitools.codegen.languages.JavaClientCodegen", - date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class DefaultApi { - private final HttpClient memberVarHttpClient; - private final ObjectMapper memberVarObjectMapper; - private final String memberVarBaseUri; - private final Consumer memberVarInterceptor; - private final Duration memberVarReadTimeout; - private final Consumer> memberVarResponseInterceptor; - private final Consumer> memberVarAsyncResponseInterceptor; - - public DefaultApi() { - this(new ApiClient()); - } - - public DefaultApi(ApiClient apiClient) { - memberVarHttpClient = apiClient.getHttpClient(); - memberVarObjectMapper = apiClient.getObjectMapper(); - memberVarBaseUri = apiClient.getBaseUri(); - memberVarInterceptor = apiClient.getRequestInterceptor(); - memberVarReadTimeout = apiClient.getReadTimeout(); - memberVarResponseInterceptor = apiClient.getResponseInterceptor(); - memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); + private final HttpClient memberVarHttpClient; + private final ObjectMapper memberVarObjectMapper; + private final String memberVarBaseUri; + private final Consumer memberVarInterceptor; + private final Duration memberVarReadTimeout; + private final Consumer> memberVarResponseInterceptor; + private final Consumer> memberVarAsyncResponseInterceptor; + + public DefaultApi() { + this(new ApiClient()); + } + + public DefaultApi(ApiClient apiClient) { + memberVarHttpClient = apiClient.getHttpClient(); + memberVarObjectMapper = apiClient.getObjectMapper(); + memberVarBaseUri = apiClient.getBaseUri(); + memberVarInterceptor = apiClient.getRequestInterceptor(); + memberVarReadTimeout = apiClient.getReadTimeout(); + memberVarResponseInterceptor = apiClient.getResponseInterceptor(); + memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); + } + + protected ApiException getApiException(String operationId, HttpResponse response) throws IOException { + String body = response.body() == null ? null : new String(response.body().readAllBytes()); + String message = formatExceptionMessage(operationId, response.statusCode(), body); + return new ApiException(response.statusCode(), message, response.headers(), body); + } + + private String formatExceptionMessage(String operationId, int statusCode, String body) { + if (body == null || body.isEmpty()) { + body = "[no body]"; } - - protected ApiException getApiException(String operationId, HttpResponse response) - throws IOException { - String body = response.body() == null ? null : new String(response.body().readAllBytes()); - String message = formatExceptionMessage(operationId, response.statusCode(), body); - return new ApiException(response.statusCode(), message, response.headers(), body); - } - - private String formatExceptionMessage(String operationId, int statusCode, String body) { - if (body == null || body.isEmpty()) { - body = "[no body]"; + return operationId + " call failed with: " + statusCode + " - " + body; + } + + /** + * + * + * @return List<String> + * @throws ApiException if fails to make API call + */ + public List idpKeysCieGet() throws ApiException { + ApiResponse> localVarResponse = idpKeysCieGetWithHttpInfo(); + return localVarResponse.getData(); + } + + /** + * + * + * @return ApiResponse<List<String>> + * @throws ApiException if fails to make API call + */ + public ApiResponse> idpKeysCieGetWithHttpInfo() throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysCieGetRequestBuilder(); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode()/ 100 != 2) { + throw getApiException("idpKeysCieGet", localVarResponse); } - return operationId + " call failed with: " + statusCode + " - " + body; + return new ApiResponse>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference>() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); } - - /** - * @throws ApiException if fails to make API call - */ - public void idpKeysCieGet() throws ApiException { - idpKeysCieGetWithHttpInfo(); + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); } + } - /** - * @return ApiResponse<Void> - * @throws ApiException if fails to make API call - */ - public ApiResponse idpKeysCieGetWithHttpInfo() throws ApiException { - HttpRequest.Builder localVarRequestBuilder = idpKeysCieGetRequestBuilder(); - try { - HttpResponse localVarResponse = - memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - try { - if (localVarResponse.statusCode() / 100 != 2) { - throw getApiException("idpKeysCieGet", localVarResponse); - } - return new ApiResponse( - localVarResponse.statusCode(), localVarResponse.headers().map(), null); - } finally { - // Drain the InputStream - while (localVarResponse.body().read() != -1) { - // Ignore - } - localVarResponse.body().close(); - } - } catch (IOException e) { - throw new ApiException(e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); - } - } - - private HttpRequest.Builder idpKeysCieGetRequestBuilder() throws ApiException { + private HttpRequest.Builder idpKeysCieGetRequestBuilder() throws ApiException { - HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); - String localVarPath = "/idp-keys/cie"; + String localVarPath = "/idp-keys/cie"; - localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); - localVarRequestBuilder.header("Accept", "application/json"); + localVarRequestBuilder.header("Accept", "application/json"); - localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); - } - return localVarRequestBuilder; + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); } - /** - * @param tag (required) - * @throws ApiException if fails to make API call - */ - public void idpKeysCieTagGet(String tag) throws ApiException { - idpKeysCieTagGetWithHttpInfo(tag); + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); } - - /** - * @param tag (required) - * @return ApiResponse<Void> - * @throws ApiException if fails to make API call - */ - public ApiResponse idpKeysCieTagGetWithHttpInfo(String tag) throws ApiException { - HttpRequest.Builder localVarRequestBuilder = idpKeysCieTagGetRequestBuilder(tag); - try { - HttpResponse localVarResponse = - memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - try { - if (localVarResponse.statusCode() / 100 != 2) { - throw getApiException("idpKeysCieTagGet", localVarResponse); - } - return new ApiResponse( - localVarResponse.statusCode(), localVarResponse.headers().map(), null); - } finally { - // Drain the InputStream - while (localVarResponse.body().read() != -1) { - // Ignore - } - localVarResponse.body().close(); - } - } catch (IOException e) { - throw new ApiException(e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); + return localVarRequestBuilder; + } + /** + * + * + * @param tag (required) + * @return CertData + * @throws ApiException if fails to make API call + */ + public CertData idpKeysCieTagGet(String tag) throws ApiException { + ApiResponse localVarResponse = idpKeysCieTagGetWithHttpInfo(tag); + return localVarResponse.getData(); + } + + /** + * + * + * @param tag (required) + * @return ApiResponse<CertData> + * @throws ApiException if fails to make API call + */ + public ApiResponse idpKeysCieTagGetWithHttpInfo(String tag) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysCieTagGetRequestBuilder(tag); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode()/ 100 != 2) { + throw getApiException("idpKeysCieTagGet", localVarResponse); } + return new ApiResponse( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); } + } - private HttpRequest.Builder idpKeysCieTagGetRequestBuilder(String tag) throws ApiException { - // verify the required parameter 'tag' is set - if (tag == null) { - throw new ApiException( - 400, "Missing the required parameter 'tag' when calling idpKeysCieTagGet"); - } + private HttpRequest.Builder idpKeysCieTagGetRequestBuilder(String tag) throws ApiException { + // verify the required parameter 'tag' is set + if (tag == null) { + throw new ApiException(400, "Missing the required parameter 'tag' when calling idpKeysCieTagGet"); + } - HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); - String localVarPath = - "/idp-keys/cie/{tag}".replace("{tag}", ApiClient.urlEncode(tag.toString())); + String localVarPath = "/idp-keys/cie/{tag}" + .replace("{tag}", ApiClient.urlEncode(tag.toString())); - localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); - localVarRequestBuilder.header("Accept", "application/json"); + localVarRequestBuilder.header("Accept", "application/xml, application/json"); - localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); - } - return localVarRequestBuilder; + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); } - /** - * @throws ApiException if fails to make API call - */ - public void idpKeysSpidGet() throws ApiException { - idpKeysSpidGetWithHttpInfo(); + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); } - - /** - * @return ApiResponse<Void> - * @throws ApiException if fails to make API call - */ - public ApiResponse idpKeysSpidGetWithHttpInfo() throws ApiException { - HttpRequest.Builder localVarRequestBuilder = idpKeysSpidGetRequestBuilder(); - try { - HttpResponse localVarResponse = - memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - try { - if (localVarResponse.statusCode() / 100 != 2) { - throw getApiException("idpKeysSpidGet", localVarResponse); - } - return new ApiResponse( - localVarResponse.statusCode(), localVarResponse.headers().map(), null); - } finally { - // Drain the InputStream - while (localVarResponse.body().read() != -1) { - // Ignore - } - localVarResponse.body().close(); - } - } catch (IOException e) { - throw new ApiException(e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); + return localVarRequestBuilder; + } + /** + * + * + * @return List<String> + * @throws ApiException if fails to make API call + */ + public List idpKeysSpidGet() throws ApiException { + ApiResponse> localVarResponse = idpKeysSpidGetWithHttpInfo(); + return localVarResponse.getData(); + } + + /** + * + * + * @return ApiResponse<List<String>> + * @throws ApiException if fails to make API call + */ + public ApiResponse> idpKeysSpidGetWithHttpInfo() throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysSpidGetRequestBuilder(); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode()/ 100 != 2) { + throw getApiException("idpKeysSpidGet", localVarResponse); } + return new ApiResponse>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference>() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } - private HttpRequest.Builder idpKeysSpidGetRequestBuilder() throws ApiException { + private HttpRequest.Builder idpKeysSpidGetRequestBuilder() throws ApiException { - HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); - String localVarPath = "/idp-keys/spid"; + String localVarPath = "/idp-keys/spid"; - localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); - localVarRequestBuilder.header("Accept", "application/json"); + localVarRequestBuilder.header("Accept", "application/json"); - localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); - } - return localVarRequestBuilder; + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); } - /** - * @param tag (required) - * @throws ApiException if fails to make API call - */ - public void idpKeysSpidTagGet(String tag) throws ApiException { - idpKeysSpidTagGetWithHttpInfo(tag); + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); } - - /** - * @param tag (required) - * @return ApiResponse<Void> - * @throws ApiException if fails to make API call - */ - public ApiResponse idpKeysSpidTagGetWithHttpInfo(String tag) throws ApiException { - HttpRequest.Builder localVarRequestBuilder = idpKeysSpidTagGetRequestBuilder(tag); - try { - HttpResponse localVarResponse = - memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - try { - if (localVarResponse.statusCode() / 100 != 2) { - throw getApiException("idpKeysSpidTagGet", localVarResponse); - } - return new ApiResponse( - localVarResponse.statusCode(), localVarResponse.headers().map(), null); - } finally { - // Drain the InputStream - while (localVarResponse.body().read() != -1) { - // Ignore - } - localVarResponse.body().close(); - } - } catch (IOException e) { - throw new ApiException(e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); + return localVarRequestBuilder; + } + /** + * + * + * @param tag (required) + * @return CertData + * @throws ApiException if fails to make API call + */ + public CertData idpKeysSpidTagGet(String tag) throws ApiException { + ApiResponse localVarResponse = idpKeysSpidTagGetWithHttpInfo(tag); + return localVarResponse.getData(); + } + + /** + * + * + * @param tag (required) + * @return ApiResponse<CertData> + * @throws ApiException if fails to make API call + */ + public ApiResponse idpKeysSpidTagGetWithHttpInfo(String tag) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysSpidTagGetRequestBuilder(tag); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode()/ 100 != 2) { + throw getApiException("idpKeysSpidTagGet", localVarResponse); } + return new ApiResponse( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } - private HttpRequest.Builder idpKeysSpidTagGetRequestBuilder(String tag) throws ApiException { - // verify the required parameter 'tag' is set - if (tag == null) { - throw new ApiException( - 400, "Missing the required parameter 'tag' when calling idpKeysSpidTagGet"); - } + private HttpRequest.Builder idpKeysSpidTagGetRequestBuilder(String tag) throws ApiException { + // verify the required parameter 'tag' is set + if (tag == null) { + throw new ApiException(400, "Missing the required parameter 'tag' when calling idpKeysSpidTagGet"); + } - HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); - String localVarPath = - "/idp-keys/spid/{tag}".replace("{tag}", ApiClient.urlEncode(tag.toString())); + String localVarPath = "/idp-keys/spid/{tag}" + .replace("{tag}", ApiClient.urlEncode(tag.toString())); - localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); - localVarRequestBuilder.header("Accept", "application/json"); + localVarRequestBuilder.header("Accept", "application/xml, application/json"); - localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); - } - return localVarRequestBuilder; + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); } + return localVarRequestBuilder; + } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java index e5c342aa..688511a7 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java @@ -1,14 +1,28 @@ -/* (C)2022-2023 */ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; -import com.fasterxml.jackson.annotation.JsonValue; -import java.util.Map; import java.util.Objects; +import java.lang.reflect.Type; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonValue; -/** Abstract class for oneOf,anyOf schemas defined in OpenAPI spec */ -@javax.annotation.Generated( - value = "org.openapitools.codegen.languages.JavaClientCodegen", - date = "2023-04-06T16:49:13.589743300+02:00[Europe/Paris]") +/** + * Abstract class for oneOf,anyOf schemas defined in OpenAPI spec + */ +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public abstract class AbstractOpenApiSchema { // store the actual instance of the schema/object @@ -38,22 +52,17 @@ public AbstractOpenApiSchema(String schemaType, Boolean isNullable) { * @return an instance of the actual schema/object */ @JsonValue - public Object getActualInstance() { - return instance; - } + public Object getActualInstance() {return instance;} /** * Set the actual instance * * @param instance the actual instance of the schema/object */ - public void setActualInstance(Object instance) { - this.instance = instance; - } + public void setActualInstance(Object instance) {this.instance = instance;} /** - * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf - * schema as well + * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf schema as well * * @return an instance of the actual schema/object */ @@ -65,7 +74,7 @@ private Object getActualInstanceRecursively(AbstractOpenApiSchema object) { if (object.getActualInstance() == null) { return null; } else if (object.getActualInstance() instanceof AbstractOpenApiSchema) { - return getActualInstanceRecursively((AbstractOpenApiSchema) object.getActualInstance()); + return getActualInstanceRecursively((AbstractOpenApiSchema)object.getActualInstance()); } else { return object.getActualInstance(); } @@ -92,8 +101,8 @@ public String toString() { } /** - * Convert the given object to string with each line indented by 4 spaces (except the first - * line). + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). */ private String toIndentedString(Object o) { if (o == null) { @@ -110,9 +119,9 @@ public boolean equals(Object o) { return false; } AbstractOpenApiSchema a = (AbstractOpenApiSchema) o; - return Objects.equals(this.instance, a.instance) - && Objects.equals(this.isNullable, a.isNullable) - && Objects.equals(this.schemaType, a.schemaType); + return Objects.equals(this.instance, a.instance) && + Objects.equals(this.isNullable, a.isNullable) && + Objects.equals(this.schemaType, a.schemaType); } @Override @@ -132,4 +141,7 @@ public Boolean isNullable() { return Boolean.FALSE; } } + + + } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java new file mode 100644 index 00000000..6fbeec22 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java @@ -0,0 +1,157 @@ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; + +import java.util.StringJoiner; +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.List; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * CIECertData + */ +@JsonPropertyOrder({ + CIECertData.JSON_PROPERTY_ENTITY_DESCRIPTOR +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +public class CIECertData { + public static final String JSON_PROPERTY_ENTITY_DESCRIPTOR = "entityDescriptor"; + private List entityDescriptor; + + public CIECertData() { + } + + public CIECertData entityDescriptor(List entityDescriptor) { + this.entityDescriptor = entityDescriptor; + return this; + } + + public CIECertData addEntityDescriptorItem(EntityDescriptor entityDescriptorItem) { + if (this.entityDescriptor == null) { + this.entityDescriptor = new ArrayList<>(); + } + this.entityDescriptor.add(entityDescriptorItem); + return this; + } + + /** + * Get entityDescriptor + * @return entityDescriptor + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_ENTITY_DESCRIPTOR) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public List getEntityDescriptor() { + return entityDescriptor; + } + + + @JsonProperty(JSON_PROPERTY_ENTITY_DESCRIPTOR) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setEntityDescriptor(List entityDescriptor) { + this.entityDescriptor = entityDescriptor; + } + + + /** + * Return true if this CIECertData object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + CIECertData ciECertData = (CIECertData) o; + return Objects.equals(this.entityDescriptor, ciECertData.entityDescriptor); + } + + @Override + public int hashCode() { + return Objects.hash(entityDescriptor); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class CIECertData {\n"); + sb.append(" entityDescriptor: ").append(toIndentedString(entityDescriptor)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `entityDescriptor` to the URL query string + if (getEntityDescriptor() != null) { + for (int i = 0; i < getEntityDescriptor().size(); i++) { + if (getEntityDescriptor().get(i) != null) { + joiner.add(getEntityDescriptor().get(i).toUrlQueryString(String.format("%sentityDescriptor%s%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); + } + } + } + + return joiner.toString(); + } +} + diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java new file mode 100644 index 00000000..e9c970a5 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java @@ -0,0 +1,281 @@ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; + +import java.util.StringJoiner; +import java.util.Map; +import java.util.HashMap; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.Collections; +import java.util.HashSet; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.JSON; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +@JsonDeserialize(using = CertData.CertDataDeserializer.class) +@JsonSerialize(using = CertData.CertDataSerializer.class) +public class CertData extends AbstractOpenApiSchema { + private static final Logger log = Logger.getLogger(CertData.class.getName()); + + public static class CertDataSerializer extends StdSerializer { + public CertDataSerializer(Class t) { + super(t); + } + + public CertDataSerializer() { + this(null); + } + + @Override + public void serialize(CertData value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + + public static class CertDataDeserializer extends StdDeserializer { + public CertDataDeserializer() { + this(CertData.class); + } + + public CertDataDeserializer(Class vc) { + super(vc); + } + + @Override + public CertData deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + Object deserialized = null; + boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS); + int match = 0; + JsonToken token = tree.traverse(jp.getCodec()).nextToken(); + // deserialize CIECertData + try { + boolean attemptParsing = true; + // ensure that we respect type coercion as set on the client ObjectMapper + if (CIECertData.class.equals(Integer.class) || CIECertData.class.equals(Long.class) || CIECertData.class.equals(Float.class) || CIECertData.class.equals(Double.class) || CIECertData.class.equals(Boolean.class) || CIECertData.class.equals(String.class)) { + attemptParsing = typeCoercion; + if (!attemptParsing) { + attemptParsing |= ((CIECertData.class.equals(Integer.class) || CIECertData.class.equals(Long.class)) && token == JsonToken.VALUE_NUMBER_INT); + attemptParsing |= ((CIECertData.class.equals(Float.class) || CIECertData.class.equals(Double.class)) && token == JsonToken.VALUE_NUMBER_FLOAT); + attemptParsing |= (CIECertData.class.equals(Boolean.class) && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE)); + attemptParsing |= (CIECertData.class.equals(String.class) && token == JsonToken.VALUE_STRING); + } + } + if (attemptParsing) { + deserialized = tree.traverse(jp.getCodec()).readValueAs(CIECertData.class); + // TODO: there is no validation against JSON schema constraints + // (min, max, enum, pattern...), this does not perform a strict JSON + // validation, which means the 'match' count may be higher than it should be. + match++; + log.log(Level.FINER, "Input data matches schema 'CIECertData'"); + } + } catch (Exception e) { + // deserialization failed, continue + log.log(Level.FINER, "Input data does not match schema 'CIECertData'", e); + } + + // deserialize SPIDCertData + try { + boolean attemptParsing = true; + // ensure that we respect type coercion as set on the client ObjectMapper + if (SPIDCertData.class.equals(Integer.class) || SPIDCertData.class.equals(Long.class) || SPIDCertData.class.equals(Float.class) || SPIDCertData.class.equals(Double.class) || SPIDCertData.class.equals(Boolean.class) || SPIDCertData.class.equals(String.class)) { + attemptParsing = typeCoercion; + if (!attemptParsing) { + attemptParsing |= ((SPIDCertData.class.equals(Integer.class) || SPIDCertData.class.equals(Long.class)) && token == JsonToken.VALUE_NUMBER_INT); + attemptParsing |= ((SPIDCertData.class.equals(Float.class) || SPIDCertData.class.equals(Double.class)) && token == JsonToken.VALUE_NUMBER_FLOAT); + attemptParsing |= (SPIDCertData.class.equals(Boolean.class) && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE)); + attemptParsing |= (SPIDCertData.class.equals(String.class) && token == JsonToken.VALUE_STRING); + } + } + if (attemptParsing) { + deserialized = tree.traverse(jp.getCodec()).readValueAs(SPIDCertData.class); + // TODO: there is no validation against JSON schema constraints + // (min, max, enum, pattern...), this does not perform a strict JSON + // validation, which means the 'match' count may be higher than it should be. + match++; + log.log(Level.FINER, "Input data matches schema 'SPIDCertData'"); + } + } catch (Exception e) { + // deserialization failed, continue + log.log(Level.FINER, "Input data does not match schema 'SPIDCertData'", e); + } + + if (match == 1) { + CertData ret = new CertData(); + ret.setActualInstance(deserialized); + return ret; + } + throw new IOException(String.format("Failed deserialization for CertData: %d classes match result, expected 1", match)); + } + + /** + * Handle deserialization of the 'null' value. + */ + @Override + public CertData getNullValue(DeserializationContext ctxt) throws JsonMappingException { + throw new JsonMappingException(ctxt.getParser(), "CertData cannot be null"); + } + } + + // store a list of schema names defined in oneOf + public static final Map> schemas = new HashMap<>(); + + public CertData() { + super("oneOf", Boolean.FALSE); + } + + public CertData(CIECertData o) { + super("oneOf", Boolean.FALSE); + setActualInstance(o); + } + + public CertData(SPIDCertData o) { + super("oneOf", Boolean.FALSE); + setActualInstance(o); + } + + static { + schemas.put("CIECertData", CIECertData.class); + schemas.put("SPIDCertData", SPIDCertData.class); + JSON.registerDescendants(CertData.class, Collections.unmodifiableMap(schemas)); + } + + @Override + public Map> getSchemas() { + return CertData.schemas; + } + + /** + * Set the instance that matches the oneOf child schema, check + * the instance parameter is valid against the oneOf child schemas: + * CIECertData, SPIDCertData + * + * It could be an instance of the 'oneOf' schemas. + * The oneOf child schemas may themselves be a composed schema (allOf, anyOf, oneOf). + */ + @Override + public void setActualInstance(Object instance) { + if (JSON.isInstanceOf(CIECertData.class, instance, new HashSet>())) { + super.setActualInstance(instance); + return; + } + + if (JSON.isInstanceOf(SPIDCertData.class, instance, new HashSet>())) { + super.setActualInstance(instance); + return; + } + + throw new RuntimeException("Invalid instance type. Must be CIECertData, SPIDCertData"); + } + + /** + * Get the actual instance, which can be the following: + * CIECertData, SPIDCertData + * + * @return The actual instance (CIECertData, SPIDCertData) + */ + @Override + public Object getActualInstance() { + return super.getActualInstance(); + } + + /** + * Get the actual instance of `CIECertData`. If the actual instance is not `CIECertData`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `CIECertData` + * @throws ClassCastException if the instance is not `CIECertData` + */ + public CIECertData getCIECertData() throws ClassCastException { + return (CIECertData)super.getActualInstance(); + } + + /** + * Get the actual instance of `SPIDCertData`. If the actual instance is not `SPIDCertData`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `SPIDCertData` + * @throws ClassCastException if the instance is not `SPIDCertData` + */ + public SPIDCertData getSPIDCertData() throws ClassCastException { + return (SPIDCertData)super.getActualInstance(); + } + + + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + if (getActualInstance() instanceof CIECertData) { + if (getActualInstance() != null) { + joiner.add(((CIECertData)getActualInstance()).toUrlQueryString(prefix + "one_of_0" + suffix)); + } + return joiner.toString(); + } + if (getActualInstance() instanceof SPIDCertData) { + if (getActualInstance() != null) { + joiner.add(((SPIDCertData)getActualInstance()).toUrlQueryString(prefix + "one_of_1" + suffix)); + } + return joiner.toString(); + } + return null; + } + +} + diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java new file mode 100644 index 00000000..1c6ef986 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java @@ -0,0 +1,145 @@ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import java.util.StringJoiner; + + +/** + * EntityDescriptor + */ +@JsonPropertyOrder({ + EntityDescriptor.JSON_PROPERTY_ENTITY_I_D +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +public class EntityDescriptor { + public static final String JSON_PROPERTY_ENTITY_I_D = "entityID"; + private String entityID; + + public EntityDescriptor() { + } + + public EntityDescriptor entityID(String entityID) { + this.entityID = entityID; + return this; + } + + /** + * Get entityID + * @return entityID + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_ENTITY_I_D) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + + public String getEntityID() { + return entityID; + } + + + @JsonProperty(JSON_PROPERTY_ENTITY_I_D) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setEntityID(String entityID) { + this.entityID = entityID; + } + + + /** + * Return true if this EntityDescriptor object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + EntityDescriptor entityDescriptor = (EntityDescriptor) o; + return Objects.equals(this.entityID, entityDescriptor.entityID); + } + + @Override + public int hashCode() { + return Objects.hash(entityID); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class EntityDescriptor {\n"); + sb.append(" entityID: ").append(toIndentedString(entityID)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `entityID` to the URL query string + if (getEntityID() != null) { + joiner.add(String.format("%sentityID%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getEntityID()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} + diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/ProblemJson.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/ProblemJson.java new file mode 100644 index 00000000..7fcc4f37 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/ProblemJson.java @@ -0,0 +1,292 @@ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import java.net.URI; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import java.util.StringJoiner; + + +/** + * ProblemJson + */ +@JsonPropertyOrder({ + ProblemJson.JSON_PROPERTY_TYPE, + ProblemJson.JSON_PROPERTY_TITLE, + ProblemJson.JSON_PROPERTY_STATUS, + ProblemJson.JSON_PROPERTY_DETAIL, + ProblemJson.JSON_PROPERTY_INSTANCE +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +public class ProblemJson { + public static final String JSON_PROPERTY_TYPE = "type"; + private URI type = URI.create("about:blank"); + + public static final String JSON_PROPERTY_TITLE = "title"; + private String title; + + public static final String JSON_PROPERTY_STATUS = "status"; + private Integer status; + + public static final String JSON_PROPERTY_DETAIL = "detail"; + private String detail; + + public static final String JSON_PROPERTY_INSTANCE = "instance"; + private URI instance; + + public ProblemJson() { + } + + public ProblemJson type(URI type) { + this.type = type; + return this; + } + + /** + * An absolute URI that identifies the problem type. When dereferenced, it SHOULD provide human-readable documentation for the problem type (e.g., using HTML). + * @return type + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public URI getType() { + return type; + } + + + @JsonProperty(JSON_PROPERTY_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setType(URI type) { + this.type = type; + } + + + public ProblemJson title(String title) { + this.title = title; + return this; + } + + /** + * A short, summary of the problem type. Written in english and readable for engineers (usually not suited for non technical stakeholders and not localized); example: Service Unavailable + * @return title + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_TITLE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getTitle() { + return title; + } + + + @JsonProperty(JSON_PROPERTY_TITLE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setTitle(String title) { + this.title = title; + } + + + public ProblemJson status(Integer status) { + this.status = status; + return this; + } + + /** + * The HTTP status code generated by the origin server for this occurrence of the problem. + * minimum: 100 + * maximum: 600 + * @return status + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Integer getStatus() { + return status; + } + + + @JsonProperty(JSON_PROPERTY_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setStatus(Integer status) { + this.status = status; + } + + + public ProblemJson detail(String detail) { + this.detail = detail; + return this; + } + + /** + * A human readable explanation specific to this occurrence of the problem. + * @return detail + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_DETAIL) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getDetail() { + return detail; + } + + + @JsonProperty(JSON_PROPERTY_DETAIL) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setDetail(String detail) { + this.detail = detail; + } + + + public ProblemJson instance(URI instance) { + this.instance = instance; + return this; + } + + /** + * An absolute URI that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced. + * @return instance + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_INSTANCE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public URI getInstance() { + return instance; + } + + + @JsonProperty(JSON_PROPERTY_INSTANCE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setInstance(URI instance) { + this.instance = instance; + } + + + /** + * Return true if this ProblemJson object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProblemJson problemJson = (ProblemJson) o; + return Objects.equals(this.type, problemJson.type) && + Objects.equals(this.title, problemJson.title) && + Objects.equals(this.status, problemJson.status) && + Objects.equals(this.detail, problemJson.detail) && + Objects.equals(this.instance, problemJson.instance); + } + + @Override + public int hashCode() { + return Objects.hash(type, title, status, detail, instance); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ProblemJson {\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append(" title: ").append(toIndentedString(title)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" detail: ").append(toIndentedString(detail)).append("\n"); + sb.append(" instance: ").append(toIndentedString(instance)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `type` to the URL query string + if (getType() != null) { + joiner.add(String.format("%stype%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getType()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `title` to the URL query string + if (getTitle() != null) { + joiner.add(String.format("%stitle%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getTitle()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `status` to the URL query string + if (getStatus() != null) { + joiner.add(String.format("%sstatus%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getStatus()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `detail` to the URL query string + if (getDetail() != null) { + joiner.add(String.format("%sdetail%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getDetail()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `instance` to the URL query string + if (getInstance() != null) { + joiner.add(String.format("%sinstance%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getInstance()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} + diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertData.java new file mode 100644 index 00000000..572534fe --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertData.java @@ -0,0 +1,143 @@ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import java.util.Objects; +import java.util.StringJoiner; + + +/** + * SPIDCertData + */ +@JsonPropertyOrder({ + SPIDCertData.JSON_PROPERTY_ENTITIES_DESCRIPTOR +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +public class SPIDCertData { + public static final String JSON_PROPERTY_ENTITIES_DESCRIPTOR = "entitiesDescriptor"; + private SPIDCertDataEntitiesDescriptor entitiesDescriptor; + + public SPIDCertData() { + } + + public SPIDCertData entitiesDescriptor(SPIDCertDataEntitiesDescriptor entitiesDescriptor) { + this.entitiesDescriptor = entitiesDescriptor; + return this; + } + + /** + * Get entitiesDescriptor + * @return entitiesDescriptor + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_ENTITIES_DESCRIPTOR) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public SPIDCertDataEntitiesDescriptor getEntitiesDescriptor() { + return entitiesDescriptor; + } + + + @JsonProperty(JSON_PROPERTY_ENTITIES_DESCRIPTOR) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setEntitiesDescriptor(SPIDCertDataEntitiesDescriptor entitiesDescriptor) { + this.entitiesDescriptor = entitiesDescriptor; + } + + + /** + * Return true if this SPIDCertData object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SPIDCertData spIDCertData = (SPIDCertData) o; + return Objects.equals(this.entitiesDescriptor, spIDCertData.entitiesDescriptor); + } + + @Override + public int hashCode() { + return Objects.hash(entitiesDescriptor); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class SPIDCertData {\n"); + sb.append(" entitiesDescriptor: ").append(toIndentedString(entitiesDescriptor)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `entitiesDescriptor` to the URL query string + if (getEntitiesDescriptor() != null) { + joiner.add(getEntitiesDescriptor().toUrlQueryString(prefix + "entitiesDescriptor" + suffix)); + } + + return joiner.toString(); + } +} + diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertDataEntitiesDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertDataEntitiesDescriptor.java new file mode 100644 index 00000000..a4169a63 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertDataEntitiesDescriptor.java @@ -0,0 +1,158 @@ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.StringJoiner; + + +/** + * SPIDCertDataEntitiesDescriptor + */ +@JsonPropertyOrder({ + SPIDCertDataEntitiesDescriptor.JSON_PROPERTY_ENTITY_DESCRIPTOR +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +public class SPIDCertDataEntitiesDescriptor { + public static final String JSON_PROPERTY_ENTITY_DESCRIPTOR = "entityDescriptor"; + private List entityDescriptor; + + public SPIDCertDataEntitiesDescriptor() { + } + + public SPIDCertDataEntitiesDescriptor entityDescriptor(List entityDescriptor) { + this.entityDescriptor = entityDescriptor; + return this; + } + + public SPIDCertDataEntitiesDescriptor addEntityDescriptorItem(EntityDescriptor entityDescriptorItem) { + if (this.entityDescriptor == null) { + this.entityDescriptor = new ArrayList<>(); + } + this.entityDescriptor.add(entityDescriptorItem); + return this; + } + + /** + * Get entityDescriptor + * @return entityDescriptor + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_ENTITY_DESCRIPTOR) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public List getEntityDescriptor() { + return entityDescriptor; + } + + + @JsonProperty(JSON_PROPERTY_ENTITY_DESCRIPTOR) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setEntityDescriptor(List entityDescriptor) { + this.entityDescriptor = entityDescriptor; + } + + + /** + * Return true if this SPIDCertData_entitiesDescriptor object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SPIDCertDataEntitiesDescriptor spIDCertDataEntitiesDescriptor = (SPIDCertDataEntitiesDescriptor) o; + return Objects.equals(this.entityDescriptor, spIDCertDataEntitiesDescriptor.entityDescriptor); + } + + @Override + public int hashCode() { + return Objects.hash(entityDescriptor); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class SPIDCertDataEntitiesDescriptor {\n"); + sb.append(" entityDescriptor: ").append(toIndentedString(entityDescriptor)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `entityDescriptor` to the URL query string + if (getEntityDescriptor() != null) { + for (int i = 0; i < getEntityDescriptor().size(); i++) { + if (getEntityDescriptor().get(i) != null) { + joiner.add(getEntityDescriptor().get(i).toUrlQueryString(String.format("%sentityDescriptor%s%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); + } + } + } + + return joiner.toString(); + } +} + From 65e29c314678b71c8f54bfd65e548cfeeb46c4c4 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 11 Apr 2023 16:46:38 +0200 Subject: [PATCH 131/403] [SLS-19] Defined skeleton getCertData - changed return type to List --- .../consumer/idp/client/IdpCertClient.java | 3 +- .../client/simple/IdpCertSimpleClient.java | 88 ++++++++++++++++++- 2 files changed, 87 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java index 7629f668..50ace9c7 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java @@ -2,8 +2,9 @@ package it.pagopa.tech.lollipop.consumer.idp.client; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import java.util.List; public interface IdpCertClient { - IdpCertData getCertData(String entityId, String instant); + List getCertData(String entityId, String instant); } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 8eae30a2..3c602363 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -1,16 +1,25 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple; +import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.OidcAssertionNotSupported; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; +import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.api.DefaultApi; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.CertData; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; + +import java.util.ArrayList; +import java.util.List; import javax.inject.Inject; public class IdpCertSimpleClient implements IdpCertClient { - ApiClient apiClient; - DefaultApi defaultApi; + private final ApiClient apiClient; + private final DefaultApi defaultApi; @Inject public IdpCertSimpleClient(ApiClient client) { @@ -24,7 +33,80 @@ public IdpCertSimpleClient(ApiClient client) { * @return */ @Override - public IdpCertData getCertData(String entityId, String instant) { + public List getCertData(String entityId, String instant) { + List listCertData = new ArrayList<>(); + + if (entityId.equals("https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO")) { //TODO inserire entityID in config + List tagList = getCIETagList(instant); + for(String tag: tagList){ + IdpCertData certData = getCIECertData(tag); + listCertData.add(certData); + } + } else { + List tagList = getSPIDTagList(instant); + for(String tag: tagList){ + IdpCertData certData = getSPIDCertData(tag, entityId); + listCertData.add(certData); + } + } + return listCertData; + } + + private List getSPIDTagList(String instant) { + List responseAssertion = new ArrayList<>(); + + try { + responseAssertion = this.defaultApi.idpKeysSpidGet(); + } catch (ApiException e) { + /*throw new LollipopAssertionNotFoundException( + "Error retrieving idp cert list: " + e.getMessage(), e);*/ + } + + //TODO gestire filtro tag (prendere quello subito prima e subito dopo rispetto all' "instant") + + return responseAssertion; + } + + private IdpCertData getSPIDCertData(String tag, String entityId) { + CertData responseAssertion; + + try { + responseAssertion = this.defaultApi.idpKeysSpidTagGet(tag); + } catch (ApiException e) { + /*throw new LollipopAssertionNotFoundException( + "Error retrieving assertion: " + e.getMessage(), e);*/ + } + + //TODO gestire filtraggio xml per entityId + + return null; + } + + private List getCIETagList(String instant) { + List responseAssertion = new ArrayList<>(); + + try { + responseAssertion = this.defaultApi.idpKeysCieGet(); + } catch (ApiException e) { + /*throw new LollipopAssertionNotFoundException( + "Error retrieving idp cert list: " + e.getMessage(), e);*/ + } + + //TODO gestire filtro tag (prendere quello subito prima e subito dopo rispetto all' "instant") + + return responseAssertion; + } + + private IdpCertData getCIECertData(String tag) { + CertData responseAssertion; + + try { + responseAssertion = this.defaultApi.idpKeysCieTagGet(tag); + } catch (ApiException e) { + /*throw new LollipopAssertionNotFoundException( + "Error retrieving assertion: " + e.getMessage(), e);*/ + } + return null; } } From b29cd8b2aa5c9e786047340b6bf4f7de3bacf7bb Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 11 Apr 2023 18:38:16 +0200 Subject: [PATCH 132/403] [SLS-19] Written basic tests for getCertData --- .../client/simple/IdpCertSimpleClient.java | 10 ++--- .../java/simple/IdpCertSimpleClientTest.java | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 3c602363..bb423fc4 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -1,20 +1,16 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple; -import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.OidcAssertionNotSupported; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; -import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.api.DefaultApi; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.CertData; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; -import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; +import javax.inject.Inject; import java.util.ArrayList; import java.util.List; -import javax.inject.Inject; public class IdpCertSimpleClient implements IdpCertClient { @@ -36,15 +32,17 @@ public IdpCertSimpleClient(ApiClient client) { public List getCertData(String entityId, String instant) { List listCertData = new ArrayList<>(); - if (entityId.equals("https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO")) { //TODO inserire entityID in config + if (entityId.equals("https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO")) { //TODO inserire entityID in classe di configurazione List tagList = getCIETagList(instant); for(String tag: tagList){ + //TODO recupero storage IdpCertData certData = getCIECertData(tag); listCertData.add(certData); } } else { List tagList = getSPIDTagList(instant); for(String tag: tagList){ + //TODO recupero storage IdpCertData certData = getSPIDCertData(tag, entityId); listCertData.add(certData); } diff --git a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java new file mode 100644 index 00000000..65c1ca74 --- /dev/null +++ b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java @@ -0,0 +1,40 @@ +package simple; + + +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClient; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.List; + +class IdpCertSimpleClientTest { + + private static IdpCertSimpleClient idpCertSimpleClient; + + private static final String instant = "1679072970"; + private static final String SPID_ENTITY_ID = "https://posteid.poste.it"; + private static final String CIE_ENTITY_ID = "https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"; + + @BeforeAll + public static void startServer() { + ApiClient client = new ApiClient(); + idpCertSimpleClient = new IdpCertSimpleClient(client); + } + @Test + void getSPIDCertData() { + List response = idpCertSimpleClient.getCertData(SPID_ENTITY_ID, instant); + + Assertions.assertNotNull(response); + } + + @Test + void getCIECertData() { + List response = idpCertSimpleClient.getCertData(CIE_ENTITY_ID, instant); + + Assertions.assertNotNull(response); + } +} \ No newline at end of file From 11cf9c8405bc8869f48d9e7df640592382c18c1f Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 11 Apr 2023 18:39:49 +0200 Subject: [PATCH 133/403] [SLS-19] Changed InputStream mapper from objectMapper to xmlMapper --- .../idp/client/simple/internal/ApiClient.java | 18 +++++++++++++++++- .../client/simple/internal/api/DefaultApi.java | 7 +++++-- .../client/simple/internal/model/CertData.java | 12 ++++++++---- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java index a3fcc124..5bd7a9d9 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java @@ -16,6 +16,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.openapitools.jackson.nullable.JsonNullableModule; @@ -56,6 +57,7 @@ public class ApiClient { private HttpClient.Builder builder; private ObjectMapper mapper; + private XmlMapper xmlMapper; private String scheme; private String host; private int port; @@ -166,6 +168,7 @@ public static List parameterToPairs( public ApiClient() { this.builder = createDefaultHttpClientBuilder(); this.mapper = createDefaultObjectMapper(); + this.xmlMapper = createDefaultXmlMapper(); updateBaseUri(getDefaultBaseUri()); interceptor = null; readTimeout = null; @@ -181,9 +184,10 @@ public ApiClient() { * @param mapper Object mapper. * @param baseUri Base URI */ - public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, String baseUri) { + public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, XmlMapper xmlMapper, String baseUri) { this.builder = builder; this.mapper = mapper; + this.xmlMapper = xmlMapper; updateBaseUri(baseUri != null ? baseUri : getDefaultBaseUri()); interceptor = null; readTimeout = null; @@ -206,6 +210,11 @@ protected ObjectMapper createDefaultObjectMapper() { return mapper; } + protected XmlMapper createDefaultXmlMapper() { + XmlMapper mapper = new XmlMapper(); + return mapper; + } + protected String getDefaultBaseUri() { return "https://api.is.eng.pagopa.it"; } @@ -266,6 +275,13 @@ public ObjectMapper getObjectMapper() { return mapper.copy(); } + public ApiClient setXmlMapper(XmlMapper mapper) { + this.xmlMapper = mapper; + return this; + } + + public XmlMapper getXmlMapper() { return xmlMapper.copy(); } + /** * Set a custom host name for the target service. * diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java index a061221b..b8ece665 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java @@ -14,6 +14,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiResponse; @@ -34,6 +35,7 @@ public class DefaultApi { private final HttpClient memberVarHttpClient; private final ObjectMapper memberVarObjectMapper; + private final XmlMapper memberVarXMLMapper; private final String memberVarBaseUri; private final Consumer memberVarInterceptor; private final Duration memberVarReadTimeout; @@ -47,6 +49,7 @@ public DefaultApi() { public DefaultApi(ApiClient apiClient) { memberVarHttpClient = apiClient.getHttpClient(); memberVarObjectMapper = apiClient.getObjectMapper(); + memberVarXMLMapper = apiClient.getXmlMapper(); memberVarBaseUri = apiClient.getBaseUri(); memberVarInterceptor = apiClient.getRequestInterceptor(); memberVarReadTimeout = apiClient.getReadTimeout(); @@ -167,7 +170,7 @@ public ApiResponse idpKeysCieTagGetWithHttpInfo(String tag) throws Api return new ApiResponse( localVarResponse.statusCode(), localVarResponse.headers().map(), - localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream + localVarResponse.body() == null ? null : memberVarXMLMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream ); } finally { } @@ -304,7 +307,7 @@ public ApiResponse idpKeysSpidTagGetWithHttpInfo(String tag) throws Ap return new ApiResponse( localVarResponse.statusCode(), localVarResponse.headers().map(), - localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream + localVarResponse.body() == null ? null : memberVarXMLMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream ); } finally { } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java index e9c970a5..baea3633 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java @@ -93,8 +93,10 @@ public CertData deserialize(JsonParser jp, DeserializationContext ctxt) throws I // TODO: there is no validation against JSON schema constraints // (min, max, enum, pattern...), this does not perform a strict JSON // validation, which means the 'match' count may be higher than it should be. - match++; - log.log(Level.FINER, "Input data matches schema 'CIECertData'"); + if (((CIECertData) deserialized).getEntityDescriptor() != null) { + match++; + log.log(Level.FINER, "Input data matches schema 'CIECertData'"); + } } } catch (Exception e) { // deserialization failed, continue @@ -119,8 +121,10 @@ public CertData deserialize(JsonParser jp, DeserializationContext ctxt) throws I // TODO: there is no validation against JSON schema constraints // (min, max, enum, pattern...), this does not perform a strict JSON // validation, which means the 'match' count may be higher than it should be. - match++; - log.log(Level.FINER, "Input data matches schema 'SPIDCertData'"); + if(((SPIDCertData) deserialized).getEntitiesDescriptor() != null){ + match++; + log.log(Level.FINER, "Input data matches schema 'SPIDCertData'"); + } } } catch (Exception e) { // deserialization failed, continue From e07e48943f47d3095b5ab44ff279d10c1544f4df Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 12:03:10 +0200 Subject: [PATCH 134/403] [SLS-19] Handled entities filtering by entityId - added exceptions --- .../exception/CertDataNotFoundException.java | 13 ++ .../CertDataTagListNotFoundException.java | 13 ++ .../exception/EntityIdNotFoundException.java | 13 ++ .../TagListSearchOutOfBoundException.java | 13 ++ .../consumer/idp/client/IdpCertClient.java | 4 +- .../client/simple/IdpCertSimpleClient.java | 162 ++++++++++---- .../simple/internal/model/CIECertData.java | 3 + .../simple/internal/model/CertData.java | 206 +++--------------- .../internal/model/EntitiesDescriptor.java | 37 ++++ .../internal/model/EntityDescriptor.java | 2 + .../simple/internal/model/SPIDCertData.java | 143 ------------ .../model/SPIDCertDataEntitiesDescriptor.java | 158 -------------- .../java/simple/IdpCertSimpleClientTest.java | 6 +- 13 files changed, 246 insertions(+), 527 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataNotFoundException.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/EntityIdNotFoundException.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/TagListSearchOutOfBoundException.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java delete mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertData.java delete mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertDataEntitiesDescriptor.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataNotFoundException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataNotFoundException.java new file mode 100644 index 00000000..95030acb --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataNotFoundException.java @@ -0,0 +1,13 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +public class CertDataNotFoundException extends Exception{ + /** + * Constructs new exception with provided message and cause + * + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public CertDataNotFoundException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java new file mode 100644 index 00000000..fe00adfb --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java @@ -0,0 +1,13 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +public class CertDataTagListNotFoundException extends Exception{ + /** + * Constructs new exception with provided message and cause + * + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public CertDataTagListNotFoundException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/EntityIdNotFoundException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/EntityIdNotFoundException.java new file mode 100644 index 00000000..7b5b35ce --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/EntityIdNotFoundException.java @@ -0,0 +1,13 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +public class EntityIdNotFoundException extends Exception{ + + /** + * Constructs new exception with provided messag + * + * @param message Detail message + */ + public EntityIdNotFoundException(String message) { + super(message); + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/TagListSearchOutOfBoundException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/TagListSearchOutOfBoundException.java new file mode 100644 index 00000000..638ca4a2 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/TagListSearchOutOfBoundException.java @@ -0,0 +1,13 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +public class TagListSearchOutOfBoundException extends Exception{ + + /** + * Constructs new exception with provided message + * + * @param message Detail message + */ + public TagListSearchOutOfBoundException(String message) { + super(message); + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java index 50ace9c7..98c03c2b 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java @@ -1,10 +1,12 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client; +import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import java.util.List; public interface IdpCertClient { - List getCertData(String entityId, String instant); + List getCertData(String entityId, String instant) throws CertDataNotFoundException, CertDataTagListNotFoundException; } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index bb423fc4..a091e120 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -1,11 +1,17 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple; +import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.EntityIdNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.TagListSearchOutOfBoundException; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.api.DefaultApi; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.CertData; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.EntitiesDescriptor; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.EntityDescriptor; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import javax.inject.Inject; @@ -17,6 +23,8 @@ public class IdpCertSimpleClient implements IdpCertClient { private final ApiClient apiClient; private final DefaultApi defaultApi; + private static final List CIE_ENTITY_IDS = new ArrayList<>(List.of("https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO")); + @Inject public IdpCertSimpleClient(ApiClient client) { this.apiClient = client; @@ -29,82 +37,140 @@ public IdpCertSimpleClient(ApiClient client) { * @return */ @Override - public List getCertData(String entityId, String instant) { + public List getCertData(String entityId, String instant) throws CertDataNotFoundException, CertDataTagListNotFoundException { List listCertData = new ArrayList<>(); + List tagList; + + if (entityId == null || instant == null || entityId.isBlank() || instant.isBlank()) { + throw new IllegalArgumentException("EntityID or Assertion Issue Instant missing"); + } - if (entityId.equals("https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO")) { //TODO inserire entityID in classe di configurazione - List tagList = getCIETagList(instant); - for(String tag: tagList){ + if (CIE_ENTITY_IDS.contains(entityId)) { //TODO inserire entityID in classe di configurazione + + try { + tagList = getCIETagList(instant); + } catch (ApiException | TagListSearchOutOfBoundException e) { + throw new CertDataTagListNotFoundException("Error retrieving certificate's tag list: " + e.getMessage(), e); + } + + for (String tag : tagList) { //TODO recupero storage - IdpCertData certData = getCIECertData(tag); - listCertData.add(certData); + try { + IdpCertData certData = getCIECertData(tag, entityId); + + if(certData != null){ + listCertData.add(certData); + } + } catch (ApiException | EntityIdNotFoundException e) { + throw new CertDataNotFoundException("Error retrieving certificate data for tag" + tag + ": " + e.getMessage(), e); + } + } } else { - List tagList = getSPIDTagList(instant); - for(String tag: tagList){ + try { + tagList = getSPIDTagList(instant); + } catch (ApiException | TagListSearchOutOfBoundException e) { + throw new CertDataTagListNotFoundException("Error retrieving certificate's tag list: " + e.getMessage(), e); + } + + for (String tag : tagList) { //TODO recupero storage - IdpCertData certData = getSPIDCertData(tag, entityId); - listCertData.add(certData); + try { + IdpCertData certData = getSPIDCertData(tag, entityId); + + if(certData != null){ + listCertData.add(certData); + } + } catch (ApiException | EntityIdNotFoundException e) { + throw new CertDataNotFoundException("Error retrieving certificate data for tag" + tag + ": " + e.getMessage(), e); + } + } } return listCertData; } - private List getSPIDTagList(String instant) { - List responseAssertion = new ArrayList<>(); + private List getSPIDTagList(String instant) throws TagListSearchOutOfBoundException { + List responseAssertion; - try { - responseAssertion = this.defaultApi.idpKeysSpidGet(); - } catch (ApiException e) { - /*throw new LollipopAssertionNotFoundException( - "Error retrieving idp cert list: " + e.getMessage(), e);*/ - } + responseAssertion = this.defaultApi.idpKeysSpidGet(); - //TODO gestire filtro tag (prendere quello subito prima e subito dopo rispetto all' "instant") + return getTagsFromInstant(responseAssertion, instant); + } + + private IdpCertData getSPIDCertData(String tag, String entityId) throws EntityIdNotFoundException { + CertData responseAssertion = null; - return responseAssertion; + responseAssertion = this.defaultApi.idpKeysSpidTagGet(tag); + + return getEntityData(((EntitiesDescriptor)responseAssertion.getActualInstance()), tag, entityId); } - private IdpCertData getSPIDCertData(String tag, String entityId) { - CertData responseAssertion; + private List getCIETagList(String instant) throws TagListSearchOutOfBoundException { + List responseAssertion; - try { - responseAssertion = this.defaultApi.idpKeysSpidTagGet(tag); - } catch (ApiException e) { - /*throw new LollipopAssertionNotFoundException( - "Error retrieving assertion: " + e.getMessage(), e);*/ - } + responseAssertion = this.defaultApi.idpKeysCieGet(); + + return getTagsFromInstant(responseAssertion, instant); + } + + private IdpCertData getCIECertData(String tag, String entityId) throws EntityIdNotFoundException { + CertData responseAssertion; - //TODO gestire filtraggio xml per entityId + responseAssertion = this.defaultApi.idpKeysCieTagGet(tag); - return null; + return getEntityData(((EntitiesDescriptor)responseAssertion.getActualInstance()), tag, entityId); } - private List getCIETagList(String instant) { - List responseAssertion = new ArrayList<>(); + private IdpCertData getEntityData(EntitiesDescriptor data, String tag, String entityId) throws EntityIdNotFoundException { + IdpCertData newData = new IdpCertData(); - try { - responseAssertion = this.defaultApi.idpKeysCieGet(); - } catch (ApiException e) { - /*throw new LollipopAssertionNotFoundException( - "Error retrieving idp cert list: " + e.getMessage(), e);*/ - } + for (EntityDescriptor entity : data.getEntityList()) { + if (entity.getEntityID().equals(entityId)){ + newData.setEntityId(entityId); + newData.setTag(tag); + newData.setCertData("test"); - //TODO gestire filtro tag (prendere quello subito prima e subito dopo rispetto all' "instant") + return newData; + } + } - return responseAssertion; + throw new EntityIdNotFoundException("Cert for entityID" + entityId + " not found"); } - private IdpCertData getCIECertData(String tag) { - CertData responseAssertion; + private List getTagsFromInstant(List tagList, String instant) throws TagListSearchOutOfBoundException { + List newTagList = new ArrayList<>(); + + if (tagList.size() <= 2) { + return tagList; + } + + int index = tagList.size() / 2; + + //TODO ordinamento tag + boolean notFound = true; + while (notFound) { + String upperTag = tagList.get(index); + String lowerTag = tagList.get(index + 1); + if (Long.valueOf(instant) <= Long.valueOf(upperTag) || upperTag.equals("latest")) { + if (Long.valueOf(instant) >= Long.valueOf(lowerTag)) { + notFound = false; + newTagList.add(upperTag); + newTagList.add(lowerTag); + } else { + index += 1; + } + } else { + index -= 1; + } + + if (index < 0 || index >= tagList.size()) { + throw new TagListSearchOutOfBoundException("Error finding the tags relative to assertion instant" + instant); + } - try { - responseAssertion = this.defaultApi.idpKeysCieTagGet(tag); - } catch (ApiException e) { - /*throw new LollipopAssertionNotFoundException( - "Error retrieving assertion: " + e.getMessage(), e);*/ } - return null; + + return newTagList; } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java index 6fbeec22..7611bcb4 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java @@ -15,6 +15,8 @@ import java.util.StringJoiner; import java.util.Objects; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; @@ -28,6 +30,7 @@ @JsonPropertyOrder({ CIECertData.JSON_PROPERTY_ENTITY_DESCRIPTOR }) +@JsonIgnoreProperties(ignoreUnknown = true) @javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class CIECertData { public static final String JSON_PROPERTY_ENTITY_DESCRIPTOR = "entityDescriptor"; diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java index baea3633..8b256dc3 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java @@ -3,7 +3,7 @@ * Client used to retrieve the public keys from the identity provider * * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech @@ -13,15 +13,11 @@ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; -import java.util.StringJoiner; -import java.util.Map; -import java.util.HashMap; +import java.util.*; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.Collections; -import java.util.HashSet; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; @@ -37,10 +33,14 @@ import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.JSON; +import lombok.Getter; +import lombok.Setter; @javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") @JsonDeserialize(using = CertData.CertDataDeserializer.class) @JsonSerialize(using = CertData.CertDataSerializer.class) +@Getter +@Setter public class CertData extends AbstractOpenApiSchema { private static final Logger log = Logger.getLogger(CertData.class.getName()); @@ -75,65 +75,42 @@ public CertData deserialize(JsonParser jp, DeserializationContext ctxt) throws I boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS); int match = 0; JsonToken token = tree.traverse(jp.getCodec()).nextToken(); + EntitiesDescriptor entitiesDescriptor = new EntitiesDescriptor(); // deserialize CIECertData try { - boolean attemptParsing = true; - // ensure that we respect type coercion as set on the client ObjectMapper - if (CIECertData.class.equals(Integer.class) || CIECertData.class.equals(Long.class) || CIECertData.class.equals(Float.class) || CIECertData.class.equals(Double.class) || CIECertData.class.equals(Boolean.class) || CIECertData.class.equals(String.class)) { - attemptParsing = typeCoercion; - if (!attemptParsing) { - attemptParsing |= ((CIECertData.class.equals(Integer.class) || CIECertData.class.equals(Long.class)) && token == JsonToken.VALUE_NUMBER_INT); - attemptParsing |= ((CIECertData.class.equals(Float.class) || CIECertData.class.equals(Double.class)) && token == JsonToken.VALUE_NUMBER_FLOAT); - attemptParsing |= (CIECertData.class.equals(Boolean.class) && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE)); - attemptParsing |= (CIECertData.class.equals(String.class) && token == JsonToken.VALUE_STRING); - } - } - if (attemptParsing) { - deserialized = tree.traverse(jp.getCodec()).readValueAs(CIECertData.class); - // TODO: there is no validation against JSON schema constraints - // (min, max, enum, pattern...), this does not perform a strict JSON - // validation, which means the 'match' count may be higher than it should be. - if (((CIECertData) deserialized).getEntityDescriptor() != null) { - match++; - log.log(Level.FINER, "Input data matches schema 'CIECertData'"); - } - } - } catch (Exception e) { - // deserialization failed, continue - log.log(Level.FINER, "Input data does not match schema 'CIECertData'", e); - } + deserialized = tree.traverse(jp.getCodec()).readValueAs(EntityDescriptor.class); - // deserialize SPIDCertData - try { - boolean attemptParsing = true; - // ensure that we respect type coercion as set on the client ObjectMapper - if (SPIDCertData.class.equals(Integer.class) || SPIDCertData.class.equals(Long.class) || SPIDCertData.class.equals(Float.class) || SPIDCertData.class.equals(Double.class) || SPIDCertData.class.equals(Boolean.class) || SPIDCertData.class.equals(String.class)) { - attemptParsing = typeCoercion; - if (!attemptParsing) { - attemptParsing |= ((SPIDCertData.class.equals(Integer.class) || SPIDCertData.class.equals(Long.class)) && token == JsonToken.VALUE_NUMBER_INT); - attemptParsing |= ((SPIDCertData.class.equals(Float.class) || SPIDCertData.class.equals(Double.class)) && token == JsonToken.VALUE_NUMBER_FLOAT); - attemptParsing |= (SPIDCertData.class.equals(Boolean.class) && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE)); - attemptParsing |= (SPIDCertData.class.equals(String.class) && token == JsonToken.VALUE_STRING); - } - } - if (attemptParsing) { - deserialized = tree.traverse(jp.getCodec()).readValueAs(SPIDCertData.class); - // TODO: there is no validation against JSON schema constraints - // (min, max, enum, pattern...), this does not perform a strict JSON - // validation, which means the 'match' count may be higher than it should be. - if(((SPIDCertData) deserialized).getEntitiesDescriptor() != null){ - match++; - log.log(Level.FINER, "Input data matches schema 'SPIDCertData'"); + + + if (((EntityDescriptor) deserialized).getEntityID() != null) { + List entityList = Arrays.asList(((EntityDescriptor)deserialized)); + entitiesDescriptor.setEntityList(entityList); + log.log(Level.FINER, "Input data matches schema 'EntityDescriptor'"); + + match++; + } else { + try{ + deserialized = tree.traverse(jp.getCodec()).readValueAs(EntitiesDescriptor.class); + + if (((EntitiesDescriptor) deserialized).getEntityList() != null) { + entitiesDescriptor.setEntityList(((EntitiesDescriptor) deserialized).getEntityList()); + log.log(Level.FINER, "Input data matches schema 'Entities Descriptor'"); + + match++; + } + } catch (Exception e){ + // deserialization failed, continue + log.log(Level.FINER, "Input data does not match schema 'Entities Descriptor'", e); } } } catch (Exception e) { // deserialization failed, continue - log.log(Level.FINER, "Input data does not match schema 'SPIDCertData'", e); + log.log(Level.FINER, "Input data does not match schema 'EntityDescriptor'", e); } if (match == 1) { CertData ret = new CertData(); - ret.setActualInstance(deserialized); + ret.setActualInstance(entitiesDescriptor); return ret; } throw new IOException(String.format("Failed deserialization for CertData: %d classes match result, expected 1", match)); @@ -155,131 +132,10 @@ public CertData() { super("oneOf", Boolean.FALSE); } - public CertData(CIECertData o) { - super("oneOf", Boolean.FALSE); - setActualInstance(o); - } - - public CertData(SPIDCertData o) { - super("oneOf", Boolean.FALSE); - setActualInstance(o); - } - - static { - schemas.put("CIECertData", CIECertData.class); - schemas.put("SPIDCertData", SPIDCertData.class); - JSON.registerDescendants(CertData.class, Collections.unmodifiableMap(schemas)); - } - @Override public Map> getSchemas() { return CertData.schemas; } - /** - * Set the instance that matches the oneOf child schema, check - * the instance parameter is valid against the oneOf child schemas: - * CIECertData, SPIDCertData - * - * It could be an instance of the 'oneOf' schemas. - * The oneOf child schemas may themselves be a composed schema (allOf, anyOf, oneOf). - */ - @Override - public void setActualInstance(Object instance) { - if (JSON.isInstanceOf(CIECertData.class, instance, new HashSet>())) { - super.setActualInstance(instance); - return; - } - - if (JSON.isInstanceOf(SPIDCertData.class, instance, new HashSet>())) { - super.setActualInstance(instance); - return; - } - - throw new RuntimeException("Invalid instance type. Must be CIECertData, SPIDCertData"); - } - - /** - * Get the actual instance, which can be the following: - * CIECertData, SPIDCertData - * - * @return The actual instance (CIECertData, SPIDCertData) - */ - @Override - public Object getActualInstance() { - return super.getActualInstance(); - } - - /** - * Get the actual instance of `CIECertData`. If the actual instance is not `CIECertData`, - * the ClassCastException will be thrown. - * - * @return The actual instance of `CIECertData` - * @throws ClassCastException if the instance is not `CIECertData` - */ - public CIECertData getCIECertData() throws ClassCastException { - return (CIECertData)super.getActualInstance(); - } - - /** - * Get the actual instance of `SPIDCertData`. If the actual instance is not `SPIDCertData`, - * the ClassCastException will be thrown. - * - * @return The actual instance of `SPIDCertData` - * @throws ClassCastException if the instance is not `SPIDCertData` - */ - public SPIDCertData getSPIDCertData() throws ClassCastException { - return (SPIDCertData)super.getActualInstance(); - } - - - - /** - * Convert the instance into URL query string. - * - * @return URL query string - */ - public String toUrlQueryString() { - return toUrlQueryString(null); - } - - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - String suffix = ""; - String containerSuffix = ""; - String containerPrefix = ""; - if (prefix == null) { - // style=form, explode=true, e.g. /pet?name=cat&type=manx - prefix = ""; - } else { - // deepObject style e.g. /pet?id[name]=cat&id[type]=manx - prefix = prefix + "["; - suffix = "]"; - containerSuffix = "]"; - containerPrefix = "["; - } - - StringJoiner joiner = new StringJoiner("&"); - - if (getActualInstance() instanceof CIECertData) { - if (getActualInstance() != null) { - joiner.add(((CIECertData)getActualInstance()).toUrlQueryString(prefix + "one_of_0" + suffix)); - } - return joiner.toString(); - } - if (getActualInstance() instanceof SPIDCertData) { - if (getActualInstance() != null) { - joiner.add(((SPIDCertData)getActualInstance()).toUrlQueryString(prefix + "one_of_1" + suffix)); - } - return joiner.toString(); - } - return null; - } - } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java new file mode 100644 index 00000000..95dffbb6 --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java @@ -0,0 +1,37 @@ +/* + * identity-services + * Client used to retrieve the public keys from the identity provider + * + * The version of the OpenAPI document: 2022-09-06T20:08:39Z + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + + +/** + * EntitiesDescriptor + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@Getter +@Setter +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +public class EntitiesDescriptor { + + @JsonProperty("EntityDescriptor") + private List entityList; + +} + diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java index 1c6ef986..f822b9dc 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java @@ -13,6 +13,7 @@ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; @@ -29,6 +30,7 @@ @JsonPropertyOrder({ EntityDescriptor.JSON_PROPERTY_ENTITY_I_D }) +@JsonIgnoreProperties(ignoreUnknown = true) @javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class EntityDescriptor { public static final String JSON_PROPERTY_ENTITY_I_D = "entityID"; diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertData.java deleted file mode 100644 index 572534fe..00000000 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertData.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; - -import java.util.Objects; -import java.util.StringJoiner; - - -/** - * SPIDCertData - */ -@JsonPropertyOrder({ - SPIDCertData.JSON_PROPERTY_ENTITIES_DESCRIPTOR -}) -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") -public class SPIDCertData { - public static final String JSON_PROPERTY_ENTITIES_DESCRIPTOR = "entitiesDescriptor"; - private SPIDCertDataEntitiesDescriptor entitiesDescriptor; - - public SPIDCertData() { - } - - public SPIDCertData entitiesDescriptor(SPIDCertDataEntitiesDescriptor entitiesDescriptor) { - this.entitiesDescriptor = entitiesDescriptor; - return this; - } - - /** - * Get entitiesDescriptor - * @return entitiesDescriptor - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_ENTITIES_DESCRIPTOR) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public SPIDCertDataEntitiesDescriptor getEntitiesDescriptor() { - return entitiesDescriptor; - } - - - @JsonProperty(JSON_PROPERTY_ENTITIES_DESCRIPTOR) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setEntitiesDescriptor(SPIDCertDataEntitiesDescriptor entitiesDescriptor) { - this.entitiesDescriptor = entitiesDescriptor; - } - - - /** - * Return true if this SPIDCertData object is equal to o. - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - SPIDCertData spIDCertData = (SPIDCertData) o; - return Objects.equals(this.entitiesDescriptor, spIDCertData.entitiesDescriptor); - } - - @Override - public int hashCode() { - return Objects.hash(entitiesDescriptor); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class SPIDCertData {\n"); - sb.append(" entitiesDescriptor: ").append(toIndentedString(entitiesDescriptor)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } - - /** - * Convert the instance into URL query string. - * - * @return URL query string - */ - public String toUrlQueryString() { - return toUrlQueryString(null); - } - - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - String suffix = ""; - String containerSuffix = ""; - String containerPrefix = ""; - if (prefix == null) { - // style=form, explode=true, e.g. /pet?name=cat&type=manx - prefix = ""; - } else { - // deepObject style e.g. /pet?id[name]=cat&id[type]=manx - prefix = prefix + "["; - suffix = "]"; - containerSuffix = "]"; - containerPrefix = "["; - } - - StringJoiner joiner = new StringJoiner("&"); - - // add `entitiesDescriptor` to the URL query string - if (getEntitiesDescriptor() != null) { - joiner.add(getEntitiesDescriptor().toUrlQueryString(prefix + "entitiesDescriptor" + suffix)); - } - - return joiner.toString(); - } -} - diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertDataEntitiesDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertDataEntitiesDescriptor.java deleted file mode 100644 index a4169a63..00000000 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/SPIDCertDataEntitiesDescriptor.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.StringJoiner; - - -/** - * SPIDCertDataEntitiesDescriptor - */ -@JsonPropertyOrder({ - SPIDCertDataEntitiesDescriptor.JSON_PROPERTY_ENTITY_DESCRIPTOR -}) -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") -public class SPIDCertDataEntitiesDescriptor { - public static final String JSON_PROPERTY_ENTITY_DESCRIPTOR = "entityDescriptor"; - private List entityDescriptor; - - public SPIDCertDataEntitiesDescriptor() { - } - - public SPIDCertDataEntitiesDescriptor entityDescriptor(List entityDescriptor) { - this.entityDescriptor = entityDescriptor; - return this; - } - - public SPIDCertDataEntitiesDescriptor addEntityDescriptorItem(EntityDescriptor entityDescriptorItem) { - if (this.entityDescriptor == null) { - this.entityDescriptor = new ArrayList<>(); - } - this.entityDescriptor.add(entityDescriptorItem); - return this; - } - - /** - * Get entityDescriptor - * @return entityDescriptor - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_ENTITY_DESCRIPTOR) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public List getEntityDescriptor() { - return entityDescriptor; - } - - - @JsonProperty(JSON_PROPERTY_ENTITY_DESCRIPTOR) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setEntityDescriptor(List entityDescriptor) { - this.entityDescriptor = entityDescriptor; - } - - - /** - * Return true if this SPIDCertData_entitiesDescriptor object is equal to o. - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - SPIDCertDataEntitiesDescriptor spIDCertDataEntitiesDescriptor = (SPIDCertDataEntitiesDescriptor) o; - return Objects.equals(this.entityDescriptor, spIDCertDataEntitiesDescriptor.entityDescriptor); - } - - @Override - public int hashCode() { - return Objects.hash(entityDescriptor); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class SPIDCertDataEntitiesDescriptor {\n"); - sb.append(" entityDescriptor: ").append(toIndentedString(entityDescriptor)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } - - /** - * Convert the instance into URL query string. - * - * @return URL query string - */ - public String toUrlQueryString() { - return toUrlQueryString(null); - } - - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - String suffix = ""; - String containerSuffix = ""; - String containerPrefix = ""; - if (prefix == null) { - // style=form, explode=true, e.g. /pet?name=cat&type=manx - prefix = ""; - } else { - // deepObject style e.g. /pet?id[name]=cat&id[type]=manx - prefix = prefix + "["; - suffix = "]"; - containerSuffix = "]"; - containerPrefix = "["; - } - - StringJoiner joiner = new StringJoiner("&"); - - // add `entityDescriptor` to the URL query string - if (getEntityDescriptor() != null) { - for (int i = 0; i < getEntityDescriptor().size(); i++) { - if (getEntityDescriptor().get(i) != null) { - joiner.add(getEntityDescriptor().get(i).toUrlQueryString(String.format("%sentityDescriptor%s%s", prefix, suffix, - "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); - } - } - } - - return joiner.toString(); - } -} - diff --git a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java index 65c1ca74..bb1acd60 100644 --- a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java @@ -1,6 +1,8 @@ package simple; +import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; @@ -25,14 +27,14 @@ public static void startServer() { idpCertSimpleClient = new IdpCertSimpleClient(client); } @Test - void getSPIDCertData() { + void getSPIDCertData() throws CertDataTagListNotFoundException, CertDataNotFoundException { List response = idpCertSimpleClient.getCertData(SPID_ENTITY_ID, instant); Assertions.assertNotNull(response); } @Test - void getCIECertData() { + void getCIECertData() throws CertDataTagListNotFoundException, CertDataNotFoundException { List response = idpCertSimpleClient.getCertData(CIE_ENTITY_ID, instant); Assertions.assertNotNull(response); From ddc5a6e8e7010b3744e15439955fd15a61ab6de5 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 12:04:05 +0200 Subject: [PATCH 135/403] [SLS-19] Moved constant outside test method --- .../simple/AssertionSimpleClientTest.java | 250 +++++++++--------- 1 file changed, 124 insertions(+), 126 deletions(-) diff --git a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java index 8a444578..4a82d1cb 100644 --- a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java +++ b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java @@ -21,6 +21,129 @@ class AssertionSimpleClientTest { private static AssertionSimpleClient assertionSimpleClient; private static ClientAndServer mockServer; + private static final String XML_STRING = " https://posteid.poste.it" + + " " + + " " + + " " + + " " + + " " + + " " + + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" + + " " + + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" + + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" + + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" + + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" + + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " + + " " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " " + + " " + + " https://posteid.poste.it " + + " " + + " " + + " " + + " " + + " " + + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" + + " " + + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" + + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" + + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" + + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" + + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " + + " " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + " " + + " " + + " " + + " https://app-backend.io.italia.it" + + " " + + " https://www.spid.gov.it/SpidL2" + + " " + + " " + + " TINIT-AAAAAA89S20I111X" + + " " + + " "; private static final String RESPONSE_STRING = "{\"response_xml\": \" https://posteid.poste.it" - + " " - + " " - + " " - + " " - + " " - + " " - + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" - + " " - + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" - + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" - + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" - + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" - + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " - + " " - + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" - + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" - + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" - + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" - + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" - + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" - + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" - + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" - + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" - + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" - + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" - + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" - + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" - + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" - + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" - + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" - + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" - + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" - + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" - + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" - + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" - + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" - + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" - + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" - + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" - + " " - + " " - + " https://posteid.poste.it " - + " " - + " " - + " " - + " " - + " " - + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" - + " " - + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" - + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" - + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" - + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" - + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " - + " " - + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" - + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" - + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" - + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" - + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" - + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" - + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" - + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" - + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" - + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" - + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" - + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" - + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" - + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" - + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" - + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" - + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" - + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" - + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" - + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" - + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" - + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" - + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" - + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" - + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" - + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" - + " " - + " " - + " " - + " https://app-backend.io.italia.it" - + " " - + " https://www.spid.gov.it/SpidL2" - + " " - + " " - + " TINIT-AAAAAA89S20I111X" - + " " - + " "; createExpectationAssertionFound(); SamlAssertion response = assertionSimpleClient.getAssertion(JWT, ASSERTION_REF); @@ -293,7 +291,7 @@ void samlAssertionFound() throws LollipopAssertionNotFoundException, OidcAsserti Assertions.assertNotNull(response.getAssertionRef()); Assertions.assertNotNull(response.getAssertionData()); Assertions.assertEquals(ASSERTION_REF, response.getAssertionRef()); - Assertions.assertEquals(xmlResponse, response.getAssertionData()); + Assertions.assertEquals(XML_STRING, response.getAssertionData()); } @Test From 353aef145a025912909f8620641cd89ef1f4e803 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 12:29:10 +0200 Subject: [PATCH 136/403] [SLS-19] Fixed tag list sorting --- .../client/simple/IdpCertSimpleClient.java | 43 +++++++++++-------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index a091e120..a7a1c9e9 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -16,6 +16,7 @@ import javax.inject.Inject; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class IdpCertSimpleClient implements IdpCertClient { @@ -62,7 +63,7 @@ public List getCertData(String entityId, String instant) throws Cer listCertData.add(certData); } } catch (ApiException | EntityIdNotFoundException e) { - throw new CertDataNotFoundException("Error retrieving certificate data for tag" + tag + ": " + e.getMessage(), e); + throw new CertDataNotFoundException("Error retrieving certificate data for tag " + tag + ": " + e.getMessage(), e); } } @@ -82,7 +83,7 @@ public List getCertData(String entityId, String instant) throws Cer listCertData.add(certData); } } catch (ApiException | EntityIdNotFoundException e) { - throw new CertDataNotFoundException("Error retrieving certificate data for tag" + tag + ": " + e.getMessage(), e); + throw new CertDataNotFoundException("Error retrieving certificate data for tag " + tag + ": " + e.getMessage(), e); } } @@ -135,7 +136,7 @@ private IdpCertData getEntityData(EntitiesDescriptor data, String tag, String en } } - throw new EntityIdNotFoundException("Cert for entityID" + entityId + " not found"); + throw new EntityIdNotFoundException("Cert for entityID " + entityId + " not found"); } private List getTagsFromInstant(List tagList, String instant) throws TagListSearchOutOfBoundException { @@ -146,31 +147,35 @@ private List getTagsFromInstant(List tagList, String instant) th } int index = tagList.size() / 2; + boolean latestRemoved = tagList.remove("latest"); + + Collections.sort(tagList); + + if(latestRemoved){ + tagList.add(0, "latest"); + } - //TODO ordinamento tag boolean notFound = true; while (notFound) { - String upperTag = tagList.get(index); - String lowerTag = tagList.get(index + 1); - if (Long.valueOf(instant) <= Long.valueOf(upperTag) || upperTag.equals("latest")) { - if (Long.valueOf(instant) >= Long.valueOf(lowerTag)) { - notFound = false; - newTagList.add(upperTag); - newTagList.add(lowerTag); + try{ + String upperTag = tagList.get(index); + String lowerTag = tagList.get(index - 1); + if (Long.valueOf(instant) <= Long.valueOf(upperTag) || upperTag.equals("latest")) { + if (Long.valueOf(instant) >= Long.valueOf(lowerTag)) { + notFound = false; + newTagList.add(upperTag); + newTagList.add(lowerTag); + } else { + index -= 1; + } } else { index += 1; } - } else { - index -= 1; + } catch (Exception e){ + throw new TagListSearchOutOfBoundException("Error finding the tags relative to assertion instant " + instant); } - - if (index < 0 || index >= tagList.size()) { - throw new TagListSearchOutOfBoundException("Error finding the tags relative to assertion instant" + instant); - } - } - return newTagList; } } From 50123506a711dc3872f1dd48484832c88623e48d Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 12:29:23 +0200 Subject: [PATCH 137/403] [SLS-19] Deleted unused class --- .../simple/internal/model/CIECertData.java | 160 ------------------ 1 file changed, 160 deletions(-) delete mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java deleted file mode 100644 index 7611bcb4..00000000 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CIECertData.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; - -import java.util.StringJoiner; -import java.util.Objects; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.ArrayList; -import java.util.List; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; - - -/** - * CIECertData - */ -@JsonPropertyOrder({ - CIECertData.JSON_PROPERTY_ENTITY_DESCRIPTOR -}) -@JsonIgnoreProperties(ignoreUnknown = true) -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") -public class CIECertData { - public static final String JSON_PROPERTY_ENTITY_DESCRIPTOR = "entityDescriptor"; - private List entityDescriptor; - - public CIECertData() { - } - - public CIECertData entityDescriptor(List entityDescriptor) { - this.entityDescriptor = entityDescriptor; - return this; - } - - public CIECertData addEntityDescriptorItem(EntityDescriptor entityDescriptorItem) { - if (this.entityDescriptor == null) { - this.entityDescriptor = new ArrayList<>(); - } - this.entityDescriptor.add(entityDescriptorItem); - return this; - } - - /** - * Get entityDescriptor - * @return entityDescriptor - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_ENTITY_DESCRIPTOR) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public List getEntityDescriptor() { - return entityDescriptor; - } - - - @JsonProperty(JSON_PROPERTY_ENTITY_DESCRIPTOR) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setEntityDescriptor(List entityDescriptor) { - this.entityDescriptor = entityDescriptor; - } - - - /** - * Return true if this CIECertData object is equal to o. - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - CIECertData ciECertData = (CIECertData) o; - return Objects.equals(this.entityDescriptor, ciECertData.entityDescriptor); - } - - @Override - public int hashCode() { - return Objects.hash(entityDescriptor); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class CIECertData {\n"); - sb.append(" entityDescriptor: ").append(toIndentedString(entityDescriptor)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } - - /** - * Convert the instance into URL query string. - * - * @return URL query string - */ - public String toUrlQueryString() { - return toUrlQueryString(null); - } - - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - String suffix = ""; - String containerSuffix = ""; - String containerPrefix = ""; - if (prefix == null) { - // style=form, explode=true, e.g. /pet?name=cat&type=manx - prefix = ""; - } else { - // deepObject style e.g. /pet?id[name]=cat&id[type]=manx - prefix = prefix + "["; - suffix = "]"; - containerSuffix = "]"; - containerPrefix = "["; - } - - StringJoiner joiner = new StringJoiner("&"); - - // add `entityDescriptor` to the URL query string - if (getEntityDescriptor() != null) { - for (int i = 0; i < getEntityDescriptor().size(); i++) { - if (getEntityDescriptor().get(i) != null) { - joiner.add(getEntityDescriptor().get(i).toUrlQueryString(String.format("%sentityDescriptor%s%s", prefix, suffix, - "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); - } - } - } - - return joiner.toString(); - } -} - From 1bdbd7b546e368342cb94addc91c3ac33d3f5e6b Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 12:30:16 +0200 Subject: [PATCH 138/403] [SLS-19] Test covered all IdpCertSimpleClient class methods --- .../java/simple/IdpCertSimpleClientTest.java | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java index bb1acd60..7972a073 100644 --- a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java @@ -3,6 +3,8 @@ import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.EntityIdNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.TagListSearchOutOfBoundException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; @@ -17,26 +19,40 @@ class IdpCertSimpleClientTest { private static IdpCertSimpleClient idpCertSimpleClient; - private static final String instant = "1679072970"; + private static final String INSTANT = "1679072970"; private static final String SPID_ENTITY_ID = "https://posteid.poste.it"; private static final String CIE_ENTITY_ID = "https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"; + private static final String WRONG_ENTITY_ID = "https://wrongEntityID.it"; + private static final String WRONG_INSTANT = "xxxxxx"; + @BeforeAll public static void startServer() { ApiClient client = new ApiClient(); idpCertSimpleClient = new IdpCertSimpleClient(client); } @Test - void getSPIDCertData() throws CertDataTagListNotFoundException, CertDataNotFoundException { - List response = idpCertSimpleClient.getCertData(SPID_ENTITY_ID, instant); + void certSPIDDataFound() throws CertDataTagListNotFoundException, CertDataNotFoundException { + List response = idpCertSimpleClient.getCertData(SPID_ENTITY_ID, INSTANT); Assertions.assertNotNull(response); } @Test - void getCIECertData() throws CertDataTagListNotFoundException, CertDataNotFoundException { - List response = idpCertSimpleClient.getCertData(CIE_ENTITY_ID, instant); + void certCIEDataFound() throws CertDataTagListNotFoundException, CertDataNotFoundException { + List response = idpCertSimpleClient.getCertData(CIE_ENTITY_ID, INSTANT); Assertions.assertNotNull(response); } + + @Test + void getCertDataWrongEntityID() throws CertDataTagListNotFoundException, CertDataNotFoundException { + Assertions.assertThrows(CertDataNotFoundException.class, () -> idpCertSimpleClient.getCertData(WRONG_ENTITY_ID, INSTANT)); + } + + @Test + void getCertDataWrongInstant() throws CertDataTagListNotFoundException, CertDataNotFoundException { + Assertions.assertThrows(CertDataTagListNotFoundException.class, () -> idpCertSimpleClient.getCertData(SPID_ENTITY_ID, WRONG_INSTANT)); + } + } \ No newline at end of file From dc999842ef51f77553e33fe219a3bf11773b859d Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 14:09:10 +0200 Subject: [PATCH 139/403] [SLS-19] Removed TODOs --- .../consumer/idp/client/simple/IdpCertSimpleClient.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index a7a1c9e9..5e24a158 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -55,7 +55,6 @@ public List getCertData(String entityId, String instant) throws Cer } for (String tag : tagList) { - //TODO recupero storage try { IdpCertData certData = getCIECertData(tag, entityId); @@ -75,7 +74,6 @@ public List getCertData(String entityId, String instant) throws Cer } for (String tag : tagList) { - //TODO recupero storage try { IdpCertData certData = getSPIDCertData(tag, entityId); From ff169138f2ff70a3d18fe33fa057e6bcc38d1365 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 14:56:49 +0200 Subject: [PATCH 140/403] [SLS-19] Completed signature retrieving from idp certification - added comments & cleaned models --- .../client/simple/AssertionSimpleClient.java | 1 + .../client/simple/IdpCertSimpleClient.java | 29 ++-- .../simple/IdpCertSimpleClientProvider.java | 1 + .../simple/internal/model/CertData.java | 3 +- .../internal/model/EntitiesDescriptor.java | 2 - .../internal/model/EntityDescriptor.java | 131 ++---------------- 6 files changed, 33 insertions(+), 134 deletions(-) diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java index 49ae014e..46cbfe29 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClient.java @@ -32,6 +32,7 @@ public AssertionSimpleClient(ApiClient client) { * @param assertionRef Assertion unique identification * @return the retrieved assertion or null if the assertion is not supported (not SAML) * @throws LollipopAssertionNotFoundException if some error occurred in the request + * @throws OidcAssertionNotSupported if the assertion retrieved is a OIDC token */ @Override public SamlAssertion getAssertion(String jwt, String assertionRef) diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 5e24a158..251ba97d 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -33,9 +33,14 @@ public IdpCertSimpleClient(ApiClient client) { } /** - * @param entityId - * @param instant - * @return + * Retrieve the certification data of the given entityId issued + * in the same timeframe as the issue instant of the SAML assertion + * + * @param entityId Identity Provider ID + * @param instant Assertion Issue Instant + * @return the certifications issued before and after the timestamp instant + * @throws CertDataTagListNotFoundException if an error occurred retrieving the list of tags or filtering the tags with the instant + * @throws CertDataNotFoundException if an error occurred retrieving the certification XML or if data for the given entityId were not found */ @Override public List getCertData(String entityId, String instant) throws CertDataNotFoundException, CertDataTagListNotFoundException { @@ -58,7 +63,7 @@ public List getCertData(String entityId, String instant) throws Cer try { IdpCertData certData = getCIECertData(tag, entityId); - if(certData != null){ + if (certData != null) { listCertData.add(certData); } } catch (ApiException | EntityIdNotFoundException e) { @@ -77,7 +82,7 @@ public List getCertData(String entityId, String instant) throws Cer try { IdpCertData certData = getSPIDCertData(tag, entityId); - if(certData != null){ + if (certData != null) { listCertData.add(certData); } } catch (ApiException | EntityIdNotFoundException e) { @@ -102,7 +107,7 @@ private IdpCertData getSPIDCertData(String tag, String entityId) throws EntityId responseAssertion = this.defaultApi.idpKeysSpidTagGet(tag); - return getEntityData(((EntitiesDescriptor)responseAssertion.getActualInstance()), tag, entityId); + return getEntityData(((EntitiesDescriptor) responseAssertion.getActualInstance()), tag, entityId); } private List getCIETagList(String instant) throws TagListSearchOutOfBoundException { @@ -118,17 +123,17 @@ private IdpCertData getCIECertData(String tag, String entityId) throws EntityIdN responseAssertion = this.defaultApi.idpKeysCieTagGet(tag); - return getEntityData(((EntitiesDescriptor)responseAssertion.getActualInstance()), tag, entityId); + return getEntityData(((EntitiesDescriptor) responseAssertion.getActualInstance()), tag, entityId); } private IdpCertData getEntityData(EntitiesDescriptor data, String tag, String entityId) throws EntityIdNotFoundException { IdpCertData newData = new IdpCertData(); for (EntityDescriptor entity : data.getEntityList()) { - if (entity.getEntityID().equals(entityId)){ + if (entity.getEntityID().equals(entityId)) { newData.setEntityId(entityId); newData.setTag(tag); - newData.setCertData("test"); + newData.setCertData(entity.getSignature()); return newData; } @@ -149,13 +154,13 @@ private List getTagsFromInstant(List tagList, String instant) th Collections.sort(tagList); - if(latestRemoved){ + if (latestRemoved) { tagList.add(0, "latest"); } boolean notFound = true; while (notFound) { - try{ + try { String upperTag = tagList.get(index); String lowerTag = tagList.get(index - 1); if (Long.valueOf(instant) <= Long.valueOf(upperTag) || upperTag.equals("latest")) { @@ -169,7 +174,7 @@ private List getTagsFromInstant(List tagList, String instant) th } else { index += 1; } - } catch (Exception e){ + } catch (Exception e) { throw new TagListSearchOutOfBoundException("Error finding the tags relative to assertion instant " + instant); } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java index 402136fd..68a756f1 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java @@ -5,6 +5,7 @@ import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; +/** Provider class for retrieving an instance of {@link IdpCertSimpleClient} */ public class IdpCertSimpleClientProvider implements IdpCertClientProvider { /** diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java index 8b256dc3..c3580595 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java @@ -78,9 +78,8 @@ public CertData deserialize(JsonParser jp, DeserializationContext ctxt) throws I EntitiesDescriptor entitiesDescriptor = new EntitiesDescriptor(); // deserialize CIECertData try { - deserialized = tree.traverse(jp.getCodec()).readValueAs(EntityDescriptor.class); - + deserialized = tree.traverse(jp.getCodec()).readValueAs(EntityDescriptor.class); if (((EntityDescriptor) deserialized).getEntityID() != null) { List entityList = Arrays.asList(((EntityDescriptor)deserialized)); diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java index 95dffbb6..9e5ace68 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java @@ -20,14 +20,12 @@ import java.util.List; - /** * EntitiesDescriptor */ @JsonIgnoreProperties(ignoreUnknown = true) @Getter @Setter -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class EntitiesDescriptor { @JsonProperty("EntityDescriptor") diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java index f822b9dc..6b602241 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java @@ -3,145 +3,40 @@ * Client used to retrieve the public keys from the identity provider * * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * + * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech * Do not edit the class manually. */ - package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Getter; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.Objects; -import java.util.StringJoiner; +import java.util.Map; /** * EntityDescriptor */ -@JsonPropertyOrder({ - EntityDescriptor.JSON_PROPERTY_ENTITY_I_D -}) @JsonIgnoreProperties(ignoreUnknown = true) -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +@Getter public class EntityDescriptor { - public static final String JSON_PROPERTY_ENTITY_I_D = "entityID"; - private String entityID; - - public EntityDescriptor() { - } - - public EntityDescriptor entityID(String entityID) { - this.entityID = entityID; - return this; - } - - /** - * Get entityID - * @return entityID - **/ - @javax.annotation.Nonnull - @JsonProperty(JSON_PROPERTY_ENTITY_I_D) - @JsonInclude(value = JsonInclude.Include.ALWAYS) - - public String getEntityID() { - return entityID; - } - - - @JsonProperty(JSON_PROPERTY_ENTITY_I_D) - @JsonInclude(value = JsonInclude.Include.ALWAYS) - public void setEntityID(String entityID) { - this.entityID = entityID; - } - - - /** - * Return true if this EntityDescriptor object is equal to o. - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - EntityDescriptor entityDescriptor = (EntityDescriptor) o; - return Objects.equals(this.entityID, entityDescriptor.entityID); - } - - @Override - public int hashCode() { - return Objects.hash(entityID); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class EntityDescriptor {\n"); - sb.append(" entityID: ").append(toIndentedString(entityID)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } - - /** - * Convert the instance into URL query string. - * - * @return URL query string - */ - public String toUrlQueryString() { - return toUrlQueryString(null); - } - - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - String suffix = ""; - String containerSuffix = ""; - String containerPrefix = ""; - if (prefix == null) { - // style=form, explode=true, e.g. /pet?name=cat&type=manx - prefix = ""; - } else { - // deepObject style e.g. /pet?id[name]=cat&id[type]=manx - prefix = prefix + "["; - suffix = "]"; - containerSuffix = "]"; - containerPrefix = "["; - } + @JsonProperty("entityID") + private String entityID; - StringJoiner joiner = new StringJoiner("&"); + private String signature; - // add `entityID` to the URL query string - if (getEntityID() != null) { - joiner.add(String.format("%sentityID%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getEntityID()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + @SuppressWarnings("unchecked") + @JsonProperty("Signature") + private void unpackNestedSignature(Map signature) { + Map keyInfo = (Map) signature.get("KeyInfo"); + Map x509Data = (Map) keyInfo.get("X509Data"); + this.signature = (String) x509Data.get("X509Certificate"); } - return joiner.toString(); - } } From 4496f80b570f2555162b933842acf21c0c950cbf Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 15:06:52 +0200 Subject: [PATCH 141/403] [SLS-19] Improved test constant instant - fixed tag list filtering --- .../consumer/idp/client/simple/IdpCertSimpleClient.java | 4 ++-- .../src/test/java/simple/IdpCertSimpleClientTest.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 251ba97d..64a0b9d9 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -155,7 +155,7 @@ private List getTagsFromInstant(List tagList, String instant) th Collections.sort(tagList); if (latestRemoved) { - tagList.add(0, "latest"); + tagList.add("latest"); } boolean notFound = true; @@ -163,7 +163,7 @@ private List getTagsFromInstant(List tagList, String instant) th try { String upperTag = tagList.get(index); String lowerTag = tagList.get(index - 1); - if (Long.valueOf(instant) <= Long.valueOf(upperTag) || upperTag.equals("latest")) { + if (upperTag.equals("latest") || Long.valueOf(instant) <= Long.valueOf(upperTag)) { if (Long.valueOf(instant) >= Long.valueOf(lowerTag)) { notFound = false; newTagList.add(upperTag); diff --git a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java index 7972a073..951748e9 100644 --- a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java @@ -13,13 +13,14 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import java.time.Instant; import java.util.List; class IdpCertSimpleClientTest { private static IdpCertSimpleClient idpCertSimpleClient; - private static final String INSTANT = "1679072970"; + private static final String INSTANT = String.valueOf(Instant.now().getEpochSecond()); private static final String SPID_ENTITY_ID = "https://posteid.poste.it"; private static final String CIE_ENTITY_ID = "https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"; From 65c885ac13248b7d445be8d75c2bddb2030b51d8 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 16:04:37 +0200 Subject: [PATCH 142/403] [SLS-19] Improved tag list filtering - added test & configuration for valid CIE entity id --- .../exception/CertDataNotFoundException.java | 1 + .../CertDataTagListNotFoundException.java | 1 + .../exception/EntityIdNotFoundException.java | 3 +- .../InvalidInstantFormatException.java | 14 +++++ .../build.gradle | 3 + .../client/simple/IdpCertSimpleClient.java | 58 ++++++++++--------- .../simple/IdpCertSimpleClientConfig.java | 15 +++++ .../simple/IdpCertSimpleClientProvider.java | 10 +++- .../simple/internal/model/CertData.java | 2 +- .../java/simple/IdpCertSimpleClientTest.java | 17 ++++-- 10 files changed, 90 insertions(+), 34 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/InvalidInstantFormatException.java create mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataNotFoundException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataNotFoundException.java index 95030acb..7665e698 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataNotFoundException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataNotFoundException.java @@ -1,5 +1,6 @@ package it.pagopa.tech.lollipop.consumer.exception; +/** Thrown in case of problems retrieving idp certification data */ public class CertDataNotFoundException extends Exception{ /** * Constructs new exception with provided message and cause diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java index fe00adfb..4355873e 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java @@ -1,5 +1,6 @@ package it.pagopa.tech.lollipop.consumer.exception; +/** Thrown in case of problems retrieving idp certification tag list */ public class CertDataTagListNotFoundException extends Exception{ /** * Constructs new exception with provided message and cause diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/EntityIdNotFoundException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/EntityIdNotFoundException.java index 7b5b35ce..0932b69c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/EntityIdNotFoundException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/EntityIdNotFoundException.java @@ -1,9 +1,10 @@ package it.pagopa.tech.lollipop.consumer.exception; +/** Thrown in case of problems finding the right data for the given entityId */ public class EntityIdNotFoundException extends Exception{ /** - * Constructs new exception with provided messag + * Constructs new exception with provided message * * @param message Detail message */ diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/InvalidInstantFormatException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/InvalidInstantFormatException.java new file mode 100644 index 00000000..3640b348 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/InvalidInstantFormatException.java @@ -0,0 +1,14 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +/** Thrown when the given instant is not a valid timestamp */ +public class InvalidInstantFormatException extends Exception { + + /** + * Constructs new exception with provided message + * + * @param message Detail message + */ + public InvalidInstantFormatException(String message) { + super(message); + } +} diff --git a/identity-service-rest-client-native/build.gradle b/identity-service-rest-client-native/build.gradle index d38a7392..3ae67e50 100644 --- a/identity-service-rest-client-native/build.gradle +++ b/identity-service-rest-client-native/build.gradle @@ -57,6 +57,9 @@ dependencies { // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.assertj:assertj-core:3.24.2' + + testImplementation 'org.mockito:mockito-core:5.2.0' + testImplementation 'org.mockito:mockito-junit-jupiter:5.2.0' //Mockserver for testing api testImplementation 'org.mock-server:mockserver-netty:5.15.0' } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 64a0b9d9..6b773812 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -1,10 +1,7 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple; -import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.EntityIdNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.TagListSearchOutOfBoundException; +import it.pagopa.tech.lollipop.consumer.exception.*; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiException; @@ -24,12 +21,14 @@ public class IdpCertSimpleClient implements IdpCertClient { private final ApiClient apiClient; private final DefaultApi defaultApi; - private static final List CIE_ENTITY_IDS = new ArrayList<>(List.of("https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO")); + private final IdpCertSimpleClientConfig entityConfig; + @Inject - public IdpCertSimpleClient(ApiClient client) { + public IdpCertSimpleClient(ApiClient client, IdpCertSimpleClientConfig entityConfig) { this.apiClient = client; this.defaultApi = new DefaultApi(client); + this.entityConfig = entityConfig; } /** @@ -51,11 +50,10 @@ public List getCertData(String entityId, String instant) throws Cer throw new IllegalArgumentException("EntityID or Assertion Issue Instant missing"); } - if (CIE_ENTITY_IDS.contains(entityId)) { //TODO inserire entityID in classe di configurazione - + if (entityConfig.getCieEntityId().contains(entityId)) { try { tagList = getCIETagList(instant); - } catch (ApiException | TagListSearchOutOfBoundException e) { + } catch (ApiException | TagListSearchOutOfBoundException | InvalidInstantFormatException e) { throw new CertDataTagListNotFoundException("Error retrieving certificate's tag list: " + e.getMessage(), e); } @@ -63,9 +61,7 @@ public List getCertData(String entityId, String instant) throws Cer try { IdpCertData certData = getCIECertData(tag, entityId); - if (certData != null) { - listCertData.add(certData); - } + listCertData.add(certData); } catch (ApiException | EntityIdNotFoundException e) { throw new CertDataNotFoundException("Error retrieving certificate data for tag " + tag + ": " + e.getMessage(), e); } @@ -74,7 +70,7 @@ public List getCertData(String entityId, String instant) throws Cer } else { try { tagList = getSPIDTagList(instant); - } catch (ApiException | TagListSearchOutOfBoundException e) { + } catch (ApiException | TagListSearchOutOfBoundException | InvalidInstantFormatException e) { throw new CertDataTagListNotFoundException("Error retrieving certificate's tag list: " + e.getMessage(), e); } @@ -82,9 +78,7 @@ public List getCertData(String entityId, String instant) throws Cer try { IdpCertData certData = getSPIDCertData(tag, entityId); - if (certData != null) { - listCertData.add(certData); - } + listCertData.add(certData); } catch (ApiException | EntityIdNotFoundException e) { throw new CertDataNotFoundException("Error retrieving certificate data for tag " + tag + ": " + e.getMessage(), e); } @@ -94,7 +88,7 @@ public List getCertData(String entityId, String instant) throws Cer return listCertData; } - private List getSPIDTagList(String instant) throws TagListSearchOutOfBoundException { + private List getSPIDTagList(String instant) throws TagListSearchOutOfBoundException, InvalidInstantFormatException { List responseAssertion; responseAssertion = this.defaultApi.idpKeysSpidGet(); @@ -110,7 +104,7 @@ private IdpCertData getSPIDCertData(String tag, String entityId) throws EntityId return getEntityData(((EntitiesDescriptor) responseAssertion.getActualInstance()), tag, entityId); } - private List getCIETagList(String instant) throws TagListSearchOutOfBoundException { + private List getCIETagList(String instant) throws TagListSearchOutOfBoundException, InvalidInstantFormatException { List responseAssertion; responseAssertion = this.defaultApi.idpKeysCieGet(); @@ -142,29 +136,41 @@ private IdpCertData getEntityData(EntitiesDescriptor data, String tag, String en throw new EntityIdNotFoundException("Cert for entityID " + entityId + " not found"); } - private List getTagsFromInstant(List tagList, String instant) throws TagListSearchOutOfBoundException { + private List getTagsFromInstant(List tagList, String instant) throws TagListSearchOutOfBoundException, InvalidInstantFormatException { List newTagList = new ArrayList<>(); + String latest = "latest"; + long longInstant; - if (tagList.size() <= 2) { - return tagList; + try { + longInstant = Long.parseLong(instant); + } catch (Exception e) { + throw new InvalidInstantFormatException("The given insant " + instant + " is not a valid timestamp"); } - int index = tagList.size() / 2; - boolean latestRemoved = tagList.remove("latest"); + boolean latestRemoved = tagList.remove(latest); Collections.sort(tagList); if (latestRemoved) { - tagList.add("latest"); + tagList.add(latest); } + int index = tagList.size() / 2; + boolean notFound = true; while (notFound) { try { + if (tagList.size() <= 2) { + String firstTimestamp = tagList.get(0); + if (firstTimestamp.equals(latest) || Long.parseLong(firstTimestamp) <= longInstant) { + return tagList; + } + } + String upperTag = tagList.get(index); String lowerTag = tagList.get(index - 1); - if (upperTag.equals("latest") || Long.valueOf(instant) <= Long.valueOf(upperTag)) { - if (Long.valueOf(instant) >= Long.valueOf(lowerTag)) { + if (upperTag.equals(latest) || longInstant <= Long.parseLong(upperTag)) { + if (longInstant >= Long.parseLong(lowerTag)) { notFound = false; newTagList.add(upperTag); newTagList.add(lowerTag); diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java new file mode 100644 index 00000000..8f0f0eab --- /dev/null +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java @@ -0,0 +1,15 @@ +package it.pagopa.tech.lollipop.consumer.idp.client.simple; + +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +@Data +@Builder +public class IdpCertSimpleClientConfig { + + @Builder.Default + private List cieEntityId = List.of("https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"); + +} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java index 68a756f1..997c923a 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java @@ -5,9 +5,17 @@ import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; +import javax.inject.Inject; + /** Provider class for retrieving an instance of {@link IdpCertSimpleClient} */ public class IdpCertSimpleClientProvider implements IdpCertClientProvider { + private final IdpCertSimpleClientConfig entityConfig; + + @Inject + public IdpCertSimpleClientProvider(IdpCertSimpleClientConfig entityConfig){ + this.entityConfig = entityConfig; + } /** * Provide an instance of {@link IdpCertSimpleClient} * @@ -15,6 +23,6 @@ public class IdpCertSimpleClientProvider implements IdpCertClientProvider { */ @Override public IdpCertClient provideClient() { - return new IdpCertSimpleClient(new ApiClient()); + return new IdpCertSimpleClient(new ApiClient(), this.entityConfig); } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java index c3580595..ace38068 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java @@ -76,7 +76,7 @@ public CertData deserialize(JsonParser jp, DeserializationContext ctxt) throws I int match = 0; JsonToken token = tree.traverse(jp.getCodec()).nextToken(); EntitiesDescriptor entitiesDescriptor = new EntitiesDescriptor(); - // deserialize CIECertData + try { deserialized = tree.traverse(jp.getCodec()).readValueAs(EntityDescriptor.class); diff --git a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java index 951748e9..866f7d24 100644 --- a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java @@ -3,15 +3,14 @@ import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.EntityIdNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.TagListSearchOutOfBoundException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClient; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; -import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; import java.time.Instant; import java.util.List; @@ -19,6 +18,7 @@ class IdpCertSimpleClientTest { private static IdpCertSimpleClient idpCertSimpleClient; + private static IdpCertSimpleClientConfig entityConfig; private static final String INSTANT = String.valueOf(Instant.now().getEpochSecond()); private static final String SPID_ENTITY_ID = "https://posteid.poste.it"; @@ -30,8 +30,10 @@ class IdpCertSimpleClientTest { @BeforeAll public static void startServer() { ApiClient client = new ApiClient(); - idpCertSimpleClient = new IdpCertSimpleClient(client); + entityConfig = Mockito.spy(IdpCertSimpleClientConfig.builder().build()); + idpCertSimpleClient = new IdpCertSimpleClient(client, entityConfig); } + @Test void certSPIDDataFound() throws CertDataTagListNotFoundException, CertDataNotFoundException { List response = idpCertSimpleClient.getCertData(SPID_ENTITY_ID, INSTANT); @@ -52,8 +54,13 @@ void getCertDataWrongEntityID() throws CertDataTagListNotFoundException, CertDat } @Test - void getCertDataWrongInstant() throws CertDataTagListNotFoundException, CertDataNotFoundException { + void getSPIDCertDataWrongInstant() throws CertDataTagListNotFoundException, CertDataNotFoundException { Assertions.assertThrows(CertDataTagListNotFoundException.class, () -> idpCertSimpleClient.getCertData(SPID_ENTITY_ID, WRONG_INSTANT)); } + @Test + void getCIECertDataWrongInstant() throws CertDataTagListNotFoundException, CertDataNotFoundException { + Assertions.assertThrows(CertDataTagListNotFoundException.class, () -> idpCertSimpleClient.getCertData(CIE_ENTITY_ID, WRONG_INSTANT)); + } + } \ No newline at end of file From ed9bb6ced32b1b4714e209946cfc268b77338dff Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 16:58:00 +0200 Subject: [PATCH 143/403] [SLS-19] Added configuration for api client for baseUri and endpoints - applied spotless --- .../simple/AssertionSimpleClientTest.java | 241 ++++---- .../exception/CertDataNotFoundException.java | 3 +- .../CertDataTagListNotFoundException.java | 3 +- .../exception/EntityIdNotFoundException.java | 3 +- .../InvalidInstantFormatException.java | 1 + .../TagListSearchOutOfBoundException.java | 3 +- .../consumer/idp/client/IdpCertClient.java | 3 +- .../client/simple/IdpCertSimpleClient.java | 84 ++- .../simple/IdpCertSimpleClientConfig.java | 12 +- .../simple/IdpCertSimpleClientProvider.java | 9 +- .../idp/client/simple/internal/ApiClient.java | 567 +++++------------ .../client/simple/internal/ApiException.java | 34 +- .../client/simple/internal/ApiResponse.java | 20 +- .../simple/internal/api/DefaultApi.java | 571 +++++++++--------- .../internal/model/AbstractOpenApiSchema.java | 54 +- .../simple/internal/model/CertData.java | 65 +- .../internal/model/EntitiesDescriptor.java | 27 +- .../internal/model/EntityDescriptor.java | 23 +- .../simple/internal/model/ProblemJson.java | 515 ++++++++-------- .../java/simple/IdpCertSimpleClientTest.java | 33 +- 20 files changed, 974 insertions(+), 1297 deletions(-) diff --git a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java index 4a82d1cb..849c2031 100644 --- a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java +++ b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java @@ -21,129 +21,124 @@ class AssertionSimpleClientTest { private static AssertionSimpleClient assertionSimpleClient; private static ClientAndServer mockServer; - private static final String XML_STRING = " https://posteid.poste.it" - + " " - + " " - + " " - + " " - + " " - + " " - + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" - + " " - + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" - + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" - + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" - + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" - + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " - + " " - + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" - + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" - + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" - + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" - + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" - + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" - + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" - + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" - + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" - + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" - + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" - + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" - + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" - + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" - + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" - + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" - + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" - + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" - + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" - + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" - + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" - + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" - + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" - + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" - + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" - + " " - + " " - + " https://posteid.poste.it " - + " " - + " " - + " " - + " " - + " " - + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" - + " " - + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" - + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" - + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" - + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" - + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " - + " " - + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" - + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" - + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" - + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" - + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" - + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" - + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" - + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" - + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" - + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" - + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" - + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" - + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" - + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" - + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" - + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" - + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" - + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" - + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" - + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" - + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" - + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" - + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" - + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" - + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" - + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" - + " " - + " " - + " " - + " https://app-backend.io.italia.it" - + " " - + " https://www.spid.gov.it/SpidL2" - + " " - + " " - + " TINIT-AAAAAA89S20I111X" - + " " - + " "; + private static final String XML_STRING = + " https://posteid.poste.it" + + " " + + " " + + " " + + " " + + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" + + " " + + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" + + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" + + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" + + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" + + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " " + + " " + + " https://posteid.poste.it " + + " " + + " " + + " " + + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" + + " " + + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" + + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" + + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" + + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" + + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + " " + + " " + + " " + + " https://app-backend.io.italia.it" + + " " + + " https://www.spid.gov.it/SpidL2" + + " " + + " " + + " " + + " TINIT-AAAAAA89S20I111X " + + " "; private static final String RESPONSE_STRING = "{\"response_xml\": \" getCertData(String entityId, String instant) throws CertDataNotFoundException, CertDataTagListNotFoundException; + List getCertData(String entityId, String instant) + throws CertDataNotFoundException, CertDataTagListNotFoundException; } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 6b773812..1b62a68c 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -10,39 +10,38 @@ import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.EntitiesDescriptor; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.EntityDescriptor; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; - -import javax.inject.Inject; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import javax.inject.Inject; public class IdpCertSimpleClient implements IdpCertClient { - private final ApiClient apiClient; private final DefaultApi defaultApi; private final IdpCertSimpleClientConfig entityConfig; - @Inject public IdpCertSimpleClient(ApiClient client, IdpCertSimpleClientConfig entityConfig) { - this.apiClient = client; this.defaultApi = new DefaultApi(client); this.entityConfig = entityConfig; } /** - * Retrieve the certification data of the given entityId issued - * in the same timeframe as the issue instant of the SAML assertion + * Retrieve the certification data of the given entityId issued in the same timeframe as the + * issue instant of the SAML assertion * * @param entityId Identity Provider ID - * @param instant Assertion Issue Instant + * @param instant Assertion Issue Instant * @return the certifications issued before and after the timestamp instant - * @throws CertDataTagListNotFoundException if an error occurred retrieving the list of tags or filtering the tags with the instant - * @throws CertDataNotFoundException if an error occurred retrieving the certification XML or if data for the given entityId were not found + * @throws CertDataTagListNotFoundException if an error occurred retrieving the list of tags or + * filtering the tags with the instant + * @throws CertDataNotFoundException if an error occurred retrieving the certification XML or if + * data for the given entityId were not found */ @Override - public List getCertData(String entityId, String instant) throws CertDataNotFoundException, CertDataTagListNotFoundException { + public List getCertData(String entityId, String instant) + throws CertDataNotFoundException, CertDataTagListNotFoundException { List listCertData = new ArrayList<>(); List tagList; @@ -53,8 +52,11 @@ public List getCertData(String entityId, String instant) throws Cer if (entityConfig.getCieEntityId().contains(entityId)) { try { tagList = getCIETagList(instant); - } catch (ApiException | TagListSearchOutOfBoundException | InvalidInstantFormatException e) { - throw new CertDataTagListNotFoundException("Error retrieving certificate's tag list: " + e.getMessage(), e); + } catch (ApiException + | TagListSearchOutOfBoundException + | InvalidInstantFormatException e) { + throw new CertDataTagListNotFoundException( + "Error retrieving certificate's tag list: " + e.getMessage(), e); } for (String tag : tagList) { @@ -63,15 +65,22 @@ public List getCertData(String entityId, String instant) throws Cer listCertData.add(certData); } catch (ApiException | EntityIdNotFoundException e) { - throw new CertDataNotFoundException("Error retrieving certificate data for tag " + tag + ": " + e.getMessage(), e); + throw new CertDataNotFoundException( + "Error retrieving certificate data for tag " + + tag + + ": " + + e.getMessage(), + e); } - } } else { try { tagList = getSPIDTagList(instant); - } catch (ApiException | TagListSearchOutOfBoundException | InvalidInstantFormatException e) { - throw new CertDataTagListNotFoundException("Error retrieving certificate's tag list: " + e.getMessage(), e); + } catch (ApiException + | TagListSearchOutOfBoundException + | InvalidInstantFormatException e) { + throw new CertDataTagListNotFoundException( + "Error retrieving certificate's tag list: " + e.getMessage(), e); } for (String tag : tagList) { @@ -80,15 +89,20 @@ public List getCertData(String entityId, String instant) throws Cer listCertData.add(certData); } catch (ApiException | EntityIdNotFoundException e) { - throw new CertDataNotFoundException("Error retrieving certificate data for tag " + tag + ": " + e.getMessage(), e); + throw new CertDataNotFoundException( + "Error retrieving certificate data for tag " + + tag + + ": " + + e.getMessage(), + e); } - } } return listCertData; } - private List getSPIDTagList(String instant) throws TagListSearchOutOfBoundException, InvalidInstantFormatException { + private List getSPIDTagList(String instant) + throws TagListSearchOutOfBoundException, InvalidInstantFormatException { List responseAssertion; responseAssertion = this.defaultApi.idpKeysSpidGet(); @@ -96,15 +110,18 @@ private List getSPIDTagList(String instant) throws TagListSearchOutOfBou return getTagsFromInstant(responseAssertion, instant); } - private IdpCertData getSPIDCertData(String tag, String entityId) throws EntityIdNotFoundException { + private IdpCertData getSPIDCertData(String tag, String entityId) + throws EntityIdNotFoundException { CertData responseAssertion = null; responseAssertion = this.defaultApi.idpKeysSpidTagGet(tag); - return getEntityData(((EntitiesDescriptor) responseAssertion.getActualInstance()), tag, entityId); + return getEntityData( + ((EntitiesDescriptor) responseAssertion.getActualInstance()), tag, entityId); } - private List getCIETagList(String instant) throws TagListSearchOutOfBoundException, InvalidInstantFormatException { + private List getCIETagList(String instant) + throws TagListSearchOutOfBoundException, InvalidInstantFormatException { List responseAssertion; responseAssertion = this.defaultApi.idpKeysCieGet(); @@ -112,15 +129,18 @@ private List getCIETagList(String instant) throws TagListSearchOutOfBoun return getTagsFromInstant(responseAssertion, instant); } - private IdpCertData getCIECertData(String tag, String entityId) throws EntityIdNotFoundException { + private IdpCertData getCIECertData(String tag, String entityId) + throws EntityIdNotFoundException { CertData responseAssertion; responseAssertion = this.defaultApi.idpKeysCieTagGet(tag); - return getEntityData(((EntitiesDescriptor) responseAssertion.getActualInstance()), tag, entityId); + return getEntityData( + ((EntitiesDescriptor) responseAssertion.getActualInstance()), tag, entityId); } - private IdpCertData getEntityData(EntitiesDescriptor data, String tag, String entityId) throws EntityIdNotFoundException { + private IdpCertData getEntityData(EntitiesDescriptor data, String tag, String entityId) + throws EntityIdNotFoundException { IdpCertData newData = new IdpCertData(); for (EntityDescriptor entity : data.getEntityList()) { @@ -136,7 +156,8 @@ private IdpCertData getEntityData(EntitiesDescriptor data, String tag, String en throw new EntityIdNotFoundException("Cert for entityID " + entityId + " not found"); } - private List getTagsFromInstant(List tagList, String instant) throws TagListSearchOutOfBoundException, InvalidInstantFormatException { + private List getTagsFromInstant(List tagList, String instant) + throws TagListSearchOutOfBoundException, InvalidInstantFormatException { List newTagList = new ArrayList<>(); String latest = "latest"; long longInstant; @@ -144,7 +165,8 @@ private List getTagsFromInstant(List tagList, String instant) th try { longInstant = Long.parseLong(instant); } catch (Exception e) { - throw new InvalidInstantFormatException("The given insant " + instant + " is not a valid timestamp"); + throw new InvalidInstantFormatException( + "The given insant " + instant + " is not a valid timestamp"); } boolean latestRemoved = tagList.remove(latest); @@ -162,7 +184,8 @@ private List getTagsFromInstant(List tagList, String instant) th try { if (tagList.size() <= 2) { String firstTimestamp = tagList.get(0); - if (firstTimestamp.equals(latest) || Long.parseLong(firstTimestamp) <= longInstant) { + if (firstTimestamp.equals(latest) + || Long.parseLong(firstTimestamp) <= longInstant) { return tagList; } } @@ -181,7 +204,8 @@ private List getTagsFromInstant(List tagList, String instant) th index += 1; } } catch (Exception e) { - throw new TagListSearchOutOfBoundException("Error finding the tags relative to assertion instant " + instant); + throw new TagListSearchOutOfBoundException( + "Error finding the tags relative to assertion instant " + instant); } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java index 8f0f0eab..d744001b 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java @@ -1,15 +1,21 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple; +import java.util.List; import lombok.Builder; import lombok.Data; -import java.util.List; - @Data @Builder public class IdpCertSimpleClientConfig { @Builder.Default - private List cieEntityId = List.of("https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"); + private List cieEntityId = + List.of("https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"); + + @Builder.Default private String baseUri = "https://api.is.eng.pagopa.it"; + + @Builder.Default private String idpKeysCieEndpoint = "/idp-keys/cie"; + @Builder.Default private String idpKeysSpidEndpoint = "/idp-keys/spid"; } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java index 997c923a..6a292a71 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java @@ -4,17 +4,16 @@ import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; - import javax.inject.Inject; /** Provider class for retrieving an instance of {@link IdpCertSimpleClient} */ public class IdpCertSimpleClientProvider implements IdpCertClientProvider { - private final IdpCertSimpleClientConfig entityConfig; + private final IdpCertSimpleClientConfig idpClientConfig; @Inject - public IdpCertSimpleClientProvider(IdpCertSimpleClientConfig entityConfig){ - this.entityConfig = entityConfig; + public IdpCertSimpleClientProvider(IdpCertSimpleClientConfig config) { + this.idpClientConfig = config; } /** * Provide an instance of {@link IdpCertSimpleClient} @@ -23,6 +22,6 @@ public IdpCertSimpleClientProvider(IdpCertSimpleClientConfig entityConfig){ */ @Override public IdpCertClient provideClient() { - return new IdpCertSimpleClient(new ApiClient(), this.entityConfig); + return new IdpCertSimpleClient(new ApiClient(this.idpClientConfig), this.idpClientConfig); } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java index 5bd7a9d9..b1c57be6 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiClient.java @@ -1,472 +1,185 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import org.openapitools.jackson.nullable.JsonNullableModule; - +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; import java.io.InputStream; import java.net.URI; import java.net.URLEncoder; import java.net.http.HttpClient; -import java.net.http.HttpConnectTimeoutException; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; -import java.time.OffsetDateTime; -import java.time.format.DateTimeFormatter; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.StringJoiner; import java.util.function.Consumer; -import java.util.stream.Collectors; - -import static java.nio.charset.StandardCharsets.UTF_8; +import lombok.Getter; +import org.openapitools.jackson.nullable.JsonNullableModule; /** * Configuration and utility class for API clients. * - *

This class can be constructed and modified, then used to instantiate the - * various API classes. The API classes use the settings in this class to - * configure themselves, but otherwise do not store a link to this class.

+ *

This class can be constructed and modified, then used to instantiate the various API classes. + * The API classes use the settings in this class to configure themselves, but otherwise do not + * store a link to this class. * - *

This class is mutable and not synchronized, so it is not thread-safe. - * The API classes generated from this are immutable and thread-safe.

+ *

This class is mutable and not synchronized, so it is not thread-safe. The API classes + * generated from this are immutable and thread-safe. * - *

The setter methods of this class return the current object to facilitate - * a fluent style of configuration.

+ *

The setter methods of this class return the current object to facilitate a fluent style of + * configuration. */ -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +@Getter +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class ApiClient { - private HttpClient.Builder builder; - private ObjectMapper mapper; - private XmlMapper xmlMapper; - private String scheme; - private String host; - private int port; - private String basePath; - private Consumer interceptor; - private Consumer> responseInterceptor; - private Consumer> asyncResponseInterceptor; - private Duration readTimeout; - private Duration connectTimeout; - - private static String valueToString(Object value) { - if (value == null) { - return ""; - } - if (value instanceof OffsetDateTime) { - return ((OffsetDateTime) value).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + private HttpClient.Builder builder; + private ObjectMapper mapper; + private XmlMapper xmlMapper; + private String scheme; + private String host; + private int port; + private String basePath; + private Consumer interceptor; + private Consumer> responseInterceptor; + private Consumer> asyncResponseInterceptor; + private Duration readTimeout; + private Duration connectTimeout; + private String idpKeysCieEndpoint; + private String idpKeysSpidEndpoint; + + /** + * URL encode a string in the UTF-8 encoding. + * + * @param s String to encode. + * @return URL-encoded representation of the input string. + */ + public static String urlEncode(String s) { + return URLEncoder.encode(s, UTF_8).replaceAll("\\+", "%20"); } - return value.toString(); - } - - /** - * URL encode a string in the UTF-8 encoding. - * - * @param s String to encode. - * @return URL-encoded representation of the input string. - */ - public static String urlEncode(String s) { - return URLEncoder.encode(s, UTF_8).replaceAll("\\+", "%20"); - } - /** - * Convert a URL query name/value parameter to a list of encoded {@link Pair} - * objects. - * - *

The value can be null, in which case an empty list is returned.

- * - * @param name The query name parameter. - * @param value The query value, which may not be a collection but may be - * null. - * @return A singleton list of the {@link Pair} objects representing the input - * parameters, which is encoded for use in a URL. If the value is null, an - * empty list is returned. - */ - public static List parameterToPairs(String name, Object value) { - if (name == null || name.isEmpty() || value == null) { - return Collections.emptyList(); + /** Create an instance of ApiClient. */ + public ApiClient(IdpCertSimpleClientConfig config) { + this.builder = createDefaultHttpClientBuilder(); + this.mapper = createDefaultObjectMapper(); + this.xmlMapper = createDefaultXmlMapper(); + updateBaseUri(config.getBaseUri()); + interceptor = null; + readTimeout = null; + connectTimeout = null; + responseInterceptor = null; + asyncResponseInterceptor = null; + this.idpKeysCieEndpoint = config.getIdpKeysCieEndpoint(); + this.idpKeysSpidEndpoint = config.getIdpKeysSpidEndpoint(); } - return Collections.singletonList(new Pair(urlEncode(name), urlEncode(valueToString(value)))); - } - /** - * Convert a URL query name/collection parameter to a list of encoded - * {@link Pair} objects. - * - * @param collectionFormat The swagger collectionFormat string (csv, tsv, etc). - * @param name The query name parameter. - * @param values A collection of values for the given query name, which may be - * null. - * @return A list of {@link Pair} objects representing the input parameters, - * which is encoded for use in a URL. If the values collection is null, an - * empty list is returned. - */ - public static List parameterToPairs( - String collectionFormat, String name, Collection values) { - if (name == null || name.isEmpty() || values == null || values.isEmpty()) { - return Collections.emptyList(); + protected ObjectMapper createDefaultObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); + mapper.registerModule(new JavaTimeModule()); + mapper.registerModule(new JsonNullableModule()); + return mapper; } - // get the collection format (default: csv) - String format = collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat; - - // create the params based on the collection format - if ("multi".equals(format)) { - return values.stream() - .map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value)))) - .collect(Collectors.toList()); + protected XmlMapper createDefaultXmlMapper() { + XmlMapper mapper = new XmlMapper(); + return mapper; } - String delimiter; - switch(format) { - case "csv": - delimiter = urlEncode(","); - break; - case "ssv": - delimiter = urlEncode(" "); - break; - case "tsv": - delimiter = urlEncode("\t"); - break; - case "pipes": - delimiter = urlEncode("|"); - break; - default: - throw new IllegalArgumentException("Illegal collection format: " + collectionFormat); + protected HttpClient.Builder createDefaultHttpClientBuilder() { + return HttpClient.newBuilder(); } - StringJoiner joiner = new StringJoiner(delimiter); - for (Object value : values) { - joiner.add(urlEncode(valueToString(value))); + public void updateBaseUri(String baseUri) { + URI uri = URI.create(baseUri); + scheme = uri.getScheme(); + host = uri.getHost(); + port = uri.getPort(); + basePath = uri.getRawPath(); } - return Collections.singletonList(new Pair(urlEncode(name), joiner.toString())); - } - - /** - * Create an instance of ApiClient. - */ - public ApiClient() { - this.builder = createDefaultHttpClientBuilder(); - this.mapper = createDefaultObjectMapper(); - this.xmlMapper = createDefaultXmlMapper(); - updateBaseUri(getDefaultBaseUri()); - interceptor = null; - readTimeout = null; - connectTimeout = null; - responseInterceptor = null; - asyncResponseInterceptor = null; - } - - /** - * Create an instance of ApiClient. - * - * @param builder Http client builder. - * @param mapper Object mapper. - * @param baseUri Base URI - */ - public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, XmlMapper xmlMapper, String baseUri) { - this.builder = builder; - this.mapper = mapper; - this.xmlMapper = xmlMapper; - updateBaseUri(baseUri != null ? baseUri : getDefaultBaseUri()); - interceptor = null; - readTimeout = null; - connectTimeout = null; - responseInterceptor = null; - asyncResponseInterceptor = null; - } - - protected ObjectMapper createDefaultObjectMapper() { - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); - mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); - mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); - mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); - mapper.registerModule(new JavaTimeModule()); - mapper.registerModule(new JsonNullableModule()); - return mapper; - } - - protected XmlMapper createDefaultXmlMapper() { - XmlMapper mapper = new XmlMapper(); - return mapper; - } - - protected String getDefaultBaseUri() { - return "https://api.is.eng.pagopa.it"; - } - - protected HttpClient.Builder createDefaultHttpClientBuilder() { - return HttpClient.newBuilder(); - } - - public void updateBaseUri(String baseUri) { - URI uri = URI.create(baseUri); - scheme = uri.getScheme(); - host = uri.getHost(); - port = uri.getPort(); - basePath = uri.getRawPath(); - } - - /** - * Set a custom {@link HttpClient.Builder} object to use when creating the - * {@link HttpClient} that is used by the API client. - * - * @param builder Custom client builder. - * @return This object. - */ - public ApiClient setHttpClientBuilder(HttpClient.Builder builder) { - this.builder = builder; - return this; - } - - /** - * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}. - * - *

The returned object is immutable and thread-safe.

- * - * @return The HTTP client. - */ - public HttpClient getHttpClient() { - return builder.build(); - } - - /** - * Set a custom {@link ObjectMapper} to serialize and deserialize the request - * and response bodies. - * - * @param mapper Custom object mapper. - * @return This object. - */ - public ApiClient setObjectMapper(ObjectMapper mapper) { - this.mapper = mapper; - return this; - } - - /** - * Get a copy of the current {@link ObjectMapper}. - * - * @return A copy of the current object mapper. - */ - public ObjectMapper getObjectMapper() { - return mapper.copy(); - } - - public ApiClient setXmlMapper(XmlMapper mapper) { - this.xmlMapper = mapper; - return this; - } - - public XmlMapper getXmlMapper() { return xmlMapper.copy(); } - - /** - * Set a custom host name for the target service. - * - * @param host The host name of the target service. - * @return This object. - */ - public ApiClient setHost(String host) { - this.host = host; - return this; - } - - /** - * Set a custom port number for the target service. - * - * @param port The port of the target service. Set this to -1 to reset the - * value to the default for the scheme. - * @return This object. - */ - public ApiClient setPort(int port) { - this.port = port; - return this; - } - - /** - * Set a custom base path for the target service, for example '/v2'. - * - * @param basePath The base path against which the rest of the path is - * resolved. - * @return This object. - */ - public ApiClient setBasePath(String basePath) { - this.basePath = basePath; - return this; - } - - /** - * Get the base URI to resolve the endpoint paths against. - * - * @return The complete base URI that the rest of the API parameters are - * resolved against. - */ - public String getBaseUri() { - return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; - } - - /** - * Set a custom scheme for the target service, for example 'https'. - * - * @param scheme The scheme of the target service - * @return This object. - */ - public ApiClient setScheme(String scheme){ - this.scheme = scheme; - return this; - } - - /** - * Set a custom request interceptor. - * - *

A request interceptor is a mechanism for altering each request before it - * is sent. After the request has been fully configured but not yet built, the - * request builder is passed into this function for further modification, - * after which it is sent out.

- * - *

This is useful for altering the requests in a custom manner, such as - * adding headers. It could also be used for logging and monitoring.

- * - * @param interceptor A function invoked before creating each request. A value - * of null resets the interceptor to a no-op. - * @return This object. - */ - public ApiClient setRequestInterceptor(Consumer interceptor) { - this.interceptor = interceptor; - return this; - } - - /** - * Get the custom interceptor. - * - * @return The custom interceptor that was set, or null if there isn't any. - */ - public Consumer getRequestInterceptor() { - return interceptor; - } + /** + * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}. + * + *

The returned object is immutable and thread-safe. + * + * @return The HTTP client. + */ + public HttpClient getHttpClient() { + return builder.build(); + } - /** - * Set a custom response interceptor. - * - *

This is useful for logging, monitoring or extraction of header variables

- * - * @param interceptor A function invoked before creating each request. A value - * of null resets the interceptor to a no-op. - * @return This object. - */ - public ApiClient setResponseInterceptor(Consumer> interceptor) { - this.responseInterceptor = interceptor; - return this; - } + /** + * Get a copy of the current {@link ObjectMapper}. + * + * @return A copy of the current object mapper. + */ + public ObjectMapper getObjectMapper() { + return mapper.copy(); + } - /** - * Get the custom response interceptor. - * - * @return The custom interceptor that was set, or null if there isn't any. - */ - public Consumer> getResponseInterceptor() { - return responseInterceptor; - } + public ApiClient setXmlMapper(XmlMapper mapper) { + this.xmlMapper = mapper; + return this; + } - /** - * Set a custom async response interceptor. Use this interceptor when asyncNative is set to 'true'. - * - *

This is useful for logging, monitoring or extraction of header variables

- * - * @param interceptor A function invoked before creating each request. A value - * of null resets the interceptor to a no-op. - * @return This object. - */ - public ApiClient setAsyncResponseInterceptor(Consumer> interceptor) { - this.asyncResponseInterceptor = interceptor; - return this; - } + /** + * Get the base URI to resolve the endpoint paths against. + * + * @return The complete base URI that the rest of the API parameters are resolved against. + */ + public String getBaseUri() { + return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; + } - /** - * Get the custom async response interceptor. Use this interceptor when asyncNative is set to 'true'. - * - * @return The custom interceptor that was set, or null if there isn't any. - */ - public Consumer> getAsyncResponseInterceptor() { - return asyncResponseInterceptor; - } + /** + * Get the custom interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer getRequestInterceptor() { + return interceptor; + } - /** - * Set the read timeout for the http client. - * - *

This is the value used by default for each request, though it can be - * overridden on a per-request basis with a request interceptor.

- * - * @param readTimeout The read timeout used by default by the http client. - * Setting this value to null resets the timeout to an - * effectively infinite value. - * @return This object. - */ - public ApiClient setReadTimeout(Duration readTimeout) { - this.readTimeout = readTimeout; - return this; - } + /** + * Get the custom response interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getResponseInterceptor() { + return responseInterceptor; + } - /** - * Get the read timeout that was set. - * - * @return The read timeout, or null if no timeout was set. Null represents - * an infinite wait time. - */ - public Duration getReadTimeout() { - return readTimeout; - } - /** - * Sets the connect timeout (in milliseconds) for the http client. - * - *

In the case where a new connection needs to be established, if - * the connection cannot be established within the given {@code - * duration}, then {@link HttpClient#send(HttpRequest,BodyHandler) - * HttpClient::send} throws an {@link HttpConnectTimeoutException}, or - * {@link HttpClient#sendAsync(HttpRequest,BodyHandler) - * HttpClient::sendAsync} completes exceptionally with an - * {@code HttpConnectTimeoutException}. If a new connection does not - * need to be established, for example if a connection can be reused - * from a previous request, then this timeout duration has no effect. - * - * @param connectTimeout connection timeout in milliseconds - * - * @return This object. - */ - public ApiClient setConnectTimeout(Duration connectTimeout) { - this.connectTimeout = connectTimeout; - this.builder.connectTimeout(connectTimeout); - return this; - } + /** + * Get the custom async response interceptor. Use this interceptor when asyncNative is set to + * 'true'. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getAsyncResponseInterceptor() { + return asyncResponseInterceptor; + } - /** - * Get connection timeout (in milliseconds). - * - * @return Timeout in milliseconds - */ - public Duration getConnectTimeout() { - return connectTimeout; - } + /** + * Get the read timeout that was set. + * + * @return The read timeout, or null if no timeout was set. Null represents an infinite wait + * time. + */ + public Duration getReadTimeout() { + return readTimeout; + } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java index b4f92de1..701b2acf 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiException.java @@ -1,21 +1,11 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; import java.net.http.HttpHeaders; -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class ApiException extends RuntimeException { private int code = 0; private HttpHeaders responseHeaders = null; @@ -31,18 +21,25 @@ public ApiException(String message) { super(message); } - public ApiException(String message, Throwable throwable, int code, HttpHeaders responseHeaders, String responseBody) { + public ApiException( + String message, + Throwable throwable, + int code, + HttpHeaders responseHeaders, + String responseBody) { super(message, throwable); this.code = code; this.responseHeaders = responseHeaders; this.responseBody = responseBody; } - public ApiException(String message, int code, HttpHeaders responseHeaders, String responseBody) { + public ApiException( + String message, int code, HttpHeaders responseHeaders, String responseBody) { this(message, (Throwable) null, code, responseHeaders, responseBody); } - public ApiException(String message, Throwable throwable, int code, HttpHeaders responseHeaders) { + public ApiException( + String message, Throwable throwable, int code, HttpHeaders responseHeaders) { this(message, throwable, code, responseHeaders, null); } @@ -55,7 +52,8 @@ public ApiException(int code, String message) { this.code = code; } - public ApiException(int code, String message, HttpHeaders responseHeaders, String responseBody) { + public ApiException( + int code, String message, HttpHeaders responseHeaders, String responseBody) { this(code, message); this.responseHeaders = responseHeaders; this.responseBody = responseBody; diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java index 04d5fc8c..582e0a4d 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ApiResponse.java @@ -1,16 +1,4 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; import java.util.List; @@ -22,9 +10,9 @@ * @param The type of data that is deserialized from response body */ public class ApiResponse { - final private int statusCode; - final private Map> headers; - final private T data; + private final int statusCode; + private final Map> headers; + private final T data; /** * @param statusCode The status code of HTTP response diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java index b8ece665..6bf55bac 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/api/DefaultApi.java @@ -1,15 +1,4 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.api; import com.fasterxml.jackson.core.type.TypeReference; @@ -19,329 +8,335 @@ import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiResponse; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.CertData; - -import java.io.InputStream; import java.io.IOException; -import java.net.http.HttpRequest; +import java.io.InputStream; import java.net.URI; import java.net.http.HttpClient; +import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; - import java.util.List; import java.util.function.Consumer; -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class DefaultApi { - private final HttpClient memberVarHttpClient; - private final ObjectMapper memberVarObjectMapper; - private final XmlMapper memberVarXMLMapper; - private final String memberVarBaseUri; - private final Consumer memberVarInterceptor; - private final Duration memberVarReadTimeout; - private final Consumer> memberVarResponseInterceptor; - private final Consumer> memberVarAsyncResponseInterceptor; - - public DefaultApi() { - this(new ApiClient()); - } - - public DefaultApi(ApiClient apiClient) { - memberVarHttpClient = apiClient.getHttpClient(); - memberVarObjectMapper = apiClient.getObjectMapper(); - memberVarXMLMapper = apiClient.getXmlMapper(); - memberVarBaseUri = apiClient.getBaseUri(); - memberVarInterceptor = apiClient.getRequestInterceptor(); - memberVarReadTimeout = apiClient.getReadTimeout(); - memberVarResponseInterceptor = apiClient.getResponseInterceptor(); - memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); - } - - protected ApiException getApiException(String operationId, HttpResponse response) throws IOException { - String body = response.body() == null ? null : new String(response.body().readAllBytes()); - String message = formatExceptionMessage(operationId, response.statusCode(), body); - return new ApiException(response.statusCode(), message, response.headers(), body); - } - - private String formatExceptionMessage(String operationId, int statusCode, String body) { - if (body == null || body.isEmpty()) { - body = "[no body]"; + private final HttpClient memberVarHttpClient; + private final ObjectMapper memberVarObjectMapper; + private final XmlMapper memberVarXMLMapper; + private final String memberVarBaseUri; + private final Consumer memberVarInterceptor; + private final Duration memberVarReadTimeout; + private final Consumer> memberVarResponseInterceptor; + private final Consumer> memberVarAsyncResponseInterceptor; + private final String memberIdpKeysCieEndpoint; + private final String memberIdpKeysSpidEndpoint; + + public DefaultApi(ApiClient apiClient) { + memberVarHttpClient = apiClient.getHttpClient(); + memberVarObjectMapper = apiClient.getObjectMapper(); + memberVarXMLMapper = apiClient.getXmlMapper(); + memberVarBaseUri = apiClient.getBaseUri(); + memberVarInterceptor = apiClient.getRequestInterceptor(); + memberVarReadTimeout = apiClient.getReadTimeout(); + memberVarResponseInterceptor = apiClient.getResponseInterceptor(); + memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); + memberIdpKeysCieEndpoint = apiClient.getIdpKeysCieEndpoint(); + memberIdpKeysSpidEndpoint = apiClient.getIdpKeysSpidEndpoint(); + } + + protected ApiException getApiException(String operationId, HttpResponse response) + throws IOException { + String body = response.body() == null ? null : new String(response.body().readAllBytes()); + String message = formatExceptionMessage(operationId, response.statusCode(), body); + return new ApiException(response.statusCode(), message, response.headers(), body); } - return operationId + " call failed with: " + statusCode + " - " + body; - } - - /** - * - * - * @return List<String> - * @throws ApiException if fails to make API call - */ - public List idpKeysCieGet() throws ApiException { - ApiResponse> localVarResponse = idpKeysCieGetWithHttpInfo(); - return localVarResponse.getData(); - } - - /** - * - * - * @return ApiResponse<List<String>> - * @throws ApiException if fails to make API call - */ - public ApiResponse> idpKeysCieGetWithHttpInfo() throws ApiException { - HttpRequest.Builder localVarRequestBuilder = idpKeysCieGetRequestBuilder(); - try { - HttpResponse localVarResponse = memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - try { - if (localVarResponse.statusCode()/ 100 != 2) { - throw getApiException("idpKeysCieGet", localVarResponse); + + private String formatExceptionMessage(String operationId, int statusCode, String body) { + if (body == null || body.isEmpty()) { + body = "[no body]"; } - return new ApiResponse>( - localVarResponse.statusCode(), - localVarResponse.headers().map(), - localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference>() {}) // closes the InputStream - ); - } finally { - } - } catch (IOException e) { - throw new ApiException(e); + return operationId + " call failed with: " + statusCode + " - " + body; } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); + + /** + * @return List<String> + * @throws ApiException if fails to make API call + */ + public List idpKeysCieGet() throws ApiException { + ApiResponse> localVarResponse = idpKeysCieGetWithHttpInfo(); + return localVarResponse.getData(); } - } - private HttpRequest.Builder idpKeysCieGetRequestBuilder() throws ApiException { + /** + * @return ApiResponse<List<String>> + * @throws ApiException if fails to make API call + */ + public ApiResponse> idpKeysCieGetWithHttpInfo() throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysCieGetRequestBuilder(); + try { + HttpResponse localVarResponse = + memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode() / 100 != 2) { + throw getApiException("idpKeysCieGet", localVarResponse); + } + return new ApiResponse>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null + ? null + : memberVarObjectMapper.readValue( + localVarResponse.body(), + new TypeReference< + List>() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } - HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + private HttpRequest.Builder idpKeysCieGetRequestBuilder() throws ApiException { - String localVarPath = "/idp-keys/cie"; + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); - localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + memberIdpKeysCieEndpoint)); - localVarRequestBuilder.header("Accept", "application/json"); + localVarRequestBuilder.header("Accept", "application/json"); - localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); - } - return localVarRequestBuilder; - } - /** - * - * - * @param tag (required) - * @return CertData - * @throws ApiException if fails to make API call - */ - public CertData idpKeysCieTagGet(String tag) throws ApiException { - ApiResponse localVarResponse = idpKeysCieTagGetWithHttpInfo(tag); - return localVarResponse.getData(); - } - - /** - * - * - * @param tag (required) - * @return ApiResponse<CertData> - * @throws ApiException if fails to make API call - */ - public ApiResponse idpKeysCieTagGetWithHttpInfo(String tag) throws ApiException { - HttpRequest.Builder localVarRequestBuilder = idpKeysCieTagGetRequestBuilder(tag); - try { - HttpResponse localVarResponse = memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - try { - if (localVarResponse.statusCode()/ 100 != 2) { - throw getApiException("idpKeysCieTagGet", localVarResponse); + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); } - return new ApiResponse( - localVarResponse.statusCode(), - localVarResponse.headers().map(), - localVarResponse.body() == null ? null : memberVarXMLMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream - ); - } finally { - } - } catch (IOException e) { - throw new ApiException(e); + return localVarRequestBuilder; } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); + + /** + * @param tag (required) + * @return CertData + * @throws ApiException if fails to make API call + */ + public CertData idpKeysCieTagGet(String tag) throws ApiException { + ApiResponse localVarResponse = idpKeysCieTagGetWithHttpInfo(tag); + return localVarResponse.getData(); } - } - private HttpRequest.Builder idpKeysCieTagGetRequestBuilder(String tag) throws ApiException { - // verify the required parameter 'tag' is set - if (tag == null) { - throw new ApiException(400, "Missing the required parameter 'tag' when calling idpKeysCieTagGet"); + /** + * @param tag (required) + * @return ApiResponse<CertData> + * @throws ApiException if fails to make API call + */ + public ApiResponse idpKeysCieTagGetWithHttpInfo(String tag) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysCieTagGetRequestBuilder(tag); + try { + HttpResponse localVarResponse = + memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode() / 100 != 2) { + throw getApiException("idpKeysCieTagGet", localVarResponse); + } + return new ApiResponse( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null + ? null + : memberVarXMLMapper.readValue( + localVarResponse.body(), + new TypeReference() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } } - HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + private HttpRequest.Builder idpKeysCieTagGetRequestBuilder(String tag) throws ApiException { + // verify the required parameter 'tag' is set + if (tag == null) { + throw new ApiException( + 400, "Missing the required parameter 'tag' when calling idpKeysCieTagGet"); + } - String localVarPath = "/idp-keys/cie/{tag}" - .replace("{tag}", ApiClient.urlEncode(tag.toString())); + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); - localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + String localVarPath = + memberIdpKeysCieEndpoint + + "/{tag}".replace("{tag}", ApiClient.urlEncode(tag.toString())); - localVarRequestBuilder.header("Accept", "application/xml, application/json"); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); - localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); - } - return localVarRequestBuilder; - } - /** - * - * - * @return List<String> - * @throws ApiException if fails to make API call - */ - public List idpKeysSpidGet() throws ApiException { - ApiResponse> localVarResponse = idpKeysSpidGetWithHttpInfo(); - return localVarResponse.getData(); - } - - /** - * - * - * @return ApiResponse<List<String>> - * @throws ApiException if fails to make API call - */ - public ApiResponse> idpKeysSpidGetWithHttpInfo() throws ApiException { - HttpRequest.Builder localVarRequestBuilder = idpKeysSpidGetRequestBuilder(); - try { - HttpResponse localVarResponse = memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - try { - if (localVarResponse.statusCode()/ 100 != 2) { - throw getApiException("idpKeysSpidGet", localVarResponse); + localVarRequestBuilder.header("Accept", "application/xml, application/json"); + + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); } - return new ApiResponse>( - localVarResponse.statusCode(), - localVarResponse.headers().map(), - localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference>() {}) // closes the InputStream - ); - } finally { - } - } catch (IOException e) { - throw new ApiException(e); + return localVarRequestBuilder; } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); + + /** + * @return List<String> + * @throws ApiException if fails to make API call + */ + public List idpKeysSpidGet() throws ApiException { + ApiResponse> localVarResponse = idpKeysSpidGetWithHttpInfo(); + return localVarResponse.getData(); } - } - private HttpRequest.Builder idpKeysSpidGetRequestBuilder() throws ApiException { + /** + * @return ApiResponse<List<String>> + * @throws ApiException if fails to make API call + */ + public ApiResponse> idpKeysSpidGetWithHttpInfo() throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysSpidGetRequestBuilder(); + try { + HttpResponse localVarResponse = + memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode() / 100 != 2) { + throw getApiException("idpKeysSpidGet", localVarResponse); + } + return new ApiResponse>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null + ? null + : memberVarObjectMapper.readValue( + localVarResponse.body(), + new TypeReference< + List>() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } - HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + private HttpRequest.Builder idpKeysSpidGetRequestBuilder() throws ApiException { - String localVarPath = "/idp-keys/spid"; + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); - localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + memberIdpKeysSpidEndpoint)); - localVarRequestBuilder.header("Accept", "application/json"); + localVarRequestBuilder.header("Accept", "application/json"); - localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); - } - return localVarRequestBuilder; - } - /** - * - * - * @param tag (required) - * @return CertData - * @throws ApiException if fails to make API call - */ - public CertData idpKeysSpidTagGet(String tag) throws ApiException { - ApiResponse localVarResponse = idpKeysSpidTagGetWithHttpInfo(tag); - return localVarResponse.getData(); - } - - /** - * - * - * @param tag (required) - * @return ApiResponse<CertData> - * @throws ApiException if fails to make API call - */ - public ApiResponse idpKeysSpidTagGetWithHttpInfo(String tag) throws ApiException { - HttpRequest.Builder localVarRequestBuilder = idpKeysSpidTagGetRequestBuilder(tag); - try { - HttpResponse localVarResponse = memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - try { - if (localVarResponse.statusCode()/ 100 != 2) { - throw getApiException("idpKeysSpidTagGet", localVarResponse); + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); } - return new ApiResponse( - localVarResponse.statusCode(), - localVarResponse.headers().map(), - localVarResponse.body() == null ? null : memberVarXMLMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream - ); - } finally { - } - } catch (IOException e) { - throw new ApiException(e); + return localVarRequestBuilder; } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); + + /** + * @param tag (required) + * @return CertData + * @throws ApiException if fails to make API call + */ + public CertData idpKeysSpidTagGet(String tag) throws ApiException { + ApiResponse localVarResponse = idpKeysSpidTagGetWithHttpInfo(tag); + return localVarResponse.getData(); } - } - private HttpRequest.Builder idpKeysSpidTagGetRequestBuilder(String tag) throws ApiException { - // verify the required parameter 'tag' is set - if (tag == null) { - throw new ApiException(400, "Missing the required parameter 'tag' when calling idpKeysSpidTagGet"); + /** + * @param tag (required) + * @return ApiResponse<CertData> + * @throws ApiException if fails to make API call + */ + public ApiResponse idpKeysSpidTagGetWithHttpInfo(String tag) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = idpKeysSpidTagGetRequestBuilder(tag); + try { + HttpResponse localVarResponse = + memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode() / 100 != 2) { + throw getApiException("idpKeysSpidTagGet", localVarResponse); + } + return new ApiResponse( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null + ? null + : memberVarXMLMapper.readValue( + localVarResponse.body(), + new TypeReference() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } } - HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + private HttpRequest.Builder idpKeysSpidTagGetRequestBuilder(String tag) throws ApiException { + // verify the required parameter 'tag' is set + if (tag == null) { + throw new ApiException( + 400, "Missing the required parameter 'tag' when calling idpKeysSpidTagGet"); + } - String localVarPath = "/idp-keys/spid/{tag}" - .replace("{tag}", ApiClient.urlEncode(tag.toString())); + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); - localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + String localVarPath = + memberIdpKeysSpidEndpoint + + "/{tag}".replace("{tag}", ApiClient.urlEncode(tag.toString())); - localVarRequestBuilder.header("Accept", "application/xml, application/json"); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); - localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + localVarRequestBuilder.header("Accept", "application/xml, application/json"); + + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; } - return localVarRequestBuilder; - } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java index 688511a7..698fe790 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/AbstractOpenApiSchema.java @@ -1,28 +1,14 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; -import java.util.Objects; -import java.lang.reflect.Type; -import java.util.Map; - import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Map; +import java.util.Objects; -/** - * Abstract class for oneOf,anyOf schemas defined in OpenAPI spec - */ -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +/** Abstract class for oneOf,anyOf schemas defined in OpenAPI spec */ +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public abstract class AbstractOpenApiSchema { // store the actual instance of the schema/object @@ -52,17 +38,22 @@ public AbstractOpenApiSchema(String schemaType, Boolean isNullable) { * @return an instance of the actual schema/object */ @JsonValue - public Object getActualInstance() {return instance;} + public Object getActualInstance() { + return instance; + } /** * Set the actual instance * * @param instance the actual instance of the schema/object */ - public void setActualInstance(Object instance) {this.instance = instance;} + public void setActualInstance(Object instance) { + this.instance = instance; + } /** - * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf schema as well + * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf + * schema as well * * @return an instance of the actual schema/object */ @@ -74,7 +65,7 @@ private Object getActualInstanceRecursively(AbstractOpenApiSchema object) { if (object.getActualInstance() == null) { return null; } else if (object.getActualInstance() instanceof AbstractOpenApiSchema) { - return getActualInstanceRecursively((AbstractOpenApiSchema)object.getActualInstance()); + return getActualInstanceRecursively((AbstractOpenApiSchema) object.getActualInstance()); } else { return object.getActualInstance(); } @@ -101,8 +92,8 @@ public String toString() { } /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). + * Convert the given object to string with each line indented by 4 spaces (except the first + * line). */ private String toIndentedString(Object o) { if (o == null) { @@ -119,9 +110,9 @@ public boolean equals(Object o) { return false; } AbstractOpenApiSchema a = (AbstractOpenApiSchema) o; - return Objects.equals(this.instance, a.instance) && - Objects.equals(this.isNullable, a.isNullable) && - Objects.equals(this.schemaType, a.schemaType); + return Objects.equals(this.instance, a.instance) + && Objects.equals(this.isNullable, a.isNullable) + && Objects.equals(this.schemaType, a.schemaType); } @Override @@ -141,7 +132,4 @@ public Boolean isNullable() { return Boolean.FALSE; } } - - - } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java index ace38068..3ff33c7c 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/CertData.java @@ -1,24 +1,6 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; -import java.util.*; - -import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; - import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; @@ -32,11 +14,16 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.ser.std.StdSerializer; -import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.JSON; +import java.io.IOException; +import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; import lombok.Getter; import lombok.Setter; -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") @JsonDeserialize(using = CertData.CertDataDeserializer.class) @JsonSerialize(using = CertData.CertDataSerializer.class) @Getter @@ -54,7 +41,8 @@ public CertDataSerializer() { } @Override - public void serialize(CertData value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + public void serialize(CertData value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException { jgen.writeObject(value.getActualInstance()); } } @@ -69,7 +57,8 @@ public CertDataDeserializer(Class vc) { } @Override - public CertData deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + public CertData deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException { JsonNode tree = jp.readValueAsTree(); Object deserialized = null; boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS); @@ -82,24 +71,30 @@ public CertData deserialize(JsonParser jp, DeserializationContext ctxt) throws I deserialized = tree.traverse(jp.getCodec()).readValueAs(EntityDescriptor.class); if (((EntityDescriptor) deserialized).getEntityID() != null) { - List entityList = Arrays.asList(((EntityDescriptor)deserialized)); + List entityList = + Arrays.asList(((EntityDescriptor) deserialized)); entitiesDescriptor.setEntityList(entityList); log.log(Level.FINER, "Input data matches schema 'EntityDescriptor'"); match++; } else { - try{ - deserialized = tree.traverse(jp.getCodec()).readValueAs(EntitiesDescriptor.class); + try { + deserialized = + tree.traverse(jp.getCodec()).readValueAs(EntitiesDescriptor.class); if (((EntitiesDescriptor) deserialized).getEntityList() != null) { - entitiesDescriptor.setEntityList(((EntitiesDescriptor) deserialized).getEntityList()); + entitiesDescriptor.setEntityList( + ((EntitiesDescriptor) deserialized).getEntityList()); log.log(Level.FINER, "Input data matches schema 'Entities Descriptor'"); match++; } - } catch (Exception e){ + } catch (Exception e) { // deserialization failed, continue - log.log(Level.FINER, "Input data does not match schema 'Entities Descriptor'", e); + log.log( + Level.FINER, + "Input data does not match schema 'Entities Descriptor'", + e); } } } catch (Exception e) { @@ -112,12 +107,14 @@ public CertData deserialize(JsonParser jp, DeserializationContext ctxt) throws I ret.setActualInstance(entitiesDescriptor); return ret; } - throw new IOException(String.format("Failed deserialization for CertData: %d classes match result, expected 1", match)); + throw new IOException( + String.format( + "Failed deserialization for CertData: %d classes match result, expected" + + " 1", + match)); } - /** - * Handle deserialization of the 'null' value. - */ + /** Handle deserialization of the 'null' value. */ @Override public CertData getNullValue(DeserializationContext ctxt) throws JsonMappingException { throw new JsonMappingException(ctxt.getParser(), "CertData cannot be null"); @@ -135,6 +132,4 @@ public CertData() { public Map> getSchemas() { return CertData.schemas; } - } - diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java index 9e5ace68..54e95d5b 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntitiesDescriptor.java @@ -1,35 +1,18 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; import lombok.Getter; import lombok.Setter; -import java.util.List; - -/** - * EntitiesDescriptor - */ +/** EntitiesDescriptor */ @JsonIgnoreProperties(ignoreUnknown = true) @Getter @Setter public class EntitiesDescriptor { - @JsonProperty("EntityDescriptor") - private List entityList; - + @JsonProperty("EntityDescriptor") + private List entityList; } - diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java index 6b602241..81788328 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java @@ -1,27 +1,12 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Getter; - import java.util.Map; +import lombok.Getter; - -/** - * EntityDescriptor - */ +/** EntityDescriptor */ @JsonIgnoreProperties(ignoreUnknown = true) @Getter public class EntityDescriptor { @@ -37,6 +22,4 @@ private void unpackNestedSignature(Map signature) { Map x509Data = (Map) keyInfo.get("X509Data"); this.signature = (String) x509Data.get("X509Certificate"); } - } - diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/ProblemJson.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/ProblemJson.java index 7fcc4f37..6ca6fd6b 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/ProblemJson.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/ProblemJson.java @@ -1,292 +1,291 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - +/* (C)2022-2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; - import java.net.URI; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Objects; import java.util.StringJoiner; - -/** - * ProblemJson - */ +/** ProblemJson */ @JsonPropertyOrder({ - ProblemJson.JSON_PROPERTY_TYPE, - ProblemJson.JSON_PROPERTY_TITLE, - ProblemJson.JSON_PROPERTY_STATUS, - ProblemJson.JSON_PROPERTY_DETAIL, - ProblemJson.JSON_PROPERTY_INSTANCE + ProblemJson.JSON_PROPERTY_TYPE, + ProblemJson.JSON_PROPERTY_TITLE, + ProblemJson.JSON_PROPERTY_STATUS, + ProblemJson.JSON_PROPERTY_DETAIL, + ProblemJson.JSON_PROPERTY_INSTANCE }) -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") +@javax.annotation.Generated( + value = "org.openapitools.codegen.languages.JavaClientCodegen", + date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") public class ProblemJson { - public static final String JSON_PROPERTY_TYPE = "type"; - private URI type = URI.create("about:blank"); + public static final String JSON_PROPERTY_TYPE = "type"; + private URI type = URI.create("about:blank"); + + public static final String JSON_PROPERTY_TITLE = "title"; + private String title; - public static final String JSON_PROPERTY_TITLE = "title"; - private String title; - - public static final String JSON_PROPERTY_STATUS = "status"; - private Integer status; - - public static final String JSON_PROPERTY_DETAIL = "detail"; - private String detail; - - public static final String JSON_PROPERTY_INSTANCE = "instance"; - private URI instance; + public static final String JSON_PROPERTY_STATUS = "status"; + private Integer status; - public ProblemJson() { - } - - public ProblemJson type(URI type) { - this.type = type; - return this; - } + public static final String JSON_PROPERTY_DETAIL = "detail"; + private String detail; - /** - * An absolute URI that identifies the problem type. When dereferenced, it SHOULD provide human-readable documentation for the problem type (e.g., using HTML). - * @return type - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_TYPE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public URI getType() { - return type; - } - - - @JsonProperty(JSON_PROPERTY_TYPE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setType(URI type) { - this.type = type; - } - - - public ProblemJson title(String title) { - this.title = title; - return this; - } - - /** - * A short, summary of the problem type. Written in english and readable for engineers (usually not suited for non technical stakeholders and not localized); example: Service Unavailable - * @return title - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_TITLE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public String getTitle() { - return title; - } - - - @JsonProperty(JSON_PROPERTY_TITLE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setTitle(String title) { - this.title = title; - } - - - public ProblemJson status(Integer status) { - this.status = status; - return this; - } - - /** - * The HTTP status code generated by the origin server for this occurrence of the problem. - * minimum: 100 - * maximum: 600 - * @return status - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_STATUS) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public Integer getStatus() { - return status; - } - - - @JsonProperty(JSON_PROPERTY_STATUS) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setStatus(Integer status) { - this.status = status; - } - - - public ProblemJson detail(String detail) { - this.detail = detail; - return this; - } - - /** - * A human readable explanation specific to this occurrence of the problem. - * @return detail - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_DETAIL) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public String getDetail() { - return detail; - } - - - @JsonProperty(JSON_PROPERTY_DETAIL) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setDetail(String detail) { - this.detail = detail; - } - - - public ProblemJson instance(URI instance) { - this.instance = instance; - return this; - } - - /** - * An absolute URI that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced. - * @return instance - **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_INSTANCE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - - public URI getInstance() { - return instance; - } - - - @JsonProperty(JSON_PROPERTY_INSTANCE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setInstance(URI instance) { - this.instance = instance; - } - - - /** - * Return true if this ProblemJson object is equal to o. - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public static final String JSON_PROPERTY_INSTANCE = "instance"; + private URI instance; + + public ProblemJson() {} + + public ProblemJson type(URI type) { + this.type = type; + return this; } - if (o == null || getClass() != o.getClass()) { - return false; + + /** + * An absolute URI that identifies the problem type. When dereferenced, it SHOULD provide + * human-readable documentation for the problem type (e.g., using HTML). + * + * @return type + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public URI getType() { + return type; } - ProblemJson problemJson = (ProblemJson) o; - return Objects.equals(this.type, problemJson.type) && - Objects.equals(this.title, problemJson.title) && - Objects.equals(this.status, problemJson.status) && - Objects.equals(this.detail, problemJson.detail) && - Objects.equals(this.instance, problemJson.instance); - } - - @Override - public int hashCode() { - return Objects.hash(type, title, status, detail, instance); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class ProblemJson {\n"); - sb.append(" type: ").append(toIndentedString(type)).append("\n"); - sb.append(" title: ").append(toIndentedString(title)).append("\n"); - sb.append(" status: ").append(toIndentedString(status)).append("\n"); - sb.append(" detail: ").append(toIndentedString(detail)).append("\n"); - sb.append(" instance: ").append(toIndentedString(instance)).append("\n"); - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; + + @JsonProperty(JSON_PROPERTY_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setType(URI type) { + this.type = type; } - return o.toString().replace("\n", "\n "); - } - - /** - * Convert the instance into URL query string. - * - * @return URL query string - */ - public String toUrlQueryString() { - return toUrlQueryString(null); - } - - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - String suffix = ""; - String containerSuffix = ""; - String containerPrefix = ""; - if (prefix == null) { - // style=form, explode=true, e.g. /pet?name=cat&type=manx - prefix = ""; - } else { - // deepObject style e.g. /pet?id[name]=cat&id[type]=manx - prefix = prefix + "["; - suffix = "]"; - containerSuffix = "]"; - containerPrefix = "["; + + public ProblemJson title(String title) { + this.title = title; + return this; } - StringJoiner joiner = new StringJoiner("&"); + /** + * A short, summary of the problem type. Written in english and readable for engineers (usually + * not suited for non technical stakeholders and not localized); example: Service Unavailable + * + * @return title + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_TITLE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public String getTitle() { + return title; + } - // add `type` to the URL query string - if (getType() != null) { - joiner.add(String.format("%stype%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getType()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + @JsonProperty(JSON_PROPERTY_TITLE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setTitle(String title) { + this.title = title; } - // add `title` to the URL query string - if (getTitle() != null) { - joiner.add(String.format("%stitle%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getTitle()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + public ProblemJson status(Integer status) { + this.status = status; + return this; } - // add `status` to the URL query string - if (getStatus() != null) { - joiner.add(String.format("%sstatus%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getStatus()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + /** + * The HTTP status code generated by the origin server for this occurrence of the problem. + * minimum: 100 maximum: 600 + * + * @return status + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public Integer getStatus() { + return status; } - // add `detail` to the URL query string - if (getDetail() != null) { - joiner.add(String.format("%sdetail%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getDetail()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + @JsonProperty(JSON_PROPERTY_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setStatus(Integer status) { + this.status = status; } - // add `instance` to the URL query string - if (getInstance() != null) { - joiner.add(String.format("%sinstance%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getInstance()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + public ProblemJson detail(String detail) { + this.detail = detail; + return this; } - return joiner.toString(); - } -} + /** + * A human readable explanation specific to this occurrence of the problem. + * + * @return detail + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_DETAIL) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public String getDetail() { + return detail; + } + + @JsonProperty(JSON_PROPERTY_DETAIL) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setDetail(String detail) { + this.detail = detail; + } + + public ProblemJson instance(URI instance) { + this.instance = instance; + return this; + } + /** + * An absolute URI that identifies the specific occurrence of the problem. It may or may not + * yield further information if dereferenced. + * + * @return instance + */ + @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_INSTANCE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public URI getInstance() { + return instance; + } + + @JsonProperty(JSON_PROPERTY_INSTANCE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setInstance(URI instance) { + this.instance = instance; + } + + /** Return true if this ProblemJson object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProblemJson problemJson = (ProblemJson) o; + return Objects.equals(this.type, problemJson.type) + && Objects.equals(this.title, problemJson.title) + && Objects.equals(this.status, problemJson.status) + && Objects.equals(this.detail, problemJson.detail) + && Objects.equals(this.instance, problemJson.instance); + } + + @Override + public int hashCode() { + return Objects.hash(type, title, status, detail, instance); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ProblemJson {\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append(" title: ").append(toIndentedString(title)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" detail: ").append(toIndentedString(detail)).append("\n"); + sb.append(" instance: ").append(toIndentedString(instance)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first + * line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `type` to the URL query string + if (getType() != null) { + joiner.add( + String.format( + "%stype%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getType()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `title` to the URL query string + if (getTitle() != null) { + joiner.add( + String.format( + "%stitle%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getTitle()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `status` to the URL query string + if (getStatus() != null) { + joiner.add( + String.format( + "%sstatus%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getStatus()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `detail` to the URL query string + if (getDetail() != null) { + joiner.add( + String.format( + "%sdetail%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getDetail()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `instance` to the URL query string + if (getInstance() != null) { + joiner.add( + String.format( + "%sinstance%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getInstance()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} diff --git a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java index 866f7d24..20a12462 100644 --- a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java @@ -1,20 +1,19 @@ +/* (C)2023 */ package simple; - import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import java.time.Instant; +import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.mockito.Mockito; -import java.time.Instant; -import java.util.List; - class IdpCertSimpleClientTest { private static IdpCertSimpleClient idpCertSimpleClient; @@ -22,15 +21,16 @@ class IdpCertSimpleClientTest { private static final String INSTANT = String.valueOf(Instant.now().getEpochSecond()); private static final String SPID_ENTITY_ID = "https://posteid.poste.it"; - private static final String CIE_ENTITY_ID = "https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"; + private static final String CIE_ENTITY_ID = + "https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"; private static final String WRONG_ENTITY_ID = "https://wrongEntityID.it"; private static final String WRONG_INSTANT = "xxxxxx"; @BeforeAll public static void startServer() { - ApiClient client = new ApiClient(); entityConfig = Mockito.spy(IdpCertSimpleClientConfig.builder().build()); + ApiClient client = new ApiClient(entityConfig); idpCertSimpleClient = new IdpCertSimpleClient(client, entityConfig); } @@ -49,18 +49,23 @@ void certCIEDataFound() throws CertDataTagListNotFoundException, CertDataNotFoun } @Test - void getCertDataWrongEntityID() throws CertDataTagListNotFoundException, CertDataNotFoundException { - Assertions.assertThrows(CertDataNotFoundException.class, () -> idpCertSimpleClient.getCertData(WRONG_ENTITY_ID, INSTANT)); + void getCertDataWrongEntityID() { + Assertions.assertThrows( + CertDataNotFoundException.class, + () -> idpCertSimpleClient.getCertData(WRONG_ENTITY_ID, INSTANT)); } @Test - void getSPIDCertDataWrongInstant() throws CertDataTagListNotFoundException, CertDataNotFoundException { - Assertions.assertThrows(CertDataTagListNotFoundException.class, () -> idpCertSimpleClient.getCertData(SPID_ENTITY_ID, WRONG_INSTANT)); + void getSPIDCertDataWrongInstant() { + Assertions.assertThrows( + CertDataTagListNotFoundException.class, + () -> idpCertSimpleClient.getCertData(SPID_ENTITY_ID, WRONG_INSTANT)); } @Test - void getCIECertDataWrongInstant() throws CertDataTagListNotFoundException, CertDataNotFoundException { - Assertions.assertThrows(CertDataTagListNotFoundException.class, () -> idpCertSimpleClient.getCertData(CIE_ENTITY_ID, WRONG_INSTANT)); + void getCIECertDataWrongInstant() { + Assertions.assertThrows( + CertDataTagListNotFoundException.class, + () -> idpCertSimpleClient.getCertData(CIE_ENTITY_ID, WRONG_INSTANT)); } - -} \ No newline at end of file +} From 77eb064cfefd4faa8264e2450b03291de588c736 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 16:58:14 +0200 Subject: [PATCH 144/403] [SLS-19] Removed unused classes --- .../client/simple/internal/Configuration.java | 39 --- .../idp/client/simple/internal/JSON.java | 247 ------------------ .../idp/client/simple/internal/Pair.java | 57 ---- .../simple/internal/RFC3339DateFormat.java | 57 ---- .../simple/internal/ServerConfiguration.java | 58 ---- .../simple/internal/ServerVariable.java | 23 -- 6 files changed, 481 deletions(-) delete mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java delete mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java delete mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java delete mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java delete mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java delete mode 100644 identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java deleted file mode 100644 index 44af4652..00000000 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Configuration.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; - -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") -public class Configuration { - private static ApiClient defaultApiClient = new ApiClient(); - - /** - * Get the default API client, which would be used when creating API - * instances without providing an API client. - * - * @return Default API client - */ - public static ApiClient getDefaultApiClient() { - return defaultApiClient; - } - - /** - * Set the default API client, which would be used when creating API - * instances without providing an API client. - * - * @param apiClient API client - */ - public static void setDefaultApiClient(ApiClient apiClient) { - defaultApiClient = apiClient; - } -} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java deleted file mode 100644 index fc1b5610..00000000 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/JSON.java +++ /dev/null @@ -1,247 +0,0 @@ -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.*; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import org.openapitools.jackson.nullable.JsonNullableModule; - -import java.text.DateFormat; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") -public class JSON { - private ObjectMapper mapper; - - public JSON() { - mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); - mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); - mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); - mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); - mapper.setDateFormat(new RFC3339DateFormat()); - mapper.registerModule(new JavaTimeModule()); - JsonNullableModule jnm = new JsonNullableModule(); - mapper.registerModule(jnm); - } - - /** - * Set the date format for JSON (de)serialization with Date properties. - * - * @param dateFormat Date format - */ - public void setDateFormat(DateFormat dateFormat) { - mapper.setDateFormat(dateFormat); - } - - /** - * Get the object mapper - * - * @return object mapper - */ - public ObjectMapper getMapper() { return mapper; } - - /** - * Returns the target model class that should be used to deserialize the input data. - * The discriminator mappings are used to determine the target model class. - * - * @param node The input data. - * @param modelClass The class that contains the discriminator mappings. - * - * @return the target model class. - */ - public static Class getClassForElement(JsonNode node, Class modelClass) { - ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass); - if (cdm != null) { - return cdm.getClassForElement(node, new HashSet>()); - } - return null; - } - - /** - * Helper class to register the discriminator mappings. - */ - private static class ClassDiscriminatorMapping { - // The model class name. - Class modelClass; - // The name of the discriminator property. - String discriminatorName; - // The discriminator mappings for a model class. - Map> discriminatorMappings; - - // Constructs a new class discriminator. - ClassDiscriminatorMapping(Class cls, String propertyName, Map> mappings) { - modelClass = cls; - discriminatorName = propertyName; - discriminatorMappings = new HashMap>(); - if (mappings != null) { - discriminatorMappings.putAll(mappings); - } - } - - // Return the name of the discriminator property for this model class. - String getDiscriminatorPropertyName() { - return discriminatorName; - } - - // Return the discriminator value or null if the discriminator is not - // present in the payload. - String getDiscriminatorValue(JsonNode node) { - // Determine the value of the discriminator property in the input data. - if (discriminatorName != null) { - // Get the value of the discriminator property, if present in the input payload. - node = node.get(discriminatorName); - if (node != null && node.isValueNode()) { - String discrValue = node.asText(); - if (discrValue != null) { - return discrValue; - } - } - } - return null; - } - - /** - * Returns the target model class that should be used to deserialize the input data. - * This function can be invoked for anyOf/oneOf composed models with discriminator mappings. - * The discriminator mappings are used to determine the target model class. - * - * @param node The input data. - * @param visitedClasses The set of classes that have already been visited. - * - * @return the target model class. - */ - Class getClassForElement(JsonNode node, Set> visitedClasses) { - if (visitedClasses.contains(modelClass)) { - // Class has already been visited. - return null; - } - // Determine the value of the discriminator property in the input data. - String discrValue = getDiscriminatorValue(node); - if (discrValue == null) { - return null; - } - Class cls = discriminatorMappings.get(discrValue); - // It may not be sufficient to return this cls directly because that target class - // may itself be a composed schema, possibly with its own discriminator. - visitedClasses.add(modelClass); - for (Class childClass : discriminatorMappings.values()) { - ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass); - if (childCdm == null) { - continue; - } - if (!discriminatorName.equals(childCdm.discriminatorName)) { - discrValue = getDiscriminatorValue(node); - if (discrValue == null) { - continue; - } - } - if (childCdm != null) { - // Recursively traverse the discriminator mappings. - Class childDiscr = childCdm.getClassForElement(node, visitedClasses); - if (childDiscr != null) { - return childDiscr; - } - } - } - return cls; - } - } - - /** - * Returns true if inst is an instance of modelClass in the OpenAPI model hierarchy. - * - * The Java class hierarchy is not implemented the same way as the OpenAPI model hierarchy, - * so it's not possible to use the instanceof keyword. - * - * @param modelClass A OpenAPI model class. - * @param inst The instance object. - * @param visitedClasses The set of classes that have already been visited. - * - * @return true if inst is an instance of modelClass in the OpenAPI model hierarchy. - */ - public static boolean isInstanceOf(Class modelClass, Object inst, Set> visitedClasses) { - if (modelClass.isInstance(inst)) { - // This handles the 'allOf' use case with single parent inheritance. - return true; - } - if (visitedClasses.contains(modelClass)) { - // This is to prevent infinite recursion when the composed schemas have - // a circular dependency. - return false; - } - visitedClasses.add(modelClass); - - // Traverse the oneOf/anyOf composed schemas. - Map> descendants = modelDescendants.get(modelClass); - if (descendants != null) { - for (Class childType : descendants.values()) { - if (isInstanceOf(childType, inst, visitedClasses)) { - return true; - } - } - } - return false; - } - - /** - * A map of discriminators for all model classes. - */ - private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap<>(); - - /** - * A map of oneOf/anyOf descendants for each model class. - */ - private static Map, Map>> modelDescendants = new HashMap<>(); - - /** - * Register a model class discriminator. - * - * @param modelClass the model class - * @param discriminatorPropertyName the name of the discriminator property - * @param mappings a map with the discriminator mappings. - */ - public static void registerDiscriminator(Class modelClass, String discriminatorPropertyName, Map> mappings) { - ClassDiscriminatorMapping m = new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings); - modelDiscriminators.put(modelClass, m); - } - - /** - * Register the oneOf/anyOf descendants of the modelClass. - * - * @param modelClass the model class - * @param descendants a map of oneOf/anyOf descendants. - */ - public static void registerDescendants(Class modelClass, Map> descendants) { - modelDescendants.put(modelClass, descendants); - } - - private static JSON json; - - static { - json = new JSON(); - } - - /** - * Get the default JSON instance. - * - * @return the default JSON instance - */ - public static JSON getDefault() { - return json; - } - - /** - * Set the default JSON instance. - * - * @param json JSON instance to be used - */ - public static void setDefault(JSON json) { - JSON.json = json; - } -} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java deleted file mode 100644 index 8d1d80c2..00000000 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/Pair.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; - -@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-11T16:21:49.277208500+02:00[Europe/Paris]") -public class Pair { - private String name = ""; - private String value = ""; - - public Pair (String name, String value) { - setName(name); - setValue(value); - } - - private void setName(String name) { - if (!isValidString(name)) { - return; - } - - this.name = name; - } - - private void setValue(String value) { - if (!isValidString(value)) { - return; - } - - this.value = value; - } - - public String getName() { - return this.name; - } - - public String getValue() { - return this.value; - } - - private boolean isValidString(String arg) { - if (arg == null) { - return false; - } - - return true; - } -} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java deleted file mode 100644 index 57853d22..00000000 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/RFC3339DateFormat.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * identity-services - * Client used to retrieve the public keys from the identity provider - * - * The version of the OpenAPI document: 2022-09-06T20:08:39Z - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; - -import com.fasterxml.jackson.databind.util.StdDateFormat; - -import java.text.DateFormat; -import java.text.DecimalFormat; -import java.text.FieldPosition; -import java.text.ParsePosition; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.TimeZone; - -public class RFC3339DateFormat extends DateFormat { - private static final long serialVersionUID = 1L; - private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); - - private final StdDateFormat fmt = new StdDateFormat() - .withTimeZone(TIMEZONE_Z) - .withColonInTimeZone(true); - - public RFC3339DateFormat() { - this.calendar = new GregorianCalendar(); - this.numberFormat = new DecimalFormat(); - } - - @Override - public Date parse(String source) { - return parse(source, new ParsePosition(0)); - } - - @Override - public Date parse(String source, ParsePosition pos) { - return fmt.parse(source, pos); - } - - @Override - public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { - return fmt.format(date, toAppendTo, fieldPosition); - } - - @Override - public Object clone() { - return super.clone(); - } -} \ No newline at end of file diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java deleted file mode 100644 index 33501d36..00000000 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerConfiguration.java +++ /dev/null @@ -1,58 +0,0 @@ -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; - -import java.util.Map; - -/** - * Representing a Server configuration. - */ -public class ServerConfiguration { - public String URL; - public String description; - public Map variables; - - /** - * @param URL A URL to the target host. - * @param description A description of the host designated by the URL. - * @param variables A map between a variable name and its value. The value is used for substitution in the server's URL template. - */ - public ServerConfiguration(String URL, String description, Map variables) { - this.URL = URL; - this.description = description; - this.variables = variables; - } - - /** - * Format URL template using given variables. - * - * @param variables A map between a variable name and its value. - * @return Formatted URL. - */ - public String URL(Map variables) { - String url = this.URL; - - // go through variables and replace placeholders - for (Map.Entry variable: this.variables.entrySet()) { - String name = variable.getKey(); - ServerVariable serverVariable = variable.getValue(); - String value = serverVariable.defaultValue; - - if (variables != null && variables.containsKey(name)) { - value = variables.get(name); - if (serverVariable.enumValues.size() > 0 && !serverVariable.enumValues.contains(value)) { - throw new IllegalArgumentException("The variable " + name + " in the server URL has invalid value " + value + "."); - } - } - url = url.replace("{" + name + "}", value); - } - return url; - } - - /** - * Format URL template using default server variables. - * - * @return Formatted URL. - */ - public String URL() { - return URL(null); - } -} diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java deleted file mode 100644 index c06da593..00000000 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/ServerVariable.java +++ /dev/null @@ -1,23 +0,0 @@ -package it.pagopa.tech.lollipop.consumer.idp.client.simple.internal; - -import java.util.HashSet; - -/** - * Representing a Server Variable for server URL template substitution. - */ -public class ServerVariable { - public String description; - public String defaultValue; - public HashSet enumValues = null; - - /** - * @param description A description for the server variable. - * @param defaultValue The default value to use for substitution. - * @param enumValues An enumeration of string values to be used if the substitution options are from a limited set. - */ - public ServerVariable(String description, String defaultValue, HashSet enumValues) { - this.description = description; - this.defaultValue = defaultValue; - this.enumValues = enumValues; - } -} From 6ab34c127d6fb9ce5a492584c1d3a49fb5343259 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 12 Apr 2023 17:14:37 +0200 Subject: [PATCH 145/403] [SLS-23] Introducing dependency to forked version of the http-signature --- gradle/verification-metadata.xml | 23 ++++++++++++++++++++++- http-verifier/build.gradle | 8 ++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 9aa9291d..1672fe1a 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1,5 +1,5 @@ - + true false @@ -143,6 +143,7 @@ + @@ -210,6 +211,10 @@ + + + + @@ -236,6 +241,10 @@ + + + + @@ -268,6 +277,10 @@ + + + + @@ -1285,6 +1298,14 @@ + + + + + + + + diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index dbb59380..6ad9f9e7 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -18,6 +18,13 @@ group 'it.pagopa.tech' repositories { mavenLocal() mavenCentral() + maven { + url = uri("https://maven.pkg.github.com/pagopa/eng-http-signatures") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + } + } } configurations { @@ -48,6 +55,7 @@ dependencies { // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.assertj:assertj-core:3.24.2' + implementation 'it.pagopa.tech:http-signatures:1.1.2' implementation project(':core') } From ff6eef20e7d872a7f845f4eb3a095bd118c4c087 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 17:25:59 +0200 Subject: [PATCH 146/403] [SLS-19] Removed unused classes from assertion-rest-client-native --- .../client/simple/internal/Configuration.java | 29 --------- .../client/simple/internal/Pair.java | 47 -------------- .../simple/internal/ServerConfiguration.java | 65 ------------------- .../simple/internal/ServerVariable.java | 23 ------- .../simple/internal/model/AssertionType.java | 52 --------------- 5 files changed, 216 deletions(-) delete mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Configuration.java delete mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Pair.java delete mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerConfiguration.java delete mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerVariable.java delete mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionType.java diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Configuration.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Configuration.java deleted file mode 100644 index 291806fa..00000000 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Configuration.java +++ /dev/null @@ -1,29 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; - -@javax.annotation.Generated( - value = "org.openapitools.codegen.languages.JavaClientCodegen", - date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") -public class Configuration { - private static ApiClient defaultApiClient = new ApiClient(); - - /** - * Get the default API client, which would be used when creating API instances without providing - * an API client. - * - * @return Default API client - */ - public static ApiClient getDefaultApiClient() { - return defaultApiClient; - } - - /** - * Set the default API client, which would be used when creating API instances without providing - * an API client. - * - * @param apiClient API client - */ - public static void setDefaultApiClient(ApiClient apiClient) { - defaultApiClient = apiClient; - } -} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Pair.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Pair.java deleted file mode 100644 index 71f7801d..00000000 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/Pair.java +++ /dev/null @@ -1,47 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; - -@javax.annotation.Generated( - value = "org.openapitools.codegen.languages.JavaClientCodegen", - date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") -public class Pair { - private String name = ""; - private String value = ""; - - public Pair(String name, String value) { - setName(name); - setValue(value); - } - - private void setName(String name) { - if (!isValidString(name)) { - return; - } - - this.name = name; - } - - private void setValue(String value) { - if (!isValidString(value)) { - return; - } - - this.value = value; - } - - public String getName() { - return this.name; - } - - public String getValue() { - return this.value; - } - - private boolean isValidString(String arg) { - if (arg == null) { - return false; - } - - return true; - } -} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerConfiguration.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerConfiguration.java deleted file mode 100644 index eb6f73d1..00000000 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerConfiguration.java +++ /dev/null @@ -1,65 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; - -import java.util.Map; - -/** Representing a Server configuration. */ -public class ServerConfiguration { - public String URL; - public String description; - public Map variables; - - /** - * @param URL A URL to the target host. - * @param description A description of the host designated by the URL. - * @param variables A map between a variable name and its value. The value is used for - * substitution in the server's URL template. - */ - public ServerConfiguration( - String URL, String description, Map variables) { - this.URL = URL; - this.description = description; - this.variables = variables; - } - - /** - * Format URL template using given variables. - * - * @param variables A map between a variable name and its value. - * @return Formatted URL. - */ - public String URL(Map variables) { - String url = this.URL; - - // go through variables and replace placeholders - for (Map.Entry variable : this.variables.entrySet()) { - String name = variable.getKey(); - ServerVariable serverVariable = variable.getValue(); - String value = serverVariable.defaultValue; - - if (variables != null && variables.containsKey(name)) { - value = variables.get(name); - if (serverVariable.enumValues.size() > 0 - && !serverVariable.enumValues.contains(value)) { - throw new IllegalArgumentException( - "The variable " - + name - + " in the server URL has invalid value " - + value - + "."); - } - } - url = url.replace("{" + name + "}", value); - } - return url; - } - - /** - * Format URL template using default server variables. - * - * @return Formatted URL. - */ - public String URL() { - return URL(null); - } -} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerVariable.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerVariable.java deleted file mode 100644 index f1db28ef..00000000 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ServerVariable.java +++ /dev/null @@ -1,23 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; - -import java.util.HashSet; - -/** Representing a Server Variable for server URL template substitution. */ -public class ServerVariable { - public String description; - public String defaultValue; - public HashSet enumValues = null; - - /** - * @param description A description for the server variable. - * @param defaultValue The default value to use for substitution. - * @param enumValues An enumeration of string values to be used if the substitution options are - * from a limited set. - */ - public ServerVariable(String description, String defaultValue, HashSet enumValues) { - this.description = description; - this.defaultValue = defaultValue; - this.enumValues = enumValues; - } -} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionType.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionType.java deleted file mode 100644 index 72a92f33..00000000 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/model/AssertionType.java +++ /dev/null @@ -1,52 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonValue; - -/** Gets or Sets AssertionType */ -public enum AssertionType { - SAML("SAML"), - - OIDC("OIDC"); - - private String value; - - AssertionType(String value) { - this.value = value; - } - - @JsonValue - public String getValue() { - return value; - } - - @Override - public String toString() { - return String.valueOf(value); - } - - @JsonCreator - public static AssertionType fromValue(String value) { - for (AssertionType b : AssertionType.values()) { - if (b.value.equals(value)) { - return b; - } - } - throw new IllegalArgumentException("Unexpected value '" + value + "'"); - } - - /** - * Convert the instance into URL query string. - * - * @param prefix prefix of the query string - * @return URL query string - */ - public String toUrlQueryString(String prefix) { - if (prefix == null) { - prefix = ""; - } - - return String.format("%s=%s", prefix, this.toString()); - } -} From 4eb159ba70e6184989ad8ebed9d6ca18c3b8cf56 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 12 Apr 2023 17:27:03 +0200 Subject: [PATCH 147/403] [SLS-19] Added uri & endpoint configuration for client used in AssertionSimpleClient - fixed tests - applied spotless --- assertion-rest-client-native/build.gradle | 3 + .../simple/AssertionSimpleClientConfig.java | 14 + .../simple/AssertionSimpleClientProvider.java | 10 +- .../client/simple/internal/ApiClient.java | 280 +----------------- .../client/simple/internal/JSON.java | 68 ----- .../simple/internal/api/DefaultApi.java | 16 +- .../simple/AssertionSimpleClientTest.java | 7 +- .../consumer/assertion/AssertionService.java | 3 +- .../assertion/impl/AssertionServiceImpl.java | 3 +- .../impl/AssertionServiceImplTest.java | 22 +- 10 files changed, 64 insertions(+), 362 deletions(-) create mode 100644 assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientConfig.java diff --git a/assertion-rest-client-native/build.gradle b/assertion-rest-client-native/build.gradle index 55886112..aff24542 100644 --- a/assertion-rest-client-native/build.gradle +++ b/assertion-rest-client-native/build.gradle @@ -59,6 +59,9 @@ dependencies { // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.assertj:assertj-core:3.24.2' + + testImplementation 'org.mockito:mockito-core:5.2.0' + testImplementation 'org.mockito:mockito-junit-jupiter:5.2.0' //Mockserver for testing api testImplementation 'org.mock-server:mockserver-netty:5.15.0' } diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientConfig.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientConfig.java new file mode 100644 index 00000000..b2230ed8 --- /dev/null +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientConfig.java @@ -0,0 +1,14 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.assertion.client.simple; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class AssertionSimpleClientConfig { + + @Builder.Default private String baseUri = "http://localhost:3000"; + + @Builder.Default private String assertionRequestEndpoint = "/assertions"; +} diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientProvider.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientProvider.java index 62fdac2c..b43e27b5 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientProvider.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientProvider.java @@ -4,10 +4,18 @@ import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClient; import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClientProvider; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiClient; +import javax.inject.Inject; /** Provider class for retrieving an instance of {@link AssertionSimpleClient} */ public class AssertionSimpleClientProvider implements AssertionClientProvider { + private final AssertionSimpleClientConfig assertionClientConfig; + + @Inject + public AssertionSimpleClientProvider(AssertionSimpleClientConfig config) { + this.assertionClientConfig = config; + } + /** * Provide an instance of {@link AssertionSimpleClient} * @@ -15,6 +23,6 @@ public class AssertionSimpleClientProvider implements AssertionClientProvider { */ @Override public AssertionClient provideClient() { - return new AssertionSimpleClient(new ApiClient()); + return new AssertionSimpleClient(new ApiClient(assertionClientConfig)); } } diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiClient.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiClient.java index 5e65f3f5..64d1e2f1 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiClient.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/ApiClient.java @@ -8,22 +8,16 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientConfig; import java.io.InputStream; import java.net.URI; import java.net.URLEncoder; import java.net.http.HttpClient; -import java.net.http.HttpConnectTimeoutException; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; -import java.time.OffsetDateTime; -import java.time.format.DateTimeFormatter; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.StringJoiner; import java.util.function.Consumer; -import java.util.stream.Collectors; +import lombok.Getter; import org.openapitools.jackson.nullable.JsonNullableModule; /** @@ -39,6 +33,7 @@ *

The setter methods of this class return the current object to facilitate a fluent style of * configuration. */ +@Getter @javax.annotation.Generated( value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2023-04-04T15:48:28.175942900+02:00[Europe/Paris]") @@ -55,16 +50,7 @@ public class ApiClient { private Consumer> asyncResponseInterceptor; private Duration readTimeout; private Duration connectTimeout; - - private static String valueToString(Object value) { - if (value == null) { - return ""; - } - if (value instanceof OffsetDateTime) { - return ((OffsetDateTime) value).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); - } - return value.toString(); - } + private String assertionRequestEndpoint; /** * URL encode a string in the UTF-8 encoding. @@ -76,105 +62,17 @@ public static String urlEncode(String s) { return URLEncoder.encode(s, UTF_8).replaceAll("\\+", "%20"); } - /** - * Convert a URL query name/value parameter to a list of encoded {@link Pair} objects. - * - *

The value can be null, in which case an empty list is returned. - * - * @param name The query name parameter. - * @param value The query value, which may not be a collection but may be null. - * @return A singleton list of the {@link Pair} objects representing the input parameters, which - * is encoded for use in a URL. If the value is null, an empty list is returned. - */ - public static List parameterToPairs(String name, Object value) { - if (name == null || name.isEmpty() || value == null) { - return Collections.emptyList(); - } - return Collections.singletonList( - new Pair(urlEncode(name), urlEncode(valueToString(value)))); - } - - /** - * Convert a URL query name/collection parameter to a list of encoded {@link Pair} objects. - * - * @param collectionFormat The swagger collectionFormat string (csv, tsv, etc). - * @param name The query name parameter. - * @param values A collection of values for the given query name, which may be null. - * @return A list of {@link Pair} objects representing the input parameters, which is encoded - * for use in a URL. If the values collection is null, an empty list is returned. - */ - public static List parameterToPairs( - String collectionFormat, String name, Collection values) { - if (name == null || name.isEmpty() || values == null || values.isEmpty()) { - return Collections.emptyList(); - } - - // get the collection format (default: csv) - String format = - collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat; - - // create the params based on the collection format - if ("multi".equals(format)) { - return values.stream() - .map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value)))) - .collect(Collectors.toList()); - } - - String delimiter; - switch (format) { - case "csv": - delimiter = urlEncode(","); - break; - case "ssv": - delimiter = urlEncode(" "); - break; - case "tsv": - delimiter = urlEncode("\t"); - break; - case "pipes": - delimiter = urlEncode("|"); - break; - default: - throw new IllegalArgumentException( - "Illegal collection format: " + collectionFormat); - } - - StringJoiner joiner = new StringJoiner(delimiter); - for (Object value : values) { - joiner.add(urlEncode(valueToString(value))); - } - - return Collections.singletonList(new Pair(urlEncode(name), joiner.toString())); - } - /** Create an instance of ApiClient. */ - public ApiClient() { + public ApiClient(AssertionSimpleClientConfig config) { this.builder = createDefaultHttpClientBuilder(); this.mapper = createDefaultObjectMapper(); - updateBaseUri(getDefaultBaseUri()); - interceptor = null; - readTimeout = null; - connectTimeout = null; - responseInterceptor = null; - asyncResponseInterceptor = null; - } - - /** - * Create an instance of ApiClient. - * - * @param builder Http client builder. - * @param mapper Object mapper. - * @param baseUri Base URI - */ - public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, String baseUri) { - this.builder = builder; - this.mapper = mapper; - updateBaseUri(baseUri != null ? baseUri : getDefaultBaseUri()); + updateBaseUri(config.getBaseUri()); interceptor = null; readTimeout = null; connectTimeout = null; responseInterceptor = null; asyncResponseInterceptor = null; + this.assertionRequestEndpoint = config.getAssertionRequestEndpoint(); } protected ObjectMapper createDefaultObjectMapper() { @@ -191,10 +89,6 @@ protected ObjectMapper createDefaultObjectMapper() { return mapper; } - protected String getDefaultBaseUri() { - return "http://localhost:3000"; - } - protected HttpClient.Builder createDefaultHttpClientBuilder() { return HttpClient.newBuilder(); } @@ -207,18 +101,6 @@ public void updateBaseUri(String baseUri) { basePath = uri.getRawPath(); } - /** - * Set a custom {@link HttpClient.Builder} object to use when creating the {@link HttpClient} - * that is used by the API client. - * - * @param builder Custom client builder. - * @return This object. - */ - public ApiClient setHttpClientBuilder(HttpClient.Builder builder) { - this.builder = builder; - return this; - } - /** * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}. * @@ -230,18 +112,6 @@ public HttpClient getHttpClient() { return builder.build(); } - /** - * Set a custom {@link ObjectMapper} to serialize and deserialize the request and response - * bodies. - * - * @param mapper Custom object mapper. - * @return This object. - */ - public ApiClient setObjectMapper(ObjectMapper mapper) { - this.mapper = mapper; - return this; - } - /** * Get a copy of the current {@link ObjectMapper}. * @@ -251,40 +121,6 @@ public ObjectMapper getObjectMapper() { return mapper.copy(); } - /** - * Set a custom host name for the target service. - * - * @param host The host name of the target service. - * @return This object. - */ - public ApiClient setHost(String host) { - this.host = host; - return this; - } - - /** - * Set a custom port number for the target service. - * - * @param port The port of the target service. Set this to -1 to reset the value to the default - * for the scheme. - * @return This object. - */ - public ApiClient setPort(int port) { - this.port = port; - return this; - } - - /** - * Set a custom base path for the target service, for example '/v2'. - * - * @param basePath The base path against which the rest of the path is resolved. - * @return This object. - */ - public ApiClient setBasePath(String basePath) { - this.basePath = basePath; - return this; - } - /** * Get the base URI to resolve the endpoint paths against. * @@ -294,36 +130,6 @@ public String getBaseUri() { return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; } - /** - * Set a custom scheme for the target service, for example 'https'. - * - * @param scheme The scheme of the target service - * @return This object. - */ - public ApiClient setScheme(String scheme) { - this.scheme = scheme; - return this; - } - - /** - * Set a custom request interceptor. - * - *

A request interceptor is a mechanism for altering each request before it is sent. After - * the request has been fully configured but not yet built, the request builder is passed into - * this function for further modification, after which it is sent out. - * - *

This is useful for altering the requests in a custom manner, such as adding headers. It - * could also be used for logging and monitoring. - * - * @param interceptor A function invoked before creating each request. A value of null resets - * the interceptor to a no-op. - * @return This object. - */ - public ApiClient setRequestInterceptor(Consumer interceptor) { - this.interceptor = interceptor; - return this; - } - /** * Get the custom interceptor. * @@ -333,20 +139,6 @@ public Consumer getRequestInterceptor() { return interceptor; } - /** - * Set a custom response interceptor. - * - *

This is useful for logging, monitoring or extraction of header variables - * - * @param interceptor A function invoked before creating each request. A value of null resets - * the interceptor to a no-op. - * @return This object. - */ - public ApiClient setResponseInterceptor(Consumer> interceptor) { - this.responseInterceptor = interceptor; - return this; - } - /** * Get the custom response interceptor. * @@ -356,21 +148,6 @@ public Consumer> getResponseInterceptor() { return responseInterceptor; } - /** - * Set a custom async response interceptor. Use this interceptor when asyncNative is set to - * 'true'. - * - *

This is useful for logging, monitoring or extraction of header variables - * - * @param interceptor A function invoked before creating each request. A value of null resets - * the interceptor to a no-op. - * @return This object. - */ - public ApiClient setAsyncResponseInterceptor(Consumer> interceptor) { - this.asyncResponseInterceptor = interceptor; - return this; - } - /** * Get the custom async response interceptor. Use this interceptor when asyncNative is set to * 'true'. @@ -381,21 +158,6 @@ public Consumer> getAsyncResponseInterceptor() { return asyncResponseInterceptor; } - /** - * Set the read timeout for the http client. - * - *

This is the value used by default for each request, though it can be overridden on a - * per-request basis with a request interceptor. - * - * @param readTimeout The read timeout used by default by the http client. Setting this value to - * null resets the timeout to an effectively infinite value. - * @return This object. - */ - public ApiClient setReadTimeout(Duration readTimeout) { - this.readTimeout = readTimeout; - return this; - } - /** * Get the read timeout that was set. * @@ -405,32 +167,4 @@ public ApiClient setReadTimeout(Duration readTimeout) { public Duration getReadTimeout() { return readTimeout; } - /** - * Sets the connect timeout (in milliseconds) for the http client. - * - *

In the case where a new connection needs to be established, if the connection cannot be - * established within the given {@code duration}, then {@link - * HttpClient#send(HttpRequest,BodyHandler) HttpClient::send} throws an {@link - * HttpConnectTimeoutException}, or {@link HttpClient#sendAsync(HttpRequest,BodyHandler) - * HttpClient::sendAsync} completes exceptionally with an {@code HttpConnectTimeoutException}. - * If a new connection does not need to be established, for example if a connection can be - * reused from a previous request, then this timeout duration has no effect. - * - * @param connectTimeout connection timeout in milliseconds - * @return This object. - */ - public ApiClient setConnectTimeout(Duration connectTimeout) { - this.connectTimeout = connectTimeout; - this.builder.connectTimeout(connectTimeout); - return this; - } - - /** - * Get connection timeout (in milliseconds). - * - * @return Timeout in milliseconds - */ - public Duration getConnectTimeout() { - return connectTimeout; - } } diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/JSON.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/JSON.java index 85ea11dc..7fd5045e 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/JSON.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/JSON.java @@ -5,9 +5,7 @@ import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.*; -import java.text.DateFormat; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Set; import org.openapitools.jackson.nullable.JsonNullableModule; @@ -33,40 +31,6 @@ public JSON() { mapper.registerModule(jnm); } - /** - * Set the date format for JSON (de)serialization with Date properties. - * - * @param dateFormat Date format - */ - public void setDateFormat(DateFormat dateFormat) { - mapper.setDateFormat(dateFormat); - } - - /** - * Get the object mapper - * - * @return object mapper - */ - public ObjectMapper getMapper() { - return mapper; - } - - /** - * Returns the target model class that should be used to deserialize the input data. The - * discriminator mappings are used to determine the target model class. - * - * @param node The input data. - * @param modelClass The class that contains the discriminator mappings. - * @return the target model class. - */ - public static Class getClassForElement(JsonNode node, Class modelClass) { - ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass); - if (cdm != null) { - return cdm.getClassForElement(node, new HashSet>()); - } - return null; - } - /** Helper class to register the discriminator mappings. */ private static class ClassDiscriminatorMapping { // The model class name. @@ -197,20 +161,6 @@ public static boolean isInstanceOf( /** A map of oneOf/anyOf descendants for each model class. */ private static Map, Map>> modelDescendants = new HashMap<>(); - /** - * Register a model class discriminator. - * - * @param modelClass the model class - * @param discriminatorPropertyName the name of the discriminator property - * @param mappings a map with the discriminator mappings. - */ - public static void registerDiscriminator( - Class modelClass, String discriminatorPropertyName, Map> mappings) { - ClassDiscriminatorMapping m = - new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings); - modelDiscriminators.put(modelClass, m); - } - /** * Register the oneOf/anyOf descendants of the modelClass. * @@ -226,22 +176,4 @@ public static void registerDescendants(Class modelClass, Map static { json = new JSON(); } - - /** - * Get the default JSON instance. - * - * @return the default JSON instance - */ - public static JSON getDefault() { - return json; - } - - /** - * Set the default JSON instance. - * - * @param json JSON instance to be used - */ - public static void setDefault(JSON json) { - JSON.json = json; - } } diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/api/DefaultApi.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/api/DefaultApi.java index 1c71e359..e56c1cf6 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/api/DefaultApi.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/api/DefaultApi.java @@ -28,10 +28,7 @@ public class DefaultApi { private final Duration memberVarReadTimeout; private final Consumer> memberVarResponseInterceptor; private final Consumer> memberVarAsyncResponseInterceptor; - - public DefaultApi() { - this(new ApiClient()); - } + private final String memberAssertionRequestEndpoint; public DefaultApi(ApiClient apiClient) { memberVarHttpClient = apiClient.getHttpClient(); @@ -41,6 +38,7 @@ public DefaultApi(ApiClient apiClient) { memberVarReadTimeout = apiClient.getReadTimeout(); memberVarResponseInterceptor = apiClient.getResponseInterceptor(); memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); + memberAssertionRequestEndpoint = apiClient.getAssertionRequestEndpoint(); } protected ApiException getApiException(String operationId, HttpResponse response) @@ -134,10 +132,12 @@ private HttpRequest.Builder getAssertionRequestBuilder( HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); String localVarPath = - "/assertions/{assertion_ref}" - .replace( - "{assertion_ref}", - ApiClient.urlEncode(assertionRef.getActualInstance().toString())); + memberAssertionRequestEndpoint + + "/{assertion_ref}" + .replace( + "{assertion_ref}", + ApiClient.urlEncode( + assertionRef.getActualInstance().toString())); localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); diff --git a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java index 849c2031..de42da14 100644 --- a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java +++ b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java @@ -13,6 +13,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; import org.mockserver.client.MockServerClient; import org.mockserver.integration.ClientAndServer; import org.mockserver.model.Header; @@ -20,6 +21,7 @@ class AssertionSimpleClientTest { private static AssertionSimpleClient assertionSimpleClient; + private static AssertionSimpleClientConfig assertionConfig; private static ClientAndServer mockServer; private static final String XML_STRING = " sut.getAssertion("", ASSERTION_REF)); @@ -95,7 +100,8 @@ void getAssertionWithEmptyJwtParameterFailure() throws LollipopAssertionNotFound } @Test - void getAssertionWithNullJwtParameterFailure() throws LollipopAssertionNotFoundException { + void getAssertionWithNullJwtParameterFailure() + throws LollipopAssertionNotFoundException, OidcAssertionNotSupported { Assertions.assertThrows( IllegalArgumentException.class, () -> sut.getAssertion(null, ASSERTION_REF)); @@ -106,7 +112,7 @@ void getAssertionWithNullJwtParameterFailure() throws LollipopAssertionNotFoundE @Test void getAssertionWithEmptyAssertionRefParameterFailure() - throws LollipopAssertionNotFoundException { + throws LollipopAssertionNotFoundException, OidcAssertionNotSupported { Assertions.assertThrows(IllegalArgumentException.class, () -> sut.getAssertion(JWT, "")); verify(assertionStorageMock, never()).getAssertion(ASSERTION_REF); @@ -116,7 +122,7 @@ void getAssertionWithEmptyAssertionRefParameterFailure() @Test void getAssertionWithNullAssertionRefParameterFailure() - throws LollipopAssertionNotFoundException { + throws LollipopAssertionNotFoundException, OidcAssertionNotSupported { Assertions.assertThrows(IllegalArgumentException.class, () -> sut.getAssertion(JWT, null)); verify(assertionStorageMock, never()).getAssertion(ASSERTION_REF); From cc9a5497d430e95125b6df0437b48894d9a4628a Mon Sep 17 00:00:00 2001 From: pp-ps Date: Wed, 12 Apr 2023 17:44:15 +0200 Subject: [PATCH 148/403] add cache layer, avoid Java archive download from mirror --- .github/workflows/release.yaml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a3553112..66214606 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -9,9 +9,17 @@ jobs: contents: read packages: write steps: + - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + id: cache + with: + key: OpenJDK11U-jdk_x64_linux_hotspot_11.0.18_10.tar.gz + path: | + - ${{ runner.temp }}/jdkfile.tar.gz + - ${{ runner.temp }}/jdkfile.sha256 - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # jdkfile version hash was locally computed and checked against https://github.com/paketo-buildpacks/adoptium/releases - - run: | + - if: steps.cache.outputs.cache-hit != 'true' + run: | echo "4a29efda1d702b8ff38e554cf932051f40ec70006caed5c4857a8cbc7a0b7db7 ${{ runner.temp }}/jdkfile.tar.gz" >> ${{ runner.temp }}/jdkfile.sha256 echo {{ runner.temp }}/jdkfile.sha256 curl -L "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.18%2B10/OpenJDK11U-jdk_x64_linux_hotspot_11.0.18_10.tar.gz" -o "${{ runner.temp }}/jdkfile.tar.gz" From 694d1774efb85519e18d729d4f22d9589e0cff77 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 12 Apr 2023 20:22:06 +0200 Subject: [PATCH 149/403] [SLS-23] Updated HttpMessageVerifier with verification process using Visma implementation. --- assertion-rest-client-native/build.gradle | 8 +- .../config/LollipopConsumerRequestConfig.java | 3 + .../exception/LollipopSignatureException.java | 52 +++++++++ .../http_verifier/HttpMessageVerifier.java | 4 +- gradle/verification-metadata.xml | 8 ++ http-verifier/build.gradle | 1 + .../visma/VismaHttpMessageVerifier.java | 105 +++++++++++++++++- .../VismaHttpMessageVerifierFactory.java | 8 +- .../VismaHttpMessageVerifierFactoryTest.java | 15 ++- .../visma/VismaHttpMessageVerifierTest.java | 33 +++++- 10 files changed, 220 insertions(+), 17 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopSignatureException.java diff --git a/assertion-rest-client-native/build.gradle b/assertion-rest-client-native/build.gradle index 55886112..e5b3864b 100644 --- a/assertion-rest-client-native/build.gradle +++ b/assertion-rest-client-native/build.gradle @@ -14,7 +14,7 @@ plugins { /*id("org.openapi.generator") version "6.5.0"*/ } -group 'it.pagopa.commons' +group 'it.pagopa.tech' repositories { mavenLocal() @@ -41,9 +41,9 @@ abstract class InstrumentedJarsRule implements AttributeCompatibilityRule parameters); + String signature, String signatureInput, Map parameters) throws LollipopSignatureException; } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 1672fe1a..6b75d156 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -722,6 +722,14 @@ + + + + + + + + diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index 6ad9f9e7..b58434ca 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -56,6 +56,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.assertj:assertj-core:3.24.2' implementation 'it.pagopa.tech:http-signatures:1.1.2' + implementation 'com.nimbusds:nimbus-jose-jwt:9.31' implementation project(':core') } diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java index 14f71baf..26c878e2 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java @@ -1,12 +1,24 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.http_verifier.visma; +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.jwk.JWK; +import com.nimbusds.jose.jwk.KeyType; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.exception.LollipopSignatureException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; -import java.io.UnsupportedEncodingException; -import java.util.Map; import lombok.AllArgsConstructor; import net.visma.autopay.http.digest.DigestException; +import net.visma.autopay.http.signature.*; + +import java.io.UnsupportedEncodingException; +import java.security.PublicKey; +import java.text.ParseException; +import java.util.Base64; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Implementation of the @HttpMessageVerifier using Visma-AutoPay http-signature of the @@ -15,7 +27,8 @@ @AllArgsConstructor public class VismaHttpMessageVerifier implements HttpMessageVerifier { - private String defaultEncoding; + String defaultEncoding; + LollipopConsumerRequestConfig lollipopConsumerRequestConfig; /** * Validates digest using Visma DigestVerifier method. Applies contentEncoding if present, @@ -33,7 +46,8 @@ public boolean verifyDigest(String digest, String requestBody, String encoding) throws LollipopDigestException, UnsupportedEncodingException { try { net.visma.autopay.http.digest.DigestVerifier.verifyDigestHeader( - digest, requestBody.getBytes(encoding != null ? encoding : defaultEncoding)); + digest, requestBody.getBytes(encoding != null ? encoding : + defaultEncoding)); return true; } catch (DigestException e) { throw new LollipopDigestException( @@ -46,7 +60,86 @@ public boolean verifyDigest(String digest, String requestBody, String encoding) /** TODO: stub */ @Override public boolean verifyHttpSignature( - String signature, String signatureInput, Map parameters) { - return false; + String signature, String signatureInput, Map parameters) throws LollipopSignatureException { + + String lollipopKey = parameters.get(lollipopConsumerRequestConfig.getLollipopKeyHeader()); + if (lollipopKey == null) { + throw new LollipopSignatureException(LollipopSignatureException.ErrorCode.MISSING_PUBLIC_KEY, + "Could not find the public key within the expected header"); + } + + String[] signatures = signature.split(","); + String[] signatureInputs = signatureInput.split(","); + + if (signatures.length != signatureInputs.length) { + throw new LollipopSignatureException(LollipopSignatureException.ErrorCode.INVALID_SIGNATURE_NUMBER, + "Available signatures and signature-inputs differ in number"); + } + + for (int i= 0; i < signatures.length; i++) { + String signatureToProcess = signatures[i]; + String signatureInputToProcess = signatureInputs[i]; + + String label = signatureToProcess.split("=")[0]; + SignatureAlgorithm signatureAlgorithm = null; + + /* Extract algorithm from signature input*/ + Pattern pattern = Pattern.compile(";alg=(.*?);'"); + Matcher matcher = pattern.matcher(signatureInputToProcess); + if (matcher.find()) + { + try { + + String algToUse = matcher.group(0); + signatureAlgorithm = SignatureAlgorithm.valueOf(algToUse); + + } catch (IndexOutOfBoundsException | IllegalStateException e) { + throw new LollipopSignatureException(LollipopSignatureException.ErrorCode + .INVALID_SIGNATURE_ALG, "Algorithm required not available", e); + } + } + + var signatureContext = + SignatureContext.builder() + .headers(parameters) + .build(); + + PublicKey publicKey = null; + try { + JWK jwk = JWK.parse(new String(Base64.getDecoder().decode(lollipopKey))); + KeyType keyType = jwk.getKeyType(); + if (KeyType.EC.equals(keyType)) { + publicKey = jwk.toECKey().toPublicKey(); + } else if (KeyType.RSA.equals(keyType)) { + publicKey = jwk.toRSAKey().toPublicKey(); + } + } catch (ParseException | JOSEException e) { + throw new RuntimeException(e); + } + + SignatureAlgorithm finalSignatureAlgorithm = signatureAlgorithm; + PublicKey finalPublicKey = publicKey; + VerificationSpec verificationSpec = VerificationSpec + .builder() + .signatureLabel(label) + .context(signatureContext) + .publicKeyGetter(keyId -> PublicKeyInfo.builder() + .publicKey(finalPublicKey) + .algorithm(finalSignatureAlgorithm) + .build() + ) + .build(); + + try { + verificationSpec.verify(); + } catch (SignatureException e) { + throw new LollipopSignatureException(LollipopSignatureException.ErrorCode.INVALID_SIGNATURE, + "The provided signature is invalid", e); + } + + } + + return true; } + } diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java index 4f794987..470a8406 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java @@ -1,6 +1,7 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.http_verifier.visma; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; import java.nio.charset.Charset; @@ -9,12 +10,15 @@ public class VismaHttpMessageVerifierFactory implements HttpMessageVerifierFactory { private final String defaultEncoding; + private final LollipopConsumerRequestConfig lollipopConsumerRequestConfig; - public VismaHttpMessageVerifierFactory(String defaultEncoding) throws Exception { + public VismaHttpMessageVerifierFactory(String defaultEncoding, + LollipopConsumerRequestConfig lollipopConsumerRequestConfig) throws Exception { if (Charset.availableCharsets().get(defaultEncoding) == null) { throw new Exception("Unavailable Encoding: " + defaultEncoding); } this.defaultEncoding = defaultEncoding; + this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; } /** @@ -25,6 +29,6 @@ public VismaHttpMessageVerifierFactory(String defaultEncoding) throws Exception */ @Override public HttpMessageVerifier create() { - return new VismaHttpMessageVerifier(defaultEncoding); + return new VismaHttpMessageVerifier(defaultEncoding, lollipopConsumerRequestConfig); } } diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java index a60932d6..ca8ce193 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java @@ -3,14 +3,23 @@ import static org.assertj.core.api.Assertions.*; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import lombok.SneakyThrows; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; class VismaHttpMessageVerifierFactoryTest { + LollipopConsumerRequestConfig lollipopConsumerRequestConfig; + + @BeforeAll + public void init() { + lollipopConsumerRequestConfig = LollipopConsumerRequestConfig.builder().build(); + } + @Test public void encodingInCostructorIsInvalid() { - assertThatThrownBy(() -> new VismaHttpMessageVerifierFactory("UTF-326")) + assertThatThrownBy(() -> new VismaHttpMessageVerifierFactory("UTF-326",lollipopConsumerRequestConfig)) .isInstanceOfSatisfying( Exception.class, e -> assertThat(e).hasMessageContaining("Unavailable Encoding: UTF-326")); @@ -18,13 +27,13 @@ public void encodingInCostructorIsInvalid() { @Test public void encodingInCostructorIsValid() { - assertThatNoException().isThrownBy(() -> new VismaHttpMessageVerifierFactory("UTF-8")); + assertThatNoException().isThrownBy(() -> new VismaHttpMessageVerifierFactory("UTF-8",lollipopConsumerRequestConfig)); } @SneakyThrows @Test public void instanceIsCreated() { - assertThat(new VismaHttpMessageVerifierFactory("UTF-8").create()) + assertThat(new VismaHttpMessageVerifierFactory("UTF-8",lollipopConsumerRequestConfig).create()) .isInstanceOf(VismaHttpMessageVerifier.class); } } diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java index 157ec82e..5f289824 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java @@ -3,14 +3,18 @@ import static org.assertj.core.api.Assertions.*; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import java.io.UnsupportedEncodingException; +import java.util.Map; + import net.visma.autopay.http.digest.DigestException; import org.junit.jupiter.api.Test; public class VismaHttpMessageVerifierTest { - public VismaHttpMessageVerifier vismaDigestVerifier = new VismaHttpMessageVerifier("UTF-8"); + public VismaHttpMessageVerifier vismaDigestVerifier = new VismaHttpMessageVerifier("UTF-8", + LollipopConsumerRequestConfig.builder().build()); @Test public void correctDigestIsVerified() { @@ -119,4 +123,31 @@ public void invalidContentEncoding() { assertThatThrownBy(() -> vismaDigestVerifier.verifyDigest(header, content, "UTF-326")) .isInstanceOf(UnsupportedEncodingException.class); } + + @Test + public void validSignatureTest() { + + String signatureInput = "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\" \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + var signature = "sig123=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + + + Map requestHeaders = Map.of( + "Content-Digest", "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:", + "x-pagopa-lollipop-original-url", "https://api-app.io.pagopa.it/first-lollipop/sign", + "x-pagopa-lollipop-original-method", "POST", + "x-pagopa-lollipop-public-key","eyJrdHkiOiJFQyIsIngiOiJGcUZEd" + + "XdFZ3U0TVVYRVJQTVZMLTg1cEd2MkQzWW1MNEoxZ2ZNa2RiYzI0IiwieSI6Im" + + "hkVjBveG1XRlN4TW9KVURwZGlocjc2clM4VlJCRXFNRmViWXlBZks5LWsiLCJjcnYiO" + + "iJQLTI1NiJ9", + "Signature-Input", signatureInput, + "Signature", signature + ); + + // execute & verify + assertThatNoException() + .isThrownBy(() -> vismaDigestVerifier.verifyHttpSignature( + signature, signatureInput, requestHeaders)); + + } + } From ec78ac5c9991a5709bf2b6424992fff4e5eddfb4 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 12 Apr 2023 17:14:37 +0200 Subject: [PATCH 150/403] [SLS-23] Introducing dependency to forked version of the http-signature --- gradle/verification-metadata.xml | 515 ++----------------------------- http-verifier/build.gradle | 8 + 2 files changed, 27 insertions(+), 496 deletions(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index bd1b1581..1672fe1a 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1,5 +1,5 @@ - + true false @@ -125,11 +125,6 @@ - - - - - @@ -140,16 +135,6 @@ - - - - - - - - - - @@ -158,11 +143,7 @@ - - - - - + @@ -177,16 +158,6 @@ - - - - - - - - - - @@ -198,11 +169,6 @@ - - - - - @@ -236,22 +202,6 @@ - - - - - - - - - - - - - - - - @@ -261,6 +211,10 @@ + + + + @@ -278,22 +232,6 @@ - - - - - - - - - - - - - - - - @@ -303,6 +241,10 @@ + + + + @@ -320,22 +262,6 @@ - - - - - - - - - - - - - - - - @@ -351,6 +277,10 @@ + + + + @@ -371,19 +301,6 @@ - - - - - - - - - - - - - @@ -394,45 +311,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -446,16 +329,6 @@ - - - - - - - - - - @@ -487,14 +360,6 @@ - - - - - - - - @@ -505,14 +370,6 @@ - - - - - - - - @@ -593,43 +450,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -832,19 +652,6 @@ - - - - - - - - - - - - - @@ -951,11 +758,6 @@ - - - - - @@ -1046,22 +848,6 @@ - - - - - - - - - - - - - - - - @@ -1112,14 +898,6 @@ - - - - - - - - @@ -1376,14 +1154,6 @@ - - - - - - - - @@ -1394,14 +1164,6 @@ - - - - - - - - @@ -1412,14 +1174,6 @@ - - - - - - - - @@ -1430,14 +1184,6 @@ - - - - - - - - @@ -1448,14 +1194,6 @@ - - - - - - - - @@ -1466,36 +1204,18 @@ - - - - - - - - - - - - - - - - - - @@ -1506,14 +1226,6 @@ - - - - - - - - @@ -1524,14 +1236,6 @@ - - - - - - - - @@ -1542,11 +1246,6 @@ - - - - - @@ -1563,14 +1262,6 @@ - - - - - - - - @@ -1581,25 +1272,12 @@ - - - - - - - - - - - - - @@ -1610,14 +1288,6 @@ - - - - - - - - @@ -1628,20 +1298,12 @@ - - - - - - - - - - - + + + - - + + @@ -1664,14 +1326,6 @@ - - - - - - - - @@ -1692,11 +1346,6 @@ - - - - - @@ -1739,14 +1388,6 @@ - - - - - - - - @@ -1757,14 +1398,6 @@ - - - - - - - - @@ -1845,14 +1478,6 @@ - - - - - - - - @@ -1921,11 +1546,6 @@ - - - - - @@ -2010,11 +1630,6 @@ - - - - - @@ -2295,14 +1910,6 @@ - - - - - - - - @@ -2373,19 +1980,6 @@ - - - - - - - - - - - - - @@ -2402,11 +1996,6 @@ - - - - - @@ -2637,20 +2226,12 @@ - - - - - - - - @@ -3021,11 +2602,6 @@ - - - - - @@ -3036,35 +2612,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -3127,14 +2674,6 @@ - - - - - - - - @@ -3153,14 +2692,6 @@ - - - - - - - - @@ -3185,14 +2716,6 @@ - - - - - - - - diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index cf570018..e346ed83 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -18,6 +18,13 @@ group 'it.pagopa.tech.lollipop.sdk.impls' repositories { mavenLocal() mavenCentral() + maven { + url = uri("https://maven.pkg.github.com/pagopa/eng-http-signatures") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + } + } } configurations { @@ -48,6 +55,7 @@ dependencies { // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.assertj:assertj-core:3.24.2' + implementation 'it.pagopa.tech:http-signatures:1.1.2' implementation project(':core') } From f0d056719698ffbd8d1533e98174056afd9001a4 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 12 Apr 2023 20:22:06 +0200 Subject: [PATCH 151/403] [SLS-23] Updated HttpMessageVerifier with verification process using Visma implementation. --- assertion-rest-client-native/build.gradle | 8 +- .../config/LollipopConsumerRequestConfig.java | 3 + .../exception/LollipopSignatureException.java | 52 +++++++++ .../http_verifier/HttpMessageVerifier.java | 4 +- gradle/verification-metadata.xml | 8 ++ http-verifier/build.gradle | 1 + .../visma/VismaHttpMessageVerifier.java | 105 +++++++++++++++++- .../VismaHttpMessageVerifierFactory.java | 8 +- .../VismaHttpMessageVerifierFactoryTest.java | 15 ++- .../visma/VismaHttpMessageVerifierTest.java | 33 +++++- 10 files changed, 221 insertions(+), 16 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopSignatureException.java diff --git a/assertion-rest-client-native/build.gradle b/assertion-rest-client-native/build.gradle index 2b76c6b7..b71cc6f4 100644 --- a/assertion-rest-client-native/build.gradle +++ b/assertion-rest-client-native/build.gradle @@ -14,6 +14,8 @@ plugins { /*id("org.openapi.generator") version "6.5.0"*/ } +group 'it.pagopa.tech' + repositories { mavenLocal() mavenCentral() @@ -39,9 +41,9 @@ abstract class InstrumentedJarsRule implements AttributeCompatibilityRule parameters); + String signature, String signatureInput, Map parameters) throws LollipopSignatureException; } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 1672fe1a..6b75d156 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -722,6 +722,14 @@ + + + + + + + + diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index e346ed83..81dcb4f3 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -56,6 +56,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.assertj:assertj-core:3.24.2' implementation 'it.pagopa.tech:http-signatures:1.1.2' + implementation 'com.nimbusds:nimbus-jose-jwt:9.31' implementation project(':core') } diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java index 14f71baf..26c878e2 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java @@ -1,12 +1,24 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.http_verifier.visma; +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.jwk.JWK; +import com.nimbusds.jose.jwk.KeyType; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.exception.LollipopSignatureException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; -import java.io.UnsupportedEncodingException; -import java.util.Map; import lombok.AllArgsConstructor; import net.visma.autopay.http.digest.DigestException; +import net.visma.autopay.http.signature.*; + +import java.io.UnsupportedEncodingException; +import java.security.PublicKey; +import java.text.ParseException; +import java.util.Base64; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Implementation of the @HttpMessageVerifier using Visma-AutoPay http-signature of the @@ -15,7 +27,8 @@ @AllArgsConstructor public class VismaHttpMessageVerifier implements HttpMessageVerifier { - private String defaultEncoding; + String defaultEncoding; + LollipopConsumerRequestConfig lollipopConsumerRequestConfig; /** * Validates digest using Visma DigestVerifier method. Applies contentEncoding if present, @@ -33,7 +46,8 @@ public boolean verifyDigest(String digest, String requestBody, String encoding) throws LollipopDigestException, UnsupportedEncodingException { try { net.visma.autopay.http.digest.DigestVerifier.verifyDigestHeader( - digest, requestBody.getBytes(encoding != null ? encoding : defaultEncoding)); + digest, requestBody.getBytes(encoding != null ? encoding : + defaultEncoding)); return true; } catch (DigestException e) { throw new LollipopDigestException( @@ -46,7 +60,86 @@ public boolean verifyDigest(String digest, String requestBody, String encoding) /** TODO: stub */ @Override public boolean verifyHttpSignature( - String signature, String signatureInput, Map parameters) { - return false; + String signature, String signatureInput, Map parameters) throws LollipopSignatureException { + + String lollipopKey = parameters.get(lollipopConsumerRequestConfig.getLollipopKeyHeader()); + if (lollipopKey == null) { + throw new LollipopSignatureException(LollipopSignatureException.ErrorCode.MISSING_PUBLIC_KEY, + "Could not find the public key within the expected header"); + } + + String[] signatures = signature.split(","); + String[] signatureInputs = signatureInput.split(","); + + if (signatures.length != signatureInputs.length) { + throw new LollipopSignatureException(LollipopSignatureException.ErrorCode.INVALID_SIGNATURE_NUMBER, + "Available signatures and signature-inputs differ in number"); + } + + for (int i= 0; i < signatures.length; i++) { + String signatureToProcess = signatures[i]; + String signatureInputToProcess = signatureInputs[i]; + + String label = signatureToProcess.split("=")[0]; + SignatureAlgorithm signatureAlgorithm = null; + + /* Extract algorithm from signature input*/ + Pattern pattern = Pattern.compile(";alg=(.*?);'"); + Matcher matcher = pattern.matcher(signatureInputToProcess); + if (matcher.find()) + { + try { + + String algToUse = matcher.group(0); + signatureAlgorithm = SignatureAlgorithm.valueOf(algToUse); + + } catch (IndexOutOfBoundsException | IllegalStateException e) { + throw new LollipopSignatureException(LollipopSignatureException.ErrorCode + .INVALID_SIGNATURE_ALG, "Algorithm required not available", e); + } + } + + var signatureContext = + SignatureContext.builder() + .headers(parameters) + .build(); + + PublicKey publicKey = null; + try { + JWK jwk = JWK.parse(new String(Base64.getDecoder().decode(lollipopKey))); + KeyType keyType = jwk.getKeyType(); + if (KeyType.EC.equals(keyType)) { + publicKey = jwk.toECKey().toPublicKey(); + } else if (KeyType.RSA.equals(keyType)) { + publicKey = jwk.toRSAKey().toPublicKey(); + } + } catch (ParseException | JOSEException e) { + throw new RuntimeException(e); + } + + SignatureAlgorithm finalSignatureAlgorithm = signatureAlgorithm; + PublicKey finalPublicKey = publicKey; + VerificationSpec verificationSpec = VerificationSpec + .builder() + .signatureLabel(label) + .context(signatureContext) + .publicKeyGetter(keyId -> PublicKeyInfo.builder() + .publicKey(finalPublicKey) + .algorithm(finalSignatureAlgorithm) + .build() + ) + .build(); + + try { + verificationSpec.verify(); + } catch (SignatureException e) { + throw new LollipopSignatureException(LollipopSignatureException.ErrorCode.INVALID_SIGNATURE, + "The provided signature is invalid", e); + } + + } + + return true; } + } diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java index 4f794987..470a8406 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java @@ -1,6 +1,7 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.http_verifier.visma; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; import java.nio.charset.Charset; @@ -9,12 +10,15 @@ public class VismaHttpMessageVerifierFactory implements HttpMessageVerifierFactory { private final String defaultEncoding; + private final LollipopConsumerRequestConfig lollipopConsumerRequestConfig; - public VismaHttpMessageVerifierFactory(String defaultEncoding) throws Exception { + public VismaHttpMessageVerifierFactory(String defaultEncoding, + LollipopConsumerRequestConfig lollipopConsumerRequestConfig) throws Exception { if (Charset.availableCharsets().get(defaultEncoding) == null) { throw new Exception("Unavailable Encoding: " + defaultEncoding); } this.defaultEncoding = defaultEncoding; + this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; } /** @@ -25,6 +29,6 @@ public VismaHttpMessageVerifierFactory(String defaultEncoding) throws Exception */ @Override public HttpMessageVerifier create() { - return new VismaHttpMessageVerifier(defaultEncoding); + return new VismaHttpMessageVerifier(defaultEncoding, lollipopConsumerRequestConfig); } } diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java index a60932d6..ca8ce193 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java @@ -3,14 +3,23 @@ import static org.assertj.core.api.Assertions.*; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import lombok.SneakyThrows; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; class VismaHttpMessageVerifierFactoryTest { + LollipopConsumerRequestConfig lollipopConsumerRequestConfig; + + @BeforeAll + public void init() { + lollipopConsumerRequestConfig = LollipopConsumerRequestConfig.builder().build(); + } + @Test public void encodingInCostructorIsInvalid() { - assertThatThrownBy(() -> new VismaHttpMessageVerifierFactory("UTF-326")) + assertThatThrownBy(() -> new VismaHttpMessageVerifierFactory("UTF-326",lollipopConsumerRequestConfig)) .isInstanceOfSatisfying( Exception.class, e -> assertThat(e).hasMessageContaining("Unavailable Encoding: UTF-326")); @@ -18,13 +27,13 @@ public void encodingInCostructorIsInvalid() { @Test public void encodingInCostructorIsValid() { - assertThatNoException().isThrownBy(() -> new VismaHttpMessageVerifierFactory("UTF-8")); + assertThatNoException().isThrownBy(() -> new VismaHttpMessageVerifierFactory("UTF-8",lollipopConsumerRequestConfig)); } @SneakyThrows @Test public void instanceIsCreated() { - assertThat(new VismaHttpMessageVerifierFactory("UTF-8").create()) + assertThat(new VismaHttpMessageVerifierFactory("UTF-8",lollipopConsumerRequestConfig).create()) .isInstanceOf(VismaHttpMessageVerifier.class); } } diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java index 157ec82e..5f289824 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java @@ -3,14 +3,18 @@ import static org.assertj.core.api.Assertions.*; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import java.io.UnsupportedEncodingException; +import java.util.Map; + import net.visma.autopay.http.digest.DigestException; import org.junit.jupiter.api.Test; public class VismaHttpMessageVerifierTest { - public VismaHttpMessageVerifier vismaDigestVerifier = new VismaHttpMessageVerifier("UTF-8"); + public VismaHttpMessageVerifier vismaDigestVerifier = new VismaHttpMessageVerifier("UTF-8", + LollipopConsumerRequestConfig.builder().build()); @Test public void correctDigestIsVerified() { @@ -119,4 +123,31 @@ public void invalidContentEncoding() { assertThatThrownBy(() -> vismaDigestVerifier.verifyDigest(header, content, "UTF-326")) .isInstanceOf(UnsupportedEncodingException.class); } + + @Test + public void validSignatureTest() { + + String signatureInput = "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\" \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + var signature = "sig123=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + + + Map requestHeaders = Map.of( + "Content-Digest", "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:", + "x-pagopa-lollipop-original-url", "https://api-app.io.pagopa.it/first-lollipop/sign", + "x-pagopa-lollipop-original-method", "POST", + "x-pagopa-lollipop-public-key","eyJrdHkiOiJFQyIsIngiOiJGcUZEd" + + "XdFZ3U0TVVYRVJQTVZMLTg1cEd2MkQzWW1MNEoxZ2ZNa2RiYzI0IiwieSI6Im" + + "hkVjBveG1XRlN4TW9KVURwZGlocjc2clM4VlJCRXFNRmViWXlBZks5LWsiLCJjcnYiO" + + "iJQLTI1NiJ9", + "Signature-Input", signatureInput, + "Signature", signature + ); + + // execute & verify + assertThatNoException() + .isThrownBy(() -> vismaDigestVerifier.verifyHttpSignature( + signature, signatureInput, requestHeaders)); + + } + } From 04ee190cfe39649bcc382138be9bb4dd0fcd2fda Mon Sep 17 00:00:00 2001 From: svariant Date: Thu, 13 Apr 2023 10:02:28 +0200 Subject: [PATCH 152/403] [SLS-19] Changed the XML tag from which the signature is obtained --- .../internal/model/EntityDescriptor.java | 41 ++++++++++++++++--- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java index 81788328..2c48ea38 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java @@ -3,23 +3,52 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Map; import lombok.Getter; -/** EntityDescriptor */ +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * EntityDescriptor + */ @JsonIgnoreProperties(ignoreUnknown = true) @Getter public class EntityDescriptor { + private static final String KEY_DESCRIPTOR = "KeyDescriptor"; + private static final String KEY_INFO = "KeyInfo"; + private static final String X_509_DATA = "X509Data"; + private static final String X_509_CERTIFICATE = "X509Certificate"; @JsonProperty("entityID") private String entityID; private String signature; + + /** + * Methods that obtains the signature used for verify the user's assertion from a series + * of nested objects contained in the idp certification xml + * + * @param signature HashMap pulled from the idp certification xml + */ @SuppressWarnings("unchecked") - @JsonProperty("Signature") + @JsonProperty("IDPSSODescriptor") private void unpackNestedSignature(Map signature) { - Map keyInfo = (Map) signature.get("KeyInfo"); - Map x509Data = (Map) keyInfo.get("X509Data"); - this.signature = (String) x509Data.get("X509Certificate"); + Map keyDescriptor = new HashMap<>(); + if (signature.get(KEY_DESCRIPTOR) instanceof List) { + List> listDescriptors = (List>) signature.get(KEY_DESCRIPTOR); + Optional> optionalFirst = listDescriptors.stream().filter(el -> el.get("use").equals("signing")).findFirst(); + + if(optionalFirst.isPresent()){ + keyDescriptor = optionalFirst.get(); + } + } else { + keyDescriptor = (Map) signature.get(KEY_DESCRIPTOR); + } + + Map keyInfo = (Map) keyDescriptor.get(KEY_INFO); + Map x509Data = (Map) keyInfo.get(X_509_DATA); + this.signature = (String) x509Data.get(X_509_CERTIFICATE); } } From 42d83ccc918ee45b3cf15ebba62d6de1daa6ebe4 Mon Sep 17 00:00:00 2001 From: svariant Date: Thu, 13 Apr 2023 10:12:17 +0200 Subject: [PATCH 153/403] [SLS-19] Spotless applied --- .../internal/model/EntityDescriptor.java | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java index 2c48ea38..f54361ce 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java @@ -3,16 +3,13 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Getter; - import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import lombok.Getter; -/** - * EntityDescriptor - */ +/** EntityDescriptor */ @JsonIgnoreProperties(ignoreUnknown = true) @Getter public class EntityDescriptor { @@ -20,15 +17,15 @@ public class EntityDescriptor { private static final String KEY_INFO = "KeyInfo"; private static final String X_509_DATA = "X509Data"; private static final String X_509_CERTIFICATE = "X509Certificate"; + @JsonProperty("entityID") private String entityID; private String signature; - /** - * Methods that obtains the signature used for verify the user's assertion from a series - * of nested objects contained in the idp certification xml + * Methods that obtains the signature used for verify the user's assertion from a series of + * nested objects contained in the idp certification xml * * @param signature HashMap pulled from the idp certification xml */ @@ -37,10 +34,14 @@ public class EntityDescriptor { private void unpackNestedSignature(Map signature) { Map keyDescriptor = new HashMap<>(); if (signature.get(KEY_DESCRIPTOR) instanceof List) { - List> listDescriptors = (List>) signature.get(KEY_DESCRIPTOR); - Optional> optionalFirst = listDescriptors.stream().filter(el -> el.get("use").equals("signing")).findFirst(); - - if(optionalFirst.isPresent()){ + List> listDescriptors = + (List>) signature.get(KEY_DESCRIPTOR); + Optional> optionalFirst = + listDescriptors.stream() + .filter(el -> el.get("use").equals("signing")) + .findFirst(); + + if (optionalFirst.isPresent()) { keyDescriptor = optionalFirst.get(); } } else { From 14b9b6560fdd3784b6b91837c92512db9ef90cc0 Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 13 Apr 2023 10:49:35 +0200 Subject: [PATCH 154/403] [SLS-21] added original method and url validation. --- .../config/LollipopConsumerRequestConfig.java | 7 ++ .../LollipopValidationException.java | 50 +++++++++++++ .../helper/LollipopConsumerFactoryHelper.java | 13 ++-- .../service/AssertionVerifierService.java | 3 +- .../impl/AssertionVerifierServiceImpl.java | 70 +++++++++++++++++++ .../AssertionVerifierServiceImplStub.java | 53 -------------- 6 files changed, 138 insertions(+), 58 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index 90e88b57..0a237a29 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -13,4 +13,11 @@ public class LollipopConsumerRequestConfig { @Builder.Default private String contentEncodingHeader = "content-encoding"; @Builder.Default private String contentDigestHeader = "content-digest"; @Builder.Default private boolean strictDigestVerify = false; + + @Builder.Default private String originalMethodHeader = "x-pagopa-lollipop-original-method"; + @Builder.Default private String originalURLHeader = "x-pagopa-lollipop-original-url"; + + @Builder.Default private String expectedFirstLcOriginalMethod = "POST"; + @Builder.Default private String expectedFirstLcOriginalUrl = " https://api-app.io.pagopa.it/first-lollipop/sign"; + } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java new file mode 100644 index 00000000..4c9e1c8d --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java @@ -0,0 +1,50 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +import java.util.Objects; + +/** + * Thrown in case of problems when computing or verifying lollipop request through the + * assertion flow + */ +public class LollipopValidationException extends Exception { + + /** Error code of this exception */ + private final ErrorCode errorCode; + + /** + * Constructs new exception with provided error code and message + * + * @param errorCode Error code + * @param message Detail message + */ + public LollipopValidationException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Constructs new exception with provided error code, message and cause + * + * @param errorCode Error code + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public LollipopValidationException(ErrorCode errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Returns error code + * + * @return Error code of this exception + */ + public ErrorCode getErrorCode() { + return errorCode; + } + + /** Error codes to classify Lollipop Request Exceptions */ + public enum ErrorCode { + UNEXPECTED_METHOD_OR_URL, + } +} \ No newline at end of file diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index 6caa8d69..ed688eda 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -7,7 +7,7 @@ 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.impl.AssertionVerifierServiceImplStub; +import it.pagopa.tech.lollipop.consumer.service.impl.AssertionVerifierServiceImpl; import it.pagopa.tech.lollipop.consumer.service.impl.HttpMessageVerifierServiceImpl; import javax.inject.Inject; @@ -35,7 +35,9 @@ public LollipopConsumerFactoryHelper( */ public HttpMessageVerifierService getHttpMessageVerifierService() { return new HttpMessageVerifierServiceImpl( - getHttpMessageVerifierFactory().create(), getLollipopConsumerRequestConfig()); + getHttpMessageVerifierFactory().create(), + getLollipopConsumerRequestConfig() + ); } /** @@ -44,8 +46,11 @@ public HttpMessageVerifierService getHttpMessageVerifierService() { * @return an instance of {@link AssertionVerifierService} */ public AssertionVerifierService getAssertionVerifierService() { - return new AssertionVerifierServiceImplStub( - getIdpCertProviderFactory().create(), getAssertionServiceFactory().create()); + return new AssertionVerifierServiceImpl( + getIdpCertProviderFactory().create(), + getAssertionServiceFactory().create(), + getLollipopConsumerRequestConfig() + ); } public HttpMessageVerifierFactory getHttpMessageVerifierFactory() { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java index 758422bf..cc555fae 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java @@ -1,6 +1,7 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service; +import it.pagopa.tech.lollipop.consumer.exception.LollipopValidationException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; /** @@ -16,5 +17,5 @@ public interface AssertionVerifierService { * @param request * @return */ - boolean validateLollipop(LollipopConsumerRequest request); + boolean validateLollipop(LollipopConsumerRequest request) throws LollipopValidationException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java new file mode 100644 index 00000000..dd66e7b3 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -0,0 +1,70 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.service.impl; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.exception.LollipopValidationException; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; +import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; +import javax.inject.Inject; +import java.util.Map; + +public class AssertionVerifierServiceImpl implements AssertionVerifierService { + + private final IdpCertProvider idpCertProvider; + private final AssertionService assertionService; + private final LollipopConsumerRequestConfig lollipopConsumerRequestConfig; + + + @Inject + public AssertionVerifierServiceImpl(IdpCertProvider idpCertProvider, AssertionService assertionService, LollipopConsumerRequestConfig lollipopConsumerRequestConfig) { + this.idpCertProvider = idpCertProvider; + this.assertionService = assertionService; + this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; + } + + @Override + public boolean validateLollipop(LollipopConsumerRequest request) throws LollipopValidationException { + + Map headerParams = request.getHeaderParams(); + + String originalMethod = headerParams.get(lollipopConsumerRequestConfig.getOriginalMethodHeader()); + String originalUrl = headerParams.get(lollipopConsumerRequestConfig.getOriginalURLHeader()); + + if (!originalMethod.equals(lollipopConsumerRequestConfig.getExpectedFirstLcOriginalMethod()) && !originalUrl.equals(lollipopConsumerRequestConfig.getExpectedFirstLcOriginalUrl())) { + String errMsg = String.format("Unexpected original method and/or original url: %s, %s", originalMethod, originalUrl); + throw new LollipopValidationException(LollipopValidationException.ErrorCode.UNEXPECTED_METHOD_OR_URL, errMsg); + } + + + + return true; + } + + private SamlAssertion getAssertion(String jwt, String assertionRef) { + return null; + } + + private boolean validateAssertionPeriod(String notBefore) { + return false; + } + + private boolean validateUserId(LollipopConsumerRequest request, SamlAssertion assertion) { + return false; + } + + private boolean validateInResponseTo(LollipopConsumerRequest request, SamlAssertion assertion) { + return false; + } + + private IdpCertData getIdpCertData(SamlAssertion assertion) { + return null; + } + + private boolean validateSignature(SamlAssertion assertion, IdpCertData idpCertData) { + return false; + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java deleted file mode 100644 index f87d7cf6..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java +++ /dev/null @@ -1,53 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.service.impl; - -import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; -import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; -import it.pagopa.tech.lollipop.consumer.model.IdpCertData; -import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; -import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; -import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; -import javax.inject.Inject; - -public class AssertionVerifierServiceImplStub implements AssertionVerifierService { - - private IdpCertProvider idpCertProvider; - private AssertionService assertionService; - - @Inject - public AssertionVerifierServiceImplStub( - IdpCertProvider idpCertProvider, AssertionService assertionService) { - this.idpCertProvider = idpCertProvider; - this.assertionService = assertionService; - } - - /** TODO: stub */ - @Override - public boolean validateLollipop(LollipopConsumerRequest request) { - return true; - } - - private SamlAssertion getAssertion(String jwt, String assertionRef) { - return null; - } - - private boolean validateAssertionPeriod(String notBefore) { - return false; - } - - private boolean validateThumbprint(LollipopConsumerRequest request, SamlAssertion assertion) { - return false; - } - - private boolean validateInResponseTo(LollipopConsumerRequest request, SamlAssertion assertion) { - return false; - } - - private IdpCertData getIdpCertData(SamlAssertion assertion) { - return null; - } - - private boolean validateSignature(SamlAssertion assertion, IdpCertData idpCertData) { - return false; - } -} From a7e7da8be9a761c2ec39bd6a8541dea361055f5d Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 13 Apr 2023 11:05:02 +0200 Subject: [PATCH 155/403] [SLS-21] added all request headers. --- .../consumer/config/LollipopConsumerRequestConfig.java | 5 +++++ .../consumer/exception/LollipopValidationException.java | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index 0a237a29..26e62488 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -16,6 +16,11 @@ public class LollipopConsumerRequestConfig { @Builder.Default private String originalMethodHeader = "x-pagopa-lollipop-original-method"; @Builder.Default private String originalURLHeader = "x-pagopa-lollipop-original-url"; + @Builder.Default private String assertionRefHeader = "x-pagopa-lollipop-assertion-ref"; + @Builder.Default private String assertionTypeHeader = "x-pagopa-lollipop-assertion-type"; + @Builder.Default private String userIdHeader = "x-pagopa-lollipop-user-id"; + @Builder.Default private String publicKeyHeader = "x-pagopa-lollipop-public-key"; + @Builder.Default private String authJWTHeader = "x-pagopa-lollipop-auth-jwt"; @Builder.Default private String expectedFirstLcOriginalMethod = "POST"; @Builder.Default private String expectedFirstLcOriginalUrl = " https://api-app.io.pagopa.it/first-lollipop/sign"; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java index 4c9e1c8d..9cc2230d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java @@ -45,6 +45,6 @@ public ErrorCode getErrorCode() { /** Error codes to classify Lollipop Request Exceptions */ public enum ErrorCode { - UNEXPECTED_METHOD_OR_URL, + UNEXPECTED_METHOD_OR_URL } } \ No newline at end of file From 52fd99d28ff60b340e327698260fb0a4af56b4bc Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 13 Apr 2023 10:49:35 +0200 Subject: [PATCH 156/403] [SLS-21] added original method and url validation. --- .../config/LollipopConsumerRequestConfig.java | 7 ++ .../LollipopValidationException.java | 50 +++++++++++++ .../helper/LollipopConsumerFactoryHelper.java | 13 ++-- .../service/AssertionVerifierService.java | 3 +- .../impl/AssertionVerifierServiceImpl.java | 70 +++++++++++++++++++ .../AssertionVerifierServiceImplStub.java | 53 -------------- 6 files changed, 138 insertions(+), 58 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index 90e88b57..0a237a29 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -13,4 +13,11 @@ public class LollipopConsumerRequestConfig { @Builder.Default private String contentEncodingHeader = "content-encoding"; @Builder.Default private String contentDigestHeader = "content-digest"; @Builder.Default private boolean strictDigestVerify = false; + + @Builder.Default private String originalMethodHeader = "x-pagopa-lollipop-original-method"; + @Builder.Default private String originalURLHeader = "x-pagopa-lollipop-original-url"; + + @Builder.Default private String expectedFirstLcOriginalMethod = "POST"; + @Builder.Default private String expectedFirstLcOriginalUrl = " https://api-app.io.pagopa.it/first-lollipop/sign"; + } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java new file mode 100644 index 00000000..4c9e1c8d --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java @@ -0,0 +1,50 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +import java.util.Objects; + +/** + * Thrown in case of problems when computing or verifying lollipop request through the + * assertion flow + */ +public class LollipopValidationException extends Exception { + + /** Error code of this exception */ + private final ErrorCode errorCode; + + /** + * Constructs new exception with provided error code and message + * + * @param errorCode Error code + * @param message Detail message + */ + public LollipopValidationException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Constructs new exception with provided error code, message and cause + * + * @param errorCode Error code + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public LollipopValidationException(ErrorCode errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Returns error code + * + * @return Error code of this exception + */ + public ErrorCode getErrorCode() { + return errorCode; + } + + /** Error codes to classify Lollipop Request Exceptions */ + public enum ErrorCode { + UNEXPECTED_METHOD_OR_URL, + } +} \ No newline at end of file diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index 6caa8d69..ed688eda 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -7,7 +7,7 @@ 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.impl.AssertionVerifierServiceImplStub; +import it.pagopa.tech.lollipop.consumer.service.impl.AssertionVerifierServiceImpl; import it.pagopa.tech.lollipop.consumer.service.impl.HttpMessageVerifierServiceImpl; import javax.inject.Inject; @@ -35,7 +35,9 @@ public LollipopConsumerFactoryHelper( */ public HttpMessageVerifierService getHttpMessageVerifierService() { return new HttpMessageVerifierServiceImpl( - getHttpMessageVerifierFactory().create(), getLollipopConsumerRequestConfig()); + getHttpMessageVerifierFactory().create(), + getLollipopConsumerRequestConfig() + ); } /** @@ -44,8 +46,11 @@ public HttpMessageVerifierService getHttpMessageVerifierService() { * @return an instance of {@link AssertionVerifierService} */ public AssertionVerifierService getAssertionVerifierService() { - return new AssertionVerifierServiceImplStub( - getIdpCertProviderFactory().create(), getAssertionServiceFactory().create()); + return new AssertionVerifierServiceImpl( + getIdpCertProviderFactory().create(), + getAssertionServiceFactory().create(), + getLollipopConsumerRequestConfig() + ); } public HttpMessageVerifierFactory getHttpMessageVerifierFactory() { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java index 758422bf..cc555fae 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java @@ -1,6 +1,7 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service; +import it.pagopa.tech.lollipop.consumer.exception.LollipopValidationException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; /** @@ -16,5 +17,5 @@ public interface AssertionVerifierService { * @param request * @return */ - boolean validateLollipop(LollipopConsumerRequest request); + boolean validateLollipop(LollipopConsumerRequest request) throws LollipopValidationException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java new file mode 100644 index 00000000..dd66e7b3 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -0,0 +1,70 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.service.impl; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.exception.LollipopValidationException; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; +import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; +import javax.inject.Inject; +import java.util.Map; + +public class AssertionVerifierServiceImpl implements AssertionVerifierService { + + private final IdpCertProvider idpCertProvider; + private final AssertionService assertionService; + private final LollipopConsumerRequestConfig lollipopConsumerRequestConfig; + + + @Inject + public AssertionVerifierServiceImpl(IdpCertProvider idpCertProvider, AssertionService assertionService, LollipopConsumerRequestConfig lollipopConsumerRequestConfig) { + this.idpCertProvider = idpCertProvider; + this.assertionService = assertionService; + this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; + } + + @Override + public boolean validateLollipop(LollipopConsumerRequest request) throws LollipopValidationException { + + Map headerParams = request.getHeaderParams(); + + String originalMethod = headerParams.get(lollipopConsumerRequestConfig.getOriginalMethodHeader()); + String originalUrl = headerParams.get(lollipopConsumerRequestConfig.getOriginalURLHeader()); + + if (!originalMethod.equals(lollipopConsumerRequestConfig.getExpectedFirstLcOriginalMethod()) && !originalUrl.equals(lollipopConsumerRequestConfig.getExpectedFirstLcOriginalUrl())) { + String errMsg = String.format("Unexpected original method and/or original url: %s, %s", originalMethod, originalUrl); + throw new LollipopValidationException(LollipopValidationException.ErrorCode.UNEXPECTED_METHOD_OR_URL, errMsg); + } + + + + return true; + } + + private SamlAssertion getAssertion(String jwt, String assertionRef) { + return null; + } + + private boolean validateAssertionPeriod(String notBefore) { + return false; + } + + private boolean validateUserId(LollipopConsumerRequest request, SamlAssertion assertion) { + return false; + } + + private boolean validateInResponseTo(LollipopConsumerRequest request, SamlAssertion assertion) { + return false; + } + + private IdpCertData getIdpCertData(SamlAssertion assertion) { + return null; + } + + private boolean validateSignature(SamlAssertion assertion, IdpCertData idpCertData) { + return false; + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java deleted file mode 100644 index f87d7cf6..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java +++ /dev/null @@ -1,53 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.service.impl; - -import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; -import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; -import it.pagopa.tech.lollipop.consumer.model.IdpCertData; -import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; -import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; -import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; -import javax.inject.Inject; - -public class AssertionVerifierServiceImplStub implements AssertionVerifierService { - - private IdpCertProvider idpCertProvider; - private AssertionService assertionService; - - @Inject - public AssertionVerifierServiceImplStub( - IdpCertProvider idpCertProvider, AssertionService assertionService) { - this.idpCertProvider = idpCertProvider; - this.assertionService = assertionService; - } - - /** TODO: stub */ - @Override - public boolean validateLollipop(LollipopConsumerRequest request) { - return true; - } - - private SamlAssertion getAssertion(String jwt, String assertionRef) { - return null; - } - - private boolean validateAssertionPeriod(String notBefore) { - return false; - } - - private boolean validateThumbprint(LollipopConsumerRequest request, SamlAssertion assertion) { - return false; - } - - private boolean validateInResponseTo(LollipopConsumerRequest request, SamlAssertion assertion) { - return false; - } - - private IdpCertData getIdpCertData(SamlAssertion assertion) { - return null; - } - - private boolean validateSignature(SamlAssertion assertion, IdpCertData idpCertData) { - return false; - } -} From 223def2715de9559be5ae1006fe3d39bd846275d Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 13 Apr 2023 11:05:02 +0200 Subject: [PATCH 157/403] [SLS-21] added all request headers. --- .../consumer/config/LollipopConsumerRequestConfig.java | 5 +++++ .../consumer/exception/LollipopValidationException.java | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index 0a237a29..26e62488 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -16,6 +16,11 @@ public class LollipopConsumerRequestConfig { @Builder.Default private String originalMethodHeader = "x-pagopa-lollipop-original-method"; @Builder.Default private String originalURLHeader = "x-pagopa-lollipop-original-url"; + @Builder.Default private String assertionRefHeader = "x-pagopa-lollipop-assertion-ref"; + @Builder.Default private String assertionTypeHeader = "x-pagopa-lollipop-assertion-type"; + @Builder.Default private String userIdHeader = "x-pagopa-lollipop-user-id"; + @Builder.Default private String publicKeyHeader = "x-pagopa-lollipop-public-key"; + @Builder.Default private String authJWTHeader = "x-pagopa-lollipop-auth-jwt"; @Builder.Default private String expectedFirstLcOriginalMethod = "POST"; @Builder.Default private String expectedFirstLcOriginalUrl = " https://api-app.io.pagopa.it/first-lollipop/sign"; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java index 4c9e1c8d..9cc2230d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java @@ -45,6 +45,6 @@ public ErrorCode getErrorCode() { /** Error codes to classify Lollipop Request Exceptions */ public enum ErrorCode { - UNEXPECTED_METHOD_OR_URL, + UNEXPECTED_METHOD_OR_URL } } \ No newline at end of file From faffa55df78e0546ed95c55ce8596988044051e3 Mon Sep 17 00:00:00 2001 From: svariant Date: Thu, 13 Apr 2023 12:15:22 +0200 Subject: [PATCH 158/403] [SLS-21] Implemented method to validate assertion period --- .../impl/AssertionVerifierServiceImpl.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index dd66e7b3..1f9e9356 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -9,8 +9,13 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; + import javax.inject.Inject; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.Map; +import java.util.concurrent.TimeUnit; public class AssertionVerifierServiceImpl implements AssertionVerifierService { @@ -40,7 +45,6 @@ public boolean validateLollipop(LollipopConsumerRequest request) throws Lollipop } - return true; } @@ -48,7 +52,19 @@ private SamlAssertion getAssertion(String jwt, String assertionRef) { return null; } - private boolean validateAssertionPeriod(String notBefore) { + public boolean validateAssertionPeriod(String notBefore) throws ParseException { + long notBeforeMilliseconds = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(notBefore).getTime(); //TODO configurazione format date + + long dateNowMilliseconds = new Date().getTime(); + + long expiresAfterMilliseconds = TimeUnit.DAYS.toMillis(30); //TODO configurazione giorni scadenza + + long dateNowLessNotBefore = (dateNowMilliseconds - notBeforeMilliseconds); + + if (0 <= dateNowLessNotBefore && (dateNowLessNotBefore <= expiresAfterMilliseconds)) { + return true; + } + return false; } From c919cde7ac7f18653bd5c9e41b2fbbd96081d914 Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 13 Apr 2023 14:47:25 +0200 Subject: [PATCH 159/403] [SLS-21] added request headers validation. --- ...lipopConsumerRequestValidationService.java | 167 ++++++++++++++++++ .../enumeration/AssertionTypeEnum.java | 10 ++ .../enumeration/LollipopMethodEnum.java | 12 ++ .../exception/LollipopVerifierException.java | 25 ++- .../lollipop/consumer/model/ECPublicKey.java | 15 ++ .../lollipop/consumer/model/RSAPublicKey.java | 15 ++ 6 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionTypeEnum.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopMethodEnum.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java new file mode 100644 index 00000000..c8801d21 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java @@ -0,0 +1,167 @@ +package it.pagopa.tech.lollipop.consumer.config.service; + +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.enumeration.AssertionTypeEnum; +import it.pagopa.tech.lollipop.consumer.enumeration.LollipopMethodEnum; +import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; + +import java.util.Map; +import java.util.regex.Pattern; + +public class LollipopConsumerRequestValidationService { + + public static boolean validateLollipopConsumerConfig(LollipopConsumerRequest request, LollipopConsumerRequestConfig config) throws LollipopVerifierException { + + Map headerParams = request.getHeaderParams(); + + validatePublicKey(headerParams.get(config.getPublicKeyHeader())); + + validateAssertionRefHeader(headerParams.get(config.getAssertionRefHeader())); + validateAssertionTypeHeader(headerParams.get(config.getAssertionTypeHeader())); + validateUserIdHeader(headerParams.get(config.getUserIdHeader())); + validateAuthJWTHeader(headerParams.get(config.getAuthJWTHeader())); + validateOriginalMethodHeader(headerParams.get(config.getOriginalMethodHeader())); + validateOriginalURLHeader(headerParams.get(config.getOriginalURLHeader())); + validateSignatureInputHeader(headerParams.get(config.getSignatureInputHeader())); + validateSignatureHeader(headerParams.get(config.getSignatureHeader())); + + return true; + } + + private static void validatePublicKey(String publicKey) throws LollipopVerifierException { + if (publicKey == null ) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_PUBLIC_KEY, "Missing Public Key Header"); + } + + if (isNotValidPublicKey(publicKey)) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_PUBLIC_KEY, "Invalid Public Key Header value"); + } + } + + private static boolean isNotValidPublicKey(String publicKey) { + // TODO + return false; + } + + private static void validateAssertionRefHeader(String assertionRef) throws LollipopVerifierException { + if (assertionRef == null ) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_ASSERTION_REF, "Missing AssertionRef Header"); + } + + if (isNotValidAssertionRef(assertionRef)) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ASSERTION_REF, "Invalid AssertionRef Header value"); + } + } + + private static boolean isNotValidAssertionRef(String signature) { + boolean matchesSHA26 = Pattern.compile("^(sha256-[A-Za-z0-9-_=]{1,44})$").matcher(signature).matches(); + boolean matchesSHA384 = Pattern.compile("^(sha384-[A-Za-z0-9-_=]{1,66})$").matcher(signature).matches(); + boolean matchesSHA512 = Pattern.compile("^(sha512-[A-Za-z0-9-_=]{1,88})$").matcher(signature).matches(); + return !matchesSHA26 && !matchesSHA384 && !matchesSHA512; + } + + private static void validateAssertionTypeHeader(String assertionType) throws LollipopVerifierException { + if (assertionType == null ) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_ASSERTION_TYPE, "Missing Assertion Type Header"); + } + + if ((!isAssertionTypeSupported(assertionType))) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ASSERTION_TYPE, "Invalid Assertion Type Header value, type not supported"); + } + } + + public static boolean isAssertionTypeSupported(String assertionType) { + for (AssertionTypeEnum supportedType : AssertionTypeEnum.values()) { + if (supportedType.name().equals(assertionType)) { + return true; + } + } + return false; + } + + private static void validateUserIdHeader(String userId) throws LollipopVerifierException { + if (userId == null ) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_USER_ID, "Missing User Id Header"); + } + + if ((isNotValidFiscalCode(userId))) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_USER_ID, "Invalid User Id Header value, type not supported"); + } + } + + private static boolean isNotValidFiscalCode(String userId) { + return !Pattern.compile("^[A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]$").matcher(userId).matches(); + } + + private static void validateAuthJWTHeader(String authJWT) throws LollipopVerifierException { + if (authJWT == null ) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_AUTH_JWT, "Missing Auth JWT Header"); + } + + if (authJWT.isBlank()) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_AUTH_JWT, "Invalid Auth JWT Header value, cannot be empty"); + } + } + + private static void validateOriginalMethodHeader(String originalMethod) throws LollipopVerifierException { + if (originalMethod == null ) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_ORIGINAL_METHOD, "Missing Original Method Header"); + } + + if (!isRequestMethodSupported(originalMethod)) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ORIGINAL_METHOD, "Invalid Original Method Header value, method not supported"); + } + } + + public static boolean isRequestMethodSupported(String originalMethod) { + for (LollipopMethodEnum supportedType : LollipopMethodEnum.values()) { + if (supportedType.name().equals(originalMethod)) { + return true; + } + } + return false; + } + + private static void validateOriginalURLHeader(String originalURL) throws LollipopVerifierException { + if (originalURL == null ) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_ORIGINAL_URL, "Missing Original URL Header"); + } + + if (isNotValidOriginalURL(originalURL)) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ORIGINAL_URL, "Invalid Original URL Header value"); + } + } + + private static boolean isNotValidOriginalURL(String originalURL) { + return !Pattern.compile("^https://").matcher(originalURL).matches(); + } + + private static void validateSignatureInputHeader(String signatureInput) throws LollipopVerifierException { + if (signatureInput == null ) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE_INPUT, "Missing Signature Input Header"); + } + + if (isNotValidSignatureInput(signatureInput)) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ORIGINAL_URL, "Invalid Signature Input Header value"); + } + } + + private static boolean isNotValidSignatureInput(String signatureInput) { + return !Pattern.compile("^(((sig[0-9]+)=[^,]*?)(, ?)?)+$").matcher(signatureInput).matches(); + } + + private static void validateSignatureHeader(String signature) throws LollipopVerifierException { + if (signature == null ) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE, "Missing Signature Header"); + } + + if (isNotValidSignature(signature)) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_SIGNATURE_HEADER, "Invalid Signature Header value"); + } + } + + private static boolean isNotValidSignature(String signature) { + return !Pattern.compile("^((sig[0-9]+)=:[A-Za-z0-9+/=]*:(, ?)?)+$").matcher(signature).matches(); + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionTypeEnum.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionTypeEnum.java new file mode 100644 index 00000000..e7cae454 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionTypeEnum.java @@ -0,0 +1,10 @@ +package it.pagopa.tech.lollipop.consumer.enumeration; + +/** + * Supported assertion type + */ +public enum AssertionTypeEnum { + SAML, + //TODO: OIDC + +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopMethodEnum.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopMethodEnum.java new file mode 100644 index 00000000..66069d8f --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopMethodEnum.java @@ -0,0 +1,12 @@ +package it.pagopa.tech.lollipop.consumer.enumeration; + +/** + * Supported Lollipop request methods + */ +public enum LollipopMethodEnum { + GET, + POST, + PUT, + PATCH, + DELETE +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java index 04e98686..7ea6685d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java @@ -47,7 +47,30 @@ public ErrorCode getErrorCode() { /** Error codes to classify Lollipop Request Exceptions */ public enum ErrorCode { MISSING_SIGNATURE, + INVALID_SIGNATURE_HEADER, - MISSING_SIGNATURE_INPUT + MISSING_SIGNATURE_INPUT, + INVALID_SIGNATURE_INPUT, + + MISSING_ASSERTION_REF, + INVALID_ASSERTION_REF, + + MISSING_ASSERTION_TYPE, + INVALID_ASSERTION_TYPE, + + MISSING_USER_ID, + INVALID_USER_ID, + + MISSING_AUTH_JWT, + INVALID_AUTH_JWT, + + MISSING_ORIGINAL_METHOD, + INVALID_ORIGINAL_METHOD, + + MISSING_ORIGINAL_URL, + INVALID_ORIGINAL_URL, + + MISSING_PUBLIC_KEY, + INVALID_PUBLIC_KEY } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java new file mode 100644 index 00000000..e3581111 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java @@ -0,0 +1,15 @@ +package it.pagopa.tech.lollipop.consumer.model; + +import lombok.Data; + +/** + * EC public key model + */ +@Data +public class ECPublicKey { + + private String crv; + private String kty; + private String x; + private String y; +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java new file mode 100644 index 00000000..628d327a --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java @@ -0,0 +1,15 @@ +package it.pagopa.tech.lollipop.consumer.model; + +import lombok.Data; + +/** + * RSA public key model + */ +@Data +public class RSAPublicKey { + + private String alg; + private String e; + private String kty; + private String n; +} From e3bae4d9e652c93bc8868b36985be010322e3325 Mon Sep 17 00:00:00 2001 From: svariant Date: Thu, 13 Apr 2023 14:48:40 +0200 Subject: [PATCH 160/403] [SLS-21] Implemented userID (fiscalCode) validation --- .../impl/AssertionVerifierServiceImpl.java | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index 1f9e9356..4c41d28a 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -9,13 +9,23 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; import javax.inject.Inject; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.io.StringReader; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; public class AssertionVerifierServiceImpl implements AssertionVerifierService { @@ -52,8 +62,8 @@ private SamlAssertion getAssertion(String jwt, String assertionRef) { return null; } - public boolean validateAssertionPeriod(String notBefore) throws ParseException { - long notBeforeMilliseconds = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(notBefore).getTime(); //TODO configurazione format date + private boolean validateAssertionPeriod(String notBefore) throws ParseException { + long notBeforeMilliseconds = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse(notBefore).getTime(); //TODO configurazione format date long dateNowMilliseconds = new Date().getTime(); @@ -68,8 +78,27 @@ public boolean validateAssertionPeriod(String notBefore) throws ParseException { return false; } - private boolean validateUserId(LollipopConsumerRequest request, SamlAssertion assertion) { - return false; + private boolean validateUserId(LollipopConsumerRequest request, SamlAssertion assertion) throws ParserConfigurationException, IOException, SAXException { + String stringXml = assertion.getAssertionData(); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document document = builder.parse(new InputSource(new StringReader(stringXml))); + + String userIdHeaders = request.getHeaderParams().get("x-pagopa-lollipop-user-id"); //TODO aggiungere a configurazione + + NodeList listElements = document.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "Attribute"); //TODO aggiungere a configurazione + String userIdAssertion = ""; + if (listElements != null && listElements.getLength() > 0) { + for (int i = 0; i < listElements.getLength(); i++) { + String userIdFound = listElements.item(i).getAttributes().getNamedItem("fiscalNumber").getNodeValue(); + if (!userIdFound.isBlank()) { + userIdAssertion = userIdFound.trim().replace("TINIT-", ""); + break; + } + } + } + + return userIdAssertion.equals(userIdHeaders); } private boolean validateInResponseTo(LollipopConsumerRequest request, SamlAssertion assertion) { From 5814ab91d875461cdc490041b9dd2aa1637496a4 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 13 Apr 2023 15:05:22 +0200 Subject: [PATCH 161/403] [SLS-23] Updated HttpMessageVerifier and related tests. Update verification-metadata.xml --- .../config/LollipopConsumerRequestConfig.java | 2 - .../exception/LollipopSignatureException.java | 6 +- .../http_verifier/HttpMessageVerifier.java | 10 +- gradle/verification-metadata.xml | 27 ++- http-verifier/build.gradle | 3 +- .../visma/VismaHttpMessageVerifier.java | 97 +++++--- .../VismaHttpMessageVerifierFactory.java | 5 +- .../VismaHttpMessageVerifierFactoryTest.java | 17 +- .../visma/VismaHttpMessageVerifierTest.java | 216 ++++++++++++++++-- 9 files changed, 305 insertions(+), 78 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index e22a2646..ac73a2be 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -14,6 +14,4 @@ public class LollipopConsumerRequestConfig { @Builder.Default private String contentDigestHeader = "content-digest"; @Builder.Default private String lollipopKeyHeader = "x-pagopa-lollipop-public-key"; @Builder.Default private boolean strictDigestVerify = false; - - } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopSignatureException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopSignatureException.java index ad5bfaf3..7d75abcd 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopSignatureException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopSignatureException.java @@ -46,7 +46,9 @@ public ErrorCode getErrorCode() { /** Error codes to classify Signature Exceptions */ public enum ErrorCode { - - INVALID_SIGNATURE_NUMBER, INVALID_SIGNATURE_ALG, MISSING_PUBLIC_KEY, INVALID_SIGNATURE, + INVALID_SIGNATURE_NUMBER, + INVALID_SIGNATURE_ALG, + MISSING_PUBLIC_KEY, + INVALID_SIGNATURE, } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java index bdaf12d5..317f730f 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/HttpMessageVerifier.java @@ -3,7 +3,6 @@ import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import it.pagopa.tech.lollipop.consumer.exception.LollipopSignatureException; - import java.io.UnsupportedEncodingException; import java.util.Map; @@ -32,11 +31,12 @@ boolean verifyDigest(String digest, String requestBody, String encoding) * Checks whether the calculated signatures of the required parameter matches with those * provided within the Signature param * - * @param signature - * @param signatureInput - * @param parameters + * @param signature Input parameter containing the expected signature + * @param signatureInput Input parameter containing the expected signature base for validation + * @param parameters Header parameters to be used in signature validation * @return boolean set to true if the signature check is valid */ boolean verifyHttpSignature( - String signature, String signatureInput, Map parameters) throws LollipopSignatureException; + String signature, String signatureInput, Map parameters) + throws LollipopSignatureException; } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 6b75d156..5b4ef644 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -143,7 +143,6 @@ - @@ -213,7 +212,6 @@ - @@ -243,7 +241,6 @@ - @@ -279,7 +276,6 @@ - @@ -652,6 +648,19 @@ + + + + + + + + + + + + + @@ -1306,12 +1315,12 @@ - - - + + + - - + + diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index 81dcb4f3..cc4669c1 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -51,11 +51,10 @@ dependencies { compatibilityRules.add(InstrumentedJarsRule) } } - implementation 'net.visma.autopay:http-signatures:1.1.0' + implementation 'it.pagopa.tech:http-signatures:1.1.4' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.assertj:assertj-core:3.24.2' - implementation 'it.pagopa.tech:http-signatures:1.1.2' implementation 'com.nimbusds:nimbus-jose-jwt:9.31' implementation project(':core') } diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java index 26c878e2..54635b32 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java @@ -8,10 +8,6 @@ import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; import it.pagopa.tech.lollipop.consumer.exception.LollipopSignatureException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; -import lombok.AllArgsConstructor; -import net.visma.autopay.http.digest.DigestException; -import net.visma.autopay.http.signature.*; - import java.io.UnsupportedEncodingException; import java.security.PublicKey; import java.text.ParseException; @@ -19,6 +15,9 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +import lombok.AllArgsConstructor; +import net.visma.autopay.http.digest.DigestException; +import net.visma.autopay.http.signature.*; /** * Implementation of the @HttpMessageVerifier using Visma-AutoPay http-signature of the @@ -46,8 +45,7 @@ public boolean verifyDigest(String digest, String requestBody, String encoding) throws LollipopDigestException, UnsupportedEncodingException { try { net.visma.autopay.http.digest.DigestVerifier.verifyDigestHeader( - digest, requestBody.getBytes(encoding != null ? encoding : - defaultEncoding)); + digest, requestBody.getBytes(encoding != null ? encoding : defaultEncoding)); return true; } catch (DigestException e) { throw new LollipopDigestException( @@ -57,14 +55,27 @@ public boolean verifyDigest(String digest, String requestBody, String encoding) } } - /** TODO: stub */ + /** + * @param signature Input parameter containing the expected signature + * @param signatureInput Input parameter containing the expected signature base for validation + * @param parameters Header parameters to be used in signature validation + * @return boolean to determine if validated + * @throws LollipopSignatureException exception containing all the error codes related to + * signature validation + */ @Override public boolean verifyHttpSignature( - String signature, String signatureInput, Map parameters) throws LollipopSignatureException { + String signature, String signatureInput, Map parameters) + throws LollipopSignatureException { + + /* Removed to enable multiple signature validation (if necessary) */ + parameters.remove(lollipopConsumerRequestConfig.getSignatureInputHeader()); + parameters.remove(lollipopConsumerRequestConfig.getSignatureHeader()); String lollipopKey = parameters.get(lollipopConsumerRequestConfig.getLollipopKeyHeader()); if (lollipopKey == null) { - throw new LollipopSignatureException(LollipopSignatureException.ErrorCode.MISSING_PUBLIC_KEY, + throw new LollipopSignatureException( + LollipopSignatureException.ErrorCode.MISSING_PUBLIC_KEY, "Could not find the public key within the expected header"); } @@ -72,11 +83,13 @@ public boolean verifyHttpSignature( String[] signatureInputs = signatureInput.split(","); if (signatures.length != signatureInputs.length) { - throw new LollipopSignatureException(LollipopSignatureException.ErrorCode.INVALID_SIGNATURE_NUMBER, + throw new LollipopSignatureException( + LollipopSignatureException.ErrorCode.INVALID_SIGNATURE_NUMBER, "Available signatures and signature-inputs differ in number"); } - for (int i= 0; i < signatures.length; i++) { + /* cicle through all signatures to validate */ + for (int i = 0; i < signatures.length; i++) { String signatureToProcess = signatures[i]; String signatureInputToProcess = signatureInputs[i]; @@ -84,62 +97,78 @@ public boolean verifyHttpSignature( SignatureAlgorithm signatureAlgorithm = null; /* Extract algorithm from signature input*/ - Pattern pattern = Pattern.compile(";alg=(.*?);'"); + Pattern pattern = Pattern.compile("alg=\"(.*?)\""); Matcher matcher = pattern.matcher(signatureInputToProcess); - if (matcher.find()) - { + if (matcher.find()) { try { String algToUse = matcher.group(0); - signatureAlgorithm = SignatureAlgorithm.valueOf(algToUse); + signatureAlgorithm = + SignatureAlgorithm.fromIdentifier( + algToUse.replaceAll("\"", "").split("=")[1]); + + if (signatureAlgorithm == null) { + throw new LollipopSignatureException( + LollipopSignatureException.ErrorCode.INVALID_SIGNATURE_ALG, + "Missing Signature Algorithm"); + } } catch (IndexOutOfBoundsException | IllegalStateException e) { - throw new LollipopSignatureException(LollipopSignatureException.ErrorCode - .INVALID_SIGNATURE_ALG, "Algorithm required not available", e); + throw new LollipopSignatureException( + LollipopSignatureException.ErrorCode.INVALID_SIGNATURE_ALG, + "Algorithm required not available", + e); } } var signatureContext = SignatureContext.builder() .headers(parameters) + .header("Signature-Input", signatureInputToProcess) + .header("Signature", signatureToProcess) .build(); + /* Attempt to recover a valid key from the provided jwt */ PublicKey publicKey = null; try { JWK jwk = JWK.parse(new String(Base64.getDecoder().decode(lollipopKey))); KeyType keyType = jwk.getKeyType(); if (KeyType.EC.equals(keyType)) { - publicKey = jwk.toECKey().toPublicKey(); + publicKey = jwk.toECKey().toECPublicKey(); } else if (KeyType.RSA.equals(keyType)) { - publicKey = jwk.toRSAKey().toPublicKey(); + publicKey = jwk.toRSAKey().toRSAPublicKey(); } } catch (ParseException | JOSEException e) { - throw new RuntimeException(e); + throw new LollipopSignatureException( + LollipopSignatureException.ErrorCode.INVALID_SIGNATURE_ALG, + "Missing Signature Algorithm"); } + /* Populate Visma Sign Validator*/ SignatureAlgorithm finalSignatureAlgorithm = signatureAlgorithm; PublicKey finalPublicKey = publicKey; - VerificationSpec verificationSpec = VerificationSpec - .builder() - .signatureLabel(label) - .context(signatureContext) - .publicKeyGetter(keyId -> PublicKeyInfo.builder() - .publicKey(finalPublicKey) - .algorithm(finalSignatureAlgorithm) - .build() - ) - .build(); + VerificationSpec verificationSpec = + VerificationSpec.builder() + .signatureLabel(label.trim()) + .context(signatureContext) + .publicKeyGetter( + keyId -> + PublicKeyInfo.builder() + .publicKey(finalPublicKey) + .algorithm(finalSignatureAlgorithm) + .build()) + .build(); try { verificationSpec.verify(); } catch (SignatureException e) { - throw new LollipopSignatureException(LollipopSignatureException.ErrorCode.INVALID_SIGNATURE, - "The provided signature is invalid", e); + throw new LollipopSignatureException( + LollipopSignatureException.ErrorCode.INVALID_SIGNATURE, + "The provided signature is invalid", + e); } - } return true; } - } diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java index 470a8406..604c3cd9 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java @@ -12,8 +12,9 @@ public class VismaHttpMessageVerifierFactory implements HttpMessageVerifierFacto private final String defaultEncoding; private final LollipopConsumerRequestConfig lollipopConsumerRequestConfig; - public VismaHttpMessageVerifierFactory(String defaultEncoding, - LollipopConsumerRequestConfig lollipopConsumerRequestConfig) throws Exception { + public VismaHttpMessageVerifierFactory( + String defaultEncoding, LollipopConsumerRequestConfig lollipopConsumerRequestConfig) + throws Exception { if (Charset.availableCharsets().get(defaultEncoding) == null) { throw new Exception("Unavailable Encoding: " + defaultEncoding); } diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java index ca8ce193..276ebaac 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java @@ -7,7 +7,9 @@ import lombok.SneakyThrows; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class VismaHttpMessageVerifierFactoryTest { LollipopConsumerRequestConfig lollipopConsumerRequestConfig; @@ -19,7 +21,10 @@ public void init() { @Test public void encodingInCostructorIsInvalid() { - assertThatThrownBy(() -> new VismaHttpMessageVerifierFactory("UTF-326",lollipopConsumerRequestConfig)) + assertThatThrownBy( + () -> + new VismaHttpMessageVerifierFactory( + "UTF-326", lollipopConsumerRequestConfig)) .isInstanceOfSatisfying( Exception.class, e -> assertThat(e).hasMessageContaining("Unavailable Encoding: UTF-326")); @@ -27,13 +32,19 @@ public void encodingInCostructorIsInvalid() { @Test public void encodingInCostructorIsValid() { - assertThatNoException().isThrownBy(() -> new VismaHttpMessageVerifierFactory("UTF-8",lollipopConsumerRequestConfig)); + assertThatNoException() + .isThrownBy( + () -> + new VismaHttpMessageVerifierFactory( + "UTF-8", lollipopConsumerRequestConfig)); } @SneakyThrows @Test public void instanceIsCreated() { - assertThat(new VismaHttpMessageVerifierFactory("UTF-8",lollipopConsumerRequestConfig).create()) + assertThat( + new VismaHttpMessageVerifierFactory("UTF-8", lollipopConsumerRequestConfig) + .create()) .isInstanceOf(VismaHttpMessageVerifier.class); } } diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java index 5f289824..7872ffd2 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java @@ -5,16 +5,17 @@ import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.exception.LollipopSignatureException; import java.io.UnsupportedEncodingException; +import java.util.HashMap; import java.util.Map; - import net.visma.autopay.http.digest.DigestException; import org.junit.jupiter.api.Test; public class VismaHttpMessageVerifierTest { - public VismaHttpMessageVerifier vismaDigestVerifier = new VismaHttpMessageVerifier("UTF-8", - LollipopConsumerRequestConfig.builder().build()); + public VismaHttpMessageVerifier vismaDigestVerifier = + new VismaHttpMessageVerifier("UTF-8", LollipopConsumerRequestConfig.builder().build()); @Test public void correctDigestIsVerified() { @@ -125,29 +126,206 @@ public void invalidContentEncoding() { } @Test - public void validSignatureTest() { + public void validLollipopSignatureCheckSingleEcdaSha256() { + + String signatureInput = + "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + var signature = + "sig123=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + + Map requestHeaders = + new HashMap<>( + Map.of( + "Content-Digest", + "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:", + "x-pagopa-lollipop-original-url", + "https://api-app.io.pagopa.it/first-lollipop/sign", + "x-pagopa-lollipop-original-method", + "POST", + "x-pagopa-lollipop-public-key", + "eyJrdHkiOiJFQyIsIngiOiJGcUZEd" + + "XdFZ3U0TVVYRVJQTVZMLTg1cEd2MkQzWW1MNEoxZ2ZNa2RiYzI0IiwieSI6Im" + + "hkVjBveG1XRlN4TW9KVURwZGlocjc2clM4VlJCRXFNRmViWXlBZks5LWsiLCJjcnYiO" + + "iJQLTI1NiJ9", + "Signature-Input", + signatureInput, + "Signature", + signature)); + + // execute & verify + assertThatNoException() + .isThrownBy( + () -> + vismaDigestVerifier.verifyHttpSignature( + signature, signatureInput, requestHeaders)); + } + + @Test + public void invalidLollipopSignatureCheck() { + + String signatureInput = + "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + var signature = + "sig123=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + + Map requestHeaders = + new HashMap<>( + Map.of( + "Content-Digest", + "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Za=:", + "x-pagopa-lollipop-original-url", + "https://api-app.io.pagopa.it/first-lollipop/sign", + "x-pagopa-lollipop-original-method", + "POST", + "x-pagopa-lollipop-public-key", + "eyJrdHkiOiJFQyIsIngiOiJGcUZEd" + + "XdFZ3U0TVVYRVJQTVZMLTg1cEd2MkQzWW1MNEoxZ2ZNa2RiYzI0IiwieSI6Im" + + "hkVjBveG1XRlN4TW9KVURwZGlocjc2clM4VlJCRXFNRmViWXlBZks5LWsiLCJjcnYiO" + + "iJQLTI1NiJ9", + "Signature-Input", + signatureInput, + "Signature", + signature)); + + // execute & verify + assertThatThrownBy( + () -> + vismaDigestVerifier.verifyHttpSignature( + signature, signatureInput, requestHeaders)) + .isInstanceOfSatisfying( + LollipopSignatureException.class, + e -> { + assertThat(e).hasMessageContaining("The provided signature is invalid"); + assertThat(e.getErrorCode()) + .isEqualTo( + LollipopSignatureException.ErrorCode.INVALID_SIGNATURE); + }); + } - String signatureInput = "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\" \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; - var signature = "sig123=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + @Test + public void validLollipopSignatureCheckSingleRsaSha256() { + String signatureInput = + "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678814391;nonce=\"aNonce\";" + + "alg=\"rsa-pss-sha256\";keyid=\"sha256-A3OhKGLYwSvdJ2txHi_SGQ3G-sHLh2Ibu91ErqFx_58\""; + var signature = + "sig1=:Jf7v1wqk4bWDZzS0aqbA8VIYxBD07KkrhVmf8ncqsCCpgtggKzVpuwzsxJGDaxqw1sQ/4/9q3JviW7cV0Iq1EbFPiX" + + "kW9j9F+JPNt+pPZCjTrcHzKSZ+Yz+MYttSS/umR0YdCPdkObu28HyZ1hcTgt2xSqyYpjxX9CPcjHn42tVJBF6Kfmxn" + + "AdcYH3vjFj30QPRyMUjQEH9FEQItcxP7H4P9vXsHsKi2o3NFwgl8Lq5zCOMURbM4BtgxJwVh97MJzqPVJEq3isEa60h" + + "quPIdIjPoL9tgMEZkbERHZzqg3KivS9cjdQ7VsWWdwu8S2mPbRVK7SAyhEpk+hnmpxg24Uw==:"; - Map requestHeaders = Map.of( - "Content-Digest", "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:", - "x-pagopa-lollipop-original-url", "https://api-app.io.pagopa.it/first-lollipop/sign", - "x-pagopa-lollipop-original-method", "POST", - "x-pagopa-lollipop-public-key","eyJrdHkiOiJFQyIsIngiOiJGcUZEd" + - "XdFZ3U0TVVYRVJQTVZMLTg1cEd2MkQzWW1MNEoxZ2ZNa2RiYzI0IiwieSI6Im" + - "hkVjBveG1XRlN4TW9KVURwZGlocjc2clM4VlJCRXFNRmViWXlBZks5LWsiLCJjcnYiO" + - "iJQLTI1NiJ9", - "Signature-Input", signatureInput, - "Signature", signature - ); + Map requestHeaders = + new HashMap<>( + Map.of( + "Content-Digest", + "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Za=:", + "x-pagopa-lollipop-original-url", + "https://api-app.io.pagopa.it/first-lollipop/sign", + "x-pagopa-lollipop-original-method", + "POST", + "x-pagopa-lollipop-public-key", + "eyJrdHkiOiJSU0EiLCJlIjoiQVFBQiIsImtpZCI6InRlc3Qta2V5LXJzYS1wc3MiLCJuIjoicjR0bW0zc" + + "jIwV2RfUGJxdlAxczItUUV0dnB1UmFWOFlxNDBnalVSOHkyUmp4YTZkcEcyR1hIYlBmdk0gIHM4Y3Q" + + "tTGgxR0g0NXgyOFJ3M1J5NTNtbS1vQVhqeVE4Nk9uRGtaNU44bFliZ2dENE8zdzZNNnBBdkxraGs5NU" + + "FuICBkVHJpZmJJRlBOVThQUE1PN095ckZBSHFnRHN6bmpQRm1UT3RDRWNOMloxRnBXZ2Nod3VZTFBMLV" + + "dva3FsdGQxMSAgbnFxemktYko5Y3ZTS0FEWWRVQUFONVdVdHpkcGl5NkxiVGdTeFA3b2NpVTRUbjBnNU" + + "k2YURaSjdBOEx6bzBLU3kgIFpZb0E0ODVtcWNPMEdWQWRWdzlscTRhT1Q5djZkLW5iNGJuTmtRVmtsTFE" + + "zZlZBdkptLXhkRE9wOUxDTkNONDhWICAycG5ET2tGVjYtVTluVjVveWM2WEkydyJ9", + "Signature-Input", + signatureInput, + "Signature", + signature)); // execute & verify assertThatNoException() - .isThrownBy(() -> vismaDigestVerifier.verifyHttpSignature( - signature, signatureInput, requestHeaders)); + .isThrownBy( + () -> + vismaDigestVerifier.verifyHttpSignature( + signature, signatureInput, requestHeaders)); + } + + @Test + public void validLollipopMultipleSignatureCheckEcdaSha256() { + + String signatureInput = + "sig1=(\"x-io-sign-qtspclauses\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\"," + + " sig2=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + var signature = + "sig1=:dncsEeKERA9wzxBO0vbPIueMK7Izk4zZNX4D0jI+t17XQJ5YrhumR3MGvMiyarb+B8MPqn+rbOJwZt6dV+oXFA==:," + + " sig2=:nbmFduqX8AdhXzqkFX+UIvicn3ZV5yZXqUO+3bceOT8WFPXRTVRcoOcjF+0+W5KLihAZjSW5GXSgCxVVEW8pqQ==:"; + Map requestHeaders = + new HashMap<>( + Map.of( + "X-io-sign-qtspclauses", + "anIoSignClauses", + "Content-Digest", + "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:", + "x-pagopa-lollipop-original-url", + "https://api-app.io.pagopa.it/first-lollipop/sign", + "x-pagopa-lollipop-original-method", + "POST", + "x-pagopa-lollipop-public-key", + "eyJrdHkiOiJFQyIsIngiOiJGcUZEd" + + "XdFZ3U0TVVYRVJQTVZMLTg1cEd2MkQzWW1MNEoxZ2ZNa2RiYzI0IiwieSI6Im" + + "hkVjBveG1XRlN4TW9KVURwZGlocjc2clM4VlJCRXFNRmViWXlBZks5LWsiLCJjcnYiO" + + "iJQLTI1NiJ9")); + + // execute & verify + assertThatNoException() + .isThrownBy( + () -> + vismaDigestVerifier.verifyHttpSignature( + signature, signatureInput, requestHeaders)); } + @Test + public void invalidLollipopMultipleSignatureWithLessInput() { + + String signatureInput = + "sig1=(\"x-io-sign-qtspclauses\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\"," + + " sig2=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + var signature = + "sig1=:dncsEeKERA9wzxBO0vbPIueMK7Izk4zZNX4D0jI+t17XQJ5YrhumR3MGvMiyarb+B8MPqn+rbOJwZt6dV+oXFA==:"; + + Map requestHeaders = + new HashMap<>( + Map.of( + "X-io-sign-qtspclauses", + "anIoSignClauses", + "Content-Digest", + "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:", + "x-pagopa-lollipop-original-url", + "https://api-app.io.pagopa.it/first-lollipop/sign", + "x-pagopa-lollipop-original-method", + "POST", + "x-pagopa-lollipop-public-key", + "eyJrdHkiOiJFQyIsIngiOiJGcUZEd" + + "XdFZ3U0TVVYRVJQTVZMLTg1cEd2MkQzWW1MNEoxZ2ZNa2RiYzI0IiwieSI6Im" + + "hkVjBveG1XRlN4TW9KVURwZGlocjc2clM4VlJCRXFNRmViWXlBZks5LWsiLCJjcnYiO" + + "iJQLTI1NiJ9")); + + // execute & verify + assertThatThrownBy( + () -> + vismaDigestVerifier.verifyHttpSignature( + signature, signatureInput, requestHeaders)) + .isInstanceOfSatisfying( + LollipopSignatureException.class, + e -> { + assertThat(e) + .hasMessageContaining( + "Available signatures and signature-inputs differ in" + + " number"); + assertThat(e.getErrorCode()) + .isEqualTo( + LollipopSignatureException.ErrorCode + .INVALID_SIGNATURE_NUMBER); + }); + } } From d0f16c645942163c316a3ef089830f39b8e39d37 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 13 Apr 2023 15:16:12 +0200 Subject: [PATCH 162/403] [SLS-23] Updated verification-metadata.xml --- gradle/verification-metadata.xml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 9aa9291d..89ef564c 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1,5 +1,5 @@ - + true false @@ -143,6 +143,7 @@ + @@ -210,6 +211,9 @@ + + + @@ -236,6 +240,9 @@ + + + @@ -268,6 +275,9 @@ + + + @@ -2209,12 +2219,18 @@ + + + + + + From c029d23df0feb863cec149ed64dfd64944b4519e Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 13 Apr 2023 15:20:36 +0200 Subject: [PATCH 163/403] [SLS-23] Updated verification-metadata.xml --- gradle/verification-metadata.xml | 492 +++++++++++++++++++++++++++++++ 1 file changed, 492 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 5b4ef644..a255d04b 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -125,6 +125,11 @@ + + + + + @@ -135,6 +140,16 @@ + + + + + + + + + + @@ -143,6 +158,12 @@ + + + + + + @@ -157,6 +178,16 @@ + + + + + + + + + + @@ -168,6 +199,11 @@ + + + + + @@ -201,6 +237,22 @@ + + + + + + + + + + + + + + + + @@ -212,6 +264,7 @@ + @@ -230,6 +283,22 @@ + + + + + + + + + + + + + + + + @@ -241,6 +310,7 @@ + @@ -259,6 +329,22 @@ + + + + + + + + + + + + + + + + @@ -276,6 +362,7 @@ + @@ -297,6 +384,19 @@ + + + + + + + + + + + + + @@ -307,11 +407,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -325,6 +459,16 @@ + + + + + + + + + + @@ -356,6 +500,14 @@ + + + + + + + + @@ -366,6 +518,14 @@ + + + + + + + + @@ -446,6 +606,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -651,14 +848,17 @@ + + + @@ -775,6 +975,11 @@ + + + + + @@ -865,6 +1070,22 @@ + + + + + + + + + + + + + + + + @@ -915,6 +1136,14 @@ + + + + + + + + @@ -1171,6 +1400,14 @@ + + + + + + + + @@ -1181,6 +1418,14 @@ + + + + + + + + @@ -1191,6 +1436,14 @@ + + + + + + + + @@ -1201,6 +1454,14 @@ + + + + + + + + @@ -1211,6 +1472,14 @@ + + + + + + + + @@ -1221,18 +1490,36 @@ + + + + + + + + + + + + + + + + + + @@ -1243,6 +1530,14 @@ + + + + + + + + @@ -1253,6 +1548,14 @@ + + + + + + + + @@ -1263,6 +1566,11 @@ + + + + + @@ -1279,6 +1587,14 @@ + + + + + + + + @@ -1289,12 +1605,25 @@ + + + + + + + + + + + + + @@ -1305,6 +1634,14 @@ + + + + + + + + @@ -1315,6 +1652,14 @@ + + + + + + + + @@ -1323,6 +1668,14 @@ + + + + + + + + @@ -1343,6 +1696,14 @@ + + + + + + + + @@ -1363,6 +1724,11 @@ + + + + + @@ -1405,6 +1771,14 @@ + + + + + + + + @@ -1415,6 +1789,14 @@ + + + + + + + + @@ -1495,6 +1877,14 @@ + + + + + + + + @@ -1563,6 +1953,11 @@ + + + + + @@ -1647,6 +2042,11 @@ + + + + + @@ -1927,6 +2327,14 @@ + + + + + + + + @@ -1997,6 +2405,19 @@ + + + + + + + + + + + + + @@ -2013,6 +2434,11 @@ + + + + + @@ -2243,12 +2669,20 @@ + + + + + + + + @@ -2619,6 +3053,11 @@ + + + + + @@ -2629,6 +3068,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2691,6 +3159,14 @@ + + + + + + + + @@ -2709,6 +3185,14 @@ + + + + + + + + @@ -2733,6 +3217,14 @@ + + + + + + + + From 366e6225e4d4128cca4f56523a8450dd44df1e37 Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Thu, 13 Apr 2023 15:21:20 +0200 Subject: [PATCH 164/403] Update pr_scan.yml --- .github/workflows/pr_scan.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index d89481d3..a66122b7 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -9,6 +9,8 @@ env: jobs: pr_scan: runs-on: ubuntu-latest + permissions: + packages: read steps: - name: Checkout project sources uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 From 0ec468372b2b02ef9e772dc9caef61e55d2dd1df Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Thu, 13 Apr 2023 15:25:20 +0200 Subject: [PATCH 165/403] Update pr_scan.yml --- .github/workflows/pr_scan.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index a66122b7..c49425d1 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -10,6 +10,7 @@ jobs: pr_scan: runs-on: ubuntu-latest permissions: + contents: read packages: read steps: - name: Checkout project sources From a81082bf36c76e0622962b45bb9da5bd81dd3dff Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Thu, 13 Apr 2023 15:34:06 +0200 Subject: [PATCH 166/403] Update pr_scan.yml --- .github/workflows/pr_scan.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index c49425d1..79a16f3a 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -37,3 +37,6 @@ jobs: if: always() with: sarif_file: ${{ steps.scan.outputs.sarif }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_ACTOR: ${{ secrets.GITHUB_ACTOR }} From eb37cbb04288fa567e4952b4f6e33ff12ca271be Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Thu, 13 Apr 2023 15:36:28 +0200 Subject: [PATCH 167/403] Update pr_scan.yml --- .github/workflows/pr_scan.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 79a16f3a..c61cdd6d 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -5,6 +5,8 @@ on: env: DOCKERFILE: Dockerfile.test-only + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_ACTOR: ${{ secrets.GITHUB_ACTOR }} jobs: pr_scan: @@ -37,6 +39,3 @@ jobs: if: always() with: sarif_file: ${{ steps.scan.outputs.sarif }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_ACTOR: ${{ secrets.GITHUB_ACTOR }} From 4f7d1176883f6345ed5ecc201aa9efe484d64ae4 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 13 Apr 2023 15:46:46 +0200 Subject: [PATCH 168/403] [SLS-23] Executed spotlessApply --- .../lollipop/consumer/config/LollipopConsumerRequestConfig.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index e22a2646..ac73a2be 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -14,6 +14,4 @@ public class LollipopConsumerRequestConfig { @Builder.Default private String contentDigestHeader = "content-digest"; @Builder.Default private String lollipopKeyHeader = "x-pagopa-lollipop-public-key"; @Builder.Default private boolean strictDigestVerify = false; - - } From 03d7937e6957f6c4da299b9f09604a869e352f76 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 13 Apr 2023 17:12:54 +0200 Subject: [PATCH 169/403] [SLS-24] Updated command to manage signature validation errors --- .../impl/LollipopConsumerCommandImpl.java | 9 ++++ .../HttpMessageVerificationResultCode.java | 5 +- .../service/HttpMessageVerifierService.java | 4 +- .../impl/HttpMessageVerifierServiceImpl.java | 26 +++++++--- .../impl/LollipopConsumerCommandImplTest.java | 39 +++++++++++--- .../HttpMessageVerifierServiceImplTest.java | 51 +++++++++++++++---- 6 files changed, 108 insertions(+), 26 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index e0702845..f59ad80a 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -5,6 +5,7 @@ import it.pagopa.tech.lollipop.consumer.enumeration.AssertionVerificationResultCode; import it.pagopa.tech.lollipop.consumer.enumeration.HttpMessageVerificationResultCode; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.exception.LollipopSignatureException; import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; import it.pagopa.tech.lollipop.consumer.model.CommandResult; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; @@ -80,6 +81,14 @@ private CommandResult getHttpMessageVerificationResult(LollipopConsumerRequest r e.getErrorCode(), e.getMessage()); return buildCommandResult( HttpMessageVerificationResultCode.DIGEST_VALIDATION_ERROR.name(), message); + } catch (LollipopSignatureException e) { + String message = + String.format( + "HTTP message validation failed on verifying signatures with message:" + + " %s", + e.getMessage()); + return buildCommandResult( + HttpMessageVerificationResultCode.SIGNATURE_VALIDATION_ERROR.name(), message); } catch (UnsupportedEncodingException e) { String message = String.format( diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/HttpMessageVerificationResultCode.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/HttpMessageVerificationResultCode.java index ea22ba65..9532d878 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/HttpMessageVerificationResultCode.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/HttpMessageVerificationResultCode.java @@ -9,6 +9,9 @@ public enum HttpMessageVerificationResultCode { /** Digest validation failed throwing an exception */ DIGEST_VALIDATION_ERROR, + /** Signature validation failed throwing an exception */ + SIGNATURE_VALIDATION_ERROR, + /** No supported encoding detected when encoding request body */ UNSUPPORTED_ENCODING, @@ -16,5 +19,5 @@ public enum HttpMessageVerificationResultCode { HTTP_MESSAGE_VALIDATION_FAILED, /** HTTP message validation completed successfully */ - HTTP_MESSAGE_VALIDATION_SUCCESS + HTTP_MESSAGE_VALIDATION_SUCCESS; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java index 39fb6b76..f9dce202 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/HttpMessageVerifierService.java @@ -2,6 +2,7 @@ package it.pagopa.tech.lollipop.consumer.service; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.exception.LollipopSignatureException; import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import java.io.UnsupportedEncodingException; @@ -22,5 +23,6 @@ public interface HttpMessageVerifierService { * @throws LollipopVerifierException thrown for general errors in the verification process */ boolean verifyHttpMessage(LollipopConsumerRequest request) - throws UnsupportedEncodingException, LollipopDigestException, LollipopVerifierException; + throws UnsupportedEncodingException, LollipopDigestException, LollipopVerifierException, + LollipopSignatureException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java index 410bfaa6..286ea7c6 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImpl.java @@ -3,12 +3,14 @@ import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.exception.LollipopSignatureException; import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; import java.io.UnsupportedEncodingException; import java.util.Arrays; +import java.util.HashMap; import java.util.Locale; import java.util.Map; import javax.inject.Inject; @@ -32,8 +34,8 @@ public HttpMessageVerifierServiceImpl( */ @Override public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest) - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + LollipopSignatureException { Map headerParams = lollipopConsumerRequest.getHeaderParams(); @@ -72,7 +74,7 @@ public boolean verifyHttpMessage(LollipopConsumerRequest lollipopConsumerRequest } } - return verifyHttpSignature(lollipopConsumerRequest); + return verifyHttpSignature(signature, signatureInput, headerParams); } /** @@ -128,8 +130,20 @@ private boolean verifyContentDigest( return httpMessageVerifier.verifyDigest(contentDigest, requestBody, contentEncoding); } - /** TODO: stub */ - private boolean verifyHttpSignature(LollipopConsumerRequest lollipopConsumerRequest) { - return true; + /** + * @param signature + * @param signatureInput + * @param headerParams + * @return + * @throws LollipopSignatureException + */ + private boolean verifyHttpSignature( + String signature, String signatureInput, Map headerParams) + throws LollipopSignatureException { + + HashMap headersToProcess = new HashMap<>(headerParams); + headersToProcess.remove(lollipopConsumerRequestConfig.getSignatureHeader()); + headersToProcess.remove(lollipopConsumerRequestConfig.getSignatureInputHeader()); + return httpMessageVerifier.verifyHttpSignature(signature, signatureInput, headersToProcess); } } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java index 7f943d56..05315ea4 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -8,6 +8,7 @@ import it.pagopa.tech.lollipop.consumer.enumeration.AssertionVerificationResultCode; import it.pagopa.tech.lollipop.consumer.enumeration.HttpMessageVerificationResultCode; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.exception.LollipopSignatureException; import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; import it.pagopa.tech.lollipop.consumer.model.CommandResult; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; @@ -36,8 +37,8 @@ void beforeAll() { @Test void failedHttpMessageValidationThrowDigestException() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + LollipopSignatureException { doThrow( new LollipopDigestException( @@ -56,6 +57,28 @@ void failedHttpMessageValidationThrowDigestException() .validateLollipop(any(LollipopConsumerRequest.class)); } + @Test + void failedHttpMessageValidationThrowSignatureException() + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + LollipopSignatureException { + + doThrow( + new LollipopSignatureException( + LollipopSignatureException.ErrorCode.INVALID_SIGNATURE, "error")) + .when(messageVerifierServiceMock) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); + + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + + Assertions.assertEquals( + HttpMessageVerificationResultCode.SIGNATURE_VALIDATION_ERROR.name(), + commandResult.getResultCode()); + + verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock, never()) + .validateLollipop(any(LollipopConsumerRequest.class)); + } + @SneakyThrows @Test void failedHttpMessageValidationThrowUnsupportedEncodingException() { @@ -77,8 +100,8 @@ void failedHttpMessageValidationThrowUnsupportedEncodingException() { @Test void failedHttpMessageValidationWithoutThrowingException() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + LollipopSignatureException { doReturn(false) .when(messageVerifierServiceMock) @@ -97,8 +120,8 @@ void failedHttpMessageValidationWithoutThrowingException() @Test void failedAssertionValidationWithoutThrowingException() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + LollipopSignatureException { doReturn(true) .when(messageVerifierServiceMock) @@ -119,8 +142,8 @@ void failedAssertionValidationWithoutThrowingException() @Test void successLollipopRequestValidation() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + LollipopSignatureException { doReturn(true) .when(messageVerifierServiceMock) diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java index 61ef2e7b..01c8e93e 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java @@ -6,11 +6,13 @@ import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; +import it.pagopa.tech.lollipop.consumer.exception.LollipopSignatureException; import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import java.io.UnsupportedEncodingException; import java.util.HashMap; +import java.util.concurrent.atomic.AtomicBoolean; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -18,10 +20,19 @@ class HttpMessageVerifierServiceImplTest { + final String VALID_SIGNATURE_INPUT = + "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" " + + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" + + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; + final String VALID_SIGNATURE = + "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + + final String INVALID_SIGNATURE = + "sig1=:aTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + final String VALID_DIGEST = "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw="; final String VALID_PAYLOAD = "a valid message payload"; final String INVALID_PAYLOAD = "an invalid payload"; - final String INVALID_ENCODING = "UTF-326"; final String VALID_ENCODING = "UTF-8"; private LollipopConsumerRequestConfig httpMessageVerifierConfig; @@ -42,13 +53,25 @@ public HttpMessageVerifierServiceImplTest() { } @BeforeEach - public void beforeEach() throws LollipopDigestException, UnsupportedEncodingException { + public void beforeEach() + throws LollipopDigestException, UnsupportedEncodingException, + LollipopSignatureException { Mockito.reset(httpMessageVerifier); when(httpMessageVerifier.verifyDigest( Mockito.eq(VALID_DIGEST), Mockito.eq(VALID_PAYLOAD), Mockito.eq(VALID_ENCODING))) .thenReturn(true); + when(httpMessageVerifier.verifyHttpSignature( + Mockito.eq(VALID_SIGNATURE), + Mockito.eq(VALID_SIGNATURE_INPUT), + Mockito.any())) + .thenReturn(true); + when(httpMessageVerifier.verifyHttpSignature( + Mockito.eq(INVALID_SIGNATURE), + Mockito.eq(VALID_SIGNATURE_INPUT), + Mockito.any())) + .thenReturn(false); when(httpMessageVerifier.verifyDigest( Mockito.eq(VALID_DIGEST), Mockito.eq(INVALID_PAYLOAD), @@ -182,19 +205,27 @@ public void requestWithoutSignatureInputToValidateThrowsException() { }); } + @Test + public void requestWithInvalidSignatureRetunsFalse() { + AtomicBoolean result = new AtomicBoolean(false); + LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); + lollipopConsumerRequest.getHeaderParams().put("Signature", INVALID_SIGNATURE); + assertThatNoException() + .isThrownBy( + () -> + result.set( + httpMessageVerifierService.verifyHttpMessage( + lollipopConsumerRequest))); + assertThat(result).isFalse(); + } + private LollipopConsumerRequest getLollipopConsumerRequest() { HashMap lollipopHeaderParams = new HashMap<>(); lollipopHeaderParams.put("Content-Digest", VALID_DIGEST); lollipopHeaderParams.put("Content-Encoding", VALID_ENCODING); - lollipopHeaderParams.put( - "Signature-Input", - "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" " - + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" - + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"); - lollipopHeaderParams.put( - "Signature", - "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"); + lollipopHeaderParams.put("Signature-Input", VALID_SIGNATURE_INPUT); + lollipopHeaderParams.put("Signature", VALID_SIGNATURE); return LollipopConsumerRequest.builder() .requestBody(VALID_PAYLOAD) From 9025f6a69464c92ad6452596507de1c88d76c7c2 Mon Sep 17 00:00:00 2001 From: giomella Date: Fri, 14 Apr 2023 10:15:54 +0200 Subject: [PATCH 170/403] [SLS-21] integrated assertion period, user id and thumbprint validation in the assertion verify flow. --- core/build.gradle | 1 + .../impl/LollipopConsumerCommandImpl.java | 20 +- .../config/LollipopConsumerRequestConfig.java | 17 +- ...lipopConsumerRequestValidationService.java | 87 ++++---- .../enumeration/AssertionRefAlgorithms.java | 29 +++ ...ertionTypeEnum.java => AssertionType.java} | 2 +- .../AssertionVerificationResultCode.java | 20 ++ ...odEnum.java => LollipopRequestMethod.java} | 2 +- ...ion.java => AssertionPeriodException.java} | 14 +- .../AssertionThumbprintException.java | 52 +++++ .../exception/AssertionUserIdException.java | 51 +++++ .../ErrorRetrievingAssertionException.java | 51 +++++ ...ipopRequestContentValidationException.java | 78 +++++++ .../exception/LollipopVerifierException.java | 25 +-- .../service/AssertionVerifierService.java | 15 +- .../impl/AssertionVerifierServiceImpl.java | 198 ++++++++++++++---- 16 files changed, 537 insertions(+), 125 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java rename core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/{AssertionTypeEnum.java => AssertionType.java} (79%) rename core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/{LollipopMethodEnum.java => LollipopRequestMethod.java} (80%) rename core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/{LollipopValidationException.java => AssertionPeriodException.java} (73%) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionUserIdException.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingAssertionException.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java diff --git a/core/build.gradle b/core/build.gradle index f570fbda..b13a86e8 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -36,6 +36,7 @@ dependencies { implementation 'javax.inject:javax.inject:1' implementation 'com.typesafe:config:1.4.2' implementation 'javax.inject:javax.inject:1' + implementation 'com.nimbusds:nimbus-jose-jwt:9.31' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.mockito:mockito-core:5.2.0' diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index e0702845..b396e5c7 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -4,8 +4,7 @@ import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionVerificationResultCode; import it.pagopa.tech.lollipop.consumer.enumeration.HttpMessageVerificationResultCode; -import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; -import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; +import it.pagopa.tech.lollipop.consumer.exception.*; import it.pagopa.tech.lollipop.consumer.model.CommandResult; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; @@ -55,7 +54,22 @@ public CommandResult doExecute(LollipopConsumerRequest request) { } private CommandResult getAssertionVerificationResult(LollipopConsumerRequest request) { - boolean result = assertionVerifierService.validateLollipop(request); + boolean result; + try { + result = assertionVerifierService.validateLollipop(request); + } catch (ErrorRetrievingAssertionException e) { + String message = String.format("Cannot obtain the assertion, validation failed with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); + return buildCommandResult(AssertionVerificationResultCode.ERROR_RETRIEVING_ASSERTION.name(), message); + } catch (AssertionPeriodException e) { + String message = String.format("Assertion validation failed on verifying period with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); + return buildCommandResult(AssertionVerificationResultCode.PERIOD_VALIDATION_ERROR.name(), message); + } catch (AssertionThumbprintException e) { + String message = String.format("Assertion validation failed on verifying thumbprint with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); + return buildCommandResult(AssertionVerificationResultCode.THUMBPRINT_VALIDATION_ERROR.name(), message); + } catch (AssertionUserIdException e) { + String message = String.format("Assertion validation failed on verifying user id with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); + return buildCommandResult(AssertionVerificationResultCode.USER_ID_VALIDATION_ERROR.name(), message); + } if (!result) { return buildCommandResult( diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index 26e62488..4cb1ab4f 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -8,12 +8,13 @@ @Data public class LollipopConsumerRequestConfig { + @Builder.Default private boolean strictDigestVerify = false; + + //request headers @Builder.Default private String signatureHeader = "signature"; @Builder.Default private String signatureInputHeader = "signature-input"; @Builder.Default private String contentEncodingHeader = "content-encoding"; @Builder.Default private String contentDigestHeader = "content-digest"; - @Builder.Default private boolean strictDigestVerify = false; - @Builder.Default private String originalMethodHeader = "x-pagopa-lollipop-original-method"; @Builder.Default private String originalURLHeader = "x-pagopa-lollipop-original-url"; @Builder.Default private String assertionRefHeader = "x-pagopa-lollipop-assertion-ref"; @@ -23,6 +24,16 @@ public class LollipopConsumerRequestConfig { @Builder.Default private String authJWTHeader = "x-pagopa-lollipop-auth-jwt"; @Builder.Default private String expectedFirstLcOriginalMethod = "POST"; - @Builder.Default private String expectedFirstLcOriginalUrl = " https://api-app.io.pagopa.it/first-lollipop/sign"; + @Builder.Default private String expectedFirstLcOriginalUrl = "https://api-app.io.pagopa.it/first-lollipop/sign"; + + // assertion validation parameters + @Builder.Default private int assertionExpireInDays = 30; + @Builder.Default private String assertionNotBeforeDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; + @Builder.Default private String samlNamespaceAssertion = "urn:oasis:names:tc:SAML:2.0:assertion"; + @Builder.Default private String assertionNotBeforeTag = "Conditions"; + @Builder.Default private String assertionFiscalCodeTag = "Attribute"; + @Builder.Default private String assertionInResponseToTag = "SubjectConfirmationData"; + + } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java index c8801d21..38a3ba55 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java @@ -1,9 +1,10 @@ package it.pagopa.tech.lollipop.consumer.config.service; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; -import it.pagopa.tech.lollipop.consumer.enumeration.AssertionTypeEnum; -import it.pagopa.tech.lollipop.consumer.enumeration.LollipopMethodEnum; -import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; +import it.pagopa.tech.lollipop.consumer.enumeration.AssertionRefAlgorithms; +import it.pagopa.tech.lollipop.consumer.enumeration.AssertionType; +import it.pagopa.tech.lollipop.consumer.enumeration.LollipopRequestMethod; +import it.pagopa.tech.lollipop.consumer.exception.LollipopRequestContentValidationException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import java.util.Map; @@ -11,10 +12,18 @@ public class LollipopConsumerRequestValidationService { - public static boolean validateLollipopConsumerConfig(LollipopConsumerRequest request, LollipopConsumerRequestConfig config) throws LollipopVerifierException { + public static boolean validateLollipopConsumerConfig(LollipopConsumerRequest request, LollipopConsumerRequestConfig config) throws LollipopRequestContentValidationException { Map headerParams = request.getHeaderParams(); + String originalMethod = headerParams.get(config.getOriginalMethodHeader()); + String originalUrl = headerParams.get(config.getOriginalURLHeader()); + + if (!originalMethod.equals(config.getExpectedFirstLcOriginalMethod()) && !originalUrl.equals(config.getExpectedFirstLcOriginalUrl())) { + String errMsg = String.format("Unexpected original method and/or original url: %s, %s", originalMethod, originalUrl); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_METHOD_OR_URL, errMsg); + } + validatePublicKey(headerParams.get(config.getPublicKeyHeader())); validateAssertionRefHeader(headerParams.get(config.getAssertionRefHeader())); @@ -29,13 +38,13 @@ public static boolean validateLollipopConsumerConfig(LollipopConsumerRequest req return true; } - private static void validatePublicKey(String publicKey) throws LollipopVerifierException { + private static void validatePublicKey(String publicKey) throws LollipopRequestContentValidationException { if (publicKey == null ) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_PUBLIC_KEY, "Missing Public Key Header"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_PUBLIC_KEY, "Missing Public Key Header"); } if (isNotValidPublicKey(publicKey)) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_PUBLIC_KEY, "Invalid Public Key Header value"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_PUBLIC_KEY, "Invalid Public Key Header value"); } } @@ -44,35 +53,35 @@ private static boolean isNotValidPublicKey(String publicKey) { return false; } - private static void validateAssertionRefHeader(String assertionRef) throws LollipopVerifierException { + private static void validateAssertionRefHeader(String assertionRef) throws LollipopRequestContentValidationException { if (assertionRef == null ) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_ASSERTION_REF, "Missing AssertionRef Header"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_REF, "Missing AssertionRef Header"); } if (isNotValidAssertionRef(assertionRef)) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ASSERTION_REF, "Invalid AssertionRef Header value"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_REF, "Invalid AssertionRef Header value"); } } private static boolean isNotValidAssertionRef(String signature) { - boolean matchesSHA26 = Pattern.compile("^(sha256-[A-Za-z0-9-_=]{1,44})$").matcher(signature).matches(); - boolean matchesSHA384 = Pattern.compile("^(sha384-[A-Za-z0-9-_=]{1,66})$").matcher(signature).matches(); - boolean matchesSHA512 = Pattern.compile("^(sha512-[A-Za-z0-9-_=]{1,88})$").matcher(signature).matches(); - return !matchesSHA26 && !matchesSHA384 && !matchesSHA512; + boolean matchesSHA256 = AssertionRefAlgorithms.SHA256.getPattern().matcher(signature).matches(); + boolean matchesSHA384 = AssertionRefAlgorithms.SHA384.getPattern().matcher(signature).matches(); + boolean matchesSHA512 = AssertionRefAlgorithms.SHA512.getPattern().matcher(signature).matches(); + return !matchesSHA256 && !matchesSHA384 && !matchesSHA512; } - private static void validateAssertionTypeHeader(String assertionType) throws LollipopVerifierException { + private static void validateAssertionTypeHeader(String assertionType) throws LollipopRequestContentValidationException { if (assertionType == null ) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_ASSERTION_TYPE, "Missing Assertion Type Header"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_TYPE, "Missing Assertion Type Header"); } if ((!isAssertionTypeSupported(assertionType))) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ASSERTION_TYPE, "Invalid Assertion Type Header value, type not supported"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_TYPE, "Invalid Assertion Type Header value, type not supported"); } } - public static boolean isAssertionTypeSupported(String assertionType) { - for (AssertionTypeEnum supportedType : AssertionTypeEnum.values()) { + private static boolean isAssertionTypeSupported(String assertionType) { + for (AssertionType supportedType : AssertionType.values()) { if (supportedType.name().equals(assertionType)) { return true; } @@ -80,13 +89,13 @@ public static boolean isAssertionTypeSupported(String assertionType) { return false; } - private static void validateUserIdHeader(String userId) throws LollipopVerifierException { + private static void validateUserIdHeader(String userId) throws LollipopRequestContentValidationException { if (userId == null ) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_USER_ID, "Missing User Id Header"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_USER_ID, "Missing User Id Header"); } if ((isNotValidFiscalCode(userId))) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_USER_ID, "Invalid User Id Header value, type not supported"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_USER_ID, "Invalid User Id Header value, type not supported"); } } @@ -94,28 +103,28 @@ private static boolean isNotValidFiscalCode(String userId) { return !Pattern.compile("^[A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]$").matcher(userId).matches(); } - private static void validateAuthJWTHeader(String authJWT) throws LollipopVerifierException { + private static void validateAuthJWTHeader(String authJWT) throws LollipopRequestContentValidationException { if (authJWT == null ) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_AUTH_JWT, "Missing Auth JWT Header"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_AUTH_JWT, "Missing Auth JWT Header"); } if (authJWT.isBlank()) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_AUTH_JWT, "Invalid Auth JWT Header value, cannot be empty"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_AUTH_JWT, "Invalid Auth JWT Header value, cannot be empty"); } } - private static void validateOriginalMethodHeader(String originalMethod) throws LollipopVerifierException { + private static void validateOriginalMethodHeader(String originalMethod) throws LollipopRequestContentValidationException { if (originalMethod == null ) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_ORIGINAL_METHOD, "Missing Original Method Header"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_METHOD, "Missing Original Method Header"); } if (!isRequestMethodSupported(originalMethod)) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ORIGINAL_METHOD, "Invalid Original Method Header value, method not supported"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_METHOD, "Invalid Original Method Header value, method not supported"); } } - public static boolean isRequestMethodSupported(String originalMethod) { - for (LollipopMethodEnum supportedType : LollipopMethodEnum.values()) { + private static boolean isRequestMethodSupported(String originalMethod) { + for (LollipopRequestMethod supportedType : LollipopRequestMethod.values()) { if (supportedType.name().equals(originalMethod)) { return true; } @@ -123,13 +132,13 @@ public static boolean isRequestMethodSupported(String originalMethod) { return false; } - private static void validateOriginalURLHeader(String originalURL) throws LollipopVerifierException { + private static void validateOriginalURLHeader(String originalURL) throws LollipopRequestContentValidationException { if (originalURL == null ) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_ORIGINAL_URL, "Missing Original URL Header"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_URL, "Missing Original URL Header"); } if (isNotValidOriginalURL(originalURL)) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ORIGINAL_URL, "Invalid Original URL Header value"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_URL, "Invalid Original URL Header value"); } } @@ -137,13 +146,13 @@ private static boolean isNotValidOriginalURL(String originalURL) { return !Pattern.compile("^https://").matcher(originalURL).matches(); } - private static void validateSignatureInputHeader(String signatureInput) throws LollipopVerifierException { + private static void validateSignatureInputHeader(String signatureInput) throws LollipopRequestContentValidationException { if (signatureInput == null ) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE_INPUT, "Missing Signature Input Header"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE_INPUT, "Missing Signature Input Header"); } if (isNotValidSignatureInput(signatureInput)) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ORIGINAL_URL, "Invalid Signature Input Header value"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE_INPUT, "Invalid Signature Input Header value"); } } @@ -151,13 +160,13 @@ private static boolean isNotValidSignatureInput(String signatureInput) { return !Pattern.compile("^(((sig[0-9]+)=[^,]*?)(, ?)?)+$").matcher(signatureInput).matches(); } - private static void validateSignatureHeader(String signature) throws LollipopVerifierException { + private static void validateSignatureHeader(String signature) throws LollipopRequestContentValidationException { if (signature == null ) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE, "Missing Signature Header"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE, "Missing Signature Header"); } if (isNotValidSignature(signature)) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_SIGNATURE_HEADER, "Invalid Signature Header value"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE_HEADER, "Invalid Signature Header value"); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java new file mode 100644 index 00000000..06e6f417 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java @@ -0,0 +1,29 @@ +package it.pagopa.tech.lollipop.consumer.enumeration; + +import java.util.regex.Pattern; + +/** + * Supported AssertionRef algorithms + */ +public enum AssertionRefAlgorithms { + + SHA256("sha256", Pattern.compile("^(sha256-[A-Za-z0-9-_=]{1,44})$")), + SHA384("sha384", Pattern.compile("^(sha384-[A-Za-z0-9-_=]{1,66})$")), + SHA512("sha512", Pattern.compile("^(sha512-[A-Za-z0-9-_=]{1,88})$")); + + private final String algorithmName; + private final Pattern pattern; + + AssertionRefAlgorithms(String algorithmName, Pattern pattern) { + this.algorithmName = algorithmName; + this.pattern = pattern; + } + + public Pattern getPattern() { + return pattern; + } + + public String getAlgorithmName() { + return algorithmName; + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionTypeEnum.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java similarity index 79% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionTypeEnum.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java index e7cae454..7a47cd22 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionTypeEnum.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java @@ -3,7 +3,7 @@ /** * Supported assertion type */ -public enum AssertionTypeEnum { +public enum AssertionType { SAML, //TODO: OIDC diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java index eb4c55da..e7cd1d0b 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java @@ -4,6 +4,26 @@ /** Result codes to classify Saml assertion validation */ public enum AssertionVerificationResultCode { + /** + * Saml assertion validation failed on retrieving the assertion + */ + ERROR_RETRIEVING_ASSERTION, + + /** + * Saml assertion validation failed on period validation + */ + PERIOD_VALIDATION_ERROR, + + /** + * Saml assertion validation failed on user id validation + */ + USER_ID_VALIDATION_ERROR, + + /** + * Saml assertion validation failed on thumbpriint validation + */ + THUMBPRINT_VALIDATION_ERROR, + /** Saml assertion validation failed without throwing an exception */ ASSERTION_VERIFICATION_FAILED, diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopMethodEnum.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopRequestMethod.java similarity index 80% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopMethodEnum.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopRequestMethod.java index 66069d8f..ed098922 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopMethodEnum.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopRequestMethod.java @@ -3,7 +3,7 @@ /** * Supported Lollipop request methods */ -public enum LollipopMethodEnum { +public enum LollipopRequestMethod { GET, POST, PUT, diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionPeriodException.java similarity index 73% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionPeriodException.java index 9cc2230d..c9c6dfc6 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionPeriodException.java @@ -3,10 +3,9 @@ import java.util.Objects; /** - * Thrown in case of problems when computing or verifying lollipop request through the - * assertion flow + * Thrown in case of problems when verifying assertion period */ -public class LollipopValidationException extends Exception { +public class AssertionPeriodException extends Exception { /** Error code of this exception */ private final ErrorCode errorCode; @@ -17,7 +16,7 @@ public class LollipopValidationException extends Exception { * @param errorCode Error code * @param message Detail message */ - public LollipopValidationException(ErrorCode errorCode, String message) { + public AssertionPeriodException(ErrorCode errorCode, String message) { super(message); this.errorCode = Objects.requireNonNull(errorCode); } @@ -29,7 +28,7 @@ public LollipopValidationException(ErrorCode errorCode, String message) { * @param message Detail message * @param cause Exception causing the constructed one */ - public LollipopValidationException(ErrorCode errorCode, String message, Throwable cause) { + public AssertionPeriodException(ErrorCode errorCode, String message, Throwable cause) { super(message, cause); this.errorCode = Objects.requireNonNull(errorCode); } @@ -45,6 +44,7 @@ public ErrorCode getErrorCode() { /** Error codes to classify Lollipop Request Exceptions */ public enum ErrorCode { - UNEXPECTED_METHOD_OR_URL + ERROR_PARSING_ASSERTION_NOT_BEFORE_DATE, + INVALID_ASSERTION_PERIOD } -} \ No newline at end of file +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java new file mode 100644 index 00000000..4f23f03d --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java @@ -0,0 +1,52 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +import java.util.Objects; + +/** + * Thrown in case of problems when verifying assertion thumbprint + */ +public class AssertionThumbprintException extends Exception { + + /** Error code of this exception */ + private final ErrorCode errorCode; + + /** + * Constructs new exception with provided error code and message + * + * @param errorCode Error code + * @param message Detail message + */ + public AssertionThumbprintException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Constructs new exception with provided error code, message and cause + * + * @param errorCode Error code + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public AssertionThumbprintException(ErrorCode errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Returns error code + * + * @return Error code of this exception + */ + public ErrorCode getErrorCode() { + return errorCode; + } + + /** Error codes to classify Lollipop Request Exceptions */ + public enum ErrorCode { + IN_RESPONSE_TO_FIELD_NOT_FOUND, + IN_RESPONSE_TO_NOT_VALID, + ERROR_CALCULATING_ASSERTION_THUMBPRINT, + INVALID_IN_RESPONSE_TO + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionUserIdException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionUserIdException.java new file mode 100644 index 00000000..106b8384 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionUserIdException.java @@ -0,0 +1,51 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +import java.util.Objects; + +/** + * Thrown in case of problems when verifying assertion user id + */ +public class AssertionUserIdException extends Exception { + + + /** Error code of this exception */ + private final ErrorCode errorCode; + + /** + * Constructs new exception with provided error code and message + * + * @param errorCode Error code + * @param message Detail message + */ + public AssertionUserIdException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Constructs new exception with provided error code, message and cause + * + * @param errorCode Error code + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public AssertionUserIdException(ErrorCode errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Returns error code + * + * @return Error code of this exception + */ + public ErrorCode getErrorCode() { + return errorCode; + } + + /** Error codes to classify Lollipop Request Exceptions */ + public enum ErrorCode { + INVALID_USER_ID, + FISCAL_CODE_FIELD_NOT_FOUND + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingAssertionException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingAssertionException.java new file mode 100644 index 00000000..7cd1f385 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingAssertionException.java @@ -0,0 +1,51 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +import java.util.Objects; + +/** + * Thrown in case of problems on retrieving the assertion + */ +public class ErrorRetrievingAssertionException extends Exception { + + /** Error code of this exception */ + private final ErrorCode errorCode; + + /** + * Constructs new exception with provided error code and message + * + * @param errorCode Error code + * @param message Detail message + */ + public ErrorRetrievingAssertionException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Constructs new exception with provided error code, message and cause + * + * @param errorCode Error code + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public ErrorRetrievingAssertionException(ErrorCode errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Returns error code + * + * @return Error code of this exception + */ + public ErrorCode getErrorCode() { + return errorCode; + } + + /** Error codes to classify Lollipop Request Exceptions */ + public enum ErrorCode { + SAML_ASSERTION_NOT_FOUND, + OIDC_TYPE_NOT_SUPPORTED, + ERROR_PARSING_ASSERTION + } +} \ No newline at end of file diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java new file mode 100644 index 00000000..a9facc20 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java @@ -0,0 +1,78 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +import java.util.Objects; + +/** + * Thrown in case of problem during Lollipop request header and body validation + */ +public class LollipopRequestContentValidationException extends Exception { + + + /** Error code of this exception */ + private final ErrorCode errorCode; + + /** + * Constructs new exception with provided error code and message + * + * @param errorCode Error code + * @param message Detail message + */ + public LollipopRequestContentValidationException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Constructs new exception with provided error code, message and cause + * + * @param errorCode Error code + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public LollipopRequestContentValidationException(ErrorCode errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Returns error code + * + * @return Error code of this exception + */ + public ErrorCode getErrorCode() { + return errorCode; + } + + /** Error codes to classify Lollipop Request Exceptions */ + public enum ErrorCode { + UNEXPECTED_METHOD_OR_URL, + + + MISSING_SIGNATURE, + INVALID_SIGNATURE_HEADER, + + MISSING_SIGNATURE_INPUT, + INVALID_SIGNATURE_INPUT, + + MISSING_ASSERTION_REF, + INVALID_ASSERTION_REF, + + MISSING_ASSERTION_TYPE, + INVALID_ASSERTION_TYPE, + + MISSING_USER_ID, + INVALID_USER_ID, + + MISSING_AUTH_JWT, + INVALID_AUTH_JWT, + + MISSING_ORIGINAL_METHOD, + INVALID_ORIGINAL_METHOD, + + MISSING_ORIGINAL_URL, + INVALID_ORIGINAL_URL, + + MISSING_PUBLIC_KEY, + INVALID_PUBLIC_KEY + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java index 7ea6685d..04e98686 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java @@ -47,30 +47,7 @@ public ErrorCode getErrorCode() { /** Error codes to classify Lollipop Request Exceptions */ public enum ErrorCode { MISSING_SIGNATURE, - INVALID_SIGNATURE_HEADER, - MISSING_SIGNATURE_INPUT, - INVALID_SIGNATURE_INPUT, - - MISSING_ASSERTION_REF, - INVALID_ASSERTION_REF, - - MISSING_ASSERTION_TYPE, - INVALID_ASSERTION_TYPE, - - MISSING_USER_ID, - INVALID_USER_ID, - - MISSING_AUTH_JWT, - INVALID_AUTH_JWT, - - MISSING_ORIGINAL_METHOD, - INVALID_ORIGINAL_METHOD, - - MISSING_ORIGINAL_URL, - INVALID_ORIGINAL_URL, - - MISSING_PUBLIC_KEY, - INVALID_PUBLIC_KEY + MISSING_SIGNATURE_INPUT } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java index cc555fae..b5cb0a1b 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java @@ -1,7 +1,10 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service; -import it.pagopa.tech.lollipop.consumer.exception.LollipopValidationException; +import it.pagopa.tech.lollipop.consumer.exception.AssertionPeriodException; +import it.pagopa.tech.lollipop.consumer.exception.AssertionThumbprintException; +import it.pagopa.tech.lollipop.consumer.exception.AssertionUserIdException; +import it.pagopa.tech.lollipop.consumer.exception.ErrorRetrievingAssertionException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; /** @@ -14,8 +17,12 @@ public interface AssertionVerifierService { * Validates Lollipop request Assertion, using the assertion-ref within the request header * params * - * @param request - * @return + * @param request the Lollipop request + * @return true if the assertion is valid + * @throws ErrorRetrievingAssertionException thrown for general errors in the verification process + * @throws AssertionPeriodException thrown for error in assertion period validation + * @throws AssertionThumbprintException thrown for error in assertion thumbprint validation + * @throws AssertionUserIdException thrown for error in user id validation */ - boolean validateLollipop(LollipopConsumerRequest request) throws LollipopValidationException; + boolean validateLollipop(LollipopConsumerRequest request) throws ErrorRetrievingAssertionException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index 4c41d28a..b1d0d8de 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -1,20 +1,27 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service.impl; +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.jwk.JWK; +import com.nimbusds.jose.jwk.ThumbprintUtils; +import com.nimbusds.jose.util.Base64URL; import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; -import it.pagopa.tech.lollipop.consumer.exception.LollipopValidationException; +import it.pagopa.tech.lollipop.consumer.enumeration.AssertionRefAlgorithms; +import it.pagopa.tech.lollipop.consumer.exception.*; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; 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; import javax.inject.Inject; +import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -23,86 +30,114 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Locale; import java.util.Map; import java.util.concurrent.TimeUnit; -import java.util.regex.Pattern; +/** + * Standard implementation of {@link AssertionVerifierService} + */ public class AssertionVerifierServiceImpl implements AssertionVerifierService { private final IdpCertProvider idpCertProvider; private final AssertionService assertionService; - private final LollipopConsumerRequestConfig lollipopConsumerRequestConfig; + private final LollipopConsumerRequestConfig lollipopRequestConfig; + private static final String IN_RESPONSE_TO = "InResponseTo"; @Inject - public AssertionVerifierServiceImpl(IdpCertProvider idpCertProvider, AssertionService assertionService, LollipopConsumerRequestConfig lollipopConsumerRequestConfig) { + public AssertionVerifierServiceImpl(IdpCertProvider idpCertProvider, AssertionService assertionService, LollipopConsumerRequestConfig lollipopRequestConfig) { this.idpCertProvider = idpCertProvider; this.assertionService = assertionService; - this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; + this.lollipopRequestConfig = lollipopRequestConfig; } + /** + * @see AssertionVerifierService#validateLollipop(LollipopConsumerRequest) + * + */ @Override - public boolean validateLollipop(LollipopConsumerRequest request) throws LollipopValidationException { - + public boolean validateLollipop(LollipopConsumerRequest request) throws ErrorRetrievingAssertionException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException { Map headerParams = request.getHeaderParams(); - String originalMethod = headerParams.get(lollipopConsumerRequestConfig.getOriginalMethodHeader()); - String originalUrl = headerParams.get(lollipopConsumerRequestConfig.getOriginalURLHeader()); + SamlAssertion assertion = getAssertion(headerParams.get(lollipopRequestConfig.getAuthJWTHeader()), headerParams.get(lollipopRequestConfig.getAssertionRefHeader())); + Document assertionDoc = buildDocumentFromAssertion(assertion); + + boolean isAssertionPeriodValid = validateAssertionPeriod(assertionDoc); + if (!isAssertionPeriodValid) { + throw new AssertionPeriodException(AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, "The assertion has expired"); + } - if (!originalMethod.equals(lollipopConsumerRequestConfig.getExpectedFirstLcOriginalMethod()) && !originalUrl.equals(lollipopConsumerRequestConfig.getExpectedFirstLcOriginalUrl())) { - String errMsg = String.format("Unexpected original method and/or original url: %s, %s", originalMethod, originalUrl); - throw new LollipopValidationException(LollipopValidationException.ErrorCode.UNEXPECTED_METHOD_OR_URL, errMsg); + boolean isUserIdValid = validateUserId(request, assertionDoc); + if (!isUserIdValid) { + throw new AssertionUserIdException(AssertionUserIdException.ErrorCode.INVALID_USER_ID, "The user id in the assertion does not match the request header"); } + boolean isInResponseToValid = validateInResponseTo(request, assertionDoc); + if (!isInResponseToValid) { + throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.INVALID_IN_RESPONSE_TO, "The hash of provided public key do not match the InResponseTo in the assertion"); + } return true; } - private SamlAssertion getAssertion(String jwt, String assertionRef) { - return null; + private SamlAssertion getAssertion(String jwt, String assertionRef) throws ErrorRetrievingAssertionException { + try { + return assertionService.getAssertion(jwt, assertionRef); + } catch (OidcAssertionNotSupported e) { + throw new ErrorRetrievingAssertionException(ErrorRetrievingAssertionException.ErrorCode.OIDC_TYPE_NOT_SUPPORTED, e.getMessage(), e); + } catch (LollipopAssertionNotFoundException e) { + throw new ErrorRetrievingAssertionException(ErrorRetrievingAssertionException.ErrorCode.SAML_ASSERTION_NOT_FOUND, e.getMessage(), e); + } + } - private boolean validateAssertionPeriod(String notBefore) throws ParseException { - long notBeforeMilliseconds = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse(notBefore).getTime(); //TODO configurazione format date + private boolean validateAssertionPeriod(Document assertionDoc) throws AssertionPeriodException { + NodeList listElements = assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionNotBeforeDateFormat()); + if (listElements == null || listElements.getLength() <= 0) { + return false; + } + String notBefore = listElements.item(0).getAttributes().getNamedItem("NotBefore").getNodeValue(); + long notBeforeMilliseconds; + try { + notBeforeMilliseconds = new SimpleDateFormat(lollipopRequestConfig.getAssertionNotBeforeDateFormat()).parse(notBefore).getTime(); + } catch (ParseException e) { + throw new AssertionPeriodException(AssertionPeriodException.ErrorCode.ERROR_PARSING_ASSERTION_NOT_BEFORE_DATE, e.getMessage(), e); + } long dateNowMilliseconds = new Date().getTime(); + long expiresAfterMilliseconds = TimeUnit.DAYS.toMillis(lollipopRequestConfig.getAssertionExpireInDays()); + long dateNowLessNotBefore = (dateNowMilliseconds - notBeforeMilliseconds); - long expiresAfterMilliseconds = TimeUnit.DAYS.toMillis(30); //TODO configurazione giorni scadenza + return 0 <= dateNowLessNotBefore && (dateNowLessNotBefore <= expiresAfterMilliseconds); + } - long dateNowLessNotBefore = (dateNowMilliseconds - notBeforeMilliseconds); + private boolean validateUserId(LollipopConsumerRequest request, Document assertionDoc) throws AssertionUserIdException { + String userIdHeader = request.getHeaderParams().get(lollipopRequestConfig.getUserIdHeader()); - if (0 <= dateNowLessNotBefore && (dateNowLessNotBefore <= expiresAfterMilliseconds)) { - return true; + String userIdFromAssertion = getUserIdFromAssertion(assertionDoc); + if (userIdFromAssertion == null) { + throw new AssertionUserIdException(AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, "Missing or invalid Fiscal Code in the retrieved saml assertion."); } - return false; + return userIdFromAssertion.equals(userIdHeader); } - private boolean validateUserId(LollipopConsumerRequest request, SamlAssertion assertion) throws ParserConfigurationException, IOException, SAXException { - String stringXml = assertion.getAssertionData(); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document document = builder.parse(new InputSource(new StringReader(stringXml))); - - String userIdHeaders = request.getHeaderParams().get("x-pagopa-lollipop-user-id"); //TODO aggiungere a configurazione - - NodeList listElements = document.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "Attribute"); //TODO aggiungere a configurazione - String userIdAssertion = ""; - if (listElements != null && listElements.getLength() > 0) { - for (int i = 0; i < listElements.getLength(); i++) { - String userIdFound = listElements.item(i).getAttributes().getNamedItem("fiscalNumber").getNodeValue(); - if (!userIdFound.isBlank()) { - userIdAssertion = userIdFound.trim().replace("TINIT-", ""); - break; - } - } + private boolean validateInResponseTo(LollipopConsumerRequest request, Document assertionDoc) throws AssertionThumbprintException { + NodeList listElements = assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionInResponseToTag()); + if (isInResponseToFieldFound(listElements)) { + throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_FIELD_NOT_FOUND, "Missing request id in the retrieved saml assertion"); } + String inResponseTo = listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO).getNodeValue(); - return userIdAssertion.equals(userIdHeaders); - } + String inResponseToAlgorithm = retrieveInResponseToAlgorithm(inResponseTo); - private boolean validateInResponseTo(LollipopConsumerRequest request, SamlAssertion assertion) { - return false; + + String publicKey = request.getHeaderParams().get(lollipopRequestConfig.getPublicKeyHeader()); + String calculatedThumbprint = calculateThumbprint(inResponseToAlgorithm, publicKey); + String assertionRefHeader = request.getHeaderParams().get(lollipopRequestConfig.getAssertionRefHeader()); + + return inResponseTo.equals(calculatedThumbprint) && inResponseTo.equals(assertionRefHeader); } private IdpCertData getIdpCertData(SamlAssertion assertion) { @@ -112,4 +147,81 @@ private IdpCertData getIdpCertData(SamlAssertion assertion) { private boolean validateSignature(SamlAssertion assertion, IdpCertData idpCertData) { return false; } + + private static Document buildDocumentFromAssertion(SamlAssertion assertion) throws ErrorRetrievingAssertionException { + String stringXml = assertion.getAssertionData(); + try { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + // completely disable DOCTYPE declaration: + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + + factory.setNamespaceAware(true); + DocumentBuilder builder = factory.newDocumentBuilder(); + return builder.parse(new InputSource(new StringReader(stringXml))); + } catch (ParserConfigurationException | SAXException | IOException e) { + throw new ErrorRetrievingAssertionException(ErrorRetrievingAssertionException.ErrorCode.ERROR_PARSING_ASSERTION, e.getMessage(), e); + } + } + + private boolean isInResponseToFieldFound(NodeList listElements) { + return listElements == null + || listElements.getLength() <= 0 + || listElements.item(0) == null + || listElements.item(0).getAttributes() == null + || listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO) == null + || listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO).getNodeValue() == null; + } + + private String getUserIdFromAssertion(Document assertionDoc) throws AssertionUserIdException { + NodeList listElements = assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionFiscalCodeTag()); + if (listElements == null || listElements.getLength() <= 0) { + throw new AssertionUserIdException(AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, "Missing or invalid Fiscal Code in the retrieved saml assertion."); + + } + + for (int i = 0; i < listElements.getLength(); i++) { + Node item = listElements.item(i); + if (item == null || item.getAttributes() == null) { + continue; + } + Node name = item.getAttributes().getNamedItem("Name"); + if (name != null && name.getNodeValue().equals("fiscalNumber") && item.getTextContent() != null) { + return item.getTextContent().trim().replace("TINIT-", ""); + } + } + return null; + } + + private String retrieveInResponseToAlgorithm(String inResponseTo) throws AssertionThumbprintException { + boolean matchesSHA256 = AssertionRefAlgorithms.SHA256.getPattern().matcher(inResponseTo).matches(); + boolean matchesSHA384 = AssertionRefAlgorithms.SHA384.getPattern().matcher(inResponseTo).matches(); + boolean matchesSHA512 = AssertionRefAlgorithms.SHA512.getPattern().matcher(inResponseTo).matches(); + + if (matchesSHA256) { + return AssertionRefAlgorithms.SHA256.getAlgorithmName(); + } + if (matchesSHA384) { + return AssertionRefAlgorithms.SHA384.getAlgorithmName(); + } + if (matchesSHA512) { + return AssertionRefAlgorithms.SHA512.getAlgorithmName(); + } + throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_NOT_VALID, "InResponseTo in the assertion do not contains a valid Assertion Ref."); + + } + + private String calculateThumbprint(String inResponseToAlgorithm, String publicKey) throws AssertionThumbprintException { + Base64URL thumbprint; + try { + thumbprint = ThumbprintUtils.compute(inResponseToAlgorithm, JWK.parse(publicKey)); + } catch (JOSEException | ParseException e) { + String errMsg = String.format("Can not calculate JwkThumbprint: %S", e.getMessage()); + throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, errMsg, e); + } + String calculatedThumbprint = String.format("%s-%s", inResponseToAlgorithm, thumbprint.decodeToString()); + if (!AssertionRefAlgorithms.valueOf(inResponseToAlgorithm.toUpperCase(Locale.ROOT)).getPattern().matcher(calculatedThumbprint).matches()) { + throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, "Error calculating the hash of the provided public key"); + } + return calculatedThumbprint; + } } From 3c3dcb8591a8f8a79ba44e52c28fbd23da9858e5 Mon Sep 17 00:00:00 2001 From: giomella Date: Fri, 14 Apr 2023 10:47:51 +0200 Subject: [PATCH 171/403] [SLS-21] moved LollipopConsumerRequestValidationService and added in the request validation flow. --- .../LollipopConsumerCommandBuilderImpl.java | 4 +- .../impl/LollipopConsumerCommandImpl.java | 14 +++- .../helper/LollipopConsumerFactoryHelper.java | 7 ++ ...lipopConsumerRequestValidationService.java | 19 +++++ ...ConsumerRequestValidationServiceImpl.java} | 78 ++++++++++--------- 5 files changed, 84 insertions(+), 38 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java rename core/src/main/java/it/pagopa/tech/lollipop/consumer/{config/service/LollipopConsumerRequestValidationService.java => service/impl/LollipopConsumerRequestValidationServiceImpl.java} (66%) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java index 95844767..c7109f2c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java @@ -28,6 +28,8 @@ public LollipopConsumerCommandBuilderImpl(LollipopConsumerFactoryHelper factoryH public LollipopConsumerCommand createCommand() { return new LollipopConsumerCommandImpl( factoryHelper.getHttpMessageVerifierService(), - factoryHelper.getAssertionVerifierService()); + factoryHelper.getAssertionVerifierService(), + factoryHelper.getRequestValidationService() + ); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index b396e5c7..87eb4b9f 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -2,6 +2,7 @@ package it.pagopa.tech.lollipop.consumer.command.impl; import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; +import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionVerificationResultCode; import it.pagopa.tech.lollipop.consumer.enumeration.HttpMessageVerificationResultCode; import it.pagopa.tech.lollipop.consumer.exception.*; @@ -17,15 +18,19 @@ public class LollipopConsumerCommandImpl implements LollipopConsumerCommand { private final HttpMessageVerifierService messageVerifierService; private final AssertionVerifierService assertionVerifierService; + private final LollipopConsumerRequestValidationService requestValidationService; public static final String VERIFICATION_SUCCESS_CODE = "SUCCESS"; + public static final String REQUEST_PARAMS_VALIDATION_FAILED = "REQUEST PARAMS VALIDATION FAILED"; @Inject public LollipopConsumerCommandImpl( HttpMessageVerifierService messageVerifierService, - AssertionVerifierService assertionVerifierService) { + AssertionVerifierService assertionVerifierService, + LollipopConsumerRequestValidationService requestValidationService) { this.messageVerifierService = messageVerifierService; this.assertionVerifierService = assertionVerifierService; + this.requestValidationService = requestValidationService; } /** @@ -38,6 +43,13 @@ public LollipopConsumerCommandImpl( @Override public CommandResult doExecute(LollipopConsumerRequest request) { + try { + requestValidationService.validateLollipopRequest(request); + } catch (LollipopRequestContentValidationException e) { + String message = String.format("Error validating Lollipop request header or body, validation failed with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); + return buildCommandResult(REQUEST_PARAMS_VALIDATION_FAILED, message); + } + CommandResult messageVerificationResult = getHttpMessageVerificationResult(request); if (!messageVerificationResult .getResultCode() diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index ed688eda..76a66ff5 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -7,8 +7,11 @@ 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 */ @@ -68,4 +71,8 @@ public AssertionServiceFactory getAssertionServiceFactory() { public LollipopConsumerRequestConfig getLollipopConsumerRequestConfig() { return LollipopConsumerRequestConfig.builder().build(); } + + public LollipopConsumerRequestValidationService getRequestValidationService() { + return new LollipopConsumerRequestValidationServiceImpl(getLollipopConsumerRequestConfig()); + } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java new file mode 100644 index 00000000..bdf34001 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java @@ -0,0 +1,19 @@ +package it.pagopa.tech.lollipop.consumer.service; + +import it.pagopa.tech.lollipop.consumer.exception.LollipopRequestContentValidationException; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; + +/** + * Interface of the service used to verify Lollipop request header params + */ +public interface LollipopConsumerRequestValidationService { + + /** + * Validates all request headers + * + * @param request the Lollipop request + * @return true if the request is validated + * @throws LollipopRequestContentValidationException if some error occurred during validation + */ + void validateLollipopRequest(LollipopConsumerRequest request) throws LollipopRequestContentValidationException; +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java similarity index 66% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java index 38a3ba55..730c484f 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java @@ -1,4 +1,4 @@ -package it.pagopa.tech.lollipop.consumer.config.service; +package it.pagopa.tech.lollipop.consumer.service.impl; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionRefAlgorithms; @@ -10,35 +10,41 @@ import java.util.Map; import java.util.regex.Pattern; -public class LollipopConsumerRequestValidationService { +public class LollipopConsumerRequestValidationServiceImpl implements it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService { - public static boolean validateLollipopConsumerConfig(LollipopConsumerRequest request, LollipopConsumerRequestConfig config) throws LollipopRequestContentValidationException { + private final LollipopConsumerRequestConfig config; + public LollipopConsumerRequestValidationServiceImpl(LollipopConsumerRequestConfig config) { + this.config = config; + } + + @Override + public void validateLollipopRequest(LollipopConsumerRequest request) throws LollipopRequestContentValidationException { Map headerParams = request.getHeaderParams(); - String originalMethod = headerParams.get(config.getOriginalMethodHeader()); - String originalUrl = headerParams.get(config.getOriginalURLHeader()); + validatesOriginalMethodAndURL(headerParams.get(this.config.getOriginalMethodHeader()), headerParams.get(this.config.getOriginalURLHeader())); - if (!originalMethod.equals(config.getExpectedFirstLcOriginalMethod()) && !originalUrl.equals(config.getExpectedFirstLcOriginalUrl())) { - String errMsg = String.format("Unexpected original method and/or original url: %s, %s", originalMethod, originalUrl); - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_METHOD_OR_URL, errMsg); - } + validatePublicKey(headerParams.get(this.config.getPublicKeyHeader())); - validatePublicKey(headerParams.get(config.getPublicKeyHeader())); + validateAssertionRefHeader(headerParams.get(this.config.getAssertionRefHeader())); + validateAssertionTypeHeader(headerParams.get(this.config.getAssertionTypeHeader())); + validateUserIdHeader(headerParams.get(this.config.getUserIdHeader())); + validateAuthJWTHeader(headerParams.get(this.config.getAuthJWTHeader())); + validateOriginalMethodHeader(headerParams.get(this.config.getOriginalMethodHeader())); + validateOriginalURLHeader(headerParams.get(this.config.getOriginalURLHeader())); + validateSignatureInputHeader(headerParams.get(this.config.getSignatureInputHeader())); + validateSignatureHeader(headerParams.get(this.config.getSignatureHeader())); + } - validateAssertionRefHeader(headerParams.get(config.getAssertionRefHeader())); - validateAssertionTypeHeader(headerParams.get(config.getAssertionTypeHeader())); - validateUserIdHeader(headerParams.get(config.getUserIdHeader())); - validateAuthJWTHeader(headerParams.get(config.getAuthJWTHeader())); - validateOriginalMethodHeader(headerParams.get(config.getOriginalMethodHeader())); - validateOriginalURLHeader(headerParams.get(config.getOriginalURLHeader())); - validateSignatureInputHeader(headerParams.get(config.getSignatureInputHeader())); - validateSignatureHeader(headerParams.get(config.getSignatureHeader())); + private void validatesOriginalMethodAndURL(String originalMethod, String originalUrl) throws LollipopRequestContentValidationException { - return true; + if (!originalMethod.equals(this.config.getExpectedFirstLcOriginalMethod()) && !originalUrl.equals(this.config.getExpectedFirstLcOriginalUrl())) { + String errMsg = String.format("Unexpected original method and/or original url: %s, %s", originalMethod, originalUrl); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_METHOD_OR_URL, errMsg); + } } - private static void validatePublicKey(String publicKey) throws LollipopRequestContentValidationException { + private void validatePublicKey(String publicKey) throws LollipopRequestContentValidationException { if (publicKey == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_PUBLIC_KEY, "Missing Public Key Header"); } @@ -48,12 +54,12 @@ private static void validatePublicKey(String publicKey) throws LollipopRequestCo } } - private static boolean isNotValidPublicKey(String publicKey) { + private boolean isNotValidPublicKey(String publicKey) { // TODO return false; } - private static void validateAssertionRefHeader(String assertionRef) throws LollipopRequestContentValidationException { + private void validateAssertionRefHeader(String assertionRef) throws LollipopRequestContentValidationException { if (assertionRef == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_REF, "Missing AssertionRef Header"); } @@ -63,14 +69,14 @@ private static void validateAssertionRefHeader(String assertionRef) throws Lolli } } - private static boolean isNotValidAssertionRef(String signature) { + private boolean isNotValidAssertionRef(String signature) { boolean matchesSHA256 = AssertionRefAlgorithms.SHA256.getPattern().matcher(signature).matches(); boolean matchesSHA384 = AssertionRefAlgorithms.SHA384.getPattern().matcher(signature).matches(); boolean matchesSHA512 = AssertionRefAlgorithms.SHA512.getPattern().matcher(signature).matches(); return !matchesSHA256 && !matchesSHA384 && !matchesSHA512; } - private static void validateAssertionTypeHeader(String assertionType) throws LollipopRequestContentValidationException { + private void validateAssertionTypeHeader(String assertionType) throws LollipopRequestContentValidationException { if (assertionType == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_TYPE, "Missing Assertion Type Header"); } @@ -80,7 +86,7 @@ private static void validateAssertionTypeHeader(String assertionType) throws Lol } } - private static boolean isAssertionTypeSupported(String assertionType) { + private boolean isAssertionTypeSupported(String assertionType) { for (AssertionType supportedType : AssertionType.values()) { if (supportedType.name().equals(assertionType)) { return true; @@ -89,7 +95,7 @@ private static boolean isAssertionTypeSupported(String assertionType) { return false; } - private static void validateUserIdHeader(String userId) throws LollipopRequestContentValidationException { + private void validateUserIdHeader(String userId) throws LollipopRequestContentValidationException { if (userId == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_USER_ID, "Missing User Id Header"); } @@ -99,11 +105,11 @@ private static void validateUserIdHeader(String userId) throws LollipopRequestCo } } - private static boolean isNotValidFiscalCode(String userId) { + private boolean isNotValidFiscalCode(String userId) { return !Pattern.compile("^[A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]$").matcher(userId).matches(); } - private static void validateAuthJWTHeader(String authJWT) throws LollipopRequestContentValidationException { + private void validateAuthJWTHeader(String authJWT) throws LollipopRequestContentValidationException { if (authJWT == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_AUTH_JWT, "Missing Auth JWT Header"); } @@ -113,7 +119,7 @@ private static void validateAuthJWTHeader(String authJWT) throws LollipopRequest } } - private static void validateOriginalMethodHeader(String originalMethod) throws LollipopRequestContentValidationException { + private void validateOriginalMethodHeader(String originalMethod) throws LollipopRequestContentValidationException { if (originalMethod == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_METHOD, "Missing Original Method Header"); } @@ -123,7 +129,7 @@ private static void validateOriginalMethodHeader(String originalMethod) throws L } } - private static boolean isRequestMethodSupported(String originalMethod) { + private boolean isRequestMethodSupported(String originalMethod) { for (LollipopRequestMethod supportedType : LollipopRequestMethod.values()) { if (supportedType.name().equals(originalMethod)) { return true; @@ -132,7 +138,7 @@ private static boolean isRequestMethodSupported(String originalMethod) { return false; } - private static void validateOriginalURLHeader(String originalURL) throws LollipopRequestContentValidationException { + private void validateOriginalURLHeader(String originalURL) throws LollipopRequestContentValidationException { if (originalURL == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_URL, "Missing Original URL Header"); } @@ -142,11 +148,11 @@ private static void validateOriginalURLHeader(String originalURL) throws Lollipo } } - private static boolean isNotValidOriginalURL(String originalURL) { + private boolean isNotValidOriginalURL(String originalURL) { return !Pattern.compile("^https://").matcher(originalURL).matches(); } - private static void validateSignatureInputHeader(String signatureInput) throws LollipopRequestContentValidationException { + private void validateSignatureInputHeader(String signatureInput) throws LollipopRequestContentValidationException { if (signatureInput == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE_INPUT, "Missing Signature Input Header"); } @@ -156,11 +162,11 @@ private static void validateSignatureInputHeader(String signatureInput) throws L } } - private static boolean isNotValidSignatureInput(String signatureInput) { + private boolean isNotValidSignatureInput(String signatureInput) { return !Pattern.compile("^(((sig[0-9]+)=[^,]*?)(, ?)?)+$").matcher(signatureInput).matches(); } - private static void validateSignatureHeader(String signature) throws LollipopRequestContentValidationException { + private void validateSignatureHeader(String signature) throws LollipopRequestContentValidationException { if (signature == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE, "Missing Signature Header"); } @@ -170,7 +176,7 @@ private static void validateSignatureHeader(String signature) throws LollipopReq } } - private static boolean isNotValidSignature(String signature) { + private boolean isNotValidSignature(String signature) { return !Pattern.compile("^((sig[0-9]+)=:[A-Za-z0-9+/=]*:(, ?)?)+$").matcher(signature).matches(); } } From a45b120b641057262141c54a695d369024531eb8 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 14 Apr 2023 11:06:09 +0200 Subject: [PATCH 172/403] [core-sprint2-sample] Updated sample --- sample/build.gradle | 11 +++ .../java/it/pagopa/tech/sample/Constants.java | 20 ------ .../pagopa/tech/sample/LollipopConstants.java | 62 ++++++++++++++++ .../tech/sample/LollipopConsumerSample.java | 72 ++++++++++++++----- 4 files changed, 129 insertions(+), 36 deletions(-) delete mode 100644 sample/src/main/java/it/pagopa/tech/sample/Constants.java create mode 100644 sample/src/main/java/it/pagopa/tech/sample/LollipopConstants.java diff --git a/sample/build.gradle b/sample/build.gradle index bde45400..a29aeb51 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -19,10 +19,21 @@ application { repositories { mavenLocal() mavenCentral() + repositories { + maven { + name = "GitHubPackages" + url = "https://maven.pkg.github.com/pagopa/eng-lollipop-consumer-java-sdk" + credentials { + username = System.getenv("GITHUB_ACTOR") + password = System.getenv("GITHUB_TOKEN") + } + } + } } dependencies { implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:core:1.0.0-SNAPSHOT' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:assertion-rest-client-native:1.0.0-SNAPSHOT' implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:http-verifier:1.0.0-SNAPSHOT' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' diff --git a/sample/src/main/java/it/pagopa/tech/sample/Constants.java b/sample/src/main/java/it/pagopa/tech/sample/Constants.java deleted file mode 100644 index 086f0d9f..00000000 --- a/sample/src/main/java/it/pagopa/tech/sample/Constants.java +++ /dev/null @@ -1,20 +0,0 @@ -package it.pagopa.tech.sample; - -public class Constants { - public static final String CONTENT_DIGEST = "content-digest"; - public static final String CONTENT_ENCODING = "content-encoding"; - public static final String SIGNATURE_INPUT = "signature-input"; - public static final String SIGNATURE = "signature"; - public static final String VALID_ENCODING_UTF8 = "UTF-8"; - public static final String INVALID_ENCODING_UTF_326 = "UTF-326"; - public static final String VALID_CONTENT_DIGEST = "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"; - public static final String INVALID_CONTENT_DIGEST = "sha-256=:fadsfeagsdage76ad564=:"; - public static final String VALID_MESSAGE_PAYLOAD = "{\"message\":\"a valid message payload\"}"; - public static final String INVALID_MESSAGE_PAYLOAD = "{\"message\":\"an invalid message payload\"}"; - public static final String SIGNATURE_HEADER_VALUE = "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; - public static final String SIGNATURE_INPUT_HEADER_VALUE = "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" " - + "\"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=" - + "\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; - - private Constants() {} -} diff --git a/sample/src/main/java/it/pagopa/tech/sample/LollipopConstants.java b/sample/src/main/java/it/pagopa/tech/sample/LollipopConstants.java new file mode 100644 index 00000000..7c80c4f1 --- /dev/null +++ b/sample/src/main/java/it/pagopa/tech/sample/LollipopConstants.java @@ -0,0 +1,62 @@ +package it.pagopa.tech.sample; + +public class LollipopConstants { + public static final String CONTENT_DIGEST = "content-digest"; + public static final String CONTENT_ENCODING = "content-encoding"; + public static final String SIGNATURE_INPUT = "signature-input"; + public static final String SIGNATURE = "signature"; + + public static final String LOLLIPOP_KEY = "x-pagopa-lollipop-public-key"; + + public static final String LOLLIPOP_ORIGIN_METHOD = "x-pagopa-lollipop-original-method"; + + public static final String LOLLIPOP_ORIGIN_URL = "x-pagopa-lollipop-original-url"; + + public static final String EXPECTED_ORIGIN_METHOD = "POST"; + public static final String EXCPECTED_ORIGIN_URL = "https://api-app.io.pagopa.it/first-lollipop/sign"; + public static final String VALID_ENCODING_UTF8 = "UTF-8"; + public static final String INVALID_ENCODING_UTF_326 = "UTF-326"; + public static final String VALID_CONTENT_DIGEST = "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"; + public static final String INVALID_CONTENT_DIGEST = "sha-256=:fadsfeagsdage76ad564=:"; + public static final String VALID_MESSAGE_PAYLOAD = "{\"message\":\"a valid message payload\"}"; + public static final String INVALID_MESSAGE_PAYLOAD = "{\"message\":\"an invalid message payload\"}"; + public static final String SIGNATURE_HEADER_VALUE = "sig123=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + public static final String INVALID_SIGNATURE_HEADER_VALUE = "sig123=:lTTTRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + public static final String SIGNATURE_INPUT_HEADER_VALUE = "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + + public static final String ECDSA_LOLLIPOP_JWT_KEY = "eyJrdHkiOiJFQyIsIngiOiJGcUZEd" + + "XdFZ3U0TVVYRVJQTVZMLTg1cEd2MkQzWW1MNEoxZ2ZNa2RiYzI0IiwieSI6Im" + + "hkVjBveG1XRlN4TW9KVURwZGlocjc2clM4VlJCRXFNRmViWXlBZks5LWsiLCJjcnYiO" + + "iJQLTI1NiJ9"; + + public static String VALID_MULTI_ECDSA_IGNATURE_INPUT = + "sig1=(\"x-io-sign-qtspclauses\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\"," + + " sig2=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + public static String VALID_MULTI_ECDSA_SIGNATURE = + "sig1=:dncsEeKERA9wzxBO0vbPIueMK7Izk4zZNX4D0jI+t17XQJ5YrhumR3MGvMiyarb+B8MPqn+rbOJwZt6dV+oXFA==:," + + " sig2=:nbmFduqX8AdhXzqkFX+UIvicn3ZV5yZXqUO+3bceOT8WFPXRTVRcoOcjF+0+W5KLihAZjSW5GXSgCxVVEW8pqQ==:"; + + public static String VALID_RSA_PSS_SIGNATURE_INPUT = + "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678814391;nonce=\"aNonce\";" + + "alg=\"rsa-pss-sha256\";keyid=\"sha256-A3OhKGLYwSvdJ2txHi_SGQ3G-sHLh2Ibu91ErqFx_58\""; + + public static String VALID_RSA_PSS_SIGNATURE = + "sig1=:q3Og7m8yL18HkrY+zgV92Gj05lrWaFMIEFSPg2PEnO5a46+2Tt/2n7kjqVaGjI1ZXtys+Wyh3cVXCdda" + + "dNARizt0BpCRdT9S4r48xsGO79Ucq4IFwZyyHNudKu5WSH4/55j5yX/YmeCtH+Nt6Nun02OZynn3iQwg" + + "LJB+CGe3h6X02iSvl4wJjKaMGE64RFHa5osE4MctoPD1j0tRkcOtgwrGmFMr282Kqrkabbx1vUpmO9T1k" + + "hjouxIryfUln9zIaZ+wWmukpAZv7TKO3CltNWgfx1XT9m/iwzHiGmtvcHbWVExdAyey8lH23MgLY43AM7y" + + "tLQNSlk1s/bPNbGmPwg==:"; + + public static String LOLLIPOP_RSA_PUBKEY = "eyJrdHkiOiJSU0EiLCJlIjoiQVFBQiIsImtpZCI6InRlc3Qta2V5LXJzYS1wc3MiLCJuIjoicjR0bW0zc" + + "jIwV2RfUGJxdlAxczItUUV0dnB1UmFWOFlxNDBnalVSOHkyUmp4YTZkcEcyR1hIYlBmdk0gIHM4Y3Q" + + "tTGgxR0g0NXgyOFJ3M1J5NTNtbS1vQVhqeVE4Nk9uRGtaNU44bFliZ2dENE8zdzZNNnBBdkxraGs5NU" + + "FuICBkVHJpZmJJRlBOVThQUE1PN095ckZBSHFnRHN6bmpQRm1UT3RDRWNOMloxRnBXZ2Nod3VZTFBMLV" + + "dva3FsdGQxMSAgbnFxemktYko5Y3ZTS0FEWWRVQUFONVdVdHpkcGl5NkxiVGdTeFA3b2NpVTRUbjBnNU" + + "k2YURaSjdBOEx6bzBLU3kgIFpZb0E0ODVtcWNPMEdWQWRWdzlscTRhT1Q5djZkLW5iNGJuTmtRVmtsTFE" + + "zZlZBdkptLXhkRE9wOUxDTkNONDhWICAycG5ET2tGVjYtVTluVjVveWM2WEkydyJ9"; + + public LollipopConstants() {} +} diff --git a/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java b/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java index 78234924..abfcc8e7 100644 --- a/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java +++ b/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java @@ -1,10 +1,15 @@ package it.pagopa.tech.sample; import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; -import it.pagopa.tech.lollipop.consumer.assertion.impl.AssertionServiceFactoryImplStub; +import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClientProvider; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientConfig; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.assertion.impl.AssertionServiceFactoryImpl; +import it.pagopa.tech.lollipop.consumer.assertion.storage.*; import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; import it.pagopa.tech.lollipop.consumer.command.impl.LollipopConsumerCommandBuilderImpl; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.helper.LollipopConsumerFactoryHelper; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; import it.pagopa.tech.lollipop.consumer.http_verifier.visma.VismaHttpMessageVerifierFactory; @@ -14,8 +19,10 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import java.util.HashMap; +import java.util.logging.Logger; + +import static it.pagopa.tech.sample.LollipopConstants.*; -import static it.pagopa.tech.sample.Constants.*; public class LollipopConsumerSample { @@ -23,32 +30,65 @@ public static void main(String[] args) throws Exception { LollipopConsumerCommandBuilder commandBuilder = new LollipopConsumerCommandBuilderImpl(buildLollipopConsumerFactoryHelper()); LollipopConsumerCommand command = commandBuilder.createCommand(); - CommandResult commandResult = command.doExecute(buildLollipopRequest(VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD)); - System.out.println(buildMessage(commandResult, "Validation of a valid Lollipop request ended with status code ")); + CommandResult commandResult = command.doExecute(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)); + Logger.getGlobal().info(buildMessage(commandResult, "Validation of a valid Lollipop request ended with status code: ")); + + commandResult = command.doExecute(buildLollipopRequest( + INVALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)); + Logger.getGlobal().info(buildMessage(commandResult, "Validation of a Lollipop request with invalid digest header ended with status code: ")); + + commandResult = command.doExecute(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, INVALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)); + Logger.getGlobal().info(buildMessage(commandResult, "Validation of a Lollipop request with invalid content ended with status code: ")); - commandResult = command.doExecute(buildLollipopRequest(INVALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD)); - System.out.println(buildMessage(commandResult, "Validation of a Lollipop request with invalid digest header ended with status code ")); + commandResult = command.doExecute(buildLollipopRequest( + VALID_CONTENT_DIGEST, INVALID_ENCODING_UTF_326, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)); + Logger.getGlobal().info(buildMessage(commandResult, "Validation of a Lollipop request with unsupported encoding ended with status code: ")); - commandResult = command.doExecute(buildLollipopRequest(VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, INVALID_MESSAGE_PAYLOAD)); - System.out.println(buildMessage(commandResult, "Validation of a Lollipop request with invalid content ended with status code ")); + commandResult = command.doExecute(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, INVALID_SIGNATURE_HEADER_VALUE)); + Logger.getGlobal().info(buildMessage(commandResult, "Validation of a Lollipop request with invalid signature ended with status code: ")); + + commandResult = command.doExecute(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, VALID_MULTI_ECDSA_IGNATURE_INPUT, VALID_MULTI_ECDSA_SIGNATURE)); + Logger.getGlobal().info(buildMessage(commandResult, "Validation of a valid Lollipop request with ecdsa multi-signature ended with status code: ")); + + commandResult = command.doExecute(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, LOLLIPOP_RSA_PUBKEY, VALID_RSA_PSS_SIGNATURE_INPUT, VALID_RSA_PSS_SIGNATURE)); + Logger.getGlobal().info(buildMessage(commandResult, "Validation of a valid Lollipop request with rsa-pss-256 signature ended with status code: ")); - commandResult = command.doExecute(buildLollipopRequest(VALID_CONTENT_DIGEST, INVALID_ENCODING_UTF_326, VALID_MESSAGE_PAYLOAD)); - System.out.println(buildMessage(commandResult, "Validation of a Lollipop request with unsupported encoding ended with status code ")); } private static LollipopConsumerFactoryHelper buildLollipopConsumerFactoryHelper() throws Exception { - HttpMessageVerifierFactory messageVerifierFactory = new VismaHttpMessageVerifierFactory(VALID_ENCODING_UTF8); + HttpMessageVerifierFactory messageVerifierFactory = new VismaHttpMessageVerifierFactory(VALID_ENCODING_UTF8, + LollipopConsumerRequestConfig.builder().build()); + AssertionStorageProvider assertionStorageProvider = new SimpleAssertionStorageProvider(); + AssertionClientProvider assertionClientProvider = + new AssertionSimpleClientProvider(AssertionSimpleClientConfig.builder().build()); IdpCertProviderFactory idpCertProviderFactory = new IdpCertProviderFactoryImplStub(); - AssertionServiceFactory assertionServiceFactory = new AssertionServiceFactoryImplStub(); + AssertionServiceFactory assertionServiceFactory = new AssertionServiceFactoryImpl( + assertionStorageProvider, assertionClientProvider, new StorageConfig()); return new LollipopConsumerFactoryHelper(messageVerifierFactory, idpCertProviderFactory, assertionServiceFactory); } - private static LollipopConsumerRequest buildLollipopRequest(String contentDigest, String encoding, String payload) { + private static LollipopConsumerRequest buildLollipopRequest( + String contentDigest, + String encoding, + String payload, + String lollipopKey, + String signatureInput, + String signature) { HashMap lollipopHeaderParams = new HashMap<>(); lollipopHeaderParams.put(CONTENT_DIGEST, contentDigest); lollipopHeaderParams.put(CONTENT_ENCODING, encoding); - lollipopHeaderParams.put(SIGNATURE_INPUT, SIGNATURE_INPUT_HEADER_VALUE); - lollipopHeaderParams.put(SIGNATURE, SIGNATURE_HEADER_VALUE); + lollipopHeaderParams.put(SIGNATURE_INPUT, signatureInput); + lollipopHeaderParams.put(SIGNATURE, signature); + lollipopHeaderParams.put(LOLLIPOP_KEY, lollipopKey); + lollipopHeaderParams.put(LOLLIPOP_ORIGIN_METHOD, EXPECTED_ORIGIN_METHOD); + lollipopHeaderParams.put(LOLLIPOP_ORIGIN_URL, EXCPECTED_ORIGIN_URL); + lollipopHeaderParams.put("X-io-sign-qtspclauses","anIoSignClauses"); + return LollipopConsumerRequest.builder() .requestBody(payload) @@ -57,6 +97,6 @@ private static LollipopConsumerRequest buildLollipopRequest(String contentDigest } private static String buildMessage(CommandResult commandResult, String s) { - return s + commandResult.getResultCode() + " and message " + commandResult.getResultMessage(); + return s + commandResult.getResultCode() + " and message: " + commandResult.getResultMessage(); } } From 5c33a9175c0938255507a0a8926246e0a0ed9ef5 Mon Sep 17 00:00:00 2001 From: giomella Date: Fri, 14 Apr 2023 15:55:47 +0200 Subject: [PATCH 173/403] [SLS-21] added unit test for AssertionVerifierServiceImpl and do some fix. --- .../enumeration/AssertionRefAlgorithms.java | 29 +- .../AssertionThumbprintException.java | 2 +- .../impl/AssertionVerifierServiceImpl.java | 19 +- .../AssertionVerifierServiceImplTest.java | 304 ++++++++++++++++++ 4 files changed, 339 insertions(+), 15 deletions(-) create mode 100644 core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java index 06e6f417..fe5a5b30 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java @@ -7,15 +7,17 @@ */ public enum AssertionRefAlgorithms { - SHA256("sha256", Pattern.compile("^(sha256-[A-Za-z0-9-_=]{1,44})$")), - SHA384("sha384", Pattern.compile("^(sha384-[A-Za-z0-9-_=]{1,66})$")), - SHA512("sha512", Pattern.compile("^(sha512-[A-Za-z0-9-_=]{1,88})$")); + SHA256("sha256", AlgorithmName.SHA_256, Pattern.compile("^(sha256-[A-Za-z0-9-_=]{1,44})$")), + SHA384("sha384", AlgorithmName.SHA_384, Pattern.compile("^(sha384-[A-Za-z0-9-_=]{1,66})$")), + SHA512("sha512", AlgorithmName.SHA_512, Pattern.compile("^(sha512-[A-Za-z0-9-_=]{1,88})$")); private final String algorithmName; + private final String hashAlgorithm; private final Pattern pattern; - AssertionRefAlgorithms(String algorithmName, Pattern pattern) { + AssertionRefAlgorithms(String algorithmName, String hashAlgorithm, Pattern pattern) { this.algorithmName = algorithmName; + this.hashAlgorithm = hashAlgorithm; this.pattern = pattern; } @@ -23,7 +25,26 @@ public Pattern getPattern() { return pattern; } + public String getHashAlgorithm() { + return hashAlgorithm; + } + public String getAlgorithmName() { return algorithmName; } + + public static AssertionRefAlgorithms getAlgorithmFromHash(String algorithmName) { + switch (algorithmName) { + case AlgorithmName.SHA_256: return SHA256; + case AlgorithmName.SHA_384: return SHA384; + case AlgorithmName.SHA_512: return SHA512; + default: throw new UnsupportedOperationException("Unsupported algorithm: " + algorithmName); + } + } + + private static class AlgorithmName { + public static final String SHA_256 = "SHA-256"; + public static final String SHA_384 = "SHA-384"; + public static final String SHA_512 = "SHA-512"; + } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java index 4f23f03d..37a12bb0 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java @@ -45,7 +45,7 @@ public ErrorCode getErrorCode() { /** Error codes to classify Lollipop Request Exceptions */ public enum ErrorCode { IN_RESPONSE_TO_FIELD_NOT_FOUND, - IN_RESPONSE_TO_NOT_VALID, + IN_RESPONSE_TO_ALGORITHM_NOT_VALID, ERROR_CALCULATING_ASSERTION_THUMBPRINT, INVALID_IN_RESPONSE_TO } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index b1d0d8de..b562c0aa 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -21,7 +21,6 @@ import org.xml.sax.SAXException; import javax.inject.Inject; -import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -30,7 +29,6 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; -import java.util.Locale; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -93,7 +91,7 @@ private SamlAssertion getAssertion(String jwt, String assertionRef) throws Error } private boolean validateAssertionPeriod(Document assertionDoc) throws AssertionPeriodException { - NodeList listElements = assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionNotBeforeDateFormat()); + NodeList listElements = assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionNotBeforeTag()); if (listElements == null || listElements.getLength() <= 0) { return false; } @@ -198,15 +196,15 @@ private String retrieveInResponseToAlgorithm(String inResponseTo) throws Asserti boolean matchesSHA512 = AssertionRefAlgorithms.SHA512.getPattern().matcher(inResponseTo).matches(); if (matchesSHA256) { - return AssertionRefAlgorithms.SHA256.getAlgorithmName(); + return AssertionRefAlgorithms.SHA256.getHashAlgorithm(); } if (matchesSHA384) { - return AssertionRefAlgorithms.SHA384.getAlgorithmName(); + return AssertionRefAlgorithms.SHA384.getHashAlgorithm(); } if (matchesSHA512) { - return AssertionRefAlgorithms.SHA512.getAlgorithmName(); + return AssertionRefAlgorithms.SHA512.getHashAlgorithm(); } - throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_NOT_VALID, "InResponseTo in the assertion do not contains a valid Assertion Ref."); + throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_ALGORITHM_NOT_VALID, "InResponseTo in the assertion do not contains a valid Assertion Ref or it contains an invalid algorithm."); } @@ -218,9 +216,10 @@ private String calculateThumbprint(String inResponseToAlgorithm, String publicKe String errMsg = String.format("Can not calculate JwkThumbprint: %S", e.getMessage()); throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, errMsg, e); } - String calculatedThumbprint = String.format("%s-%s", inResponseToAlgorithm, thumbprint.decodeToString()); - if (!AssertionRefAlgorithms.valueOf(inResponseToAlgorithm.toUpperCase(Locale.ROOT)).getPattern().matcher(calculatedThumbprint).matches()) { - throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, "Error calculating the hash of the provided public key"); + AssertionRefAlgorithms algo = AssertionRefAlgorithms.getAlgorithmFromHash(inResponseToAlgorithm); + String calculatedThumbprint = String.format("%s-%s", algo.getAlgorithmName(), thumbprint); + if (!algo.getPattern().matcher(calculatedThumbprint).matches()) { + throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, "The calculated thumbprint does not match the expected pattern: " + calculatedThumbprint); } return calculatedThumbprint; } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java new file mode 100644 index 00000000..ad9433e9 --- /dev/null +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java @@ -0,0 +1,304 @@ +package it.pagopa.tech.lollipop.consumer.service.impl; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.exception.*; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; +import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + +class AssertionVerifierServiceImplTest { + + private IdpCertProvider idpCertProviderMock; + private AssertionService assertionServiceMock; + private static LollipopConsumerRequestConfig lollipopRequestConfigMock; + + private AssertionVerifierService sut; + + private static final String VALID_FISCAL_CODE = "AAAAAA89S20I111X"; + private static final String INVALID_JWK = "{ alg: \"\", e: \"e\", kty: \"RSA\", n: \"n\"}"; + private static final String VALID_JWK = "{ kty: \"EC\", crv: \"P-256\", x: \"SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74\", y: \"lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI\"}"; + private static final String VALID_SHA_256_ASSERTION_REF = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; + private static final String VALID_SHA_384_ASSERTION_REF = "sha384-lqxC_2kqMdwiBWoD-Us63Fha6e3bE1Y3yUz8G6IJTldohJCIBVDfvS8acB3GJBhw"; + private static final String VALID_SHA_512_ASSERTION_REF = "sha512-nX5CfUc5R-FoYKYZwvQMuc4Tt-heb7vHi_O-AMUSqHNVCw9kNaN2SVuN-DXtGXyUhrcVcQdCyY6FVzl_vyWXNA"; + + private static final String EMPTY_ASSERTION_XML = ""; + private static final String ASSERTION_XML_WITH_INVALID_PERIOD_DATE_FORMAT = "https://app-backend.io.italia.it"; + private static final String ASSERTION_XML_WITH_EXPIRED_PERIOD = "https://app-backend.io.italia.it"; + private static String ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG; + private static String ASSERTION_XML_WITHOUT_FISCAL_CODE; + private static String ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG; + private static String ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM; + private static String ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM; + private static String ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM; + private static String ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM; + + @BeforeAll + static void prepareInput() { + lollipopRequestConfigMock = spy(LollipopConsumerRequestConfig.builder().build()); + + String todayTimestamp = new SimpleDateFormat(lollipopRequestConfigMock.getAssertionNotBeforeDateFormat()).format(new Date()); + ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG = "https://app-backend.io.italia.it"; + ASSERTION_XML_WITHOUT_FISCAL_CODE = " https://app-backend.io.italia.it \t "; + ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG = " https://app-backend.io.italia.it \t TINIT-AAAAAA89S20I111X "; + ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM = " \t\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thttps://app-backend.io.italia.it\t\t\t\t\t\t\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t\t\t\t\t"; + ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM = " \t\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thttps://app-backend.io.italia.it\t\t\t\t\t\t\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t\t\t\t\t"; + ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM = " \t\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thttps://app-backend.io.italia.it\t\t\t\t\t\t\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t\t\t\t\t"; + ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM = " \t\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thttps://app-backend.io.italia.it\t\t\t\t\t\t\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t\t\t\t\t"; + } + + @BeforeEach + void setUp() { + idpCertProviderMock = mock(IdpCertProvider.class); + assertionServiceMock = mock(AssertionService.class); + + sut = new AssertionVerifierServiceImpl(idpCertProviderMock, assertionServiceMock, lollipopRequestConfigMock); + } + + @Test + void validateLollipopGetAssertionFailureWithOidcAssertionException() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + doThrow(OidcAssertionNotSupported.class).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + ErrorRetrievingAssertionException e = assertThrows(ErrorRetrievingAssertionException.class, () -> sut.validateLollipop(request)); + + Assertions.assertTrue(e.getCause() instanceof OidcAssertionNotSupported); + Assertions.assertEquals(ErrorRetrievingAssertionException.ErrorCode.OIDC_TYPE_NOT_SUPPORTED, e.getErrorCode()); + } + + @Test + void validateLollipopGetAssertionFailureWithAssertionNotFoundException() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + doThrow(LollipopAssertionNotFoundException.class).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + ErrorRetrievingAssertionException e = assertThrows(ErrorRetrievingAssertionException.class, () -> sut.validateLollipop(request)); + + Assertions.assertTrue(e.getCause() instanceof LollipopAssertionNotFoundException); + Assertions.assertEquals(ErrorRetrievingAssertionException.ErrorCode.SAML_ASSERTION_NOT_FOUND, e.getErrorCode()); + } + + @Test + void validateLollipopBuildAssertionDocFailure() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(""); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + ErrorRetrievingAssertionException e = assertThrows(ErrorRetrievingAssertionException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(ErrorRetrievingAssertionException.ErrorCode.ERROR_PARSING_ASSERTION, e.getErrorCode()); + } + + @Test + void validateLollipopValidatePeriodFailureWithFieldNotFoundInAssertionDoc() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(EMPTY_ASSERTION_XML); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionPeriodException e = assertThrows(AssertionPeriodException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, e.getErrorCode()); + } + + @Test + void validateLollipopValidatePeriodFailureWithInvalidDateFormat() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_INVALID_PERIOD_DATE_FORMAT); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionPeriodException e = assertThrows(AssertionPeriodException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionPeriodException.ErrorCode.ERROR_PARSING_ASSERTION_NOT_BEFORE_DATE, e.getErrorCode()); + } + + @Test + void validateLollipopValidatePeriodFailureWithExpiredAssertion() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_EXPIRED_PERIOD); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionPeriodException e = assertThrows(AssertionPeriodException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, e.getErrorCode()); + } + + @Test + void validateLollipopValidateUserIdFailureWithoutAttributeTagInAssertionDoc() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionUserIdException e = assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, e.getErrorCode()); + } + + @Test + void validateLollipopValidateUserIdFailureWithoutFiscalCodeInAssertionDoc() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITHOUT_FISCAL_CODE); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionUserIdException e = assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, e.getErrorCode()); + } + + @Test + void validateLollipopValidateUserIdFailureWithInvalidUserIdHeader() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionUserIdException e = assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionUserIdException.ErrorCode.INVALID_USER_ID, e.getErrorCode()); + } + + @Test + void validateLollipopValidateThumbprintFailureWithoutSubjectConfirmationDataTagInAssertionDoc() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", VALID_FISCAL_CODE); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionThumbprintException e = assertThrows(AssertionThumbprintException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_FIELD_NOT_FOUND, e.getErrorCode()); + } + + @Test + void validateLollipopValidateThumbprintFailureWithInvalidInResponseToAlgorithm() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", VALID_FISCAL_CODE); + + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionThumbprintException e = assertThrows(AssertionThumbprintException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_ALGORITHM_NOT_VALID, e.getErrorCode()); + } + + @Test + void validateLollipopValidateThumbprintFailureWithErrorCalculatingThumbprint() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", VALID_FISCAL_CODE); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionThumbprintException e = assertThrows(AssertionThumbprintException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, e.getErrorCode()); + Assertions.assertTrue(e.getCause() instanceof ParseException); + } + + @Test + void validateLollipopValidateThumbprintFailureWithInvalidPublicKey() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", INVALID_JWK, VALID_FISCAL_CODE); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionThumbprintException e = assertThrows(AssertionThumbprintException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionThumbprintException.ErrorCode.INVALID_IN_RESPONSE_TO, e.getErrorCode()); + } + + @Test + void validateLollipopSuccessWithSHA256Algorithm() throws LollipopAssertionNotFoundException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, OidcAssertionNotSupported { + LollipopConsumerRequest request = getLollipopConsumerRequest(VALID_SHA_256_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + boolean result = sut.validateLollipop(request); + + Assertions.assertTrue(result); + } + + @Test + void validateLollipopSuccessWithSHA384Algorithm() throws LollipopAssertionNotFoundException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, OidcAssertionNotSupported { + LollipopConsumerRequest request = getLollipopConsumerRequest(VALID_SHA_384_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + boolean result = sut.validateLollipop(request); + + Assertions.assertTrue(result); + } + + @Test + void validateLollipopSuccessWithSHA512Algorithm() throws LollipopAssertionNotFoundException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, OidcAssertionNotSupported { + LollipopConsumerRequest request = getLollipopConsumerRequest(VALID_SHA_512_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + boolean result = sut.validateLollipop(request); + + Assertions.assertTrue(result); + } + + private LollipopConsumerRequest getLollipopConsumerRequest(String assertionRef, String publicKey, String userId) { + HashMap headers = new HashMap<>(); + headers.put(lollipopRequestConfigMock.getAuthJWTHeader(), ""); + headers.put(lollipopRequestConfigMock.getAssertionRefHeader(), assertionRef); + headers.put(lollipopRequestConfigMock.getUserIdHeader(), userId); + headers.put(lollipopRequestConfigMock.getPublicKeyHeader(), publicKey); + + return LollipopConsumerRequest.builder() + .headerParams(headers) + .build(); + } +} \ No newline at end of file From 7e6903aded2d03d4b671de0efe486693b99837cd Mon Sep 17 00:00:00 2001 From: giomella Date: Fri, 14 Apr 2023 16:07:16 +0200 Subject: [PATCH 174/403] [SLS-21] added unit test for LollipopConsumerCommandImpl. --- .../impl/LollipopConsumerCommandImplTest.java | 138 ++++++++++++++++-- 1 file changed, 128 insertions(+), 10 deletions(-) diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java index 7f943d56..8bea929a 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -7,13 +7,14 @@ import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionVerificationResultCode; import it.pagopa.tech.lollipop.consumer.enumeration.HttpMessageVerificationResultCode; -import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; -import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; +import it.pagopa.tech.lollipop.consumer.exception.*; import it.pagopa.tech.lollipop.consumer.model.CommandResult; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; import java.io.UnsupportedEncodingException; + +import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; import lombok.SneakyThrows; import org.junit.jupiter.api.*; import org.mockito.*; @@ -22,26 +23,30 @@ class LollipopConsumerCommandImplTest { private static HttpMessageVerifierService messageVerifierServiceMock; private static AssertionVerifierService assertionVerifierServiceMock; + private LollipopConsumerRequestValidationService requestValidationServiceMock; private static LollipopConsumerCommand sut; @BeforeEach void beforeAll() { messageVerifierServiceMock = Mockito.mock(HttpMessageVerifierService.class); assertionVerifierServiceMock = Mockito.mock(AssertionVerifierService.class); + requestValidationServiceMock = Mockito.mock(LollipopConsumerRequestValidationService.class); sut = Mockito.spy( new LollipopConsumerCommandImpl( - messageVerifierServiceMock, assertionVerifierServiceMock)); + messageVerifierServiceMock, + assertionVerifierServiceMock, + requestValidationServiceMock + )); } @Test void failedHttpMessageValidationThrowDigestException() throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException { + LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { - doThrow( - new LollipopDigestException( - LollipopDigestException.ErrorCode.INCORRECT_DIGEST, "error")) + doThrow(new LollipopDigestException( + LollipopDigestException.ErrorCode.INCORRECT_DIGEST, "error")) .when(messageVerifierServiceMock) .verifyHttpMessage(any(LollipopConsumerRequest.class)); @@ -51,6 +56,7 @@ void failedHttpMessageValidationThrowDigestException() HttpMessageVerificationResultCode.DIGEST_VALIDATION_ERROR.name(), commandResult.getResultCode()); + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock, never()) .validateLollipop(any(LollipopConsumerRequest.class)); @@ -70,6 +76,7 @@ void failedHttpMessageValidationThrowUnsupportedEncodingException() { HttpMessageVerificationResultCode.UNSUPPORTED_ENCODING.name(), commandResult.getResultCode()); + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock, never()) .validateLollipop(any(LollipopConsumerRequest.class)); @@ -78,7 +85,7 @@ void failedHttpMessageValidationThrowUnsupportedEncodingException() { @Test void failedHttpMessageValidationWithoutThrowingException() throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException { + LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { doReturn(false) .when(messageVerifierServiceMock) @@ -90,6 +97,7 @@ void failedHttpMessageValidationWithoutThrowingException() HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_FAILED.name(), commandResult.getResultCode()); + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock, never()) .validateLollipop(any(LollipopConsumerRequest.class)); @@ -98,7 +106,7 @@ void failedHttpMessageValidationWithoutThrowingException() @Test void failedAssertionValidationWithoutThrowingException() throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException { + LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { doReturn(true) .when(messageVerifierServiceMock) @@ -113,6 +121,7 @@ void failedAssertionValidationWithoutThrowingException() AssertionVerificationResultCode.ASSERTION_VERIFICATION_FAILED.name(), commandResult.getResultCode()); + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } @@ -120,7 +129,7 @@ void failedAssertionValidationWithoutThrowingException() @Test void successLollipopRequestValidation() throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException { + LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { doReturn(true) .when(messageVerifierServiceMock) @@ -133,6 +142,115 @@ void successLollipopRequestValidation() Assertions.assertEquals("SUCCESS", commandResult.getResultCode()); + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); + } + + @Test + void failedLollipopRequestValidation() + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + + + doThrow(LollipopRequestContentValidationException.class).when(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + + Assertions.assertEquals("REQUEST PARAMS VALIDATION FAILED", commandResult.getResultCode()); + + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(messageVerifierServiceMock, never()).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock, never()).validateLollipop(any(LollipopConsumerRequest.class)); + } + + @Test + void failedAssertionValidationThrowErrorRetrievingAssertionException() + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + + doReturn(true) + .when(messageVerifierServiceMock) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); + doThrow(ErrorRetrievingAssertionException.class) + .when(assertionVerifierServiceMock) + .validateLollipop(any(LollipopConsumerRequest.class)); + + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + + Assertions.assertEquals( + AssertionVerificationResultCode.ERROR_RETRIEVING_ASSERTION.name(), + commandResult.getResultCode()); + + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); + } + + @Test + void failedAssertionValidationThrowAssertionPeriodException() + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + + doReturn(true) + .when(messageVerifierServiceMock) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); + doThrow(AssertionPeriodException.class) + .when(assertionVerifierServiceMock) + .validateLollipop(any(LollipopConsumerRequest.class)); + + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + + Assertions.assertEquals( + AssertionVerificationResultCode.PERIOD_VALIDATION_ERROR.name(), + commandResult.getResultCode()); + + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); + } + + @Test + void failedAssertionValidationThrowAssertionThumbprintException() + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + + doReturn(true) + .when(messageVerifierServiceMock) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); + doThrow(AssertionThumbprintException.class) + .when(assertionVerifierServiceMock) + .validateLollipop(any(LollipopConsumerRequest.class)); + + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + + Assertions.assertEquals( + AssertionVerificationResultCode.THUMBPRINT_VALIDATION_ERROR.name(), + commandResult.getResultCode()); + + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); + } + + @Test + void failedAssertionValidationThrowAssertionUserIdException() + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + + doReturn(true) + .when(messageVerifierServiceMock) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); + doThrow(AssertionUserIdException.class) + .when(assertionVerifierServiceMock) + .validateLollipop(any(LollipopConsumerRequest.class)); + + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + + Assertions.assertEquals( + AssertionVerificationResultCode.USER_ID_VALIDATION_ERROR.name(), + commandResult.getResultCode()); + + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } From e1254d6561ed5df3d57f25d2f3ef55a9b0e2bc94 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 14 Apr 2023 16:48:57 +0200 Subject: [PATCH 175/403] [SLS-33] Introducing sonarqube plugin and management in pr_scan action --- .github/workflows/pr_scan.yml | 17 ++++++++++++++++- build.gradle | 8 ++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index c61cdd6d..49eb09d5 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -7,6 +7,8 @@ env: DOCKERFILE: Dockerfile.test-only GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_ACTOR: ${{ secrets.GITHUB_ACTOR }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + PROJECT_KEY: 'eng-lollipop-consumer-java-sdk' jobs: pr_scan: @@ -21,10 +23,23 @@ jobs: fetch-depth: 0 - name: Setup Gradle uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 + - name: Cache SonarCloud packages + uses: actions/cache@v1 + with: + path: ~/.sonar-project.properties/cache + key: ${{ runner.os }}-sonar-project.properties + restore-keys: ${{ runner.os }}-sonar-project.properties - name: Make gradlew executable run: chmod +x ./gradlew - name: Run build with Gradle Wrapper - run: ./gradlew build + run: ./gradlew build sonarqube + -Dsonar.organization=pagopa + -Dsonar.projectKey=${{ env.PROJECT_KEY }} + -Dsonar.host.url=https://sonarcloud.io + -Dsonar.login=${{ env.SONAR_TOKEN }} + -Dsonar.pullrequest.key=${{ github.event.pull_request.number }} + -Dsonar.pullrequest.branch=${{ github.head_ref }} + -Dsonar.pullrequest.base=${{ github.base_ref }} - name: Build the Docker image run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest - name: Run the Anchore Grype scan action diff --git a/build.gradle b/build.gradle index 75f4874d..e71094e6 100644 --- a/build.gradle +++ b/build.gradle @@ -4,6 +4,7 @@ plugins { id("com.diffplug.spotless") version "6.17.0" id("nebula.lint") version "18.0.3" id("org.kordamp.gradle.reproducible") version "0.50.0" + id "org.sonarqube" version "3.5.0.2730" } repositories { @@ -130,6 +131,13 @@ subprojects { } } } + subprojects { + sonar { + properties { + property "sonar.sources", "src" + } + } + } } } From 3c0e8b57927aeedc4240064e985b8f968650b7e5 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 14 Apr 2023 16:51:24 +0200 Subject: [PATCH 176/403] [SLS-33] Updated pr_scan.yml --- .github/workflows/pr_scan.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 49eb09d5..aab57743 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -24,11 +24,11 @@ jobs: - name: Setup Gradle uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 - name: Cache SonarCloud packages - uses: actions/cache@v1 - with: - path: ~/.sonar-project.properties/cache - key: ${{ runner.os }}-sonar-project.properties - restore-keys: ${{ runner.os }}-sonar-project.properties + uses: actions/cache@v1 + with: + path: ~/.sonar-project.properties/cache + key: ${{ runner.os }}-sonar-project.properties + restore-keys: ${{ runner.os }}-sonar-project.properties - name: Make gradlew executable run: chmod +x ./gradlew - name: Run build with Gradle Wrapper From 7318d9c1434d721ad78261c5bdfc304016cfef52 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 14 Apr 2023 16:53:44 +0200 Subject: [PATCH 177/403] [SLS-33] Updated verification-metadata.xml --- gradle/verification-metadata.xml | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index a255d04b..81b8304f 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -934,9 +934,11 @@ + + @@ -1663,9 +1665,11 @@ + + @@ -3193,6 +3197,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 96611e4d502fa4743b7f739b8465bb46cb4c1a3d Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 14 Apr 2023 17:15:58 +0200 Subject: [PATCH 178/403] [SLS-33] Updated pr_scan.yml --- .github/workflows/pr_scan.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index aab57743..2644b1c2 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -37,9 +37,6 @@ jobs: -Dsonar.projectKey=${{ env.PROJECT_KEY }} -Dsonar.host.url=https://sonarcloud.io -Dsonar.login=${{ env.SONAR_TOKEN }} - -Dsonar.pullrequest.key=${{ github.event.pull_request.number }} - -Dsonar.pullrequest.branch=${{ github.head_ref }} - -Dsonar.pullrequest.base=${{ github.base_ref }} - name: Build the Docker image run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest - name: Run the Anchore Grype scan action From 9ab2e7400feedae03cd3be8269bd800f2c5741ad Mon Sep 17 00:00:00 2001 From: giomella Date: Fri, 14 Apr 2023 18:19:30 +0200 Subject: [PATCH 179/403] [SLS-21] added unit test for LollipopConsumerRequestValidationServiceImpl and do some fix. --- core/build.gradle | 1 + ...ipopRequestContentValidationException.java | 6 +- ...pConsumerRequestValidationServiceImpl.java | 42 +- .../AssertionVerifierServiceImplTest.java | 7 +- ...sumerRequestValidationServiceImplTest.java | 362 ++++++++++++++++++ 5 files changed, 395 insertions(+), 23 deletions(-) create mode 100644 core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java diff --git a/core/build.gradle b/core/build.gradle index b13a86e8..cb35f651 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -37,6 +37,7 @@ dependencies { implementation 'com.typesafe:config:1.4.2' implementation 'javax.inject:javax.inject:1' implementation 'com.nimbusds:nimbus-jose-jwt:9.31' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.2' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.mockito:mockito-core:5.2.0' diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java index a9facc20..5e6516ad 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java @@ -45,11 +45,11 @@ public ErrorCode getErrorCode() { /** Error codes to classify Lollipop Request Exceptions */ public enum ErrorCode { - UNEXPECTED_METHOD_OR_URL, - + UNEXPECTED_ORIGINAL_METHOD, + UNEXPECTED_ORIGINAL_URL, MISSING_SIGNATURE, - INVALID_SIGNATURE_HEADER, + INVALID_SIGNATURE, MISSING_SIGNATURE_INPUT, INVALID_SIGNATURE_INPUT, diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java index 730c484f..b4908609 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java @@ -1,16 +1,21 @@ package it.pagopa.tech.lollipop.consumer.service.impl; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionRefAlgorithms; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionType; import it.pagopa.tech.lollipop.consumer.enumeration.LollipopRequestMethod; import it.pagopa.tech.lollipop.consumer.exception.LollipopRequestContentValidationException; +import it.pagopa.tech.lollipop.consumer.model.ECPublicKey; 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.Map; import java.util.regex.Pattern; -public class LollipopConsumerRequestValidationServiceImpl implements it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService { +public class LollipopConsumerRequestValidationServiceImpl implements LollipopConsumerRequestValidationService { private final LollipopConsumerRequestConfig config; @@ -22,8 +27,6 @@ public LollipopConsumerRequestValidationServiceImpl(LollipopConsumerRequestConfi public void validateLollipopRequest(LollipopConsumerRequest request) throws LollipopRequestContentValidationException { Map headerParams = request.getHeaderParams(); - validatesOriginalMethodAndURL(headerParams.get(this.config.getOriginalMethodHeader()), headerParams.get(this.config.getOriginalURLHeader())); - validatePublicKey(headerParams.get(this.config.getPublicKeyHeader())); validateAssertionRefHeader(headerParams.get(this.config.getAssertionRefHeader())); @@ -36,26 +39,23 @@ public void validateLollipopRequest(LollipopConsumerRequest request) throws Loll validateSignatureHeader(headerParams.get(this.config.getSignatureHeader())); } - private void validatesOriginalMethodAndURL(String originalMethod, String originalUrl) throws LollipopRequestContentValidationException { - - if (!originalMethod.equals(this.config.getExpectedFirstLcOriginalMethod()) && !originalUrl.equals(this.config.getExpectedFirstLcOriginalUrl())) { - String errMsg = String.format("Unexpected original method and/or original url: %s, %s", originalMethod, originalUrl); - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_METHOD_OR_URL, errMsg); - } - } - private void validatePublicKey(String publicKey) throws LollipopRequestContentValidationException { if (publicKey == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_PUBLIC_KEY, "Missing Public Key Header"); } - if (isNotValidPublicKey(publicKey)) { + if (isNotValidPublicKey(publicKey, ECPublicKey.class) && isNotValidPublicKey(publicKey, RSAPublicKey.class)) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_PUBLIC_KEY, "Invalid Public Key Header value"); } } - private boolean isNotValidPublicKey(String publicKey) { - // TODO + private boolean isNotValidPublicKey(String publicKey, Class clazz) { + ObjectMapper mapper = new ObjectMapper(); + try { + mapper.readValue(publicKey, clazz); + } catch (JsonProcessingException e) { + return true; + } return false; } @@ -127,6 +127,11 @@ private void validateOriginalMethodHeader(String originalMethod) throws Lollipop if (!isRequestMethodSupported(originalMethod)) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_METHOD, "Invalid Original Method Header value, method not supported"); } + + if (!originalMethod.equals(this.config.getExpectedFirstLcOriginalMethod())) { + String errMsg = String.format("Unexpected original method: %s", originalMethod); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_METHOD, errMsg); + } } private boolean isRequestMethodSupported(String originalMethod) { @@ -146,10 +151,15 @@ private void validateOriginalURLHeader(String originalURL) throws LollipopReques if (isNotValidOriginalURL(originalURL)) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_URL, "Invalid Original URL Header value"); } + + if (!originalURL.equals(this.config.getExpectedFirstLcOriginalUrl())) { + String errMsg = String.format("Unexpected original url: %s", originalURL); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_URL, errMsg); + } } private boolean isNotValidOriginalURL(String originalURL) { - return !Pattern.compile("^https://").matcher(originalURL).matches(); + return !Pattern.compile("^https://\\S+").matcher(originalURL).matches(); } private void validateSignatureInputHeader(String signatureInput) throws LollipopRequestContentValidationException { @@ -172,7 +182,7 @@ private void validateSignatureHeader(String signature) throws LollipopRequestCon } if (isNotValidSignature(signature)) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE_HEADER, "Invalid Signature Header value"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE, "Invalid Signature Header value"); } } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java index ad9433e9..a31f63ed 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java @@ -29,8 +29,7 @@ class AssertionVerifierServiceImplTest { private AssertionVerifierService sut; private static final String VALID_FISCAL_CODE = "AAAAAA89S20I111X"; - private static final String INVALID_JWK = "{ alg: \"\", e: \"e\", kty: \"RSA\", n: \"n\"}"; - private static final String VALID_JWK = "{ kty: \"EC\", crv: \"P-256\", x: \"SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74\", y: \"lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI\"}"; + private static final String VALID_JWK = "{ \"kty\": \"EC\", \"crv\": \"P-256\", \"x\": \"SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74\", \"y\": \"lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI\"}"; private static final String VALID_SHA_256_ASSERTION_REF = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; private static final String VALID_SHA_384_ASSERTION_REF = "sha384-lqxC_2kqMdwiBWoD-Us63Fha6e3bE1Y3yUz8G6IJTldohJCIBVDfvS8acB3GJBhw"; private static final String VALID_SHA_512_ASSERTION_REF = "sha512-nX5CfUc5R-FoYKYZwvQMuc4Tt-heb7vHi_O-AMUSqHNVCw9kNaN2SVuN-DXtGXyUhrcVcQdCyY6FVzl_vyWXNA"; @@ -235,8 +234,8 @@ void validateLollipopValidateThumbprintFailureWithErrorCalculatingThumbprint() t } @Test - void validateLollipopValidateThumbprintFailureWithInvalidPublicKey() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { - LollipopConsumerRequest request = getLollipopConsumerRequest("", INVALID_JWK, VALID_FISCAL_CODE); + void validateLollipopValidateThumbprintFailureWithDifferentAssertionRefAndCalculatedThumbprint() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", VALID_JWK, VALID_FISCAL_CODE); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java new file mode 100644 index 00000000..0e921866 --- /dev/null +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java @@ -0,0 +1,362 @@ +package it.pagopa.tech.lollipop.consumer.service.impl; + +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.enumeration.AssertionType; +import it.pagopa.tech.lollipop.consumer.exception.LollipopRequestContentValidationException; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.spy; + +class LollipopConsumerRequestValidationServiceImplTest { + + public static final String VALID_EC_PUBLIC_KEY = "{ \"kty\": \"EC\", \"x\": \"FqFDuwEgu4MUXERPMVL-85pGv2D3YmL4J1gfMkdbc24\", \"y\": \"hdV0oxmWFSxMoJUDpdihr76rS8VRBEqMFebYyAfK9-k\", \"crv\": \"P-256\"}"; + public static final String VALID_RSA_PUBLIC_KEY = "{ \"alg\": \"RS256\", \"e\": \"AQAB\", \"kty\": \"RSA\", \"n\": \"yeNlzlub94YgerT030codqEztjfU_S6X4DbDA_iVKkjAWtYfPHDzz_sPCT1Axz6isZdf3lHpq_gYX4Sz\"}"; + public static final String VALID_ASSERTION_REF = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; + public static final String VALID_FISCAL_CODE = "AAAAAA89S20I111X"; + public static final String VALID_JWT = "aValidJWT"; + public static final String VALID_SIGNATURE_INPUT = "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + public static final String VALID_SIGNATURE = "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + public static final String RANDOM_STRING = ""; + private LollipopConsumerRequestConfig config; + + private LollipopConsumerRequestValidationService sut; + + @BeforeEach + void setUp() { + config = spy(LollipopConsumerRequestConfig.builder().build()); + sut = new LollipopConsumerRequestValidationServiceImpl(config); + } + + @Test + void validatePublicKeyFailureHeaderNotPresent() { + HashMap headers = new HashMap<>(); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_PUBLIC_KEY, e.getErrorCode()); + } + + @Test + void validatePublicKeyFailureHeaderInvalidFormat() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), RANDOM_STRING); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_PUBLIC_KEY, e.getErrorCode()); + } + + @Test + void validateAssertionRefFailureHeaderNotPresent() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_REF, e.getErrorCode()); + } + + @Test + void validateAssertionRefFailureInvalidFormat() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), RANDOM_STRING); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_REF, e.getErrorCode()); + } + + @Test + void validateAssertionTypeFailureHeaderNotPresent() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_TYPE, e.getErrorCode()); + } + + @Test + void validateAssertionTypeFailureInvalidFormat() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), RANDOM_STRING); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_TYPE, e.getErrorCode()); + } + + @Test + void validateUserIdFailureHeaderNotPresent() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_USER_ID, e.getErrorCode()); + } + + @Test + void validateUserIdFailureInvalidFormat() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), RANDOM_STRING); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_USER_ID, e.getErrorCode()); + } + + @Test + void validateAuthJWKFailureHeaderNotPresent() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_AUTH_JWT, e.getErrorCode()); + } + + @Test + void validateAuthJWKFailureInvalidFormat() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), RANDOM_STRING); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_AUTH_JWT, e.getErrorCode()); + } + + @Test + void validateOriginalMethodFailureHeaderNotPresent() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_METHOD, e.getErrorCode()); + } + + @Test + void validateOriginalMethodFailureNotSupported() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), "INVALID_METHOD"); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_METHOD, e.getErrorCode()); + } + + @Test + void validateOriginalMethodFailureDifferentFromExpectedMethod() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), "PUT"); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_METHOD, e.getErrorCode()); + } + @Test + void validateOriginalURLFailureHeaderNotPresent() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_URL, e.getErrorCode()); + } + + @Test + void validateOriginalURLFailureInvalidFormat() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); + headers.put(config.getOriginalURLHeader(), RANDOM_STRING); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_URL, e.getErrorCode()); + } + + @Test + void validateOriginalURLFailureDifferentFromExpectedMethod() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); + headers.put(config.getOriginalURLHeader(), "https://pagopa.it"); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_URL, e.getErrorCode()); + } + + @Test + void validateSignatureInputFailureHeaderNotPresent() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); + headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE_INPUT, e.getErrorCode()); + } + + @Test + void validateSignatureInputFailureInvalidFormat() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); + headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); + headers.put(config.getSignatureInputHeader(), RANDOM_STRING); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE_INPUT, e.getErrorCode()); + } + + @Test + void validateSignatureFailureHeaderNotPresent() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); + headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); + headers.put(config.getSignatureInputHeader(), VALID_SIGNATURE_INPUT); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE, e.getErrorCode()); + } + + @Test + void validateSignatureFailureInvalidFormat() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); + headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); + headers.put(config.getSignatureInputHeader(), VALID_SIGNATURE_INPUT); + headers.put(config.getSignatureHeader(), RANDOM_STRING); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE, e.getErrorCode()); + } + + @Test + void validateRequestSuccessWithECPublicKey() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); + headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); + headers.put(config.getSignatureInputHeader(), VALID_SIGNATURE_INPUT); + headers.put(config.getSignatureHeader(), VALID_SIGNATURE); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + assertDoesNotThrow(() -> sut.validateLollipopRequest(request)); + } + + @Test + void validateRequestSuccessWithRSAPublicKey() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_RSA_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); + headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); + headers.put(config.getSignatureInputHeader(), VALID_SIGNATURE_INPUT); + headers.put(config.getSignatureHeader(), VALID_SIGNATURE); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + assertDoesNotThrow(() -> sut.validateLollipopRequest(request)); + } +} \ No newline at end of file From b30eacbcdea2c6826a9c4b59bfffee02e9456001 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 14 Apr 2023 18:28:05 +0200 Subject: [PATCH 180/403] [SLS-33] Updated pr_scan.yml, introducing jacoco test coverage plugin --- .github/workflows/pr_scan.yml | 5 +- build.gradle | 23 ++++++- core/build.gradle | 7 +++ gradle/verification-metadata.xml | 61 +++++++++++++++++++ .../build.gradle | 7 +++ redis-storage/build.gradle | 7 +++ settings.gradle | 2 +- test-coverage/build.gradle | 47 ++++++++++++++ 8 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 test-coverage/build.gradle diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 2644b1c2..2b8337f7 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -8,7 +8,7 @@ env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_ACTOR: ${{ secrets.GITHUB_ACTOR }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - PROJECT_KEY: 'eng-lollipop-consumer-java-sdk' + PROJECT_KEY: 'pagopa.eng-lollipop-consumer-java-sdk' jobs: pr_scan: @@ -37,6 +37,9 @@ jobs: -Dsonar.projectKey=${{ env.PROJECT_KEY }} -Dsonar.host.url=https://sonarcloud.io -Dsonar.login=${{ env.SONAR_TOKEN }} + -Dsonar.pullrequest.key=${{ github.event.pull_request.number }} + -Dsonar.pullrequest.branch=${{ github.head_ref }} + -Dsonar.pullrequest.base=${{ github.base_ref }} - name: Build the Docker image run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest - name: Run the Anchore Grype scan action diff --git a/build.gradle b/build.gradle index e71094e6..28173590 100644 --- a/build.gradle +++ b/build.gradle @@ -5,10 +5,19 @@ plugins { id("nebula.lint") version "18.0.3" id("org.kordamp.gradle.reproducible") version "0.50.0" id "org.sonarqube" version "3.5.0.2730" + id 'jacoco' } repositories { + mavenLocal() mavenCentral() + maven { + url = uri("https://maven.pkg.github.com/pagopa/eng-http-signatures") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + } + } gradlePluginPortal() } @@ -19,7 +28,7 @@ allprojects { targetCompatibility = '11' apply plugin: 'com.diffplug.spotless' apply plugin: 'nebula.lint' - gradleLint.rules = ['all-dependency'] + gradleLint.rules = [] configurations { spotless { @@ -80,6 +89,7 @@ subprojects { apply plugin: 'java' apply plugin: 'org.kordamp.gradle.reproducible' apply plugin: 'maven-publish' + apply plugin: 'jacoco' apply plugin: 'org.graalvm.buildtools.native' @@ -138,6 +148,17 @@ subprojects { } } } + + test { + finalizedBy jacocoTestReport // report is always generated after tests run + jacoco { + excludes = ["**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*"] + } + } + jacocoTestReport { + dependsOn test // tests are required to run before generating the report + } + } } diff --git a/core/build.gradle b/core/build.gradle index f570fbda..3c415733 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -16,6 +16,13 @@ plugins { repositories { mavenLocal() mavenCentral() + maven { + url = uri("https://maven.pkg.github.com/pagopa/eng-http-signatures") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + } + } } configurations { diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 81b8304f..34eb4069 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2590,6 +2590,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3127,6 +3164,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/identity-service-rest-client-native/build.gradle b/identity-service-rest-client-native/build.gradle index 31069e5a..54368b11 100644 --- a/identity-service-rest-client-native/build.gradle +++ b/identity-service-rest-client-native/build.gradle @@ -18,6 +18,13 @@ group 'it.pagopa.tech.lollipop.sdk.impls' repositories { mavenLocal() mavenCentral() + maven { + url = uri("https://maven.pkg.github.com/pagopa/eng-http-signatures") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + } + } } configurations { diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle index cad17071..dcab70e8 100644 --- a/redis-storage/build.gradle +++ b/redis-storage/build.gradle @@ -16,6 +16,13 @@ plugins { repositories { mavenLocal() mavenCentral() + maven { + url = uri("https://maven.pkg.github.com/pagopa/eng-http-signatures") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + } + } } configurations { diff --git a/settings.gradle b/settings.gradle index 8e918fab..d9f15bbf 100644 --- a/settings.gradle +++ b/settings.gradle @@ -29,4 +29,4 @@ gradleEnterprise { } rootProject.name = 'eng-lollipop-consumer-java-sdk' -include 'core', 'assertion-rest-client-native', 'http-verifier', 'identity-service-rest-client-native', 'redis-storage' +include 'core', 'assertion-rest-client-native', 'http-verifier', 'identity-service-rest-client-native', 'redis-storage', 'test-coverage' diff --git a/test-coverage/build.gradle b/test-coverage/build.gradle new file mode 100644 index 00000000..63607a1f --- /dev/null +++ b/test-coverage/build.gradle @@ -0,0 +1,47 @@ +plugins { + id 'base' + id 'jacoco-report-aggregation' +} + +repositories { + mavenLocal() + mavenCentral() + maven { + url = uri("https://maven.pkg.github.com/pagopa/eng-http-signatures") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + } + }} + +dependencies { + jacocoAggregation project(':http-verifier') + jacocoAggregation project(':identity-service-rest-client-native') + jacocoAggregation project(':assertion-rest-client-native') +} + +reporting { + reports { + testCodeCoverageReport(JacocoCoverageReport) { + testType = TestSuiteType.UNIT_TEST + } + } +} + +tasks.named('check') { + dependsOn tasks.named('testCodeCoverageReport', JacocoReport) +} + +testCodeCoverageReport { + getClassDirectories().setFrom(files( + [project(':http-verifier'), + project(':identity-service-rest-client-native'), + project(':assertion-rest-client-native'), + project(':core') + ].collect { + it.fileTree(dir: "${it.buildDir}/classes", exclude: [ + "**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*" + ]) + } + )) +} From 3e372fa9e3083d8b29c5200213d2f900be389f14 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 14 Apr 2023 18:37:11 +0200 Subject: [PATCH 181/403] [SLS-33] Updated build.gradle --- test-coverage/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test-coverage/build.gradle b/test-coverage/build.gradle index 63607a1f..8a804e88 100644 --- a/test-coverage/build.gradle +++ b/test-coverage/build.gradle @@ -35,9 +35,9 @@ tasks.named('check') { testCodeCoverageReport { getClassDirectories().setFrom(files( [project(':http-verifier'), - project(':identity-service-rest-client-native'), - project(':assertion-rest-client-native'), - project(':core') + project(':identity-service-rest-client-native'), + project(':assertion-rest-client-native'), + project(':core') ].collect { it.fileTree(dir: "${it.buildDir}/classes", exclude: [ "**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*" From 8cd7efc3714931f794a10ff8e767268c8746c9a2 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 14 Apr 2023 18:45:47 +0200 Subject: [PATCH 182/403] [SLS-33] Updated pr_scan.yml --- .github/workflows/pr_scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 2b8337f7..533dfbb2 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -32,7 +32,7 @@ jobs: - name: Make gradlew executable run: chmod +x ./gradlew - name: Run build with Gradle Wrapper - run: ./gradlew build sonarqube + run: ./gradlew build sonar -Dsonar.organization=pagopa -Dsonar.projectKey=${{ env.PROJECT_KEY }} -Dsonar.host.url=https://sonarcloud.io From b0e6becf2eecdae0ca88242739401f941d502de7 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 14 Apr 2023 18:48:42 +0200 Subject: [PATCH 183/403] [SLS-33] Updated pr_scan.yml --- .github/workflows/pr_scan.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 533dfbb2..66e140c7 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -32,7 +32,7 @@ jobs: - name: Make gradlew executable run: chmod +x ./gradlew - name: Run build with Gradle Wrapper - run: ./gradlew build sonar + run: ./gradlew build testCodeCoverageReport -Dsonar.organization=pagopa -Dsonar.projectKey=${{ env.PROJECT_KEY }} -Dsonar.host.url=https://sonarcloud.io @@ -40,6 +40,14 @@ jobs: -Dsonar.pullrequest.key=${{ github.event.pull_request.number }} -Dsonar.pullrequest.branch=${{ github.head_ref }} -Dsonar.pullrequest.base=${{ github.base_ref }} + - name: Add coverage to PR + id: jacoco + uses: madrapps/jacoco-report@v1.3 + with: + paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCoverage/testCoverage.xml + token: ${{ secrets.GITHUB_TOKEN }} + min-coverage-overall: 40 + min-coverage-changed-files: 60 - name: Build the Docker image run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest - name: Run the Anchore Grype scan action @@ -54,3 +62,12 @@ jobs: if: always() with: sarif_file: ${{ steps.scan.outputs.sarif }} + - name: Run Sonar Scanner + run: ./gradlew sonar + -Dsonar.organization=pagopa + -Dsonar.projectKey=${{ env.PROJECT_KEY }} + -Dsonar.host.url=https://sonarcloud.io + -Dsonar.login=${{ env.SONAR_TOKEN }} + -Dsonar.pullrequest.key=${{ github.event.pull_request.number }} + -Dsonar.pullrequest.branch=${{ github.head_ref }} + -Dsonar.pullrequest.base=${{ github.base_ref }} From 4b66efddf21590c6906bde5796c89ee33d34ad8b Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 14 Apr 2023 18:54:50 +0200 Subject: [PATCH 184/403] [SLS-33] Updated pr_scan.yml --- .github/workflows/pr_scan.yml | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 66e140c7..f8226200 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -33,18 +33,11 @@ jobs: run: chmod +x ./gradlew - name: Run build with Gradle Wrapper run: ./gradlew build testCodeCoverageReport - -Dsonar.organization=pagopa - -Dsonar.projectKey=${{ env.PROJECT_KEY }} - -Dsonar.host.url=https://sonarcloud.io - -Dsonar.login=${{ env.SONAR_TOKEN }} - -Dsonar.pullrequest.key=${{ github.event.pull_request.number }} - -Dsonar.pullrequest.branch=${{ github.head_ref }} - -Dsonar.pullrequest.base=${{ github.base_ref }} - name: Add coverage to PR id: jacoco - uses: madrapps/jacoco-report@v1.3 + uses: madrapps/jacoco-report@7a334255fbce42f385d7567c25d986a9c62e2971 with: - paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCoverage/testCoverage.xml + paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCoverageReport/testCoverageReport.xml token: ${{ secrets.GITHUB_TOKEN }} min-coverage-overall: 40 min-coverage-changed-files: 60 From 5ee066940c5cd52d1699e9d025052259dceb4f7f Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 14 Apr 2023 18:59:41 +0200 Subject: [PATCH 185/403] [SLS-33] Updated pr_scan.yml --- .github/workflows/pr_scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index f8226200..81fdae03 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -37,7 +37,7 @@ jobs: id: jacoco uses: madrapps/jacoco-report@7a334255fbce42f385d7567c25d986a9c62e2971 with: - paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCoverageReport/testCoverageReport.xml + paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml token: ${{ secrets.GITHUB_TOKEN }} min-coverage-overall: 40 min-coverage-changed-files: 60 From b4b62a899ddae338fd07f40f49906020d4675ca4 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 14 Apr 2023 19:10:26 +0200 Subject: [PATCH 186/403] [SLS-33] Updated pr_scan.yml --- .github/workflows/pr_scan.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 81fdae03..5cdac27b 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -14,8 +14,9 @@ jobs: pr_scan: runs-on: ubuntu-latest permissions: - contents: read - packages: read + contents: write + pull-requests: write + steps: - name: Checkout project sources uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 From 781663966fc9a136d3bef32da6f84908477da6e4 Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 17 Apr 2023 09:21:34 +0200 Subject: [PATCH 187/403] [SLS-21] fix javadoc. --- .../service/LollipopConsumerRequestValidationService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java index bdf34001..67da2603 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java @@ -12,7 +12,6 @@ public interface LollipopConsumerRequestValidationService { * Validates all request headers * * @param request the Lollipop request - * @return true if the request is validated * @throws LollipopRequestContentValidationException if some error occurred during validation */ void validateLollipopRequest(LollipopConsumerRequest request) throws LollipopRequestContentValidationException; From 81aaffb15d575a417eb3b71170890e0f459f6e55 Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 17 Apr 2023 09:27:54 +0200 Subject: [PATCH 188/403] [SLS-21] applied spotless formatting. --- .../LollipopConsumerCommandBuilderImpl.java | 3 +- .../impl/LollipopConsumerCommandImpl.java | 47 +- .../config/LollipopConsumerRequestConfig.java | 14 +- .../enumeration/AssertionRefAlgorithms.java | 18 +- .../consumer/enumeration/AssertionType.java | 7 +- .../AssertionVerificationResultCode.java | 16 +- .../enumeration/LollipopRequestMethod.java | 5 +- .../exception/AssertionPeriodException.java | 5 +- .../AssertionThumbprintException.java | 5 +- .../exception/AssertionUserIdException.java | 6 +- .../ErrorRetrievingAssertionException.java | 7 +- ...ipopRequestContentValidationException.java | 9 +- .../helper/LollipopConsumerFactoryHelper.java | 8 +- .../lollipop/consumer/model/ECPublicKey.java | 5 +- .../lollipop/consumer/model/RSAPublicKey.java | 5 +- .../service/AssertionVerifierService.java | 7 +- ...lipopConsumerRequestValidationService.java | 8 +- .../impl/AssertionVerifierServiceImpl.java | 179 ++++--- ...pConsumerRequestValidationServiceImpl.java | 158 +++++-- .../impl/LollipopConsumerCommandImplTest.java | 110 +++-- .../AssertionVerifierServiceImplTest.java | 445 ++++++++++++++---- ...sumerRequestValidationServiceImplTest.java | 277 ++++++++--- 22 files changed, 964 insertions(+), 380 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java index c7109f2c..6c10346c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java @@ -29,7 +29,6 @@ public LollipopConsumerCommand createCommand() { return new LollipopConsumerCommandImpl( factoryHelper.getHttpMessageVerifierService(), factoryHelper.getAssertionVerifierService(), - factoryHelper.getRequestValidationService() - ); + factoryHelper.getRequestValidationService()); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index 87eb4b9f..b931cd7b 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -2,7 +2,6 @@ package it.pagopa.tech.lollipop.consumer.command.impl; import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; -import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionVerificationResultCode; import it.pagopa.tech.lollipop.consumer.enumeration.HttpMessageVerificationResultCode; import it.pagopa.tech.lollipop.consumer.exception.*; @@ -10,6 +9,7 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; 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 java.io.UnsupportedEncodingException; import javax.inject.Inject; @@ -21,7 +21,8 @@ public class LollipopConsumerCommandImpl implements LollipopConsumerCommand { private final LollipopConsumerRequestValidationService requestValidationService; public static final String VERIFICATION_SUCCESS_CODE = "SUCCESS"; - public static final String REQUEST_PARAMS_VALIDATION_FAILED = "REQUEST PARAMS VALIDATION FAILED"; + public static final String REQUEST_PARAMS_VALIDATION_FAILED = + "REQUEST PARAMS VALIDATION FAILED"; @Inject public LollipopConsumerCommandImpl( @@ -46,7 +47,11 @@ public CommandResult doExecute(LollipopConsumerRequest request) { try { requestValidationService.validateLollipopRequest(request); } catch (LollipopRequestContentValidationException e) { - String message = String.format("Error validating Lollipop request header or body, validation failed with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); + String message = + String.format( + "Error validating Lollipop request header or body, validation failed" + + " with error code %s and message: %s", + e.getErrorCode(), e.getMessage()); return buildCommandResult(REQUEST_PARAMS_VALIDATION_FAILED, message); } @@ -70,17 +75,37 @@ private CommandResult getAssertionVerificationResult(LollipopConsumerRequest req try { result = assertionVerifierService.validateLollipop(request); } catch (ErrorRetrievingAssertionException e) { - String message = String.format("Cannot obtain the assertion, validation failed with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); - return buildCommandResult(AssertionVerificationResultCode.ERROR_RETRIEVING_ASSERTION.name(), message); + String message = + String.format( + "Cannot obtain the assertion, validation failed with error code %s" + + " and message: %s", + e.getErrorCode(), e.getMessage()); + return buildCommandResult( + AssertionVerificationResultCode.ERROR_RETRIEVING_ASSERTION.name(), message); } catch (AssertionPeriodException e) { - String message = String.format("Assertion validation failed on verifying period with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); - return buildCommandResult(AssertionVerificationResultCode.PERIOD_VALIDATION_ERROR.name(), message); + String message = + String.format( + "Assertion validation failed on verifying period with error code %s" + + " and message: %s", + e.getErrorCode(), e.getMessage()); + return buildCommandResult( + AssertionVerificationResultCode.PERIOD_VALIDATION_ERROR.name(), message); } catch (AssertionThumbprintException e) { - String message = String.format("Assertion validation failed on verifying thumbprint with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); - return buildCommandResult(AssertionVerificationResultCode.THUMBPRINT_VALIDATION_ERROR.name(), message); + String message = + String.format( + "Assertion validation failed on verifying thumbprint with error code" + + " %s and message: %s", + e.getErrorCode(), e.getMessage()); + return buildCommandResult( + AssertionVerificationResultCode.THUMBPRINT_VALIDATION_ERROR.name(), message); } catch (AssertionUserIdException e) { - String message = String.format("Assertion validation failed on verifying user id with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); - return buildCommandResult(AssertionVerificationResultCode.USER_ID_VALIDATION_ERROR.name(), message); + String message = + String.format( + "Assertion validation failed on verifying user id with error code %s" + + " and message: %s", + e.getErrorCode(), e.getMessage()); + return buildCommandResult( + AssertionVerificationResultCode.USER_ID_VALIDATION_ERROR.name(), message); } if (!result) { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index 4cb1ab4f..d746503b 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -10,7 +10,7 @@ public class LollipopConsumerRequestConfig { @Builder.Default private boolean strictDigestVerify = false; - //request headers + // request headers @Builder.Default private String signatureHeader = "signature"; @Builder.Default private String signatureInputHeader = "signature-input"; @Builder.Default private String contentEncodingHeader = "content-encoding"; @@ -24,16 +24,18 @@ public class LollipopConsumerRequestConfig { @Builder.Default private String authJWTHeader = "x-pagopa-lollipop-auth-jwt"; @Builder.Default private String expectedFirstLcOriginalMethod = "POST"; - @Builder.Default private String expectedFirstLcOriginalUrl = "https://api-app.io.pagopa.it/first-lollipop/sign"; + + @Builder.Default + private String expectedFirstLcOriginalUrl = "https://api-app.io.pagopa.it/first-lollipop/sign"; // assertion validation parameters @Builder.Default private int assertionExpireInDays = 30; @Builder.Default private String assertionNotBeforeDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; - @Builder.Default private String samlNamespaceAssertion = "urn:oasis:names:tc:SAML:2.0:assertion"; + + @Builder.Default + private String samlNamespaceAssertion = "urn:oasis:names:tc:SAML:2.0:assertion"; + @Builder.Default private String assertionNotBeforeTag = "Conditions"; @Builder.Default private String assertionFiscalCodeTag = "Attribute"; @Builder.Default private String assertionInResponseToTag = "SubjectConfirmationData"; - - - } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java index fe5a5b30..cbe1adb8 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java @@ -1,12 +1,10 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.enumeration; import java.util.regex.Pattern; -/** - * Supported AssertionRef algorithms - */ +/** Supported AssertionRef algorithms */ public enum AssertionRefAlgorithms { - SHA256("sha256", AlgorithmName.SHA_256, Pattern.compile("^(sha256-[A-Za-z0-9-_=]{1,44})$")), SHA384("sha384", AlgorithmName.SHA_384, Pattern.compile("^(sha384-[A-Za-z0-9-_=]{1,66})$")), SHA512("sha512", AlgorithmName.SHA_512, Pattern.compile("^(sha512-[A-Za-z0-9-_=]{1,88})$")); @@ -35,10 +33,14 @@ public String getAlgorithmName() { public static AssertionRefAlgorithms getAlgorithmFromHash(String algorithmName) { switch (algorithmName) { - case AlgorithmName.SHA_256: return SHA256; - case AlgorithmName.SHA_384: return SHA384; - case AlgorithmName.SHA_512: return SHA512; - default: throw new UnsupportedOperationException("Unsupported algorithm: " + algorithmName); + case AlgorithmName.SHA_256: + return SHA256; + case AlgorithmName.SHA_384: + return SHA384; + case AlgorithmName.SHA_512: + return SHA512; + default: + throw new UnsupportedOperationException("Unsupported algorithm: " + algorithmName); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java index 7a47cd22..e9f6f4d0 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java @@ -1,10 +1,9 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.enumeration; -/** - * Supported assertion type - */ +/** Supported assertion type */ public enum AssertionType { SAML, - //TODO: OIDC + // TODO: OIDC } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java index e7cd1d0b..d3b505f0 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java @@ -4,24 +4,16 @@ /** Result codes to classify Saml assertion validation */ public enum AssertionVerificationResultCode { - /** - * Saml assertion validation failed on retrieving the assertion - */ + /** Saml assertion validation failed on retrieving the assertion */ ERROR_RETRIEVING_ASSERTION, - /** - * Saml assertion validation failed on period validation - */ + /** Saml assertion validation failed on period validation */ PERIOD_VALIDATION_ERROR, - /** - * Saml assertion validation failed on user id validation - */ + /** Saml assertion validation failed on user id validation */ USER_ID_VALIDATION_ERROR, - /** - * Saml assertion validation failed on thumbpriint validation - */ + /** Saml assertion validation failed on thumbpriint validation */ THUMBPRINT_VALIDATION_ERROR, /** Saml assertion validation failed without throwing an exception */ diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopRequestMethod.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopRequestMethod.java index ed098922..fe1b87a8 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopRequestMethod.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopRequestMethod.java @@ -1,8 +1,7 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.enumeration; -/** - * Supported Lollipop request methods - */ +/** Supported Lollipop request methods */ public enum LollipopRequestMethod { GET, POST, diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionPeriodException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionPeriodException.java index c9c6dfc6..1ecce2f9 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionPeriodException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionPeriodException.java @@ -1,10 +1,9 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.exception; import java.util.Objects; -/** - * Thrown in case of problems when verifying assertion period - */ +/** Thrown in case of problems when verifying assertion period */ public class AssertionPeriodException extends Exception { /** Error code of this exception */ diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java index 37a12bb0..bfd28080 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java @@ -1,10 +1,9 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.exception; import java.util.Objects; -/** - * Thrown in case of problems when verifying assertion thumbprint - */ +/** Thrown in case of problems when verifying assertion thumbprint */ public class AssertionThumbprintException extends Exception { /** Error code of this exception */ diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionUserIdException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionUserIdException.java index 106b8384..1c334b98 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionUserIdException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionUserIdException.java @@ -1,13 +1,11 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.exception; import java.util.Objects; -/** - * Thrown in case of problems when verifying assertion user id - */ +/** Thrown in case of problems when verifying assertion user id */ public class AssertionUserIdException extends Exception { - /** Error code of this exception */ private final ErrorCode errorCode; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingAssertionException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingAssertionException.java index 7cd1f385..f8476d6d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingAssertionException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingAssertionException.java @@ -1,10 +1,9 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.exception; import java.util.Objects; -/** - * Thrown in case of problems on retrieving the assertion - */ +/** Thrown in case of problems on retrieving the assertion */ public class ErrorRetrievingAssertionException extends Exception { /** Error code of this exception */ @@ -48,4 +47,4 @@ public enum ErrorCode { OIDC_TYPE_NOT_SUPPORTED, ERROR_PARSING_ASSERTION } -} \ No newline at end of file +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java index 5e6516ad..833e3bd4 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java @@ -1,13 +1,11 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.exception; import java.util.Objects; -/** - * Thrown in case of problem during Lollipop request header and body validation - */ +/** Thrown in case of problem during Lollipop request header and body validation */ public class LollipopRequestContentValidationException extends Exception { - /** Error code of this exception */ private final ErrorCode errorCode; @@ -29,7 +27,8 @@ public LollipopRequestContentValidationException(ErrorCode errorCode, String mes * @param message Detail message * @param cause Exception causing the constructed one */ - public LollipopRequestContentValidationException(ErrorCode errorCode, String message, Throwable cause) { + public LollipopRequestContentValidationException( + ErrorCode errorCode, String message, Throwable cause) { super(message, cause); this.errorCode = Objects.requireNonNull(errorCode); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index 76a66ff5..7fee7de2 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -11,7 +11,6 @@ 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 */ @@ -38,9 +37,7 @@ public LollipopConsumerFactoryHelper( */ public HttpMessageVerifierService getHttpMessageVerifierService() { return new HttpMessageVerifierServiceImpl( - getHttpMessageVerifierFactory().create(), - getLollipopConsumerRequestConfig() - ); + getHttpMessageVerifierFactory().create(), getLollipopConsumerRequestConfig()); } /** @@ -52,8 +49,7 @@ public AssertionVerifierService getAssertionVerifierService() { return new AssertionVerifierServiceImpl( getIdpCertProviderFactory().create(), getAssertionServiceFactory().create(), - getLollipopConsumerRequestConfig() - ); + getLollipopConsumerRequestConfig()); } public HttpMessageVerifierFactory getHttpMessageVerifierFactory() { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java index e3581111..8610b7dc 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java @@ -1,10 +1,9 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.model; import lombok.Data; -/** - * EC public key model - */ +/** EC public key model */ @Data public class ECPublicKey { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java index 628d327a..60e103e2 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java @@ -1,10 +1,9 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.model; import lombok.Data; -/** - * RSA public key model - */ +/** RSA public key model */ @Data public class RSAPublicKey { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java index b5cb0a1b..92df175d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java @@ -19,10 +19,13 @@ public interface AssertionVerifierService { * * @param request the Lollipop request * @return true if the assertion is valid - * @throws ErrorRetrievingAssertionException thrown for general errors in the verification process + * @throws ErrorRetrievingAssertionException thrown for general errors in the verification + * process * @throws AssertionPeriodException thrown for error in assertion period validation * @throws AssertionThumbprintException thrown for error in assertion thumbprint validation * @throws AssertionUserIdException thrown for error in user id validation */ - boolean validateLollipop(LollipopConsumerRequest request) throws ErrorRetrievingAssertionException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException; + boolean validateLollipop(LollipopConsumerRequest request) + throws ErrorRetrievingAssertionException, AssertionPeriodException, + AssertionThumbprintException, AssertionUserIdException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java index 67da2603..0c479f1b 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java @@ -1,11 +1,10 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service; import it.pagopa.tech.lollipop.consumer.exception.LollipopRequestContentValidationException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; -/** - * Interface of the service used to verify Lollipop request header params - */ +/** Interface of the service used to verify Lollipop request header params */ public interface LollipopConsumerRequestValidationService { /** @@ -14,5 +13,6 @@ public interface LollipopConsumerRequestValidationService { * @param request the Lollipop request * @throws LollipopRequestContentValidationException if some error occurred during validation */ - void validateLollipopRequest(LollipopConsumerRequest request) throws LollipopRequestContentValidationException; + void validateLollipopRequest(LollipopConsumerRequest request) + throws LollipopRequestContentValidationException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index b562c0aa..14161ccf 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -14,16 +14,6 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; -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; - -import javax.inject.Inject; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.io.StringReader; import java.text.ParseException; @@ -31,10 +21,17 @@ import java.util.Date; import java.util.Map; import java.util.concurrent.TimeUnit; +import javax.inject.Inject; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +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; -/** - * Standard implementation of {@link AssertionVerifierService} - */ +/** Standard implementation of {@link AssertionVerifierService} */ public class AssertionVerifierServiceImpl implements AssertionVerifierService { private final IdpCertProvider idpCertProvider; @@ -44,7 +41,10 @@ public class AssertionVerifierServiceImpl implements AssertionVerifierService { private static final String IN_RESPONSE_TO = "InResponseTo"; @Inject - public AssertionVerifierServiceImpl(IdpCertProvider idpCertProvider, AssertionService assertionService, LollipopConsumerRequestConfig lollipopRequestConfig) { + public AssertionVerifierServiceImpl( + IdpCertProvider idpCertProvider, + AssertionService assertionService, + LollipopConsumerRequestConfig lollipopRequestConfig) { this.idpCertProvider = idpCertProvider; this.assertionService = assertionService; this.lollipopRequestConfig = lollipopRequestConfig; @@ -52,88 +52,128 @@ public AssertionVerifierServiceImpl(IdpCertProvider idpCertProvider, AssertionSe /** * @see AssertionVerifierService#validateLollipop(LollipopConsumerRequest) - * */ @Override - public boolean validateLollipop(LollipopConsumerRequest request) throws ErrorRetrievingAssertionException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException { + public boolean validateLollipop(LollipopConsumerRequest request) + throws ErrorRetrievingAssertionException, AssertionPeriodException, + AssertionThumbprintException, AssertionUserIdException { Map headerParams = request.getHeaderParams(); - SamlAssertion assertion = getAssertion(headerParams.get(lollipopRequestConfig.getAuthJWTHeader()), headerParams.get(lollipopRequestConfig.getAssertionRefHeader())); + SamlAssertion assertion = + getAssertion( + headerParams.get(lollipopRequestConfig.getAuthJWTHeader()), + headerParams.get(lollipopRequestConfig.getAssertionRefHeader())); Document assertionDoc = buildDocumentFromAssertion(assertion); boolean isAssertionPeriodValid = validateAssertionPeriod(assertionDoc); if (!isAssertionPeriodValid) { - throw new AssertionPeriodException(AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, "The assertion has expired"); + throw new AssertionPeriodException( + AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, + "The assertion has expired"); } boolean isUserIdValid = validateUserId(request, assertionDoc); if (!isUserIdValid) { - throw new AssertionUserIdException(AssertionUserIdException.ErrorCode.INVALID_USER_ID, "The user id in the assertion does not match the request header"); + throw new AssertionUserIdException( + AssertionUserIdException.ErrorCode.INVALID_USER_ID, + "The user id in the assertion does not match the request header"); } boolean isInResponseToValid = validateInResponseTo(request, assertionDoc); if (!isInResponseToValid) { - throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.INVALID_IN_RESPONSE_TO, "The hash of provided public key do not match the InResponseTo in the assertion"); + throw new AssertionThumbprintException( + AssertionThumbprintException.ErrorCode.INVALID_IN_RESPONSE_TO, + "The hash of provided public key do not match the InResponseTo in the" + + " assertion"); } return true; } - private SamlAssertion getAssertion(String jwt, String assertionRef) throws ErrorRetrievingAssertionException { + private SamlAssertion getAssertion(String jwt, String assertionRef) + throws ErrorRetrievingAssertionException { try { return assertionService.getAssertion(jwt, assertionRef); } catch (OidcAssertionNotSupported e) { - throw new ErrorRetrievingAssertionException(ErrorRetrievingAssertionException.ErrorCode.OIDC_TYPE_NOT_SUPPORTED, e.getMessage(), e); + throw new ErrorRetrievingAssertionException( + ErrorRetrievingAssertionException.ErrorCode.OIDC_TYPE_NOT_SUPPORTED, + e.getMessage(), + e); } catch (LollipopAssertionNotFoundException e) { - throw new ErrorRetrievingAssertionException(ErrorRetrievingAssertionException.ErrorCode.SAML_ASSERTION_NOT_FOUND, e.getMessage(), e); + throw new ErrorRetrievingAssertionException( + ErrorRetrievingAssertionException.ErrorCode.SAML_ASSERTION_NOT_FOUND, + e.getMessage(), + e); } - } private boolean validateAssertionPeriod(Document assertionDoc) throws AssertionPeriodException { - NodeList listElements = assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionNotBeforeTag()); + NodeList listElements = + assertionDoc.getElementsByTagNameNS( + lollipopRequestConfig.getSamlNamespaceAssertion(), + lollipopRequestConfig.getAssertionNotBeforeTag()); if (listElements == null || listElements.getLength() <= 0) { return false; } - String notBefore = listElements.item(0).getAttributes().getNamedItem("NotBefore").getNodeValue(); + String notBefore = + listElements.item(0).getAttributes().getNamedItem("NotBefore").getNodeValue(); long notBeforeMilliseconds; try { - notBeforeMilliseconds = new SimpleDateFormat(lollipopRequestConfig.getAssertionNotBeforeDateFormat()).parse(notBefore).getTime(); + notBeforeMilliseconds = + new SimpleDateFormat(lollipopRequestConfig.getAssertionNotBeforeDateFormat()) + .parse(notBefore) + .getTime(); } catch (ParseException e) { - throw new AssertionPeriodException(AssertionPeriodException.ErrorCode.ERROR_PARSING_ASSERTION_NOT_BEFORE_DATE, e.getMessage(), e); + throw new AssertionPeriodException( + AssertionPeriodException.ErrorCode.ERROR_PARSING_ASSERTION_NOT_BEFORE_DATE, + e.getMessage(), + e); } long dateNowMilliseconds = new Date().getTime(); - long expiresAfterMilliseconds = TimeUnit.DAYS.toMillis(lollipopRequestConfig.getAssertionExpireInDays()); + long expiresAfterMilliseconds = + TimeUnit.DAYS.toMillis(lollipopRequestConfig.getAssertionExpireInDays()); long dateNowLessNotBefore = (dateNowMilliseconds - notBeforeMilliseconds); return 0 <= dateNowLessNotBefore && (dateNowLessNotBefore <= expiresAfterMilliseconds); } - private boolean validateUserId(LollipopConsumerRequest request, Document assertionDoc) throws AssertionUserIdException { - String userIdHeader = request.getHeaderParams().get(lollipopRequestConfig.getUserIdHeader()); + private boolean validateUserId(LollipopConsumerRequest request, Document assertionDoc) + throws AssertionUserIdException { + String userIdHeader = + request.getHeaderParams().get(lollipopRequestConfig.getUserIdHeader()); String userIdFromAssertion = getUserIdFromAssertion(assertionDoc); if (userIdFromAssertion == null) { - throw new AssertionUserIdException(AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, "Missing or invalid Fiscal Code in the retrieved saml assertion."); + throw new AssertionUserIdException( + AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, + "Missing or invalid Fiscal Code in the retrieved saml assertion."); } return userIdFromAssertion.equals(userIdHeader); } - private boolean validateInResponseTo(LollipopConsumerRequest request, Document assertionDoc) throws AssertionThumbprintException { - NodeList listElements = assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionInResponseToTag()); + private boolean validateInResponseTo(LollipopConsumerRequest request, Document assertionDoc) + throws AssertionThumbprintException { + NodeList listElements = + assertionDoc.getElementsByTagNameNS( + lollipopRequestConfig.getSamlNamespaceAssertion(), + lollipopRequestConfig.getAssertionInResponseToTag()); if (isInResponseToFieldFound(listElements)) { - throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_FIELD_NOT_FOUND, "Missing request id in the retrieved saml assertion"); + throw new AssertionThumbprintException( + AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_FIELD_NOT_FOUND, + "Missing request id in the retrieved saml assertion"); } - String inResponseTo = listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO).getNodeValue(); + String inResponseTo = + listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO).getNodeValue(); String inResponseToAlgorithm = retrieveInResponseToAlgorithm(inResponseTo); - - String publicKey = request.getHeaderParams().get(lollipopRequestConfig.getPublicKeyHeader()); + String publicKey = + request.getHeaderParams().get(lollipopRequestConfig.getPublicKeyHeader()); String calculatedThumbprint = calculateThumbprint(inResponseToAlgorithm, publicKey); - String assertionRefHeader = request.getHeaderParams().get(lollipopRequestConfig.getAssertionRefHeader()); + String assertionRefHeader = + request.getHeaderParams().get(lollipopRequestConfig.getAssertionRefHeader()); return inResponseTo.equals(calculatedThumbprint) && inResponseTo.equals(assertionRefHeader); } @@ -146,7 +186,8 @@ private boolean validateSignature(SamlAssertion assertion, IdpCertData idpCertDa return false; } - private static Document buildDocumentFromAssertion(SamlAssertion assertion) throws ErrorRetrievingAssertionException { + private static Document buildDocumentFromAssertion(SamlAssertion assertion) + throws ErrorRetrievingAssertionException { String stringXml = assertion.getAssertionData(); try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); @@ -157,7 +198,10 @@ private static Document buildDocumentFromAssertion(SamlAssertion assertion) thro DocumentBuilder builder = factory.newDocumentBuilder(); return builder.parse(new InputSource(new StringReader(stringXml))); } catch (ParserConfigurationException | SAXException | IOException e) { - throw new ErrorRetrievingAssertionException(ErrorRetrievingAssertionException.ErrorCode.ERROR_PARSING_ASSERTION, e.getMessage(), e); + throw new ErrorRetrievingAssertionException( + ErrorRetrievingAssertionException.ErrorCode.ERROR_PARSING_ASSERTION, + e.getMessage(), + e); } } @@ -167,14 +211,19 @@ private boolean isInResponseToFieldFound(NodeList listElements) { || listElements.item(0) == null || listElements.item(0).getAttributes() == null || listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO) == null - || listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO).getNodeValue() == null; + || listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO).getNodeValue() + == null; } private String getUserIdFromAssertion(Document assertionDoc) throws AssertionUserIdException { - NodeList listElements = assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionFiscalCodeTag()); + NodeList listElements = + assertionDoc.getElementsByTagNameNS( + lollipopRequestConfig.getSamlNamespaceAssertion(), + lollipopRequestConfig.getAssertionFiscalCodeTag()); if (listElements == null || listElements.getLength() <= 0) { - throw new AssertionUserIdException(AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, "Missing or invalid Fiscal Code in the retrieved saml assertion."); - + throw new AssertionUserIdException( + AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, + "Missing or invalid Fiscal Code in the retrieved saml assertion."); } for (int i = 0; i < listElements.getLength(); i++) { @@ -183,17 +232,23 @@ private String getUserIdFromAssertion(Document assertionDoc) throws AssertionUse continue; } Node name = item.getAttributes().getNamedItem("Name"); - if (name != null && name.getNodeValue().equals("fiscalNumber") && item.getTextContent() != null) { + if (name != null + && name.getNodeValue().equals("fiscalNumber") + && item.getTextContent() != null) { return item.getTextContent().trim().replace("TINIT-", ""); } } return null; } - private String retrieveInResponseToAlgorithm(String inResponseTo) throws AssertionThumbprintException { - boolean matchesSHA256 = AssertionRefAlgorithms.SHA256.getPattern().matcher(inResponseTo).matches(); - boolean matchesSHA384 = AssertionRefAlgorithms.SHA384.getPattern().matcher(inResponseTo).matches(); - boolean matchesSHA512 = AssertionRefAlgorithms.SHA512.getPattern().matcher(inResponseTo).matches(); + private String retrieveInResponseToAlgorithm(String inResponseTo) + throws AssertionThumbprintException { + boolean matchesSHA256 = + AssertionRefAlgorithms.SHA256.getPattern().matcher(inResponseTo).matches(); + boolean matchesSHA384 = + AssertionRefAlgorithms.SHA384.getPattern().matcher(inResponseTo).matches(); + boolean matchesSHA512 = + AssertionRefAlgorithms.SHA512.getPattern().matcher(inResponseTo).matches(); if (matchesSHA256) { return AssertionRefAlgorithms.SHA256.getHashAlgorithm(); @@ -204,22 +259,32 @@ private String retrieveInResponseToAlgorithm(String inResponseTo) throws Asserti if (matchesSHA512) { return AssertionRefAlgorithms.SHA512.getHashAlgorithm(); } - throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_ALGORITHM_NOT_VALID, "InResponseTo in the assertion do not contains a valid Assertion Ref or it contains an invalid algorithm."); - + throw new AssertionThumbprintException( + AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_ALGORITHM_NOT_VALID, + "InResponseTo in the assertion do not contains a valid Assertion Ref or it contains" + + " an invalid algorithm."); } - private String calculateThumbprint(String inResponseToAlgorithm, String publicKey) throws AssertionThumbprintException { + private String calculateThumbprint(String inResponseToAlgorithm, String publicKey) + throws AssertionThumbprintException { Base64URL thumbprint; try { - thumbprint = ThumbprintUtils.compute(inResponseToAlgorithm, JWK.parse(publicKey)); + thumbprint = ThumbprintUtils.compute(inResponseToAlgorithm, JWK.parse(publicKey)); } catch (JOSEException | ParseException e) { String errMsg = String.format("Can not calculate JwkThumbprint: %S", e.getMessage()); - throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, errMsg, e); + throw new AssertionThumbprintException( + AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, + errMsg, + e); } - AssertionRefAlgorithms algo = AssertionRefAlgorithms.getAlgorithmFromHash(inResponseToAlgorithm); + AssertionRefAlgorithms algo = + AssertionRefAlgorithms.getAlgorithmFromHash(inResponseToAlgorithm); String calculatedThumbprint = String.format("%s-%s", algo.getAlgorithmName(), thumbprint); if (!algo.getPattern().matcher(calculatedThumbprint).matches()) { - throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, "The calculated thumbprint does not match the expected pattern: " + calculatedThumbprint); + throw new AssertionThumbprintException( + AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, + "The calculated thumbprint does not match the expected pattern: " + + calculatedThumbprint); } return calculatedThumbprint; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java index b4908609..810b795c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service.impl; import com.fasterxml.jackson.core.JsonProcessingException; @@ -11,11 +12,11 @@ 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.Map; import java.util.regex.Pattern; -public class LollipopConsumerRequestValidationServiceImpl implements LollipopConsumerRequestValidationService { +public class LollipopConsumerRequestValidationServiceImpl + implements LollipopConsumerRequestValidationService { private final LollipopConsumerRequestConfig config; @@ -24,7 +25,8 @@ public LollipopConsumerRequestValidationServiceImpl(LollipopConsumerRequestConfi } @Override - public void validateLollipopRequest(LollipopConsumerRequest request) throws LollipopRequestContentValidationException { + public void validateLollipopRequest(LollipopConsumerRequest request) + throws LollipopRequestContentValidationException { Map headerParams = request.getHeaderParams(); validatePublicKey(headerParams.get(this.config.getPublicKeyHeader())); @@ -39,13 +41,19 @@ public void validateLollipopRequest(LollipopConsumerRequest request) throws Loll validateSignatureHeader(headerParams.get(this.config.getSignatureHeader())); } - private void validatePublicKey(String publicKey) throws LollipopRequestContentValidationException { - if (publicKey == null ) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_PUBLIC_KEY, "Missing Public Key Header"); + private void validatePublicKey(String publicKey) + throws LollipopRequestContentValidationException { + if (publicKey == null) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.MISSING_PUBLIC_KEY, + "Missing Public Key Header"); } - if (isNotValidPublicKey(publicKey, ECPublicKey.class) && isNotValidPublicKey(publicKey, RSAPublicKey.class)) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_PUBLIC_KEY, "Invalid Public Key Header value"); + if (isNotValidPublicKey(publicKey, ECPublicKey.class) + && isNotValidPublicKey(publicKey, RSAPublicKey.class)) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.INVALID_PUBLIC_KEY, + "Invalid Public Key Header value"); } } @@ -59,30 +67,43 @@ private boolean isNotValidPublicKey(String publicKey, Class clazz) { return false; } - private void validateAssertionRefHeader(String assertionRef) throws LollipopRequestContentValidationException { - if (assertionRef == null ) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_REF, "Missing AssertionRef Header"); + private void validateAssertionRefHeader(String assertionRef) + throws LollipopRequestContentValidationException { + if (assertionRef == null) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_REF, + "Missing AssertionRef Header"); } if (isNotValidAssertionRef(assertionRef)) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_REF, "Invalid AssertionRef Header value"); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_REF, + "Invalid AssertionRef Header value"); } } private boolean isNotValidAssertionRef(String signature) { - boolean matchesSHA256 = AssertionRefAlgorithms.SHA256.getPattern().matcher(signature).matches(); - boolean matchesSHA384 = AssertionRefAlgorithms.SHA384.getPattern().matcher(signature).matches(); - boolean matchesSHA512 = AssertionRefAlgorithms.SHA512.getPattern().matcher(signature).matches(); + boolean matchesSHA256 = + AssertionRefAlgorithms.SHA256.getPattern().matcher(signature).matches(); + boolean matchesSHA384 = + AssertionRefAlgorithms.SHA384.getPattern().matcher(signature).matches(); + boolean matchesSHA512 = + AssertionRefAlgorithms.SHA512.getPattern().matcher(signature).matches(); return !matchesSHA256 && !matchesSHA384 && !matchesSHA512; } - private void validateAssertionTypeHeader(String assertionType) throws LollipopRequestContentValidationException { - if (assertionType == null ) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_TYPE, "Missing Assertion Type Header"); + private void validateAssertionTypeHeader(String assertionType) + throws LollipopRequestContentValidationException { + if (assertionType == null) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_TYPE, + "Missing Assertion Type Header"); } if ((!isAssertionTypeSupported(assertionType))) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_TYPE, "Invalid Assertion Type Header value, type not supported"); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_TYPE, + "Invalid Assertion Type Header value, type not supported"); } } @@ -95,42 +116,62 @@ private boolean isAssertionTypeSupported(String assertionType) { return false; } - private void validateUserIdHeader(String userId) throws LollipopRequestContentValidationException { - if (userId == null ) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_USER_ID, "Missing User Id Header"); + private void validateUserIdHeader(String userId) + throws LollipopRequestContentValidationException { + if (userId == null) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.MISSING_USER_ID, + "Missing User Id Header"); } if ((isNotValidFiscalCode(userId))) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_USER_ID, "Invalid User Id Header value, type not supported"); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.INVALID_USER_ID, + "Invalid User Id Header value, type not supported"); } } private boolean isNotValidFiscalCode(String userId) { - return !Pattern.compile("^[A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]$").matcher(userId).matches(); + return !Pattern.compile( + "^[A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]$") + .matcher(userId) + .matches(); } - private void validateAuthJWTHeader(String authJWT) throws LollipopRequestContentValidationException { - if (authJWT == null ) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_AUTH_JWT, "Missing Auth JWT Header"); + private void validateAuthJWTHeader(String authJWT) + throws LollipopRequestContentValidationException { + if (authJWT == null) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.MISSING_AUTH_JWT, + "Missing Auth JWT Header"); } if (authJWT.isBlank()) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_AUTH_JWT, "Invalid Auth JWT Header value, cannot be empty"); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.INVALID_AUTH_JWT, + "Invalid Auth JWT Header value, cannot be empty"); } } - private void validateOriginalMethodHeader(String originalMethod) throws LollipopRequestContentValidationException { - if (originalMethod == null ) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_METHOD, "Missing Original Method Header"); + private void validateOriginalMethodHeader(String originalMethod) + throws LollipopRequestContentValidationException { + if (originalMethod == null) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_METHOD, + "Missing Original Method Header"); } if (!isRequestMethodSupported(originalMethod)) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_METHOD, "Invalid Original Method Header value, method not supported"); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_METHOD, + "Invalid Original Method Header value, method not supported"); } if (!originalMethod.equals(this.config.getExpectedFirstLcOriginalMethod())) { String errMsg = String.format("Unexpected original method: %s", originalMethod); - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_METHOD, errMsg); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_METHOD, + errMsg); } } @@ -143,18 +184,25 @@ private boolean isRequestMethodSupported(String originalMethod) { return false; } - private void validateOriginalURLHeader(String originalURL) throws LollipopRequestContentValidationException { - if (originalURL == null ) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_URL, "Missing Original URL Header"); + private void validateOriginalURLHeader(String originalURL) + throws LollipopRequestContentValidationException { + if (originalURL == null) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_URL, + "Missing Original URL Header"); } if (isNotValidOriginalURL(originalURL)) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_URL, "Invalid Original URL Header value"); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_URL, + "Invalid Original URL Header value"); } if (!originalURL.equals(this.config.getExpectedFirstLcOriginalUrl())) { String errMsg = String.format("Unexpected original url: %s", originalURL); - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_URL, errMsg); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_URL, + errMsg); } } @@ -162,31 +210,45 @@ private boolean isNotValidOriginalURL(String originalURL) { return !Pattern.compile("^https://\\S+").matcher(originalURL).matches(); } - private void validateSignatureInputHeader(String signatureInput) throws LollipopRequestContentValidationException { - if (signatureInput == null ) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE_INPUT, "Missing Signature Input Header"); + private void validateSignatureInputHeader(String signatureInput) + throws LollipopRequestContentValidationException { + if (signatureInput == null) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE_INPUT, + "Missing Signature Input Header"); } if (isNotValidSignatureInput(signatureInput)) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE_INPUT, "Invalid Signature Input Header value"); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE_INPUT, + "Invalid Signature Input Header value"); } } private boolean isNotValidSignatureInput(String signatureInput) { - return !Pattern.compile("^(((sig[0-9]+)=[^,]*?)(, ?)?)+$").matcher(signatureInput).matches(); + return !Pattern.compile("^(((sig[0-9]+)=[^,]*?)(, ?)?)+$") + .matcher(signatureInput) + .matches(); } - private void validateSignatureHeader(String signature) throws LollipopRequestContentValidationException { - if (signature == null ) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE, "Missing Signature Header"); + private void validateSignatureHeader(String signature) + throws LollipopRequestContentValidationException { + if (signature == null) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE, + "Missing Signature Header"); } if (isNotValidSignature(signature)) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE, "Invalid Signature Header value"); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE, + "Invalid Signature Header value"); } } private boolean isNotValidSignature(String signature) { - return !Pattern.compile("^((sig[0-9]+)=:[A-Za-z0-9+/=]*:(, ?)?)+$").matcher(signature).matches(); + return !Pattern.compile("^((sig[0-9]+)=:[A-Za-z0-9+/=]*:(, ?)?)+$") + .matcher(signature) + .matches(); } } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java index 8bea929a..5db79c3b 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -12,9 +12,8 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; -import java.io.UnsupportedEncodingException; - import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; +import java.io.UnsupportedEncodingException; import lombok.SneakyThrows; import org.junit.jupiter.api.*; import org.mockito.*; @@ -36,17 +35,19 @@ void beforeAll() { new LollipopConsumerCommandImpl( messageVerifierServiceMock, assertionVerifierServiceMock, - requestValidationServiceMock - )); + requestValidationServiceMock)); } @Test void failedHttpMessageValidationThrowDigestException() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { - - doThrow(new LollipopDigestException( - LollipopDigestException.ErrorCode.INCORRECT_DIGEST, "error")) + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException { + + doThrow( + new LollipopDigestException( + LollipopDigestException.ErrorCode.INCORRECT_DIGEST, "error")) .when(messageVerifierServiceMock) .verifyHttpMessage(any(LollipopConsumerRequest.class)); @@ -56,7 +57,8 @@ void failedHttpMessageValidationThrowDigestException() HttpMessageVerificationResultCode.DIGEST_VALIDATION_ERROR.name(), commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock, never()) .validateLollipop(any(LollipopConsumerRequest.class)); @@ -76,7 +78,8 @@ void failedHttpMessageValidationThrowUnsupportedEncodingException() { HttpMessageVerificationResultCode.UNSUPPORTED_ENCODING.name(), commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock, never()) .validateLollipop(any(LollipopConsumerRequest.class)); @@ -84,8 +87,10 @@ void failedHttpMessageValidationThrowUnsupportedEncodingException() { @Test void failedHttpMessageValidationWithoutThrowingException() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException { doReturn(false) .when(messageVerifierServiceMock) @@ -97,7 +102,8 @@ void failedHttpMessageValidationWithoutThrowingException() HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_FAILED.name(), commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock, never()) .validateLollipop(any(LollipopConsumerRequest.class)); @@ -105,8 +111,10 @@ void failedHttpMessageValidationWithoutThrowingException() @Test void failedAssertionValidationWithoutThrowingException() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException { doReturn(true) .when(messageVerifierServiceMock) @@ -121,15 +129,18 @@ void failedAssertionValidationWithoutThrowingException() AssertionVerificationResultCode.ASSERTION_VERIFICATION_FAILED.name(), commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } @Test void successLollipopRequestValidation() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException { doReturn(true) .when(messageVerifierServiceMock) @@ -142,31 +153,40 @@ void successLollipopRequestValidation() Assertions.assertEquals("SUCCESS", commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } @Test void failedLollipopRequestValidation() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { - - - doThrow(LollipopRequestContentValidationException.class).when(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException { + + doThrow(LollipopRequestContentValidationException.class) + .when(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); Assertions.assertEquals("REQUEST PARAMS VALIDATION FAILED", commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); - verify(messageVerifierServiceMock, never()).verifyHttpMessage(any(LollipopConsumerRequest.class)); - verify(assertionVerifierServiceMock, never()).validateLollipop(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(messageVerifierServiceMock, never()) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock, never()) + .validateLollipop(any(LollipopConsumerRequest.class)); } @Test void failedAssertionValidationThrowErrorRetrievingAssertionException() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException { doReturn(true) .when(messageVerifierServiceMock) @@ -181,15 +201,18 @@ void failedAssertionValidationThrowErrorRetrievingAssertionException() AssertionVerificationResultCode.ERROR_RETRIEVING_ASSERTION.name(), commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } @Test void failedAssertionValidationThrowAssertionPeriodException() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException { doReturn(true) .when(messageVerifierServiceMock) @@ -204,15 +227,18 @@ void failedAssertionValidationThrowAssertionPeriodException() AssertionVerificationResultCode.PERIOD_VALIDATION_ERROR.name(), commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } @Test void failedAssertionValidationThrowAssertionThumbprintException() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException { doReturn(true) .when(messageVerifierServiceMock) @@ -227,15 +253,18 @@ void failedAssertionValidationThrowAssertionThumbprintException() AssertionVerificationResultCode.THUMBPRINT_VALIDATION_ERROR.name(), commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } @Test void failedAssertionValidationThrowAssertionUserIdException() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException { doReturn(true) .when(messageVerifierServiceMock) @@ -250,7 +279,8 @@ void failedAssertionValidationThrowAssertionUserIdException() AssertionVerificationResultCode.USER_ID_VALIDATION_ERROR.name(), commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java index a31f63ed..402782c5 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java @@ -1,5 +1,9 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service.impl; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.*; @@ -7,18 +11,14 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; class AssertionVerifierServiceImplTest { @@ -29,14 +29,43 @@ class AssertionVerifierServiceImplTest { private AssertionVerifierService sut; private static final String VALID_FISCAL_CODE = "AAAAAA89S20I111X"; - private static final String VALID_JWK = "{ \"kty\": \"EC\", \"crv\": \"P-256\", \"x\": \"SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74\", \"y\": \"lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI\"}"; - private static final String VALID_SHA_256_ASSERTION_REF = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; - private static final String VALID_SHA_384_ASSERTION_REF = "sha384-lqxC_2kqMdwiBWoD-Us63Fha6e3bE1Y3yUz8G6IJTldohJCIBVDfvS8acB3GJBhw"; - private static final String VALID_SHA_512_ASSERTION_REF = "sha512-nX5CfUc5R-FoYKYZwvQMuc4Tt-heb7vHi_O-AMUSqHNVCw9kNaN2SVuN-DXtGXyUhrcVcQdCyY6FVzl_vyWXNA"; - - private static final String EMPTY_ASSERTION_XML = ""; - private static final String ASSERTION_XML_WITH_INVALID_PERIOD_DATE_FORMAT = "https://app-backend.io.italia.it"; - private static final String ASSERTION_XML_WITH_EXPIRED_PERIOD = "https://app-backend.io.italia.it"; + private static final String VALID_JWK = + "{ \"kty\": \"EC\", \"crv\": \"P-256\", \"x\":" + + " \"SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74\", \"y\":" + + " \"lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI\"}"; + private static final String VALID_SHA_256_ASSERTION_REF = + "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; + private static final String VALID_SHA_384_ASSERTION_REF = + "sha384-lqxC_2kqMdwiBWoD-Us63Fha6e3bE1Y3yUz8G6IJTldohJCIBVDfvS8acB3GJBhw"; + private static final String VALID_SHA_512_ASSERTION_REF = + "sha512-nX5CfUc5R-FoYKYZwvQMuc4Tt-heb7vHi_O-AMUSqHNVCw9kNaN2SVuN-DXtGXyUhrcVcQdCyY6FVzl_vyWXNA"; + + private static final String EMPTY_ASSERTION_XML = + ""; + private static final String ASSERTION_XML_WITH_INVALID_PERIOD_DATE_FORMAT = + "https://app-backend.io.italia.it"; + private static final String ASSERTION_XML_WITH_EXPIRED_PERIOD = + "https://app-backend.io.italia.it"; private static String ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG; private static String ASSERTION_XML_WITHOUT_FISCAL_CODE; private static String ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG; @@ -49,14 +78,196 @@ class AssertionVerifierServiceImplTest { static void prepareInput() { lollipopRequestConfigMock = spy(LollipopConsumerRequestConfig.builder().build()); - String todayTimestamp = new SimpleDateFormat(lollipopRequestConfigMock.getAssertionNotBeforeDateFormat()).format(new Date()); - ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG = "https://app-backend.io.italia.it"; - ASSERTION_XML_WITHOUT_FISCAL_CODE = " https://app-backend.io.italia.it \t "; - ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG = " https://app-backend.io.italia.it \t TINIT-AAAAAA89S20I111X "; - ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM = " \t\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thttps://app-backend.io.italia.it\t\t\t\t\t\t\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t\t\t\t\t"; - ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM = " \t\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thttps://app-backend.io.italia.it\t\t\t\t\t\t\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t\t\t\t\t"; - ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM = " \t\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thttps://app-backend.io.italia.it\t\t\t\t\t\t\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t\t\t\t\t"; - ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM = " \t\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thttps://app-backend.io.italia.it\t\t\t\t\t\t\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t\t\t\t\t"; + String todayTimestamp = + new SimpleDateFormat(lollipopRequestConfigMock.getAssertionNotBeforeDateFormat()) + .format(new Date()); + ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG = + "https://app-backend.io.italia.it"; + ASSERTION_XML_WITHOUT_FISCAL_CODE = + " " + + " " + + " " + + " " + + " https://app-backend.io.italia.it " + + " \t " + + " " + + " " + + " "; + ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG = + " " + + " " + + " " + + " " + + " https://app-backend.io.italia.it " + + " \t " + + " " + + " TINIT-AAAAAA89S20I111X " + + " " + + " "; + ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM = + " " + + " \t" + + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t" + + "\t\t\t\t\t\t\t\t\t" + + "\t\t\t\t" + + "\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t" + + "\t\t\t\t" + + "\t"; + ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM = + " " + + " \t" + + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t" + + "\t\t\t\t\t\t\t\t\t" + + "\t\t\t\t" + + "\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t" + + "\t\t\t\t" + + "\t"; + ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM = + " " + + " \t" + + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t" + + "\t\t\t\t\t\t\t\t\t" + + "\t\t\t\t" + + "\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t" + + "\t\t\t\t" + + "\t"; + ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM = + " " + + " \t" + + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t" + + "\t\t\t\t\t\t\t\t\t" + + "\t\t\t\t" + + "\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t" + + "\t\t\t\t" + + "\t"; } @BeforeEach @@ -64,35 +275,54 @@ void setUp() { idpCertProviderMock = mock(IdpCertProvider.class); assertionServiceMock = mock(AssertionService.class); - sut = new AssertionVerifierServiceImpl(idpCertProviderMock, assertionServiceMock, lollipopRequestConfigMock); + sut = + new AssertionVerifierServiceImpl( + idpCertProviderMock, assertionServiceMock, lollipopRequestConfigMock); } @Test - void validateLollipopGetAssertionFailureWithOidcAssertionException() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopGetAssertionFailureWithOidcAssertionException() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); - doThrow(OidcAssertionNotSupported.class).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doThrow(OidcAssertionNotSupported.class) + .when(assertionServiceMock) + .getAssertion(anyString(), anyString()); - ErrorRetrievingAssertionException e = assertThrows(ErrorRetrievingAssertionException.class, () -> sut.validateLollipop(request)); + ErrorRetrievingAssertionException e = + assertThrows( + ErrorRetrievingAssertionException.class, + () -> sut.validateLollipop(request)); Assertions.assertTrue(e.getCause() instanceof OidcAssertionNotSupported); - Assertions.assertEquals(ErrorRetrievingAssertionException.ErrorCode.OIDC_TYPE_NOT_SUPPORTED, e.getErrorCode()); + Assertions.assertEquals( + ErrorRetrievingAssertionException.ErrorCode.OIDC_TYPE_NOT_SUPPORTED, + e.getErrorCode()); } @Test - void validateLollipopGetAssertionFailureWithAssertionNotFoundException() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopGetAssertionFailureWithAssertionNotFoundException() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); - doThrow(LollipopAssertionNotFoundException.class).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doThrow(LollipopAssertionNotFoundException.class) + .when(assertionServiceMock) + .getAssertion(anyString(), anyString()); - ErrorRetrievingAssertionException e = assertThrows(ErrorRetrievingAssertionException.class, () -> sut.validateLollipop(request)); + ErrorRetrievingAssertionException e = + assertThrows( + ErrorRetrievingAssertionException.class, + () -> sut.validateLollipop(request)); Assertions.assertTrue(e.getCause() instanceof LollipopAssertionNotFoundException); - Assertions.assertEquals(ErrorRetrievingAssertionException.ErrorCode.SAML_ASSERTION_NOT_FOUND, e.getErrorCode()); + Assertions.assertEquals( + ErrorRetrievingAssertionException.ErrorCode.SAML_ASSERTION_NOT_FOUND, + e.getErrorCode()); } @Test - void validateLollipopBuildAssertionDocFailure() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopBuildAssertionDocFailure() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -100,13 +330,19 @@ void validateLollipopBuildAssertionDocFailure() throws OidcAssertionNotSupported doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - ErrorRetrievingAssertionException e = assertThrows(ErrorRetrievingAssertionException.class, () -> sut.validateLollipop(request)); + ErrorRetrievingAssertionException e = + assertThrows( + ErrorRetrievingAssertionException.class, + () -> sut.validateLollipop(request)); - Assertions.assertEquals(ErrorRetrievingAssertionException.ErrorCode.ERROR_PARSING_ASSERTION, e.getErrorCode()); + Assertions.assertEquals( + ErrorRetrievingAssertionException.ErrorCode.ERROR_PARSING_ASSERTION, + e.getErrorCode()); } @Test - void validateLollipopValidatePeriodFailureWithFieldNotFoundInAssertionDoc() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidatePeriodFailureWithFieldNotFoundInAssertionDoc() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -114,13 +350,16 @@ void validateLollipopValidatePeriodFailureWithFieldNotFoundInAssertionDoc() thro doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionPeriodException e = assertThrows(AssertionPeriodException.class, () -> sut.validateLollipop(request)); + AssertionPeriodException e = + assertThrows(AssertionPeriodException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, e.getErrorCode()); + Assertions.assertEquals( + AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, e.getErrorCode()); } @Test - void validateLollipopValidatePeriodFailureWithInvalidDateFormat() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidatePeriodFailureWithInvalidDateFormat() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -128,13 +367,17 @@ void validateLollipopValidatePeriodFailureWithInvalidDateFormat() throws OidcAss doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionPeriodException e = assertThrows(AssertionPeriodException.class, () -> sut.validateLollipop(request)); + AssertionPeriodException e = + assertThrows(AssertionPeriodException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionPeriodException.ErrorCode.ERROR_PARSING_ASSERTION_NOT_BEFORE_DATE, e.getErrorCode()); + Assertions.assertEquals( + AssertionPeriodException.ErrorCode.ERROR_PARSING_ASSERTION_NOT_BEFORE_DATE, + e.getErrorCode()); } @Test - void validateLollipopValidatePeriodFailureWithExpiredAssertion() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidatePeriodFailureWithExpiredAssertion() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -142,13 +385,16 @@ void validateLollipopValidatePeriodFailureWithExpiredAssertion() throws OidcAsse doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionPeriodException e = assertThrows(AssertionPeriodException.class, () -> sut.validateLollipop(request)); + AssertionPeriodException e = + assertThrows(AssertionPeriodException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, e.getErrorCode()); + Assertions.assertEquals( + AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, e.getErrorCode()); } @Test - void validateLollipopValidateUserIdFailureWithoutAttributeTagInAssertionDoc() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateUserIdFailureWithoutAttributeTagInAssertionDoc() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -156,13 +402,16 @@ void validateLollipopValidateUserIdFailureWithoutAttributeTagInAssertionDoc() th doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionUserIdException e = assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); + AssertionUserIdException e = + assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, e.getErrorCode()); + Assertions.assertEquals( + AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, e.getErrorCode()); } @Test - void validateLollipopValidateUserIdFailureWithoutFiscalCodeInAssertionDoc() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateUserIdFailureWithoutFiscalCodeInAssertionDoc() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -170,13 +419,16 @@ void validateLollipopValidateUserIdFailureWithoutFiscalCodeInAssertionDoc() thro doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionUserIdException e = assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); + AssertionUserIdException e = + assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, e.getErrorCode()); + Assertions.assertEquals( + AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, e.getErrorCode()); } @Test - void validateLollipopValidateUserIdFailureWithInvalidUserIdHeader() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateUserIdFailureWithInvalidUserIdHeader() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -184,13 +436,16 @@ void validateLollipopValidateUserIdFailureWithInvalidUserIdHeader() throws OidcA doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionUserIdException e = assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); + AssertionUserIdException e = + assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionUserIdException.ErrorCode.INVALID_USER_ID, e.getErrorCode()); + Assertions.assertEquals( + AssertionUserIdException.ErrorCode.INVALID_USER_ID, e.getErrorCode()); } @Test - void validateLollipopValidateThumbprintFailureWithoutSubjectConfirmationDataTagInAssertionDoc() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateThumbprintFailureWithoutSubjectConfirmationDataTagInAssertionDoc() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", VALID_FISCAL_CODE); SamlAssertion assertion = new SamlAssertion(); @@ -198,28 +453,37 @@ void validateLollipopValidateThumbprintFailureWithoutSubjectConfirmationDataTagI doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionThumbprintException e = assertThrows(AssertionThumbprintException.class, () -> sut.validateLollipop(request)); + AssertionThumbprintException e = + assertThrows( + AssertionThumbprintException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_FIELD_NOT_FOUND, e.getErrorCode()); + Assertions.assertEquals( + AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_FIELD_NOT_FOUND, + e.getErrorCode()); } @Test - void validateLollipopValidateThumbprintFailureWithInvalidInResponseToAlgorithm() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateThumbprintFailureWithInvalidInResponseToAlgorithm() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", VALID_FISCAL_CODE); - SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionThumbprintException e = assertThrows(AssertionThumbprintException.class, () -> sut.validateLollipop(request)); + AssertionThumbprintException e = + assertThrows( + AssertionThumbprintException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_ALGORITHM_NOT_VALID, e.getErrorCode()); + Assertions.assertEquals( + AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_ALGORITHM_NOT_VALID, + e.getErrorCode()); } @Test - void validateLollipopValidateThumbprintFailureWithErrorCalculatingThumbprint() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateThumbprintFailureWithErrorCalculatingThumbprint() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", VALID_FISCAL_CODE); SamlAssertion assertion = new SamlAssertion(); @@ -227,29 +491,43 @@ void validateLollipopValidateThumbprintFailureWithErrorCalculatingThumbprint() t doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionThumbprintException e = assertThrows(AssertionThumbprintException.class, () -> sut.validateLollipop(request)); + AssertionThumbprintException e = + assertThrows( + AssertionThumbprintException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, e.getErrorCode()); + Assertions.assertEquals( + AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, + e.getErrorCode()); Assertions.assertTrue(e.getCause() instanceof ParseException); } @Test - void validateLollipopValidateThumbprintFailureWithDifferentAssertionRefAndCalculatedThumbprint() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { - LollipopConsumerRequest request = getLollipopConsumerRequest("", VALID_JWK, VALID_FISCAL_CODE); + void validateLollipopValidateThumbprintFailureWithDifferentAssertionRefAndCalculatedThumbprint() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = + getLollipopConsumerRequest("", VALID_JWK, VALID_FISCAL_CODE); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionThumbprintException e = assertThrows(AssertionThumbprintException.class, () -> sut.validateLollipop(request)); + AssertionThumbprintException e = + assertThrows( + AssertionThumbprintException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionThumbprintException.ErrorCode.INVALID_IN_RESPONSE_TO, e.getErrorCode()); + Assertions.assertEquals( + AssertionThumbprintException.ErrorCode.INVALID_IN_RESPONSE_TO, e.getErrorCode()); } @Test - void validateLollipopSuccessWithSHA256Algorithm() throws LollipopAssertionNotFoundException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, OidcAssertionNotSupported { - LollipopConsumerRequest request = getLollipopConsumerRequest(VALID_SHA_256_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); + void validateLollipopSuccessWithSHA256Algorithm() + throws LollipopAssertionNotFoundException, AssertionPeriodException, + AssertionThumbprintException, AssertionUserIdException, + ErrorRetrievingAssertionException, OidcAssertionNotSupported { + LollipopConsumerRequest request = + getLollipopConsumerRequest( + VALID_SHA_256_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); @@ -262,8 +540,13 @@ void validateLollipopSuccessWithSHA256Algorithm() throws LollipopAssertionNotFou } @Test - void validateLollipopSuccessWithSHA384Algorithm() throws LollipopAssertionNotFoundException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, OidcAssertionNotSupported { - LollipopConsumerRequest request = getLollipopConsumerRequest(VALID_SHA_384_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); + void validateLollipopSuccessWithSHA384Algorithm() + throws LollipopAssertionNotFoundException, AssertionPeriodException, + AssertionThumbprintException, AssertionUserIdException, + ErrorRetrievingAssertionException, OidcAssertionNotSupported { + LollipopConsumerRequest request = + getLollipopConsumerRequest( + VALID_SHA_384_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM); @@ -276,8 +559,13 @@ void validateLollipopSuccessWithSHA384Algorithm() throws LollipopAssertionNotFou } @Test - void validateLollipopSuccessWithSHA512Algorithm() throws LollipopAssertionNotFoundException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, OidcAssertionNotSupported { - LollipopConsumerRequest request = getLollipopConsumerRequest(VALID_SHA_512_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); + void validateLollipopSuccessWithSHA512Algorithm() + throws LollipopAssertionNotFoundException, AssertionPeriodException, + AssertionThumbprintException, AssertionUserIdException, + ErrorRetrievingAssertionException, OidcAssertionNotSupported { + LollipopConsumerRequest request = + getLollipopConsumerRequest( + VALID_SHA_512_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM); @@ -289,15 +577,14 @@ void validateLollipopSuccessWithSHA512Algorithm() throws LollipopAssertionNotFou Assertions.assertTrue(result); } - private LollipopConsumerRequest getLollipopConsumerRequest(String assertionRef, String publicKey, String userId) { + private LollipopConsumerRequest getLollipopConsumerRequest( + String assertionRef, String publicKey, String userId) { HashMap headers = new HashMap<>(); headers.put(lollipopRequestConfigMock.getAuthJWTHeader(), ""); headers.put(lollipopRequestConfigMock.getAssertionRefHeader(), assertionRef); headers.put(lollipopRequestConfigMock.getUserIdHeader(), userId); headers.put(lollipopRequestConfigMock.getPublicKeyHeader(), publicKey); - return LollipopConsumerRequest.builder() - .headerParams(headers) - .build(); + return LollipopConsumerRequest.builder().headerParams(headers).build(); } -} \ No newline at end of file +} diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java index 0e921866..8a380f98 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java @@ -1,27 +1,35 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service.impl; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.spy; + import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionType; import it.pagopa.tech.lollipop.consumer.exception.LollipopRequestContentValidationException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; +import java.util.HashMap; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.HashMap; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.spy; - class LollipopConsumerRequestValidationServiceImplTest { - public static final String VALID_EC_PUBLIC_KEY = "{ \"kty\": \"EC\", \"x\": \"FqFDuwEgu4MUXERPMVL-85pGv2D3YmL4J1gfMkdbc24\", \"y\": \"hdV0oxmWFSxMoJUDpdihr76rS8VRBEqMFebYyAfK9-k\", \"crv\": \"P-256\"}"; - public static final String VALID_RSA_PUBLIC_KEY = "{ \"alg\": \"RS256\", \"e\": \"AQAB\", \"kty\": \"RSA\", \"n\": \"yeNlzlub94YgerT030codqEztjfU_S6X4DbDA_iVKkjAWtYfPHDzz_sPCT1Axz6isZdf3lHpq_gYX4Sz\"}"; - public static final String VALID_ASSERTION_REF = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; + public static final String VALID_EC_PUBLIC_KEY = + "{ \"kty\": \"EC\", \"x\": \"FqFDuwEgu4MUXERPMVL-85pGv2D3YmL4J1gfMkdbc24\", \"y\":" + + " \"hdV0oxmWFSxMoJUDpdihr76rS8VRBEqMFebYyAfK9-k\", \"crv\": \"P-256\"}"; + public static final String VALID_RSA_PUBLIC_KEY = + "{ \"alg\": \"RS256\", \"e\": \"AQAB\", \"kty\": \"RSA\", \"n\":" + + " \"yeNlzlub94YgerT030codqEztjfU_S6X4DbDA_iVKkjAWtYfPHDzz_sPCT1Axz6isZdf3lHpq_gYX4Sz\"}"; + public static final String VALID_ASSERTION_REF = + "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; public static final String VALID_FISCAL_CODE = "AAAAAA89S20I111X"; public static final String VALID_JWT = "aValidJWT"; - public static final String VALID_SIGNATURE_INPUT = "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; - public static final String VALID_SIGNATURE = "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + public static final String VALID_SIGNATURE_INPUT = + "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + public static final String VALID_SIGNATURE = + "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; public static final String RANDOM_STRING = ""; private LollipopConsumerRequestConfig config; @@ -36,33 +44,51 @@ void setUp() { @Test void validatePublicKeyFailureHeaderNotPresent() { HashMap headers = new HashMap<>(); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_PUBLIC_KEY, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.MISSING_PUBLIC_KEY, + e.getErrorCode()); } @Test void validatePublicKeyFailureHeaderInvalidFormat() { HashMap headers = new HashMap<>(); headers.put(config.getPublicKeyHeader(), RANDOM_STRING); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_PUBLIC_KEY, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.INVALID_PUBLIC_KEY, + e.getErrorCode()); } @Test void validateAssertionRefFailureHeaderNotPresent() { HashMap headers = new HashMap<>(); headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_REF, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_REF, + e.getErrorCode()); } @Test @@ -70,11 +96,17 @@ void validateAssertionRefFailureInvalidFormat() { HashMap headers = new HashMap<>(); headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); headers.put(config.getAssertionRefHeader(), RANDOM_STRING); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_REF, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_REF, + e.getErrorCode()); } @Test @@ -82,11 +114,17 @@ void validateAssertionTypeFailureHeaderNotPresent() { HashMap headers = new HashMap<>(); headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_TYPE, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_TYPE, + e.getErrorCode()); } @Test @@ -95,11 +133,17 @@ void validateAssertionTypeFailureInvalidFormat() { headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); headers.put(config.getAssertionTypeHeader(), RANDOM_STRING); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_TYPE, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_TYPE, + e.getErrorCode()); } @Test @@ -108,11 +152,17 @@ void validateUserIdFailureHeaderNotPresent() { headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_USER_ID, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.MISSING_USER_ID, + e.getErrorCode()); } @Test @@ -122,11 +172,17 @@ void validateUserIdFailureInvalidFormat() { headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); headers.put(config.getUserIdHeader(), RANDOM_STRING); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_USER_ID, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.INVALID_USER_ID, + e.getErrorCode()); } @Test @@ -136,11 +192,17 @@ void validateAuthJWKFailureHeaderNotPresent() { headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_AUTH_JWT, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.MISSING_AUTH_JWT, + e.getErrorCode()); } @Test @@ -151,11 +213,17 @@ void validateAuthJWKFailureInvalidFormat() { headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); headers.put(config.getAuthJWTHeader(), RANDOM_STRING); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_AUTH_JWT, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.INVALID_AUTH_JWT, + e.getErrorCode()); } @Test @@ -166,11 +234,17 @@ void validateOriginalMethodFailureHeaderNotPresent() { headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); headers.put(config.getAuthJWTHeader(), VALID_JWT); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_METHOD, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_METHOD, + e.getErrorCode()); } @Test @@ -182,11 +256,17 @@ void validateOriginalMethodFailureNotSupported() { headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); headers.put(config.getAuthJWTHeader(), VALID_JWT); headers.put(config.getOriginalMethodHeader(), "INVALID_METHOD"); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_METHOD, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_METHOD, + e.getErrorCode()); } @Test @@ -198,12 +278,19 @@ void validateOriginalMethodFailureDifferentFromExpectedMethod() { headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); headers.put(config.getAuthJWTHeader(), VALID_JWT); headers.put(config.getOriginalMethodHeader(), "PUT"); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_METHOD, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_METHOD, + e.getErrorCode()); } + @Test void validateOriginalURLFailureHeaderNotPresent() { HashMap headers = new HashMap<>(); @@ -213,11 +300,17 @@ void validateOriginalURLFailureHeaderNotPresent() { headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); headers.put(config.getAuthJWTHeader(), VALID_JWT); headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_URL, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_URL, + e.getErrorCode()); } @Test @@ -230,11 +323,17 @@ void validateOriginalURLFailureInvalidFormat() { headers.put(config.getAuthJWTHeader(), VALID_JWT); headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); headers.put(config.getOriginalURLHeader(), RANDOM_STRING); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_URL, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_URL, + e.getErrorCode()); } @Test @@ -247,11 +346,17 @@ void validateOriginalURLFailureDifferentFromExpectedMethod() { headers.put(config.getAuthJWTHeader(), VALID_JWT); headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); headers.put(config.getOriginalURLHeader(), "https://pagopa.it"); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_URL, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_URL, + e.getErrorCode()); } @Test @@ -264,11 +369,17 @@ void validateSignatureInputFailureHeaderNotPresent() { headers.put(config.getAuthJWTHeader(), VALID_JWT); headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE_INPUT, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE_INPUT, + e.getErrorCode()); } @Test @@ -282,11 +393,17 @@ void validateSignatureInputFailureInvalidFormat() { headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); headers.put(config.getSignatureInputHeader(), RANDOM_STRING); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE_INPUT, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE_INPUT, + e.getErrorCode()); } @Test @@ -300,11 +417,17 @@ void validateSignatureFailureHeaderNotPresent() { headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); headers.put(config.getSignatureInputHeader(), VALID_SIGNATURE_INPUT); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE, + e.getErrorCode()); } @Test @@ -319,11 +442,17 @@ void validateSignatureFailureInvalidFormat() { headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); headers.put(config.getSignatureInputHeader(), VALID_SIGNATURE_INPUT); headers.put(config.getSignatureHeader(), RANDOM_STRING); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE, + e.getErrorCode()); } @Test @@ -338,7 +467,8 @@ void validateRequestSuccessWithECPublicKey() { headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); headers.put(config.getSignatureInputHeader(), VALID_SIGNATURE_INPUT); headers.put(config.getSignatureHeader(), VALID_SIGNATURE); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); assertDoesNotThrow(() -> sut.validateLollipopRequest(request)); } @@ -355,8 +485,9 @@ void validateRequestSuccessWithRSAPublicKey() { headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); headers.put(config.getSignatureInputHeader(), VALID_SIGNATURE_INPUT); headers.put(config.getSignatureHeader(), VALID_SIGNATURE); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); assertDoesNotThrow(() -> sut.validateLollipopRequest(request)); } -} \ No newline at end of file +} From 60e21c3e545d1717b2e154ff3f9197589e2b60a9 Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 17 Apr 2023 09:38:32 +0200 Subject: [PATCH 189/403] [SLS-21] updated verification-metadata.xml. --- gradle/verification-metadata.xml | 82 ++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 26 deletions(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index bd1b1581..9865a91a 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1,5 +1,5 @@ - + true false @@ -236,14 +236,6 @@ - - - - - - - - @@ -252,6 +244,14 @@ + + + + + + + + @@ -278,14 +278,6 @@ - - - - - - - - @@ -294,6 +286,14 @@ + + + + + + + + @@ -320,14 +320,6 @@ - - - - - - - - @@ -336,6 +328,14 @@ + + + + + + + + @@ -351,6 +351,9 @@ + + + @@ -834,14 +837,17 @@ + + + @@ -915,6 +921,16 @@ + + + + + + + + + + @@ -2223,6 +2239,7 @@ + @@ -2288,6 +2305,7 @@ + @@ -2648,8 +2666,8 @@ - + @@ -2709,6 +2727,7 @@ + @@ -2732,6 +2751,7 @@ + @@ -2755,6 +2775,7 @@ + @@ -2778,6 +2799,7 @@ + @@ -2801,6 +2823,7 @@ + @@ -2820,9 +2843,11 @@ + + @@ -2842,6 +2867,7 @@ + @@ -2861,9 +2887,11 @@ + + @@ -2879,9 +2907,11 @@ + + From 2829299ff44c23fb66c5a05b415e20346703ca20 Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 17 Apr 2023 09:40:06 +0200 Subject: [PATCH 190/403] [SLS-21] updated comment. --- .../tech/lollipop/consumer/enumeration/AssertionType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java index e9f6f4d0..71701573 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java @@ -4,6 +4,6 @@ /** Supported assertion type */ public enum AssertionType { SAML, - // TODO: OIDC + // Not supported yet: OIDC } From 7af0fd4f82cbd09823ebcd06bc8cc418724fa7d6 Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 13 Apr 2023 10:49:35 +0200 Subject: [PATCH 191/403] [SLS-21] added original method and url validation. --- .../config/LollipopConsumerRequestConfig.java | 7 ++ .../LollipopValidationException.java | 50 +++++++++++++ .../helper/LollipopConsumerFactoryHelper.java | 13 ++-- .../service/AssertionVerifierService.java | 3 +- .../impl/AssertionVerifierServiceImpl.java | 70 +++++++++++++++++++ .../AssertionVerifierServiceImplStub.java | 53 -------------- 6 files changed, 138 insertions(+), 58 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index ac73a2be..a87881c6 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -14,4 +14,11 @@ public class LollipopConsumerRequestConfig { @Builder.Default private String contentDigestHeader = "content-digest"; @Builder.Default private String lollipopKeyHeader = "x-pagopa-lollipop-public-key"; @Builder.Default private boolean strictDigestVerify = false; + + @Builder.Default private String originalMethodHeader = "x-pagopa-lollipop-original-method"; + @Builder.Default private String originalURLHeader = "x-pagopa-lollipop-original-url"; + + @Builder.Default private String expectedFirstLcOriginalMethod = "POST"; + @Builder.Default private String expectedFirstLcOriginalUrl = " https://api-app.io.pagopa.it/first-lollipop/sign"; + } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java new file mode 100644 index 00000000..4c9e1c8d --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java @@ -0,0 +1,50 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +import java.util.Objects; + +/** + * Thrown in case of problems when computing or verifying lollipop request through the + * assertion flow + */ +public class LollipopValidationException extends Exception { + + /** Error code of this exception */ + private final ErrorCode errorCode; + + /** + * Constructs new exception with provided error code and message + * + * @param errorCode Error code + * @param message Detail message + */ + public LollipopValidationException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Constructs new exception with provided error code, message and cause + * + * @param errorCode Error code + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public LollipopValidationException(ErrorCode errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Returns error code + * + * @return Error code of this exception + */ + public ErrorCode getErrorCode() { + return errorCode; + } + + /** Error codes to classify Lollipop Request Exceptions */ + public enum ErrorCode { + UNEXPECTED_METHOD_OR_URL, + } +} \ No newline at end of file diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index 6caa8d69..ed688eda 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -7,7 +7,7 @@ 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.impl.AssertionVerifierServiceImplStub; +import it.pagopa.tech.lollipop.consumer.service.impl.AssertionVerifierServiceImpl; import it.pagopa.tech.lollipop.consumer.service.impl.HttpMessageVerifierServiceImpl; import javax.inject.Inject; @@ -35,7 +35,9 @@ public LollipopConsumerFactoryHelper( */ public HttpMessageVerifierService getHttpMessageVerifierService() { return new HttpMessageVerifierServiceImpl( - getHttpMessageVerifierFactory().create(), getLollipopConsumerRequestConfig()); + getHttpMessageVerifierFactory().create(), + getLollipopConsumerRequestConfig() + ); } /** @@ -44,8 +46,11 @@ public HttpMessageVerifierService getHttpMessageVerifierService() { * @return an instance of {@link AssertionVerifierService} */ public AssertionVerifierService getAssertionVerifierService() { - return new AssertionVerifierServiceImplStub( - getIdpCertProviderFactory().create(), getAssertionServiceFactory().create()); + return new AssertionVerifierServiceImpl( + getIdpCertProviderFactory().create(), + getAssertionServiceFactory().create(), + getLollipopConsumerRequestConfig() + ); } public HttpMessageVerifierFactory getHttpMessageVerifierFactory() { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java index 758422bf..cc555fae 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java @@ -1,6 +1,7 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service; +import it.pagopa.tech.lollipop.consumer.exception.LollipopValidationException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; /** @@ -16,5 +17,5 @@ public interface AssertionVerifierService { * @param request * @return */ - boolean validateLollipop(LollipopConsumerRequest request); + boolean validateLollipop(LollipopConsumerRequest request) throws LollipopValidationException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java new file mode 100644 index 00000000..dd66e7b3 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -0,0 +1,70 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.service.impl; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.exception.LollipopValidationException; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; +import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; +import javax.inject.Inject; +import java.util.Map; + +public class AssertionVerifierServiceImpl implements AssertionVerifierService { + + private final IdpCertProvider idpCertProvider; + private final AssertionService assertionService; + private final LollipopConsumerRequestConfig lollipopConsumerRequestConfig; + + + @Inject + public AssertionVerifierServiceImpl(IdpCertProvider idpCertProvider, AssertionService assertionService, LollipopConsumerRequestConfig lollipopConsumerRequestConfig) { + this.idpCertProvider = idpCertProvider; + this.assertionService = assertionService; + this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; + } + + @Override + public boolean validateLollipop(LollipopConsumerRequest request) throws LollipopValidationException { + + Map headerParams = request.getHeaderParams(); + + String originalMethod = headerParams.get(lollipopConsumerRequestConfig.getOriginalMethodHeader()); + String originalUrl = headerParams.get(lollipopConsumerRequestConfig.getOriginalURLHeader()); + + if (!originalMethod.equals(lollipopConsumerRequestConfig.getExpectedFirstLcOriginalMethod()) && !originalUrl.equals(lollipopConsumerRequestConfig.getExpectedFirstLcOriginalUrl())) { + String errMsg = String.format("Unexpected original method and/or original url: %s, %s", originalMethod, originalUrl); + throw new LollipopValidationException(LollipopValidationException.ErrorCode.UNEXPECTED_METHOD_OR_URL, errMsg); + } + + + + return true; + } + + private SamlAssertion getAssertion(String jwt, String assertionRef) { + return null; + } + + private boolean validateAssertionPeriod(String notBefore) { + return false; + } + + private boolean validateUserId(LollipopConsumerRequest request, SamlAssertion assertion) { + return false; + } + + private boolean validateInResponseTo(LollipopConsumerRequest request, SamlAssertion assertion) { + return false; + } + + private IdpCertData getIdpCertData(SamlAssertion assertion) { + return null; + } + + private boolean validateSignature(SamlAssertion assertion, IdpCertData idpCertData) { + return false; + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java deleted file mode 100644 index f87d7cf6..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplStub.java +++ /dev/null @@ -1,53 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.service.impl; - -import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; -import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; -import it.pagopa.tech.lollipop.consumer.model.IdpCertData; -import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; -import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; -import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; -import javax.inject.Inject; - -public class AssertionVerifierServiceImplStub implements AssertionVerifierService { - - private IdpCertProvider idpCertProvider; - private AssertionService assertionService; - - @Inject - public AssertionVerifierServiceImplStub( - IdpCertProvider idpCertProvider, AssertionService assertionService) { - this.idpCertProvider = idpCertProvider; - this.assertionService = assertionService; - } - - /** TODO: stub */ - @Override - public boolean validateLollipop(LollipopConsumerRequest request) { - return true; - } - - private SamlAssertion getAssertion(String jwt, String assertionRef) { - return null; - } - - private boolean validateAssertionPeriod(String notBefore) { - return false; - } - - private boolean validateThumbprint(LollipopConsumerRequest request, SamlAssertion assertion) { - return false; - } - - private boolean validateInResponseTo(LollipopConsumerRequest request, SamlAssertion assertion) { - return false; - } - - private IdpCertData getIdpCertData(SamlAssertion assertion) { - return null; - } - - private boolean validateSignature(SamlAssertion assertion, IdpCertData idpCertData) { - return false; - } -} From 89d4d07adbff898d6403fd462d18d73eacee8f20 Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 13 Apr 2023 11:05:02 +0200 Subject: [PATCH 192/403] [SLS-21] added all request headers. --- .../consumer/config/LollipopConsumerRequestConfig.java | 5 +++++ .../consumer/exception/LollipopValidationException.java | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index a87881c6..4a9f3b44 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -17,6 +17,11 @@ public class LollipopConsumerRequestConfig { @Builder.Default private String originalMethodHeader = "x-pagopa-lollipop-original-method"; @Builder.Default private String originalURLHeader = "x-pagopa-lollipop-original-url"; + @Builder.Default private String assertionRefHeader = "x-pagopa-lollipop-assertion-ref"; + @Builder.Default private String assertionTypeHeader = "x-pagopa-lollipop-assertion-type"; + @Builder.Default private String userIdHeader = "x-pagopa-lollipop-user-id"; + @Builder.Default private String publicKeyHeader = "x-pagopa-lollipop-public-key"; + @Builder.Default private String authJWTHeader = "x-pagopa-lollipop-auth-jwt"; @Builder.Default private String expectedFirstLcOriginalMethod = "POST"; @Builder.Default private String expectedFirstLcOriginalUrl = " https://api-app.io.pagopa.it/first-lollipop/sign"; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java index 4c9e1c8d..9cc2230d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java @@ -45,6 +45,6 @@ public ErrorCode getErrorCode() { /** Error codes to classify Lollipop Request Exceptions */ public enum ErrorCode { - UNEXPECTED_METHOD_OR_URL, + UNEXPECTED_METHOD_OR_URL } } \ No newline at end of file From 700bc7d3f7b83a47db015033c58d02b2eb0e58a8 Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 13 Apr 2023 10:49:35 +0200 Subject: [PATCH 193/403] [SLS-21] added original method and url validation. --- .../consumer/config/LollipopConsumerRequestConfig.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index 4a9f3b44..94b5e47c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -12,7 +12,6 @@ public class LollipopConsumerRequestConfig { @Builder.Default private String signatureInputHeader = "signature-input"; @Builder.Default private String contentEncodingHeader = "content-encoding"; @Builder.Default private String contentDigestHeader = "content-digest"; - @Builder.Default private String lollipopKeyHeader = "x-pagopa-lollipop-public-key"; @Builder.Default private boolean strictDigestVerify = false; @Builder.Default private String originalMethodHeader = "x-pagopa-lollipop-original-method"; @@ -24,6 +23,6 @@ public class LollipopConsumerRequestConfig { @Builder.Default private String authJWTHeader = "x-pagopa-lollipop-auth-jwt"; @Builder.Default private String expectedFirstLcOriginalMethod = "POST"; - @Builder.Default private String expectedFirstLcOriginalUrl = " https://api-app.io.pagopa.it/first-lollipop/sign"; + @Builder.Default private String expectedFirstLcOriginalUrl = "https://api-app.io.pagopa.it/first-lollipop/sign"; } From c9e8c89195749d68383d4bfabcbd5cb9b2040027 Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 13 Apr 2023 14:47:25 +0200 Subject: [PATCH 194/403] [SLS-21] added request headers validation. --- ...lipopConsumerRequestValidationService.java | 167 ++++++++++++++++++ .../enumeration/AssertionTypeEnum.java | 10 ++ .../enumeration/LollipopMethodEnum.java | 12 ++ .../exception/LollipopVerifierException.java | 25 ++- .../lollipop/consumer/model/ECPublicKey.java | 15 ++ .../lollipop/consumer/model/RSAPublicKey.java | 15 ++ 6 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionTypeEnum.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopMethodEnum.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java new file mode 100644 index 00000000..c8801d21 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java @@ -0,0 +1,167 @@ +package it.pagopa.tech.lollipop.consumer.config.service; + +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.enumeration.AssertionTypeEnum; +import it.pagopa.tech.lollipop.consumer.enumeration.LollipopMethodEnum; +import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; + +import java.util.Map; +import java.util.regex.Pattern; + +public class LollipopConsumerRequestValidationService { + + public static boolean validateLollipopConsumerConfig(LollipopConsumerRequest request, LollipopConsumerRequestConfig config) throws LollipopVerifierException { + + Map headerParams = request.getHeaderParams(); + + validatePublicKey(headerParams.get(config.getPublicKeyHeader())); + + validateAssertionRefHeader(headerParams.get(config.getAssertionRefHeader())); + validateAssertionTypeHeader(headerParams.get(config.getAssertionTypeHeader())); + validateUserIdHeader(headerParams.get(config.getUserIdHeader())); + validateAuthJWTHeader(headerParams.get(config.getAuthJWTHeader())); + validateOriginalMethodHeader(headerParams.get(config.getOriginalMethodHeader())); + validateOriginalURLHeader(headerParams.get(config.getOriginalURLHeader())); + validateSignatureInputHeader(headerParams.get(config.getSignatureInputHeader())); + validateSignatureHeader(headerParams.get(config.getSignatureHeader())); + + return true; + } + + private static void validatePublicKey(String publicKey) throws LollipopVerifierException { + if (publicKey == null ) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_PUBLIC_KEY, "Missing Public Key Header"); + } + + if (isNotValidPublicKey(publicKey)) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_PUBLIC_KEY, "Invalid Public Key Header value"); + } + } + + private static boolean isNotValidPublicKey(String publicKey) { + // TODO + return false; + } + + private static void validateAssertionRefHeader(String assertionRef) throws LollipopVerifierException { + if (assertionRef == null ) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_ASSERTION_REF, "Missing AssertionRef Header"); + } + + if (isNotValidAssertionRef(assertionRef)) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ASSERTION_REF, "Invalid AssertionRef Header value"); + } + } + + private static boolean isNotValidAssertionRef(String signature) { + boolean matchesSHA26 = Pattern.compile("^(sha256-[A-Za-z0-9-_=]{1,44})$").matcher(signature).matches(); + boolean matchesSHA384 = Pattern.compile("^(sha384-[A-Za-z0-9-_=]{1,66})$").matcher(signature).matches(); + boolean matchesSHA512 = Pattern.compile("^(sha512-[A-Za-z0-9-_=]{1,88})$").matcher(signature).matches(); + return !matchesSHA26 && !matchesSHA384 && !matchesSHA512; + } + + private static void validateAssertionTypeHeader(String assertionType) throws LollipopVerifierException { + if (assertionType == null ) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_ASSERTION_TYPE, "Missing Assertion Type Header"); + } + + if ((!isAssertionTypeSupported(assertionType))) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ASSERTION_TYPE, "Invalid Assertion Type Header value, type not supported"); + } + } + + public static boolean isAssertionTypeSupported(String assertionType) { + for (AssertionTypeEnum supportedType : AssertionTypeEnum.values()) { + if (supportedType.name().equals(assertionType)) { + return true; + } + } + return false; + } + + private static void validateUserIdHeader(String userId) throws LollipopVerifierException { + if (userId == null ) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_USER_ID, "Missing User Id Header"); + } + + if ((isNotValidFiscalCode(userId))) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_USER_ID, "Invalid User Id Header value, type not supported"); + } + } + + private static boolean isNotValidFiscalCode(String userId) { + return !Pattern.compile("^[A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]$").matcher(userId).matches(); + } + + private static void validateAuthJWTHeader(String authJWT) throws LollipopVerifierException { + if (authJWT == null ) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_AUTH_JWT, "Missing Auth JWT Header"); + } + + if (authJWT.isBlank()) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_AUTH_JWT, "Invalid Auth JWT Header value, cannot be empty"); + } + } + + private static void validateOriginalMethodHeader(String originalMethod) throws LollipopVerifierException { + if (originalMethod == null ) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_ORIGINAL_METHOD, "Missing Original Method Header"); + } + + if (!isRequestMethodSupported(originalMethod)) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ORIGINAL_METHOD, "Invalid Original Method Header value, method not supported"); + } + } + + public static boolean isRequestMethodSupported(String originalMethod) { + for (LollipopMethodEnum supportedType : LollipopMethodEnum.values()) { + if (supportedType.name().equals(originalMethod)) { + return true; + } + } + return false; + } + + private static void validateOriginalURLHeader(String originalURL) throws LollipopVerifierException { + if (originalURL == null ) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_ORIGINAL_URL, "Missing Original URL Header"); + } + + if (isNotValidOriginalURL(originalURL)) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ORIGINAL_URL, "Invalid Original URL Header value"); + } + } + + private static boolean isNotValidOriginalURL(String originalURL) { + return !Pattern.compile("^https://").matcher(originalURL).matches(); + } + + private static void validateSignatureInputHeader(String signatureInput) throws LollipopVerifierException { + if (signatureInput == null ) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE_INPUT, "Missing Signature Input Header"); + } + + if (isNotValidSignatureInput(signatureInput)) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ORIGINAL_URL, "Invalid Signature Input Header value"); + } + } + + private static boolean isNotValidSignatureInput(String signatureInput) { + return !Pattern.compile("^(((sig[0-9]+)=[^,]*?)(, ?)?)+$").matcher(signatureInput).matches(); + } + + private static void validateSignatureHeader(String signature) throws LollipopVerifierException { + if (signature == null ) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE, "Missing Signature Header"); + } + + if (isNotValidSignature(signature)) { + throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_SIGNATURE_HEADER, "Invalid Signature Header value"); + } + } + + private static boolean isNotValidSignature(String signature) { + return !Pattern.compile("^((sig[0-9]+)=:[A-Za-z0-9+/=]*:(, ?)?)+$").matcher(signature).matches(); + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionTypeEnum.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionTypeEnum.java new file mode 100644 index 00000000..e7cae454 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionTypeEnum.java @@ -0,0 +1,10 @@ +package it.pagopa.tech.lollipop.consumer.enumeration; + +/** + * Supported assertion type + */ +public enum AssertionTypeEnum { + SAML, + //TODO: OIDC + +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopMethodEnum.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopMethodEnum.java new file mode 100644 index 00000000..66069d8f --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopMethodEnum.java @@ -0,0 +1,12 @@ +package it.pagopa.tech.lollipop.consumer.enumeration; + +/** + * Supported Lollipop request methods + */ +public enum LollipopMethodEnum { + GET, + POST, + PUT, + PATCH, + DELETE +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java index 04e98686..7ea6685d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java @@ -47,7 +47,30 @@ public ErrorCode getErrorCode() { /** Error codes to classify Lollipop Request Exceptions */ public enum ErrorCode { MISSING_SIGNATURE, + INVALID_SIGNATURE_HEADER, - MISSING_SIGNATURE_INPUT + MISSING_SIGNATURE_INPUT, + INVALID_SIGNATURE_INPUT, + + MISSING_ASSERTION_REF, + INVALID_ASSERTION_REF, + + MISSING_ASSERTION_TYPE, + INVALID_ASSERTION_TYPE, + + MISSING_USER_ID, + INVALID_USER_ID, + + MISSING_AUTH_JWT, + INVALID_AUTH_JWT, + + MISSING_ORIGINAL_METHOD, + INVALID_ORIGINAL_METHOD, + + MISSING_ORIGINAL_URL, + INVALID_ORIGINAL_URL, + + MISSING_PUBLIC_KEY, + INVALID_PUBLIC_KEY } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java new file mode 100644 index 00000000..e3581111 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java @@ -0,0 +1,15 @@ +package it.pagopa.tech.lollipop.consumer.model; + +import lombok.Data; + +/** + * EC public key model + */ +@Data +public class ECPublicKey { + + private String crv; + private String kty; + private String x; + private String y; +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java new file mode 100644 index 00000000..628d327a --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java @@ -0,0 +1,15 @@ +package it.pagopa.tech.lollipop.consumer.model; + +import lombok.Data; + +/** + * RSA public key model + */ +@Data +public class RSAPublicKey { + + private String alg; + private String e; + private String kty; + private String n; +} From d365501f5edbd8773dcedea3f42c0fffc1e9e323 Mon Sep 17 00:00:00 2001 From: svariant Date: Thu, 13 Apr 2023 12:15:22 +0200 Subject: [PATCH 195/403] [SLS-21] Implemented method to validate assertion period --- .../impl/AssertionVerifierServiceImpl.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index dd66e7b3..1f9e9356 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -9,8 +9,13 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; + import javax.inject.Inject; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.Map; +import java.util.concurrent.TimeUnit; public class AssertionVerifierServiceImpl implements AssertionVerifierService { @@ -40,7 +45,6 @@ public boolean validateLollipop(LollipopConsumerRequest request) throws Lollipop } - return true; } @@ -48,7 +52,19 @@ private SamlAssertion getAssertion(String jwt, String assertionRef) { return null; } - private boolean validateAssertionPeriod(String notBefore) { + public boolean validateAssertionPeriod(String notBefore) throws ParseException { + long notBeforeMilliseconds = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(notBefore).getTime(); //TODO configurazione format date + + long dateNowMilliseconds = new Date().getTime(); + + long expiresAfterMilliseconds = TimeUnit.DAYS.toMillis(30); //TODO configurazione giorni scadenza + + long dateNowLessNotBefore = (dateNowMilliseconds - notBeforeMilliseconds); + + if (0 <= dateNowLessNotBefore && (dateNowLessNotBefore <= expiresAfterMilliseconds)) { + return true; + } + return false; } From 361608c2777838b32db1a79249210251b460060f Mon Sep 17 00:00:00 2001 From: svariant Date: Thu, 13 Apr 2023 14:48:40 +0200 Subject: [PATCH 196/403] [SLS-21] Implemented userID (fiscalCode) validation --- .../impl/AssertionVerifierServiceImpl.java | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index 1f9e9356..4c41d28a 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -9,13 +9,23 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; import javax.inject.Inject; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.io.StringReader; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; public class AssertionVerifierServiceImpl implements AssertionVerifierService { @@ -52,8 +62,8 @@ private SamlAssertion getAssertion(String jwt, String assertionRef) { return null; } - public boolean validateAssertionPeriod(String notBefore) throws ParseException { - long notBeforeMilliseconds = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(notBefore).getTime(); //TODO configurazione format date + private boolean validateAssertionPeriod(String notBefore) throws ParseException { + long notBeforeMilliseconds = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse(notBefore).getTime(); //TODO configurazione format date long dateNowMilliseconds = new Date().getTime(); @@ -68,8 +78,27 @@ public boolean validateAssertionPeriod(String notBefore) throws ParseException { return false; } - private boolean validateUserId(LollipopConsumerRequest request, SamlAssertion assertion) { - return false; + private boolean validateUserId(LollipopConsumerRequest request, SamlAssertion assertion) throws ParserConfigurationException, IOException, SAXException { + String stringXml = assertion.getAssertionData(); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document document = builder.parse(new InputSource(new StringReader(stringXml))); + + String userIdHeaders = request.getHeaderParams().get("x-pagopa-lollipop-user-id"); //TODO aggiungere a configurazione + + NodeList listElements = document.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "Attribute"); //TODO aggiungere a configurazione + String userIdAssertion = ""; + if (listElements != null && listElements.getLength() > 0) { + for (int i = 0; i < listElements.getLength(); i++) { + String userIdFound = listElements.item(i).getAttributes().getNamedItem("fiscalNumber").getNodeValue(); + if (!userIdFound.isBlank()) { + userIdAssertion = userIdFound.trim().replace("TINIT-", ""); + break; + } + } + } + + return userIdAssertion.equals(userIdHeaders); } private boolean validateInResponseTo(LollipopConsumerRequest request, SamlAssertion assertion) { From c4e925579f23e2751d12a0716262cf0f11dbe94c Mon Sep 17 00:00:00 2001 From: giomella Date: Fri, 14 Apr 2023 10:15:54 +0200 Subject: [PATCH 197/403] [SLS-21] integrated assertion period, user id and thumbprint validation in the assertion verify flow. --- core/build.gradle | 1 + .../impl/LollipopConsumerCommandImpl.java | 21 +- .../config/LollipopConsumerRequestConfig.java | 15 +- ...lipopConsumerRequestValidationService.java | 87 ++++---- .../enumeration/AssertionRefAlgorithms.java | 29 +++ ...ertionTypeEnum.java => AssertionType.java} | 2 +- .../AssertionVerificationResultCode.java | 20 ++ ...odEnum.java => LollipopRequestMethod.java} | 2 +- ...ion.java => AssertionPeriodException.java} | 14 +- .../AssertionThumbprintException.java | 52 +++++ .../exception/AssertionUserIdException.java | 51 +++++ .../ErrorRetrievingAssertionException.java | 51 +++++ ...ipopRequestContentValidationException.java | 78 +++++++ .../exception/LollipopVerifierException.java | 25 +-- .../service/AssertionVerifierService.java | 15 +- .../impl/AssertionVerifierServiceImpl.java | 198 ++++++++++++++---- 16 files changed, 536 insertions(+), 125 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java rename core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/{AssertionTypeEnum.java => AssertionType.java} (79%) rename core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/{LollipopMethodEnum.java => LollipopRequestMethod.java} (80%) rename core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/{LollipopValidationException.java => AssertionPeriodException.java} (73%) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionUserIdException.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingAssertionException.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java diff --git a/core/build.gradle b/core/build.gradle index f570fbda..b13a86e8 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -36,6 +36,7 @@ dependencies { implementation 'javax.inject:javax.inject:1' implementation 'com.typesafe:config:1.4.2' implementation 'javax.inject:javax.inject:1' + implementation 'com.nimbusds:nimbus-jose-jwt:9.31' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.mockito:mockito-core:5.2.0' diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index f59ad80a..9d2f23eb 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -4,9 +4,7 @@ import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionVerificationResultCode; import it.pagopa.tech.lollipop.consumer.enumeration.HttpMessageVerificationResultCode; -import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; -import it.pagopa.tech.lollipop.consumer.exception.LollipopSignatureException; -import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; +import it.pagopa.tech.lollipop.consumer.exception.*; import it.pagopa.tech.lollipop.consumer.model.CommandResult; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; @@ -56,7 +54,22 @@ public CommandResult doExecute(LollipopConsumerRequest request) { } private CommandResult getAssertionVerificationResult(LollipopConsumerRequest request) { - boolean result = assertionVerifierService.validateLollipop(request); + boolean result; + try { + result = assertionVerifierService.validateLollipop(request); + } catch (ErrorRetrievingAssertionException e) { + String message = String.format("Cannot obtain the assertion, validation failed with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); + return buildCommandResult(AssertionVerificationResultCode.ERROR_RETRIEVING_ASSERTION.name(), message); + } catch (AssertionPeriodException e) { + String message = String.format("Assertion validation failed on verifying period with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); + return buildCommandResult(AssertionVerificationResultCode.PERIOD_VALIDATION_ERROR.name(), message); + } catch (AssertionThumbprintException e) { + String message = String.format("Assertion validation failed on verifying thumbprint with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); + return buildCommandResult(AssertionVerificationResultCode.THUMBPRINT_VALIDATION_ERROR.name(), message); + } catch (AssertionUserIdException e) { + String message = String.format("Assertion validation failed on verifying user id with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); + return buildCommandResult(AssertionVerificationResultCode.USER_ID_VALIDATION_ERROR.name(), message); + } if (!result) { return buildCommandResult( diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index 94b5e47c..4cb1ab4f 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -8,12 +8,13 @@ @Data public class LollipopConsumerRequestConfig { + @Builder.Default private boolean strictDigestVerify = false; + + //request headers @Builder.Default private String signatureHeader = "signature"; @Builder.Default private String signatureInputHeader = "signature-input"; @Builder.Default private String contentEncodingHeader = "content-encoding"; @Builder.Default private String contentDigestHeader = "content-digest"; - @Builder.Default private boolean strictDigestVerify = false; - @Builder.Default private String originalMethodHeader = "x-pagopa-lollipop-original-method"; @Builder.Default private String originalURLHeader = "x-pagopa-lollipop-original-url"; @Builder.Default private String assertionRefHeader = "x-pagopa-lollipop-assertion-ref"; @@ -25,4 +26,14 @@ public class LollipopConsumerRequestConfig { @Builder.Default private String expectedFirstLcOriginalMethod = "POST"; @Builder.Default private String expectedFirstLcOriginalUrl = "https://api-app.io.pagopa.it/first-lollipop/sign"; + // assertion validation parameters + @Builder.Default private int assertionExpireInDays = 30; + @Builder.Default private String assertionNotBeforeDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; + @Builder.Default private String samlNamespaceAssertion = "urn:oasis:names:tc:SAML:2.0:assertion"; + @Builder.Default private String assertionNotBeforeTag = "Conditions"; + @Builder.Default private String assertionFiscalCodeTag = "Attribute"; + @Builder.Default private String assertionInResponseToTag = "SubjectConfirmationData"; + + + } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java index c8801d21..38a3ba55 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java @@ -1,9 +1,10 @@ package it.pagopa.tech.lollipop.consumer.config.service; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; -import it.pagopa.tech.lollipop.consumer.enumeration.AssertionTypeEnum; -import it.pagopa.tech.lollipop.consumer.enumeration.LollipopMethodEnum; -import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; +import it.pagopa.tech.lollipop.consumer.enumeration.AssertionRefAlgorithms; +import it.pagopa.tech.lollipop.consumer.enumeration.AssertionType; +import it.pagopa.tech.lollipop.consumer.enumeration.LollipopRequestMethod; +import it.pagopa.tech.lollipop.consumer.exception.LollipopRequestContentValidationException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import java.util.Map; @@ -11,10 +12,18 @@ public class LollipopConsumerRequestValidationService { - public static boolean validateLollipopConsumerConfig(LollipopConsumerRequest request, LollipopConsumerRequestConfig config) throws LollipopVerifierException { + public static boolean validateLollipopConsumerConfig(LollipopConsumerRequest request, LollipopConsumerRequestConfig config) throws LollipopRequestContentValidationException { Map headerParams = request.getHeaderParams(); + String originalMethod = headerParams.get(config.getOriginalMethodHeader()); + String originalUrl = headerParams.get(config.getOriginalURLHeader()); + + if (!originalMethod.equals(config.getExpectedFirstLcOriginalMethod()) && !originalUrl.equals(config.getExpectedFirstLcOriginalUrl())) { + String errMsg = String.format("Unexpected original method and/or original url: %s, %s", originalMethod, originalUrl); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_METHOD_OR_URL, errMsg); + } + validatePublicKey(headerParams.get(config.getPublicKeyHeader())); validateAssertionRefHeader(headerParams.get(config.getAssertionRefHeader())); @@ -29,13 +38,13 @@ public static boolean validateLollipopConsumerConfig(LollipopConsumerRequest req return true; } - private static void validatePublicKey(String publicKey) throws LollipopVerifierException { + private static void validatePublicKey(String publicKey) throws LollipopRequestContentValidationException { if (publicKey == null ) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_PUBLIC_KEY, "Missing Public Key Header"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_PUBLIC_KEY, "Missing Public Key Header"); } if (isNotValidPublicKey(publicKey)) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_PUBLIC_KEY, "Invalid Public Key Header value"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_PUBLIC_KEY, "Invalid Public Key Header value"); } } @@ -44,35 +53,35 @@ private static boolean isNotValidPublicKey(String publicKey) { return false; } - private static void validateAssertionRefHeader(String assertionRef) throws LollipopVerifierException { + private static void validateAssertionRefHeader(String assertionRef) throws LollipopRequestContentValidationException { if (assertionRef == null ) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_ASSERTION_REF, "Missing AssertionRef Header"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_REF, "Missing AssertionRef Header"); } if (isNotValidAssertionRef(assertionRef)) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ASSERTION_REF, "Invalid AssertionRef Header value"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_REF, "Invalid AssertionRef Header value"); } } private static boolean isNotValidAssertionRef(String signature) { - boolean matchesSHA26 = Pattern.compile("^(sha256-[A-Za-z0-9-_=]{1,44})$").matcher(signature).matches(); - boolean matchesSHA384 = Pattern.compile("^(sha384-[A-Za-z0-9-_=]{1,66})$").matcher(signature).matches(); - boolean matchesSHA512 = Pattern.compile("^(sha512-[A-Za-z0-9-_=]{1,88})$").matcher(signature).matches(); - return !matchesSHA26 && !matchesSHA384 && !matchesSHA512; + boolean matchesSHA256 = AssertionRefAlgorithms.SHA256.getPattern().matcher(signature).matches(); + boolean matchesSHA384 = AssertionRefAlgorithms.SHA384.getPattern().matcher(signature).matches(); + boolean matchesSHA512 = AssertionRefAlgorithms.SHA512.getPattern().matcher(signature).matches(); + return !matchesSHA256 && !matchesSHA384 && !matchesSHA512; } - private static void validateAssertionTypeHeader(String assertionType) throws LollipopVerifierException { + private static void validateAssertionTypeHeader(String assertionType) throws LollipopRequestContentValidationException { if (assertionType == null ) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_ASSERTION_TYPE, "Missing Assertion Type Header"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_TYPE, "Missing Assertion Type Header"); } if ((!isAssertionTypeSupported(assertionType))) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ASSERTION_TYPE, "Invalid Assertion Type Header value, type not supported"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_TYPE, "Invalid Assertion Type Header value, type not supported"); } } - public static boolean isAssertionTypeSupported(String assertionType) { - for (AssertionTypeEnum supportedType : AssertionTypeEnum.values()) { + private static boolean isAssertionTypeSupported(String assertionType) { + for (AssertionType supportedType : AssertionType.values()) { if (supportedType.name().equals(assertionType)) { return true; } @@ -80,13 +89,13 @@ public static boolean isAssertionTypeSupported(String assertionType) { return false; } - private static void validateUserIdHeader(String userId) throws LollipopVerifierException { + private static void validateUserIdHeader(String userId) throws LollipopRequestContentValidationException { if (userId == null ) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_USER_ID, "Missing User Id Header"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_USER_ID, "Missing User Id Header"); } if ((isNotValidFiscalCode(userId))) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_USER_ID, "Invalid User Id Header value, type not supported"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_USER_ID, "Invalid User Id Header value, type not supported"); } } @@ -94,28 +103,28 @@ private static boolean isNotValidFiscalCode(String userId) { return !Pattern.compile("^[A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]$").matcher(userId).matches(); } - private static void validateAuthJWTHeader(String authJWT) throws LollipopVerifierException { + private static void validateAuthJWTHeader(String authJWT) throws LollipopRequestContentValidationException { if (authJWT == null ) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_AUTH_JWT, "Missing Auth JWT Header"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_AUTH_JWT, "Missing Auth JWT Header"); } if (authJWT.isBlank()) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_AUTH_JWT, "Invalid Auth JWT Header value, cannot be empty"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_AUTH_JWT, "Invalid Auth JWT Header value, cannot be empty"); } } - private static void validateOriginalMethodHeader(String originalMethod) throws LollipopVerifierException { + private static void validateOriginalMethodHeader(String originalMethod) throws LollipopRequestContentValidationException { if (originalMethod == null ) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_ORIGINAL_METHOD, "Missing Original Method Header"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_METHOD, "Missing Original Method Header"); } if (!isRequestMethodSupported(originalMethod)) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ORIGINAL_METHOD, "Invalid Original Method Header value, method not supported"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_METHOD, "Invalid Original Method Header value, method not supported"); } } - public static boolean isRequestMethodSupported(String originalMethod) { - for (LollipopMethodEnum supportedType : LollipopMethodEnum.values()) { + private static boolean isRequestMethodSupported(String originalMethod) { + for (LollipopRequestMethod supportedType : LollipopRequestMethod.values()) { if (supportedType.name().equals(originalMethod)) { return true; } @@ -123,13 +132,13 @@ public static boolean isRequestMethodSupported(String originalMethod) { return false; } - private static void validateOriginalURLHeader(String originalURL) throws LollipopVerifierException { + private static void validateOriginalURLHeader(String originalURL) throws LollipopRequestContentValidationException { if (originalURL == null ) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_ORIGINAL_URL, "Missing Original URL Header"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_URL, "Missing Original URL Header"); } if (isNotValidOriginalURL(originalURL)) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ORIGINAL_URL, "Invalid Original URL Header value"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_URL, "Invalid Original URL Header value"); } } @@ -137,13 +146,13 @@ private static boolean isNotValidOriginalURL(String originalURL) { return !Pattern.compile("^https://").matcher(originalURL).matches(); } - private static void validateSignatureInputHeader(String signatureInput) throws LollipopVerifierException { + private static void validateSignatureInputHeader(String signatureInput) throws LollipopRequestContentValidationException { if (signatureInput == null ) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE_INPUT, "Missing Signature Input Header"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE_INPUT, "Missing Signature Input Header"); } if (isNotValidSignatureInput(signatureInput)) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_ORIGINAL_URL, "Invalid Signature Input Header value"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE_INPUT, "Invalid Signature Input Header value"); } } @@ -151,13 +160,13 @@ private static boolean isNotValidSignatureInput(String signatureInput) { return !Pattern.compile("^(((sig[0-9]+)=[^,]*?)(, ?)?)+$").matcher(signatureInput).matches(); } - private static void validateSignatureHeader(String signature) throws LollipopVerifierException { + private static void validateSignatureHeader(String signature) throws LollipopRequestContentValidationException { if (signature == null ) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.MISSING_SIGNATURE, "Missing Signature Header"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE, "Missing Signature Header"); } if (isNotValidSignature(signature)) { - throw new LollipopVerifierException(LollipopVerifierException.ErrorCode.INVALID_SIGNATURE_HEADER, "Invalid Signature Header value"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE_HEADER, "Invalid Signature Header value"); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java new file mode 100644 index 00000000..06e6f417 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java @@ -0,0 +1,29 @@ +package it.pagopa.tech.lollipop.consumer.enumeration; + +import java.util.regex.Pattern; + +/** + * Supported AssertionRef algorithms + */ +public enum AssertionRefAlgorithms { + + SHA256("sha256", Pattern.compile("^(sha256-[A-Za-z0-9-_=]{1,44})$")), + SHA384("sha384", Pattern.compile("^(sha384-[A-Za-z0-9-_=]{1,66})$")), + SHA512("sha512", Pattern.compile("^(sha512-[A-Za-z0-9-_=]{1,88})$")); + + private final String algorithmName; + private final Pattern pattern; + + AssertionRefAlgorithms(String algorithmName, Pattern pattern) { + this.algorithmName = algorithmName; + this.pattern = pattern; + } + + public Pattern getPattern() { + return pattern; + } + + public String getAlgorithmName() { + return algorithmName; + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionTypeEnum.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java similarity index 79% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionTypeEnum.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java index e7cae454..7a47cd22 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionTypeEnum.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java @@ -3,7 +3,7 @@ /** * Supported assertion type */ -public enum AssertionTypeEnum { +public enum AssertionType { SAML, //TODO: OIDC diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java index eb4c55da..e7cd1d0b 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java @@ -4,6 +4,26 @@ /** Result codes to classify Saml assertion validation */ public enum AssertionVerificationResultCode { + /** + * Saml assertion validation failed on retrieving the assertion + */ + ERROR_RETRIEVING_ASSERTION, + + /** + * Saml assertion validation failed on period validation + */ + PERIOD_VALIDATION_ERROR, + + /** + * Saml assertion validation failed on user id validation + */ + USER_ID_VALIDATION_ERROR, + + /** + * Saml assertion validation failed on thumbpriint validation + */ + THUMBPRINT_VALIDATION_ERROR, + /** Saml assertion validation failed without throwing an exception */ ASSERTION_VERIFICATION_FAILED, diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopMethodEnum.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopRequestMethod.java similarity index 80% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopMethodEnum.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopRequestMethod.java index 66069d8f..ed098922 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopMethodEnum.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopRequestMethod.java @@ -3,7 +3,7 @@ /** * Supported Lollipop request methods */ -public enum LollipopMethodEnum { +public enum LollipopRequestMethod { GET, POST, PUT, diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionPeriodException.java similarity index 73% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionPeriodException.java index 9cc2230d..c9c6dfc6 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopValidationException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionPeriodException.java @@ -3,10 +3,9 @@ import java.util.Objects; /** - * Thrown in case of problems when computing or verifying lollipop request through the - * assertion flow + * Thrown in case of problems when verifying assertion period */ -public class LollipopValidationException extends Exception { +public class AssertionPeriodException extends Exception { /** Error code of this exception */ private final ErrorCode errorCode; @@ -17,7 +16,7 @@ public class LollipopValidationException extends Exception { * @param errorCode Error code * @param message Detail message */ - public LollipopValidationException(ErrorCode errorCode, String message) { + public AssertionPeriodException(ErrorCode errorCode, String message) { super(message); this.errorCode = Objects.requireNonNull(errorCode); } @@ -29,7 +28,7 @@ public LollipopValidationException(ErrorCode errorCode, String message) { * @param message Detail message * @param cause Exception causing the constructed one */ - public LollipopValidationException(ErrorCode errorCode, String message, Throwable cause) { + public AssertionPeriodException(ErrorCode errorCode, String message, Throwable cause) { super(message, cause); this.errorCode = Objects.requireNonNull(errorCode); } @@ -45,6 +44,7 @@ public ErrorCode getErrorCode() { /** Error codes to classify Lollipop Request Exceptions */ public enum ErrorCode { - UNEXPECTED_METHOD_OR_URL + ERROR_PARSING_ASSERTION_NOT_BEFORE_DATE, + INVALID_ASSERTION_PERIOD } -} \ No newline at end of file +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java new file mode 100644 index 00000000..4f23f03d --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java @@ -0,0 +1,52 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +import java.util.Objects; + +/** + * Thrown in case of problems when verifying assertion thumbprint + */ +public class AssertionThumbprintException extends Exception { + + /** Error code of this exception */ + private final ErrorCode errorCode; + + /** + * Constructs new exception with provided error code and message + * + * @param errorCode Error code + * @param message Detail message + */ + public AssertionThumbprintException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Constructs new exception with provided error code, message and cause + * + * @param errorCode Error code + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public AssertionThumbprintException(ErrorCode errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Returns error code + * + * @return Error code of this exception + */ + public ErrorCode getErrorCode() { + return errorCode; + } + + /** Error codes to classify Lollipop Request Exceptions */ + public enum ErrorCode { + IN_RESPONSE_TO_FIELD_NOT_FOUND, + IN_RESPONSE_TO_NOT_VALID, + ERROR_CALCULATING_ASSERTION_THUMBPRINT, + INVALID_IN_RESPONSE_TO + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionUserIdException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionUserIdException.java new file mode 100644 index 00000000..106b8384 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionUserIdException.java @@ -0,0 +1,51 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +import java.util.Objects; + +/** + * Thrown in case of problems when verifying assertion user id + */ +public class AssertionUserIdException extends Exception { + + + /** Error code of this exception */ + private final ErrorCode errorCode; + + /** + * Constructs new exception with provided error code and message + * + * @param errorCode Error code + * @param message Detail message + */ + public AssertionUserIdException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Constructs new exception with provided error code, message and cause + * + * @param errorCode Error code + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public AssertionUserIdException(ErrorCode errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Returns error code + * + * @return Error code of this exception + */ + public ErrorCode getErrorCode() { + return errorCode; + } + + /** Error codes to classify Lollipop Request Exceptions */ + public enum ErrorCode { + INVALID_USER_ID, + FISCAL_CODE_FIELD_NOT_FOUND + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingAssertionException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingAssertionException.java new file mode 100644 index 00000000..7cd1f385 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingAssertionException.java @@ -0,0 +1,51 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +import java.util.Objects; + +/** + * Thrown in case of problems on retrieving the assertion + */ +public class ErrorRetrievingAssertionException extends Exception { + + /** Error code of this exception */ + private final ErrorCode errorCode; + + /** + * Constructs new exception with provided error code and message + * + * @param errorCode Error code + * @param message Detail message + */ + public ErrorRetrievingAssertionException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Constructs new exception with provided error code, message and cause + * + * @param errorCode Error code + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public ErrorRetrievingAssertionException(ErrorCode errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Returns error code + * + * @return Error code of this exception + */ + public ErrorCode getErrorCode() { + return errorCode; + } + + /** Error codes to classify Lollipop Request Exceptions */ + public enum ErrorCode { + SAML_ASSERTION_NOT_FOUND, + OIDC_TYPE_NOT_SUPPORTED, + ERROR_PARSING_ASSERTION + } +} \ No newline at end of file diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java new file mode 100644 index 00000000..a9facc20 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java @@ -0,0 +1,78 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +import java.util.Objects; + +/** + * Thrown in case of problem during Lollipop request header and body validation + */ +public class LollipopRequestContentValidationException extends Exception { + + + /** Error code of this exception */ + private final ErrorCode errorCode; + + /** + * Constructs new exception with provided error code and message + * + * @param errorCode Error code + * @param message Detail message + */ + public LollipopRequestContentValidationException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Constructs new exception with provided error code, message and cause + * + * @param errorCode Error code + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public LollipopRequestContentValidationException(ErrorCode errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Returns error code + * + * @return Error code of this exception + */ + public ErrorCode getErrorCode() { + return errorCode; + } + + /** Error codes to classify Lollipop Request Exceptions */ + public enum ErrorCode { + UNEXPECTED_METHOD_OR_URL, + + + MISSING_SIGNATURE, + INVALID_SIGNATURE_HEADER, + + MISSING_SIGNATURE_INPUT, + INVALID_SIGNATURE_INPUT, + + MISSING_ASSERTION_REF, + INVALID_ASSERTION_REF, + + MISSING_ASSERTION_TYPE, + INVALID_ASSERTION_TYPE, + + MISSING_USER_ID, + INVALID_USER_ID, + + MISSING_AUTH_JWT, + INVALID_AUTH_JWT, + + MISSING_ORIGINAL_METHOD, + INVALID_ORIGINAL_METHOD, + + MISSING_ORIGINAL_URL, + INVALID_ORIGINAL_URL, + + MISSING_PUBLIC_KEY, + INVALID_PUBLIC_KEY + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java index 7ea6685d..04e98686 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java @@ -47,30 +47,7 @@ public ErrorCode getErrorCode() { /** Error codes to classify Lollipop Request Exceptions */ public enum ErrorCode { MISSING_SIGNATURE, - INVALID_SIGNATURE_HEADER, - MISSING_SIGNATURE_INPUT, - INVALID_SIGNATURE_INPUT, - - MISSING_ASSERTION_REF, - INVALID_ASSERTION_REF, - - MISSING_ASSERTION_TYPE, - INVALID_ASSERTION_TYPE, - - MISSING_USER_ID, - INVALID_USER_ID, - - MISSING_AUTH_JWT, - INVALID_AUTH_JWT, - - MISSING_ORIGINAL_METHOD, - INVALID_ORIGINAL_METHOD, - - MISSING_ORIGINAL_URL, - INVALID_ORIGINAL_URL, - - MISSING_PUBLIC_KEY, - INVALID_PUBLIC_KEY + MISSING_SIGNATURE_INPUT } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java index cc555fae..b5cb0a1b 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java @@ -1,7 +1,10 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service; -import it.pagopa.tech.lollipop.consumer.exception.LollipopValidationException; +import it.pagopa.tech.lollipop.consumer.exception.AssertionPeriodException; +import it.pagopa.tech.lollipop.consumer.exception.AssertionThumbprintException; +import it.pagopa.tech.lollipop.consumer.exception.AssertionUserIdException; +import it.pagopa.tech.lollipop.consumer.exception.ErrorRetrievingAssertionException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; /** @@ -14,8 +17,12 @@ public interface AssertionVerifierService { * Validates Lollipop request Assertion, using the assertion-ref within the request header * params * - * @param request - * @return + * @param request the Lollipop request + * @return true if the assertion is valid + * @throws ErrorRetrievingAssertionException thrown for general errors in the verification process + * @throws AssertionPeriodException thrown for error in assertion period validation + * @throws AssertionThumbprintException thrown for error in assertion thumbprint validation + * @throws AssertionUserIdException thrown for error in user id validation */ - boolean validateLollipop(LollipopConsumerRequest request) throws LollipopValidationException; + boolean validateLollipop(LollipopConsumerRequest request) throws ErrorRetrievingAssertionException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index 4c41d28a..b1d0d8de 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -1,20 +1,27 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service.impl; +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.jwk.JWK; +import com.nimbusds.jose.jwk.ThumbprintUtils; +import com.nimbusds.jose.util.Base64URL; import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; -import it.pagopa.tech.lollipop.consumer.exception.LollipopValidationException; +import it.pagopa.tech.lollipop.consumer.enumeration.AssertionRefAlgorithms; +import it.pagopa.tech.lollipop.consumer.exception.*; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; 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; import javax.inject.Inject; +import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -23,86 +30,114 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Locale; import java.util.Map; import java.util.concurrent.TimeUnit; -import java.util.regex.Pattern; +/** + * Standard implementation of {@link AssertionVerifierService} + */ public class AssertionVerifierServiceImpl implements AssertionVerifierService { private final IdpCertProvider idpCertProvider; private final AssertionService assertionService; - private final LollipopConsumerRequestConfig lollipopConsumerRequestConfig; + private final LollipopConsumerRequestConfig lollipopRequestConfig; + private static final String IN_RESPONSE_TO = "InResponseTo"; @Inject - public AssertionVerifierServiceImpl(IdpCertProvider idpCertProvider, AssertionService assertionService, LollipopConsumerRequestConfig lollipopConsumerRequestConfig) { + public AssertionVerifierServiceImpl(IdpCertProvider idpCertProvider, AssertionService assertionService, LollipopConsumerRequestConfig lollipopRequestConfig) { this.idpCertProvider = idpCertProvider; this.assertionService = assertionService; - this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; + this.lollipopRequestConfig = lollipopRequestConfig; } + /** + * @see AssertionVerifierService#validateLollipop(LollipopConsumerRequest) + * + */ @Override - public boolean validateLollipop(LollipopConsumerRequest request) throws LollipopValidationException { - + public boolean validateLollipop(LollipopConsumerRequest request) throws ErrorRetrievingAssertionException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException { Map headerParams = request.getHeaderParams(); - String originalMethod = headerParams.get(lollipopConsumerRequestConfig.getOriginalMethodHeader()); - String originalUrl = headerParams.get(lollipopConsumerRequestConfig.getOriginalURLHeader()); + SamlAssertion assertion = getAssertion(headerParams.get(lollipopRequestConfig.getAuthJWTHeader()), headerParams.get(lollipopRequestConfig.getAssertionRefHeader())); + Document assertionDoc = buildDocumentFromAssertion(assertion); + + boolean isAssertionPeriodValid = validateAssertionPeriod(assertionDoc); + if (!isAssertionPeriodValid) { + throw new AssertionPeriodException(AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, "The assertion has expired"); + } - if (!originalMethod.equals(lollipopConsumerRequestConfig.getExpectedFirstLcOriginalMethod()) && !originalUrl.equals(lollipopConsumerRequestConfig.getExpectedFirstLcOriginalUrl())) { - String errMsg = String.format("Unexpected original method and/or original url: %s, %s", originalMethod, originalUrl); - throw new LollipopValidationException(LollipopValidationException.ErrorCode.UNEXPECTED_METHOD_OR_URL, errMsg); + boolean isUserIdValid = validateUserId(request, assertionDoc); + if (!isUserIdValid) { + throw new AssertionUserIdException(AssertionUserIdException.ErrorCode.INVALID_USER_ID, "The user id in the assertion does not match the request header"); } + boolean isInResponseToValid = validateInResponseTo(request, assertionDoc); + if (!isInResponseToValid) { + throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.INVALID_IN_RESPONSE_TO, "The hash of provided public key do not match the InResponseTo in the assertion"); + } return true; } - private SamlAssertion getAssertion(String jwt, String assertionRef) { - return null; + private SamlAssertion getAssertion(String jwt, String assertionRef) throws ErrorRetrievingAssertionException { + try { + return assertionService.getAssertion(jwt, assertionRef); + } catch (OidcAssertionNotSupported e) { + throw new ErrorRetrievingAssertionException(ErrorRetrievingAssertionException.ErrorCode.OIDC_TYPE_NOT_SUPPORTED, e.getMessage(), e); + } catch (LollipopAssertionNotFoundException e) { + throw new ErrorRetrievingAssertionException(ErrorRetrievingAssertionException.ErrorCode.SAML_ASSERTION_NOT_FOUND, e.getMessage(), e); + } + } - private boolean validateAssertionPeriod(String notBefore) throws ParseException { - long notBeforeMilliseconds = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse(notBefore).getTime(); //TODO configurazione format date + private boolean validateAssertionPeriod(Document assertionDoc) throws AssertionPeriodException { + NodeList listElements = assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionNotBeforeDateFormat()); + if (listElements == null || listElements.getLength() <= 0) { + return false; + } + String notBefore = listElements.item(0).getAttributes().getNamedItem("NotBefore").getNodeValue(); + long notBeforeMilliseconds; + try { + notBeforeMilliseconds = new SimpleDateFormat(lollipopRequestConfig.getAssertionNotBeforeDateFormat()).parse(notBefore).getTime(); + } catch (ParseException e) { + throw new AssertionPeriodException(AssertionPeriodException.ErrorCode.ERROR_PARSING_ASSERTION_NOT_BEFORE_DATE, e.getMessage(), e); + } long dateNowMilliseconds = new Date().getTime(); + long expiresAfterMilliseconds = TimeUnit.DAYS.toMillis(lollipopRequestConfig.getAssertionExpireInDays()); + long dateNowLessNotBefore = (dateNowMilliseconds - notBeforeMilliseconds); - long expiresAfterMilliseconds = TimeUnit.DAYS.toMillis(30); //TODO configurazione giorni scadenza + return 0 <= dateNowLessNotBefore && (dateNowLessNotBefore <= expiresAfterMilliseconds); + } - long dateNowLessNotBefore = (dateNowMilliseconds - notBeforeMilliseconds); + private boolean validateUserId(LollipopConsumerRequest request, Document assertionDoc) throws AssertionUserIdException { + String userIdHeader = request.getHeaderParams().get(lollipopRequestConfig.getUserIdHeader()); - if (0 <= dateNowLessNotBefore && (dateNowLessNotBefore <= expiresAfterMilliseconds)) { - return true; + String userIdFromAssertion = getUserIdFromAssertion(assertionDoc); + if (userIdFromAssertion == null) { + throw new AssertionUserIdException(AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, "Missing or invalid Fiscal Code in the retrieved saml assertion."); } - return false; + return userIdFromAssertion.equals(userIdHeader); } - private boolean validateUserId(LollipopConsumerRequest request, SamlAssertion assertion) throws ParserConfigurationException, IOException, SAXException { - String stringXml = assertion.getAssertionData(); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document document = builder.parse(new InputSource(new StringReader(stringXml))); - - String userIdHeaders = request.getHeaderParams().get("x-pagopa-lollipop-user-id"); //TODO aggiungere a configurazione - - NodeList listElements = document.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "Attribute"); //TODO aggiungere a configurazione - String userIdAssertion = ""; - if (listElements != null && listElements.getLength() > 0) { - for (int i = 0; i < listElements.getLength(); i++) { - String userIdFound = listElements.item(i).getAttributes().getNamedItem("fiscalNumber").getNodeValue(); - if (!userIdFound.isBlank()) { - userIdAssertion = userIdFound.trim().replace("TINIT-", ""); - break; - } - } + private boolean validateInResponseTo(LollipopConsumerRequest request, Document assertionDoc) throws AssertionThumbprintException { + NodeList listElements = assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionInResponseToTag()); + if (isInResponseToFieldFound(listElements)) { + throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_FIELD_NOT_FOUND, "Missing request id in the retrieved saml assertion"); } + String inResponseTo = listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO).getNodeValue(); - return userIdAssertion.equals(userIdHeaders); - } + String inResponseToAlgorithm = retrieveInResponseToAlgorithm(inResponseTo); - private boolean validateInResponseTo(LollipopConsumerRequest request, SamlAssertion assertion) { - return false; + + String publicKey = request.getHeaderParams().get(lollipopRequestConfig.getPublicKeyHeader()); + String calculatedThumbprint = calculateThumbprint(inResponseToAlgorithm, publicKey); + String assertionRefHeader = request.getHeaderParams().get(lollipopRequestConfig.getAssertionRefHeader()); + + return inResponseTo.equals(calculatedThumbprint) && inResponseTo.equals(assertionRefHeader); } private IdpCertData getIdpCertData(SamlAssertion assertion) { @@ -112,4 +147,81 @@ private IdpCertData getIdpCertData(SamlAssertion assertion) { private boolean validateSignature(SamlAssertion assertion, IdpCertData idpCertData) { return false; } + + private static Document buildDocumentFromAssertion(SamlAssertion assertion) throws ErrorRetrievingAssertionException { + String stringXml = assertion.getAssertionData(); + try { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + // completely disable DOCTYPE declaration: + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + + factory.setNamespaceAware(true); + DocumentBuilder builder = factory.newDocumentBuilder(); + return builder.parse(new InputSource(new StringReader(stringXml))); + } catch (ParserConfigurationException | SAXException | IOException e) { + throw new ErrorRetrievingAssertionException(ErrorRetrievingAssertionException.ErrorCode.ERROR_PARSING_ASSERTION, e.getMessage(), e); + } + } + + private boolean isInResponseToFieldFound(NodeList listElements) { + return listElements == null + || listElements.getLength() <= 0 + || listElements.item(0) == null + || listElements.item(0).getAttributes() == null + || listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO) == null + || listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO).getNodeValue() == null; + } + + private String getUserIdFromAssertion(Document assertionDoc) throws AssertionUserIdException { + NodeList listElements = assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionFiscalCodeTag()); + if (listElements == null || listElements.getLength() <= 0) { + throw new AssertionUserIdException(AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, "Missing or invalid Fiscal Code in the retrieved saml assertion."); + + } + + for (int i = 0; i < listElements.getLength(); i++) { + Node item = listElements.item(i); + if (item == null || item.getAttributes() == null) { + continue; + } + Node name = item.getAttributes().getNamedItem("Name"); + if (name != null && name.getNodeValue().equals("fiscalNumber") && item.getTextContent() != null) { + return item.getTextContent().trim().replace("TINIT-", ""); + } + } + return null; + } + + private String retrieveInResponseToAlgorithm(String inResponseTo) throws AssertionThumbprintException { + boolean matchesSHA256 = AssertionRefAlgorithms.SHA256.getPattern().matcher(inResponseTo).matches(); + boolean matchesSHA384 = AssertionRefAlgorithms.SHA384.getPattern().matcher(inResponseTo).matches(); + boolean matchesSHA512 = AssertionRefAlgorithms.SHA512.getPattern().matcher(inResponseTo).matches(); + + if (matchesSHA256) { + return AssertionRefAlgorithms.SHA256.getAlgorithmName(); + } + if (matchesSHA384) { + return AssertionRefAlgorithms.SHA384.getAlgorithmName(); + } + if (matchesSHA512) { + return AssertionRefAlgorithms.SHA512.getAlgorithmName(); + } + throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_NOT_VALID, "InResponseTo in the assertion do not contains a valid Assertion Ref."); + + } + + private String calculateThumbprint(String inResponseToAlgorithm, String publicKey) throws AssertionThumbprintException { + Base64URL thumbprint; + try { + thumbprint = ThumbprintUtils.compute(inResponseToAlgorithm, JWK.parse(publicKey)); + } catch (JOSEException | ParseException e) { + String errMsg = String.format("Can not calculate JwkThumbprint: %S", e.getMessage()); + throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, errMsg, e); + } + String calculatedThumbprint = String.format("%s-%s", inResponseToAlgorithm, thumbprint.decodeToString()); + if (!AssertionRefAlgorithms.valueOf(inResponseToAlgorithm.toUpperCase(Locale.ROOT)).getPattern().matcher(calculatedThumbprint).matches()) { + throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, "Error calculating the hash of the provided public key"); + } + return calculatedThumbprint; + } } From 63c0f4dd5d01c78c5e99168f6f7e5cd14364415c Mon Sep 17 00:00:00 2001 From: giomella Date: Fri, 14 Apr 2023 10:47:51 +0200 Subject: [PATCH 198/403] [SLS-21] moved LollipopConsumerRequestValidationService and added in the request validation flow. --- .../LollipopConsumerCommandBuilderImpl.java | 4 +- .../impl/LollipopConsumerCommandImpl.java | 14 +++- .../helper/LollipopConsumerFactoryHelper.java | 7 ++ ...lipopConsumerRequestValidationService.java | 19 +++++ ...ConsumerRequestValidationServiceImpl.java} | 78 ++++++++++--------- 5 files changed, 84 insertions(+), 38 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java rename core/src/main/java/it/pagopa/tech/lollipop/consumer/{config/service/LollipopConsumerRequestValidationService.java => service/impl/LollipopConsumerRequestValidationServiceImpl.java} (66%) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java index 95844767..c7109f2c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java @@ -28,6 +28,8 @@ public LollipopConsumerCommandBuilderImpl(LollipopConsumerFactoryHelper factoryH public LollipopConsumerCommand createCommand() { return new LollipopConsumerCommandImpl( factoryHelper.getHttpMessageVerifierService(), - factoryHelper.getAssertionVerifierService()); + factoryHelper.getAssertionVerifierService(), + factoryHelper.getRequestValidationService() + ); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index 9d2f23eb..03cd4df6 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -2,6 +2,7 @@ package it.pagopa.tech.lollipop.consumer.command.impl; import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; +import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionVerificationResultCode; import it.pagopa.tech.lollipop.consumer.enumeration.HttpMessageVerificationResultCode; import it.pagopa.tech.lollipop.consumer.exception.*; @@ -17,15 +18,19 @@ public class LollipopConsumerCommandImpl implements LollipopConsumerCommand { private final HttpMessageVerifierService messageVerifierService; private final AssertionVerifierService assertionVerifierService; + private final LollipopConsumerRequestValidationService requestValidationService; public static final String VERIFICATION_SUCCESS_CODE = "SUCCESS"; + public static final String REQUEST_PARAMS_VALIDATION_FAILED = "REQUEST PARAMS VALIDATION FAILED"; @Inject public LollipopConsumerCommandImpl( HttpMessageVerifierService messageVerifierService, - AssertionVerifierService assertionVerifierService) { + AssertionVerifierService assertionVerifierService, + LollipopConsumerRequestValidationService requestValidationService) { this.messageVerifierService = messageVerifierService; this.assertionVerifierService = assertionVerifierService; + this.requestValidationService = requestValidationService; } /** @@ -38,6 +43,13 @@ public LollipopConsumerCommandImpl( @Override public CommandResult doExecute(LollipopConsumerRequest request) { + try { + requestValidationService.validateLollipopRequest(request); + } catch (LollipopRequestContentValidationException e) { + String message = String.format("Error validating Lollipop request header or body, validation failed with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); + return buildCommandResult(REQUEST_PARAMS_VALIDATION_FAILED, message); + } + CommandResult messageVerificationResult = getHttpMessageVerificationResult(request); if (!messageVerificationResult .getResultCode() diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index ed688eda..76a66ff5 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -7,8 +7,11 @@ 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 */ @@ -68,4 +71,8 @@ public AssertionServiceFactory getAssertionServiceFactory() { public LollipopConsumerRequestConfig getLollipopConsumerRequestConfig() { return LollipopConsumerRequestConfig.builder().build(); } + + public LollipopConsumerRequestValidationService getRequestValidationService() { + return new LollipopConsumerRequestValidationServiceImpl(getLollipopConsumerRequestConfig()); + } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java new file mode 100644 index 00000000..bdf34001 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java @@ -0,0 +1,19 @@ +package it.pagopa.tech.lollipop.consumer.service; + +import it.pagopa.tech.lollipop.consumer.exception.LollipopRequestContentValidationException; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; + +/** + * Interface of the service used to verify Lollipop request header params + */ +public interface LollipopConsumerRequestValidationService { + + /** + * Validates all request headers + * + * @param request the Lollipop request + * @return true if the request is validated + * @throws LollipopRequestContentValidationException if some error occurred during validation + */ + void validateLollipopRequest(LollipopConsumerRequest request) throws LollipopRequestContentValidationException; +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java similarity index 66% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java rename to core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java index 38a3ba55..730c484f 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/service/LollipopConsumerRequestValidationService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java @@ -1,4 +1,4 @@ -package it.pagopa.tech.lollipop.consumer.config.service; +package it.pagopa.tech.lollipop.consumer.service.impl; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionRefAlgorithms; @@ -10,35 +10,41 @@ import java.util.Map; import java.util.regex.Pattern; -public class LollipopConsumerRequestValidationService { +public class LollipopConsumerRequestValidationServiceImpl implements it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService { - public static boolean validateLollipopConsumerConfig(LollipopConsumerRequest request, LollipopConsumerRequestConfig config) throws LollipopRequestContentValidationException { + private final LollipopConsumerRequestConfig config; + public LollipopConsumerRequestValidationServiceImpl(LollipopConsumerRequestConfig config) { + this.config = config; + } + + @Override + public void validateLollipopRequest(LollipopConsumerRequest request) throws LollipopRequestContentValidationException { Map headerParams = request.getHeaderParams(); - String originalMethod = headerParams.get(config.getOriginalMethodHeader()); - String originalUrl = headerParams.get(config.getOriginalURLHeader()); + validatesOriginalMethodAndURL(headerParams.get(this.config.getOriginalMethodHeader()), headerParams.get(this.config.getOriginalURLHeader())); - if (!originalMethod.equals(config.getExpectedFirstLcOriginalMethod()) && !originalUrl.equals(config.getExpectedFirstLcOriginalUrl())) { - String errMsg = String.format("Unexpected original method and/or original url: %s, %s", originalMethod, originalUrl); - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_METHOD_OR_URL, errMsg); - } + validatePublicKey(headerParams.get(this.config.getPublicKeyHeader())); - validatePublicKey(headerParams.get(config.getPublicKeyHeader())); + validateAssertionRefHeader(headerParams.get(this.config.getAssertionRefHeader())); + validateAssertionTypeHeader(headerParams.get(this.config.getAssertionTypeHeader())); + validateUserIdHeader(headerParams.get(this.config.getUserIdHeader())); + validateAuthJWTHeader(headerParams.get(this.config.getAuthJWTHeader())); + validateOriginalMethodHeader(headerParams.get(this.config.getOriginalMethodHeader())); + validateOriginalURLHeader(headerParams.get(this.config.getOriginalURLHeader())); + validateSignatureInputHeader(headerParams.get(this.config.getSignatureInputHeader())); + validateSignatureHeader(headerParams.get(this.config.getSignatureHeader())); + } - validateAssertionRefHeader(headerParams.get(config.getAssertionRefHeader())); - validateAssertionTypeHeader(headerParams.get(config.getAssertionTypeHeader())); - validateUserIdHeader(headerParams.get(config.getUserIdHeader())); - validateAuthJWTHeader(headerParams.get(config.getAuthJWTHeader())); - validateOriginalMethodHeader(headerParams.get(config.getOriginalMethodHeader())); - validateOriginalURLHeader(headerParams.get(config.getOriginalURLHeader())); - validateSignatureInputHeader(headerParams.get(config.getSignatureInputHeader())); - validateSignatureHeader(headerParams.get(config.getSignatureHeader())); + private void validatesOriginalMethodAndURL(String originalMethod, String originalUrl) throws LollipopRequestContentValidationException { - return true; + if (!originalMethod.equals(this.config.getExpectedFirstLcOriginalMethod()) && !originalUrl.equals(this.config.getExpectedFirstLcOriginalUrl())) { + String errMsg = String.format("Unexpected original method and/or original url: %s, %s", originalMethod, originalUrl); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_METHOD_OR_URL, errMsg); + } } - private static void validatePublicKey(String publicKey) throws LollipopRequestContentValidationException { + private void validatePublicKey(String publicKey) throws LollipopRequestContentValidationException { if (publicKey == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_PUBLIC_KEY, "Missing Public Key Header"); } @@ -48,12 +54,12 @@ private static void validatePublicKey(String publicKey) throws LollipopRequestCo } } - private static boolean isNotValidPublicKey(String publicKey) { + private boolean isNotValidPublicKey(String publicKey) { // TODO return false; } - private static void validateAssertionRefHeader(String assertionRef) throws LollipopRequestContentValidationException { + private void validateAssertionRefHeader(String assertionRef) throws LollipopRequestContentValidationException { if (assertionRef == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_REF, "Missing AssertionRef Header"); } @@ -63,14 +69,14 @@ private static void validateAssertionRefHeader(String assertionRef) throws Lolli } } - private static boolean isNotValidAssertionRef(String signature) { + private boolean isNotValidAssertionRef(String signature) { boolean matchesSHA256 = AssertionRefAlgorithms.SHA256.getPattern().matcher(signature).matches(); boolean matchesSHA384 = AssertionRefAlgorithms.SHA384.getPattern().matcher(signature).matches(); boolean matchesSHA512 = AssertionRefAlgorithms.SHA512.getPattern().matcher(signature).matches(); return !matchesSHA256 && !matchesSHA384 && !matchesSHA512; } - private static void validateAssertionTypeHeader(String assertionType) throws LollipopRequestContentValidationException { + private void validateAssertionTypeHeader(String assertionType) throws LollipopRequestContentValidationException { if (assertionType == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_TYPE, "Missing Assertion Type Header"); } @@ -80,7 +86,7 @@ private static void validateAssertionTypeHeader(String assertionType) throws Lol } } - private static boolean isAssertionTypeSupported(String assertionType) { + private boolean isAssertionTypeSupported(String assertionType) { for (AssertionType supportedType : AssertionType.values()) { if (supportedType.name().equals(assertionType)) { return true; @@ -89,7 +95,7 @@ private static boolean isAssertionTypeSupported(String assertionType) { return false; } - private static void validateUserIdHeader(String userId) throws LollipopRequestContentValidationException { + private void validateUserIdHeader(String userId) throws LollipopRequestContentValidationException { if (userId == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_USER_ID, "Missing User Id Header"); } @@ -99,11 +105,11 @@ private static void validateUserIdHeader(String userId) throws LollipopRequestCo } } - private static boolean isNotValidFiscalCode(String userId) { + private boolean isNotValidFiscalCode(String userId) { return !Pattern.compile("^[A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]$").matcher(userId).matches(); } - private static void validateAuthJWTHeader(String authJWT) throws LollipopRequestContentValidationException { + private void validateAuthJWTHeader(String authJWT) throws LollipopRequestContentValidationException { if (authJWT == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_AUTH_JWT, "Missing Auth JWT Header"); } @@ -113,7 +119,7 @@ private static void validateAuthJWTHeader(String authJWT) throws LollipopRequest } } - private static void validateOriginalMethodHeader(String originalMethod) throws LollipopRequestContentValidationException { + private void validateOriginalMethodHeader(String originalMethod) throws LollipopRequestContentValidationException { if (originalMethod == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_METHOD, "Missing Original Method Header"); } @@ -123,7 +129,7 @@ private static void validateOriginalMethodHeader(String originalMethod) throws L } } - private static boolean isRequestMethodSupported(String originalMethod) { + private boolean isRequestMethodSupported(String originalMethod) { for (LollipopRequestMethod supportedType : LollipopRequestMethod.values()) { if (supportedType.name().equals(originalMethod)) { return true; @@ -132,7 +138,7 @@ private static boolean isRequestMethodSupported(String originalMethod) { return false; } - private static void validateOriginalURLHeader(String originalURL) throws LollipopRequestContentValidationException { + private void validateOriginalURLHeader(String originalURL) throws LollipopRequestContentValidationException { if (originalURL == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_URL, "Missing Original URL Header"); } @@ -142,11 +148,11 @@ private static void validateOriginalURLHeader(String originalURL) throws Lollipo } } - private static boolean isNotValidOriginalURL(String originalURL) { + private boolean isNotValidOriginalURL(String originalURL) { return !Pattern.compile("^https://").matcher(originalURL).matches(); } - private static void validateSignatureInputHeader(String signatureInput) throws LollipopRequestContentValidationException { + private void validateSignatureInputHeader(String signatureInput) throws LollipopRequestContentValidationException { if (signatureInput == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE_INPUT, "Missing Signature Input Header"); } @@ -156,11 +162,11 @@ private static void validateSignatureInputHeader(String signatureInput) throws L } } - private static boolean isNotValidSignatureInput(String signatureInput) { + private boolean isNotValidSignatureInput(String signatureInput) { return !Pattern.compile("^(((sig[0-9]+)=[^,]*?)(, ?)?)+$").matcher(signatureInput).matches(); } - private static void validateSignatureHeader(String signature) throws LollipopRequestContentValidationException { + private void validateSignatureHeader(String signature) throws LollipopRequestContentValidationException { if (signature == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE, "Missing Signature Header"); } @@ -170,7 +176,7 @@ private static void validateSignatureHeader(String signature) throws LollipopReq } } - private static boolean isNotValidSignature(String signature) { + private boolean isNotValidSignature(String signature) { return !Pattern.compile("^((sig[0-9]+)=:[A-Za-z0-9+/=]*:(, ?)?)+$").matcher(signature).matches(); } } From b7f7cdc7f0920aa1dc802041b10aa2e12d228caa Mon Sep 17 00:00:00 2001 From: giomella Date: Fri, 14 Apr 2023 15:55:47 +0200 Subject: [PATCH 199/403] [SLS-21] added unit test for AssertionVerifierServiceImpl and do some fix. --- .../enumeration/AssertionRefAlgorithms.java | 29 +- .../AssertionThumbprintException.java | 2 +- .../impl/AssertionVerifierServiceImpl.java | 19 +- .../AssertionVerifierServiceImplTest.java | 304 ++++++++++++++++++ 4 files changed, 339 insertions(+), 15 deletions(-) create mode 100644 core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java index 06e6f417..fe5a5b30 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java @@ -7,15 +7,17 @@ */ public enum AssertionRefAlgorithms { - SHA256("sha256", Pattern.compile("^(sha256-[A-Za-z0-9-_=]{1,44})$")), - SHA384("sha384", Pattern.compile("^(sha384-[A-Za-z0-9-_=]{1,66})$")), - SHA512("sha512", Pattern.compile("^(sha512-[A-Za-z0-9-_=]{1,88})$")); + SHA256("sha256", AlgorithmName.SHA_256, Pattern.compile("^(sha256-[A-Za-z0-9-_=]{1,44})$")), + SHA384("sha384", AlgorithmName.SHA_384, Pattern.compile("^(sha384-[A-Za-z0-9-_=]{1,66})$")), + SHA512("sha512", AlgorithmName.SHA_512, Pattern.compile("^(sha512-[A-Za-z0-9-_=]{1,88})$")); private final String algorithmName; + private final String hashAlgorithm; private final Pattern pattern; - AssertionRefAlgorithms(String algorithmName, Pattern pattern) { + AssertionRefAlgorithms(String algorithmName, String hashAlgorithm, Pattern pattern) { this.algorithmName = algorithmName; + this.hashAlgorithm = hashAlgorithm; this.pattern = pattern; } @@ -23,7 +25,26 @@ public Pattern getPattern() { return pattern; } + public String getHashAlgorithm() { + return hashAlgorithm; + } + public String getAlgorithmName() { return algorithmName; } + + public static AssertionRefAlgorithms getAlgorithmFromHash(String algorithmName) { + switch (algorithmName) { + case AlgorithmName.SHA_256: return SHA256; + case AlgorithmName.SHA_384: return SHA384; + case AlgorithmName.SHA_512: return SHA512; + default: throw new UnsupportedOperationException("Unsupported algorithm: " + algorithmName); + } + } + + private static class AlgorithmName { + public static final String SHA_256 = "SHA-256"; + public static final String SHA_384 = "SHA-384"; + public static final String SHA_512 = "SHA-512"; + } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java index 4f23f03d..37a12bb0 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java @@ -45,7 +45,7 @@ public ErrorCode getErrorCode() { /** Error codes to classify Lollipop Request Exceptions */ public enum ErrorCode { IN_RESPONSE_TO_FIELD_NOT_FOUND, - IN_RESPONSE_TO_NOT_VALID, + IN_RESPONSE_TO_ALGORITHM_NOT_VALID, ERROR_CALCULATING_ASSERTION_THUMBPRINT, INVALID_IN_RESPONSE_TO } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index b1d0d8de..b562c0aa 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -21,7 +21,6 @@ import org.xml.sax.SAXException; import javax.inject.Inject; -import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -30,7 +29,6 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; -import java.util.Locale; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -93,7 +91,7 @@ private SamlAssertion getAssertion(String jwt, String assertionRef) throws Error } private boolean validateAssertionPeriod(Document assertionDoc) throws AssertionPeriodException { - NodeList listElements = assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionNotBeforeDateFormat()); + NodeList listElements = assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionNotBeforeTag()); if (listElements == null || listElements.getLength() <= 0) { return false; } @@ -198,15 +196,15 @@ private String retrieveInResponseToAlgorithm(String inResponseTo) throws Asserti boolean matchesSHA512 = AssertionRefAlgorithms.SHA512.getPattern().matcher(inResponseTo).matches(); if (matchesSHA256) { - return AssertionRefAlgorithms.SHA256.getAlgorithmName(); + return AssertionRefAlgorithms.SHA256.getHashAlgorithm(); } if (matchesSHA384) { - return AssertionRefAlgorithms.SHA384.getAlgorithmName(); + return AssertionRefAlgorithms.SHA384.getHashAlgorithm(); } if (matchesSHA512) { - return AssertionRefAlgorithms.SHA512.getAlgorithmName(); + return AssertionRefAlgorithms.SHA512.getHashAlgorithm(); } - throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_NOT_VALID, "InResponseTo in the assertion do not contains a valid Assertion Ref."); + throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_ALGORITHM_NOT_VALID, "InResponseTo in the assertion do not contains a valid Assertion Ref or it contains an invalid algorithm."); } @@ -218,9 +216,10 @@ private String calculateThumbprint(String inResponseToAlgorithm, String publicKe String errMsg = String.format("Can not calculate JwkThumbprint: %S", e.getMessage()); throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, errMsg, e); } - String calculatedThumbprint = String.format("%s-%s", inResponseToAlgorithm, thumbprint.decodeToString()); - if (!AssertionRefAlgorithms.valueOf(inResponseToAlgorithm.toUpperCase(Locale.ROOT)).getPattern().matcher(calculatedThumbprint).matches()) { - throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, "Error calculating the hash of the provided public key"); + AssertionRefAlgorithms algo = AssertionRefAlgorithms.getAlgorithmFromHash(inResponseToAlgorithm); + String calculatedThumbprint = String.format("%s-%s", algo.getAlgorithmName(), thumbprint); + if (!algo.getPattern().matcher(calculatedThumbprint).matches()) { + throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, "The calculated thumbprint does not match the expected pattern: " + calculatedThumbprint); } return calculatedThumbprint; } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java new file mode 100644 index 00000000..ad9433e9 --- /dev/null +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java @@ -0,0 +1,304 @@ +package it.pagopa.tech.lollipop.consumer.service.impl; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.exception.*; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; +import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + +class AssertionVerifierServiceImplTest { + + private IdpCertProvider idpCertProviderMock; + private AssertionService assertionServiceMock; + private static LollipopConsumerRequestConfig lollipopRequestConfigMock; + + private AssertionVerifierService sut; + + private static final String VALID_FISCAL_CODE = "AAAAAA89S20I111X"; + private static final String INVALID_JWK = "{ alg: \"\", e: \"e\", kty: \"RSA\", n: \"n\"}"; + private static final String VALID_JWK = "{ kty: \"EC\", crv: \"P-256\", x: \"SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74\", y: \"lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI\"}"; + private static final String VALID_SHA_256_ASSERTION_REF = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; + private static final String VALID_SHA_384_ASSERTION_REF = "sha384-lqxC_2kqMdwiBWoD-Us63Fha6e3bE1Y3yUz8G6IJTldohJCIBVDfvS8acB3GJBhw"; + private static final String VALID_SHA_512_ASSERTION_REF = "sha512-nX5CfUc5R-FoYKYZwvQMuc4Tt-heb7vHi_O-AMUSqHNVCw9kNaN2SVuN-DXtGXyUhrcVcQdCyY6FVzl_vyWXNA"; + + private static final String EMPTY_ASSERTION_XML = ""; + private static final String ASSERTION_XML_WITH_INVALID_PERIOD_DATE_FORMAT = "https://app-backend.io.italia.it"; + private static final String ASSERTION_XML_WITH_EXPIRED_PERIOD = "https://app-backend.io.italia.it"; + private static String ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG; + private static String ASSERTION_XML_WITHOUT_FISCAL_CODE; + private static String ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG; + private static String ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM; + private static String ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM; + private static String ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM; + private static String ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM; + + @BeforeAll + static void prepareInput() { + lollipopRequestConfigMock = spy(LollipopConsumerRequestConfig.builder().build()); + + String todayTimestamp = new SimpleDateFormat(lollipopRequestConfigMock.getAssertionNotBeforeDateFormat()).format(new Date()); + ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG = "https://app-backend.io.italia.it"; + ASSERTION_XML_WITHOUT_FISCAL_CODE = " https://app-backend.io.italia.it \t "; + ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG = " https://app-backend.io.italia.it \t TINIT-AAAAAA89S20I111X "; + ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM = " \t\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thttps://app-backend.io.italia.it\t\t\t\t\t\t\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t\t\t\t\t"; + ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM = " \t\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thttps://app-backend.io.italia.it\t\t\t\t\t\t\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t\t\t\t\t"; + ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM = " \t\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thttps://app-backend.io.italia.it\t\t\t\t\t\t\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t\t\t\t\t"; + ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM = " \t\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thttps://app-backend.io.italia.it\t\t\t\t\t\t\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t\t\t\t\t"; + } + + @BeforeEach + void setUp() { + idpCertProviderMock = mock(IdpCertProvider.class); + assertionServiceMock = mock(AssertionService.class); + + sut = new AssertionVerifierServiceImpl(idpCertProviderMock, assertionServiceMock, lollipopRequestConfigMock); + } + + @Test + void validateLollipopGetAssertionFailureWithOidcAssertionException() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + doThrow(OidcAssertionNotSupported.class).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + ErrorRetrievingAssertionException e = assertThrows(ErrorRetrievingAssertionException.class, () -> sut.validateLollipop(request)); + + Assertions.assertTrue(e.getCause() instanceof OidcAssertionNotSupported); + Assertions.assertEquals(ErrorRetrievingAssertionException.ErrorCode.OIDC_TYPE_NOT_SUPPORTED, e.getErrorCode()); + } + + @Test + void validateLollipopGetAssertionFailureWithAssertionNotFoundException() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + doThrow(LollipopAssertionNotFoundException.class).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + ErrorRetrievingAssertionException e = assertThrows(ErrorRetrievingAssertionException.class, () -> sut.validateLollipop(request)); + + Assertions.assertTrue(e.getCause() instanceof LollipopAssertionNotFoundException); + Assertions.assertEquals(ErrorRetrievingAssertionException.ErrorCode.SAML_ASSERTION_NOT_FOUND, e.getErrorCode()); + } + + @Test + void validateLollipopBuildAssertionDocFailure() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(""); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + ErrorRetrievingAssertionException e = assertThrows(ErrorRetrievingAssertionException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(ErrorRetrievingAssertionException.ErrorCode.ERROR_PARSING_ASSERTION, e.getErrorCode()); + } + + @Test + void validateLollipopValidatePeriodFailureWithFieldNotFoundInAssertionDoc() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(EMPTY_ASSERTION_XML); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionPeriodException e = assertThrows(AssertionPeriodException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, e.getErrorCode()); + } + + @Test + void validateLollipopValidatePeriodFailureWithInvalidDateFormat() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_INVALID_PERIOD_DATE_FORMAT); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionPeriodException e = assertThrows(AssertionPeriodException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionPeriodException.ErrorCode.ERROR_PARSING_ASSERTION_NOT_BEFORE_DATE, e.getErrorCode()); + } + + @Test + void validateLollipopValidatePeriodFailureWithExpiredAssertion() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_EXPIRED_PERIOD); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionPeriodException e = assertThrows(AssertionPeriodException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, e.getErrorCode()); + } + + @Test + void validateLollipopValidateUserIdFailureWithoutAttributeTagInAssertionDoc() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionUserIdException e = assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, e.getErrorCode()); + } + + @Test + void validateLollipopValidateUserIdFailureWithoutFiscalCodeInAssertionDoc() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITHOUT_FISCAL_CODE); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionUserIdException e = assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, e.getErrorCode()); + } + + @Test + void validateLollipopValidateUserIdFailureWithInvalidUserIdHeader() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionUserIdException e = assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionUserIdException.ErrorCode.INVALID_USER_ID, e.getErrorCode()); + } + + @Test + void validateLollipopValidateThumbprintFailureWithoutSubjectConfirmationDataTagInAssertionDoc() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", VALID_FISCAL_CODE); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionThumbprintException e = assertThrows(AssertionThumbprintException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_FIELD_NOT_FOUND, e.getErrorCode()); + } + + @Test + void validateLollipopValidateThumbprintFailureWithInvalidInResponseToAlgorithm() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", VALID_FISCAL_CODE); + + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionThumbprintException e = assertThrows(AssertionThumbprintException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_ALGORITHM_NOT_VALID, e.getErrorCode()); + } + + @Test + void validateLollipopValidateThumbprintFailureWithErrorCalculatingThumbprint() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", VALID_FISCAL_CODE); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionThumbprintException e = assertThrows(AssertionThumbprintException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, e.getErrorCode()); + Assertions.assertTrue(e.getCause() instanceof ParseException); + } + + @Test + void validateLollipopValidateThumbprintFailureWithInvalidPublicKey() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", INVALID_JWK, VALID_FISCAL_CODE); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + AssertionThumbprintException e = assertThrows(AssertionThumbprintException.class, () -> sut.validateLollipop(request)); + + Assertions.assertEquals(AssertionThumbprintException.ErrorCode.INVALID_IN_RESPONSE_TO, e.getErrorCode()); + } + + @Test + void validateLollipopSuccessWithSHA256Algorithm() throws LollipopAssertionNotFoundException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, OidcAssertionNotSupported { + LollipopConsumerRequest request = getLollipopConsumerRequest(VALID_SHA_256_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + boolean result = sut.validateLollipop(request); + + Assertions.assertTrue(result); + } + + @Test + void validateLollipopSuccessWithSHA384Algorithm() throws LollipopAssertionNotFoundException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, OidcAssertionNotSupported { + LollipopConsumerRequest request = getLollipopConsumerRequest(VALID_SHA_384_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + boolean result = sut.validateLollipop(request); + + Assertions.assertTrue(result); + } + + @Test + void validateLollipopSuccessWithSHA512Algorithm() throws LollipopAssertionNotFoundException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, OidcAssertionNotSupported { + LollipopConsumerRequest request = getLollipopConsumerRequest(VALID_SHA_512_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + + boolean result = sut.validateLollipop(request); + + Assertions.assertTrue(result); + } + + private LollipopConsumerRequest getLollipopConsumerRequest(String assertionRef, String publicKey, String userId) { + HashMap headers = new HashMap<>(); + headers.put(lollipopRequestConfigMock.getAuthJWTHeader(), ""); + headers.put(lollipopRequestConfigMock.getAssertionRefHeader(), assertionRef); + headers.put(lollipopRequestConfigMock.getUserIdHeader(), userId); + headers.put(lollipopRequestConfigMock.getPublicKeyHeader(), publicKey); + + return LollipopConsumerRequest.builder() + .headerParams(headers) + .build(); + } +} \ No newline at end of file From a5efb63ab56c64866a438e66bfaa54d2dba0888a Mon Sep 17 00:00:00 2001 From: giomella Date: Fri, 14 Apr 2023 16:07:16 +0200 Subject: [PATCH 200/403] [SLS-21] added unit test for LollipopConsumerCommandImpl. --- .../impl/LollipopConsumerCommandImplTest.java | 146 ++++++++++++++++-- 1 file changed, 132 insertions(+), 14 deletions(-) diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java index 05315ea4..68276d4d 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -7,14 +7,14 @@ import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionVerificationResultCode; import it.pagopa.tech.lollipop.consumer.enumeration.HttpMessageVerificationResultCode; -import it.pagopa.tech.lollipop.consumer.exception.LollipopDigestException; -import it.pagopa.tech.lollipop.consumer.exception.LollipopSignatureException; -import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; +import it.pagopa.tech.lollipop.consumer.exception.*; import it.pagopa.tech.lollipop.consumer.model.CommandResult; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; import java.io.UnsupportedEncodingException; + +import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; import lombok.SneakyThrows; import org.junit.jupiter.api.*; import org.mockito.*; @@ -23,26 +23,31 @@ class LollipopConsumerCommandImplTest { private static HttpMessageVerifierService messageVerifierServiceMock; private static AssertionVerifierService assertionVerifierServiceMock; + private LollipopConsumerRequestValidationService requestValidationServiceMock; private static LollipopConsumerCommand sut; @BeforeEach void beforeAll() { messageVerifierServiceMock = Mockito.mock(HttpMessageVerifierService.class); assertionVerifierServiceMock = Mockito.mock(AssertionVerifierService.class); + requestValidationServiceMock = Mockito.mock(LollipopConsumerRequestValidationService.class); sut = Mockito.spy( new LollipopConsumerCommandImpl( - messageVerifierServiceMock, assertionVerifierServiceMock)); + messageVerifierServiceMock, + assertionVerifierServiceMock, + requestValidationServiceMock + )); } @Test void failedHttpMessageValidationThrowDigestException() - throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException, LollipopSignatureException { - doThrow( - new LollipopDigestException( - LollipopDigestException.ErrorCode.INCORRECT_DIGEST, "error")) + doThrow(new LollipopDigestException( + LollipopDigestException.ErrorCode.INCORRECT_DIGEST, "error")) .when(messageVerifierServiceMock) .verifyHttpMessage(any(LollipopConsumerRequest.class)); @@ -74,6 +79,7 @@ void failedHttpMessageValidationThrowSignatureException() HttpMessageVerificationResultCode.SIGNATURE_VALIDATION_ERROR.name(), commandResult.getResultCode()); + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock, never()) .validateLollipop(any(LollipopConsumerRequest.class)); @@ -93,6 +99,7 @@ void failedHttpMessageValidationThrowUnsupportedEncodingException() { HttpMessageVerificationResultCode.UNSUPPORTED_ENCODING.name(), commandResult.getResultCode()); + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock, never()) .validateLollipop(any(LollipopConsumerRequest.class)); @@ -100,8 +107,8 @@ void failedHttpMessageValidationThrowUnsupportedEncodingException() { @Test void failedHttpMessageValidationWithoutThrowingException() - throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, - LollipopSignatureException { + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException, LollipopSignatureException { doReturn(false) .when(messageVerifierServiceMock) @@ -113,6 +120,7 @@ void failedHttpMessageValidationWithoutThrowingException() HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_FAILED.name(), commandResult.getResultCode()); + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock, never()) .validateLollipop(any(LollipopConsumerRequest.class)); @@ -120,8 +128,8 @@ void failedHttpMessageValidationWithoutThrowingException() @Test void failedAssertionValidationWithoutThrowingException() - throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, - LollipopSignatureException { + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException, LollipopSignatureException { doReturn(true) .when(messageVerifierServiceMock) @@ -136,14 +144,15 @@ void failedAssertionValidationWithoutThrowingException() AssertionVerificationResultCode.ASSERTION_VERIFICATION_FAILED.name(), commandResult.getResultCode()); + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } @Test void successLollipopRequestValidation() - throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, - LollipopSignatureException { + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException, LollipopSignatureException { doReturn(true) .when(messageVerifierServiceMock) @@ -156,6 +165,115 @@ void successLollipopRequestValidation() Assertions.assertEquals("SUCCESS", commandResult.getResultCode()); + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); + } + + @Test + void failedLollipopRequestValidation() + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + + + doThrow(LollipopRequestContentValidationException.class).when(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + + Assertions.assertEquals("REQUEST PARAMS VALIDATION FAILED", commandResult.getResultCode()); + + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(messageVerifierServiceMock, never()).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock, never()).validateLollipop(any(LollipopConsumerRequest.class)); + } + + @Test + void failedAssertionValidationThrowErrorRetrievingAssertionException() + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + + doReturn(true) + .when(messageVerifierServiceMock) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); + doThrow(ErrorRetrievingAssertionException.class) + .when(assertionVerifierServiceMock) + .validateLollipop(any(LollipopConsumerRequest.class)); + + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + + Assertions.assertEquals( + AssertionVerificationResultCode.ERROR_RETRIEVING_ASSERTION.name(), + commandResult.getResultCode()); + + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); + } + + @Test + void failedAssertionValidationThrowAssertionPeriodException() + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + + doReturn(true) + .when(messageVerifierServiceMock) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); + doThrow(AssertionPeriodException.class) + .when(assertionVerifierServiceMock) + .validateLollipop(any(LollipopConsumerRequest.class)); + + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + + Assertions.assertEquals( + AssertionVerificationResultCode.PERIOD_VALIDATION_ERROR.name(), + commandResult.getResultCode()); + + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); + } + + @Test + void failedAssertionValidationThrowAssertionThumbprintException() + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + + doReturn(true) + .when(messageVerifierServiceMock) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); + doThrow(AssertionThumbprintException.class) + .when(assertionVerifierServiceMock) + .validateLollipop(any(LollipopConsumerRequest.class)); + + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + + Assertions.assertEquals( + AssertionVerificationResultCode.THUMBPRINT_VALIDATION_ERROR.name(), + commandResult.getResultCode()); + + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); + } + + @Test + void failedAssertionValidationThrowAssertionUserIdException() + throws LollipopDigestException, UnsupportedEncodingException, + LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + + doReturn(true) + .when(messageVerifierServiceMock) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); + doThrow(AssertionUserIdException.class) + .when(assertionVerifierServiceMock) + .validateLollipop(any(LollipopConsumerRequest.class)); + + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + + Assertions.assertEquals( + AssertionVerificationResultCode.USER_ID_VALIDATION_ERROR.name(), + commandResult.getResultCode()); + + verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } From d218664528ce6fe1514fd267c6ef9412bc7a6a89 Mon Sep 17 00:00:00 2001 From: giomella Date: Fri, 14 Apr 2023 18:19:30 +0200 Subject: [PATCH 201/403] [SLS-21] added unit test for LollipopConsumerRequestValidationServiceImpl and do some fix. --- core/build.gradle | 1 + ...ipopRequestContentValidationException.java | 6 +- ...pConsumerRequestValidationServiceImpl.java | 42 +- .../AssertionVerifierServiceImplTest.java | 7 +- ...sumerRequestValidationServiceImplTest.java | 362 ++++++++++++++++++ 5 files changed, 395 insertions(+), 23 deletions(-) create mode 100644 core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java diff --git a/core/build.gradle b/core/build.gradle index b13a86e8..cb35f651 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -37,6 +37,7 @@ dependencies { implementation 'com.typesafe:config:1.4.2' implementation 'javax.inject:javax.inject:1' implementation 'com.nimbusds:nimbus-jose-jwt:9.31' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.2' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.mockito:mockito-core:5.2.0' diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java index a9facc20..5e6516ad 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java @@ -45,11 +45,11 @@ public ErrorCode getErrorCode() { /** Error codes to classify Lollipop Request Exceptions */ public enum ErrorCode { - UNEXPECTED_METHOD_OR_URL, - + UNEXPECTED_ORIGINAL_METHOD, + UNEXPECTED_ORIGINAL_URL, MISSING_SIGNATURE, - INVALID_SIGNATURE_HEADER, + INVALID_SIGNATURE, MISSING_SIGNATURE_INPUT, INVALID_SIGNATURE_INPUT, diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java index 730c484f..b4908609 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java @@ -1,16 +1,21 @@ package it.pagopa.tech.lollipop.consumer.service.impl; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionRefAlgorithms; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionType; import it.pagopa.tech.lollipop.consumer.enumeration.LollipopRequestMethod; import it.pagopa.tech.lollipop.consumer.exception.LollipopRequestContentValidationException; +import it.pagopa.tech.lollipop.consumer.model.ECPublicKey; 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.Map; import java.util.regex.Pattern; -public class LollipopConsumerRequestValidationServiceImpl implements it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService { +public class LollipopConsumerRequestValidationServiceImpl implements LollipopConsumerRequestValidationService { private final LollipopConsumerRequestConfig config; @@ -22,8 +27,6 @@ public LollipopConsumerRequestValidationServiceImpl(LollipopConsumerRequestConfi public void validateLollipopRequest(LollipopConsumerRequest request) throws LollipopRequestContentValidationException { Map headerParams = request.getHeaderParams(); - validatesOriginalMethodAndURL(headerParams.get(this.config.getOriginalMethodHeader()), headerParams.get(this.config.getOriginalURLHeader())); - validatePublicKey(headerParams.get(this.config.getPublicKeyHeader())); validateAssertionRefHeader(headerParams.get(this.config.getAssertionRefHeader())); @@ -36,26 +39,23 @@ public void validateLollipopRequest(LollipopConsumerRequest request) throws Loll validateSignatureHeader(headerParams.get(this.config.getSignatureHeader())); } - private void validatesOriginalMethodAndURL(String originalMethod, String originalUrl) throws LollipopRequestContentValidationException { - - if (!originalMethod.equals(this.config.getExpectedFirstLcOriginalMethod()) && !originalUrl.equals(this.config.getExpectedFirstLcOriginalUrl())) { - String errMsg = String.format("Unexpected original method and/or original url: %s, %s", originalMethod, originalUrl); - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_METHOD_OR_URL, errMsg); - } - } - private void validatePublicKey(String publicKey) throws LollipopRequestContentValidationException { if (publicKey == null ) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_PUBLIC_KEY, "Missing Public Key Header"); } - if (isNotValidPublicKey(publicKey)) { + if (isNotValidPublicKey(publicKey, ECPublicKey.class) && isNotValidPublicKey(publicKey, RSAPublicKey.class)) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_PUBLIC_KEY, "Invalid Public Key Header value"); } } - private boolean isNotValidPublicKey(String publicKey) { - // TODO + private boolean isNotValidPublicKey(String publicKey, Class clazz) { + ObjectMapper mapper = new ObjectMapper(); + try { + mapper.readValue(publicKey, clazz); + } catch (JsonProcessingException e) { + return true; + } return false; } @@ -127,6 +127,11 @@ private void validateOriginalMethodHeader(String originalMethod) throws Lollipop if (!isRequestMethodSupported(originalMethod)) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_METHOD, "Invalid Original Method Header value, method not supported"); } + + if (!originalMethod.equals(this.config.getExpectedFirstLcOriginalMethod())) { + String errMsg = String.format("Unexpected original method: %s", originalMethod); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_METHOD, errMsg); + } } private boolean isRequestMethodSupported(String originalMethod) { @@ -146,10 +151,15 @@ private void validateOriginalURLHeader(String originalURL) throws LollipopReques if (isNotValidOriginalURL(originalURL)) { throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_URL, "Invalid Original URL Header value"); } + + if (!originalURL.equals(this.config.getExpectedFirstLcOriginalUrl())) { + String errMsg = String.format("Unexpected original url: %s", originalURL); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_URL, errMsg); + } } private boolean isNotValidOriginalURL(String originalURL) { - return !Pattern.compile("^https://").matcher(originalURL).matches(); + return !Pattern.compile("^https://\\S+").matcher(originalURL).matches(); } private void validateSignatureInputHeader(String signatureInput) throws LollipopRequestContentValidationException { @@ -172,7 +182,7 @@ private void validateSignatureHeader(String signature) throws LollipopRequestCon } if (isNotValidSignature(signature)) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE_HEADER, "Invalid Signature Header value"); + throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE, "Invalid Signature Header value"); } } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java index ad9433e9..a31f63ed 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java @@ -29,8 +29,7 @@ class AssertionVerifierServiceImplTest { private AssertionVerifierService sut; private static final String VALID_FISCAL_CODE = "AAAAAA89S20I111X"; - private static final String INVALID_JWK = "{ alg: \"\", e: \"e\", kty: \"RSA\", n: \"n\"}"; - private static final String VALID_JWK = "{ kty: \"EC\", crv: \"P-256\", x: \"SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74\", y: \"lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI\"}"; + private static final String VALID_JWK = "{ \"kty\": \"EC\", \"crv\": \"P-256\", \"x\": \"SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74\", \"y\": \"lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI\"}"; private static final String VALID_SHA_256_ASSERTION_REF = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; private static final String VALID_SHA_384_ASSERTION_REF = "sha384-lqxC_2kqMdwiBWoD-Us63Fha6e3bE1Y3yUz8G6IJTldohJCIBVDfvS8acB3GJBhw"; private static final String VALID_SHA_512_ASSERTION_REF = "sha512-nX5CfUc5R-FoYKYZwvQMuc4Tt-heb7vHi_O-AMUSqHNVCw9kNaN2SVuN-DXtGXyUhrcVcQdCyY6FVzl_vyWXNA"; @@ -235,8 +234,8 @@ void validateLollipopValidateThumbprintFailureWithErrorCalculatingThumbprint() t } @Test - void validateLollipopValidateThumbprintFailureWithInvalidPublicKey() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { - LollipopConsumerRequest request = getLollipopConsumerRequest("", INVALID_JWK, VALID_FISCAL_CODE); + void validateLollipopValidateThumbprintFailureWithDifferentAssertionRefAndCalculatedThumbprint() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = getLollipopConsumerRequest("", VALID_JWK, VALID_FISCAL_CODE); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java new file mode 100644 index 00000000..0e921866 --- /dev/null +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java @@ -0,0 +1,362 @@ +package it.pagopa.tech.lollipop.consumer.service.impl; + +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.enumeration.AssertionType; +import it.pagopa.tech.lollipop.consumer.exception.LollipopRequestContentValidationException; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.spy; + +class LollipopConsumerRequestValidationServiceImplTest { + + public static final String VALID_EC_PUBLIC_KEY = "{ \"kty\": \"EC\", \"x\": \"FqFDuwEgu4MUXERPMVL-85pGv2D3YmL4J1gfMkdbc24\", \"y\": \"hdV0oxmWFSxMoJUDpdihr76rS8VRBEqMFebYyAfK9-k\", \"crv\": \"P-256\"}"; + public static final String VALID_RSA_PUBLIC_KEY = "{ \"alg\": \"RS256\", \"e\": \"AQAB\", \"kty\": \"RSA\", \"n\": \"yeNlzlub94YgerT030codqEztjfU_S6X4DbDA_iVKkjAWtYfPHDzz_sPCT1Axz6isZdf3lHpq_gYX4Sz\"}"; + public static final String VALID_ASSERTION_REF = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; + public static final String VALID_FISCAL_CODE = "AAAAAA89S20I111X"; + public static final String VALID_JWT = "aValidJWT"; + public static final String VALID_SIGNATURE_INPUT = "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + public static final String VALID_SIGNATURE = "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + public static final String RANDOM_STRING = ""; + private LollipopConsumerRequestConfig config; + + private LollipopConsumerRequestValidationService sut; + + @BeforeEach + void setUp() { + config = spy(LollipopConsumerRequestConfig.builder().build()); + sut = new LollipopConsumerRequestValidationServiceImpl(config); + } + + @Test + void validatePublicKeyFailureHeaderNotPresent() { + HashMap headers = new HashMap<>(); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_PUBLIC_KEY, e.getErrorCode()); + } + + @Test + void validatePublicKeyFailureHeaderInvalidFormat() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), RANDOM_STRING); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_PUBLIC_KEY, e.getErrorCode()); + } + + @Test + void validateAssertionRefFailureHeaderNotPresent() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_REF, e.getErrorCode()); + } + + @Test + void validateAssertionRefFailureInvalidFormat() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), RANDOM_STRING); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_REF, e.getErrorCode()); + } + + @Test + void validateAssertionTypeFailureHeaderNotPresent() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_TYPE, e.getErrorCode()); + } + + @Test + void validateAssertionTypeFailureInvalidFormat() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), RANDOM_STRING); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_TYPE, e.getErrorCode()); + } + + @Test + void validateUserIdFailureHeaderNotPresent() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_USER_ID, e.getErrorCode()); + } + + @Test + void validateUserIdFailureInvalidFormat() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), RANDOM_STRING); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_USER_ID, e.getErrorCode()); + } + + @Test + void validateAuthJWKFailureHeaderNotPresent() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_AUTH_JWT, e.getErrorCode()); + } + + @Test + void validateAuthJWKFailureInvalidFormat() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), RANDOM_STRING); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_AUTH_JWT, e.getErrorCode()); + } + + @Test + void validateOriginalMethodFailureHeaderNotPresent() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_METHOD, e.getErrorCode()); + } + + @Test + void validateOriginalMethodFailureNotSupported() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), "INVALID_METHOD"); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_METHOD, e.getErrorCode()); + } + + @Test + void validateOriginalMethodFailureDifferentFromExpectedMethod() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), "PUT"); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_METHOD, e.getErrorCode()); + } + @Test + void validateOriginalURLFailureHeaderNotPresent() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_URL, e.getErrorCode()); + } + + @Test + void validateOriginalURLFailureInvalidFormat() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); + headers.put(config.getOriginalURLHeader(), RANDOM_STRING); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_URL, e.getErrorCode()); + } + + @Test + void validateOriginalURLFailureDifferentFromExpectedMethod() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); + headers.put(config.getOriginalURLHeader(), "https://pagopa.it"); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_URL, e.getErrorCode()); + } + + @Test + void validateSignatureInputFailureHeaderNotPresent() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); + headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE_INPUT, e.getErrorCode()); + } + + @Test + void validateSignatureInputFailureInvalidFormat() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); + headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); + headers.put(config.getSignatureInputHeader(), RANDOM_STRING); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE_INPUT, e.getErrorCode()); + } + + @Test + void validateSignatureFailureHeaderNotPresent() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); + headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); + headers.put(config.getSignatureInputHeader(), VALID_SIGNATURE_INPUT); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE, e.getErrorCode()); + } + + @Test + void validateSignatureFailureInvalidFormat() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); + headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); + headers.put(config.getSignatureInputHeader(), VALID_SIGNATURE_INPUT); + headers.put(config.getSignatureHeader(), RANDOM_STRING); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + + assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE, e.getErrorCode()); + } + + @Test + void validateRequestSuccessWithECPublicKey() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); + headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); + headers.put(config.getSignatureInputHeader(), VALID_SIGNATURE_INPUT); + headers.put(config.getSignatureHeader(), VALID_SIGNATURE); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + assertDoesNotThrow(() -> sut.validateLollipopRequest(request)); + } + + @Test + void validateRequestSuccessWithRSAPublicKey() { + HashMap headers = new HashMap<>(); + headers.put(config.getPublicKeyHeader(), VALID_RSA_PUBLIC_KEY); + headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); + headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); + headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); + headers.put(config.getAuthJWTHeader(), VALID_JWT); + headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); + headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); + headers.put(config.getSignatureInputHeader(), VALID_SIGNATURE_INPUT); + headers.put(config.getSignatureHeader(), VALID_SIGNATURE); + LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + + assertDoesNotThrow(() -> sut.validateLollipopRequest(request)); + } +} \ No newline at end of file From 4026c0e58ee2d22a9e7d8e36180987bb9236888e Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 17 Apr 2023 09:21:34 +0200 Subject: [PATCH 202/403] [SLS-21] fix javadoc. --- .../service/LollipopConsumerRequestValidationService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java index bdf34001..67da2603 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java @@ -12,7 +12,6 @@ public interface LollipopConsumerRequestValidationService { * Validates all request headers * * @param request the Lollipop request - * @return true if the request is validated * @throws LollipopRequestContentValidationException if some error occurred during validation */ void validateLollipopRequest(LollipopConsumerRequest request) throws LollipopRequestContentValidationException; From 7d23988e72669fdd7ff8a66035b8d8bb6ef9434b Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 17 Apr 2023 09:27:54 +0200 Subject: [PATCH 203/403] [SLS-21] applied spotless formatting. --- .../LollipopConsumerCommandBuilderImpl.java | 3 +- .../impl/LollipopConsumerCommandImpl.java | 47 +- .../config/LollipopConsumerRequestConfig.java | 14 +- .../enumeration/AssertionRefAlgorithms.java | 18 +- .../consumer/enumeration/AssertionType.java | 7 +- .../AssertionVerificationResultCode.java | 16 +- .../enumeration/LollipopRequestMethod.java | 5 +- .../exception/AssertionPeriodException.java | 5 +- .../AssertionThumbprintException.java | 5 +- .../exception/AssertionUserIdException.java | 6 +- .../ErrorRetrievingAssertionException.java | 7 +- ...ipopRequestContentValidationException.java | 9 +- .../helper/LollipopConsumerFactoryHelper.java | 8 +- .../lollipop/consumer/model/ECPublicKey.java | 5 +- .../lollipop/consumer/model/RSAPublicKey.java | 5 +- .../service/AssertionVerifierService.java | 7 +- ...lipopConsumerRequestValidationService.java | 8 +- .../impl/AssertionVerifierServiceImpl.java | 179 ++++--- ...pConsumerRequestValidationServiceImpl.java | 158 +++++-- .../impl/LollipopConsumerCommandImplTest.java | 111 +++-- .../AssertionVerifierServiceImplTest.java | 445 ++++++++++++++---- ...sumerRequestValidationServiceImplTest.java | 277 ++++++++--- 22 files changed, 965 insertions(+), 380 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java index c7109f2c..6c10346c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java @@ -29,7 +29,6 @@ public LollipopConsumerCommand createCommand() { return new LollipopConsumerCommandImpl( factoryHelper.getHttpMessageVerifierService(), factoryHelper.getAssertionVerifierService(), - factoryHelper.getRequestValidationService() - ); + factoryHelper.getRequestValidationService()); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index 03cd4df6..1ff773c0 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -2,7 +2,6 @@ package it.pagopa.tech.lollipop.consumer.command.impl; import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; -import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionVerificationResultCode; import it.pagopa.tech.lollipop.consumer.enumeration.HttpMessageVerificationResultCode; import it.pagopa.tech.lollipop.consumer.exception.*; @@ -10,6 +9,7 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; 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 java.io.UnsupportedEncodingException; import javax.inject.Inject; @@ -21,7 +21,8 @@ public class LollipopConsumerCommandImpl implements LollipopConsumerCommand { private final LollipopConsumerRequestValidationService requestValidationService; public static final String VERIFICATION_SUCCESS_CODE = "SUCCESS"; - public static final String REQUEST_PARAMS_VALIDATION_FAILED = "REQUEST PARAMS VALIDATION FAILED"; + public static final String REQUEST_PARAMS_VALIDATION_FAILED = + "REQUEST PARAMS VALIDATION FAILED"; @Inject public LollipopConsumerCommandImpl( @@ -46,7 +47,11 @@ public CommandResult doExecute(LollipopConsumerRequest request) { try { requestValidationService.validateLollipopRequest(request); } catch (LollipopRequestContentValidationException e) { - String message = String.format("Error validating Lollipop request header or body, validation failed with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); + String message = + String.format( + "Error validating Lollipop request header or body, validation failed" + + " with error code %s and message: %s", + e.getErrorCode(), e.getMessage()); return buildCommandResult(REQUEST_PARAMS_VALIDATION_FAILED, message); } @@ -70,17 +75,37 @@ private CommandResult getAssertionVerificationResult(LollipopConsumerRequest req try { result = assertionVerifierService.validateLollipop(request); } catch (ErrorRetrievingAssertionException e) { - String message = String.format("Cannot obtain the assertion, validation failed with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); - return buildCommandResult(AssertionVerificationResultCode.ERROR_RETRIEVING_ASSERTION.name(), message); + String message = + String.format( + "Cannot obtain the assertion, validation failed with error code %s" + + " and message: %s", + e.getErrorCode(), e.getMessage()); + return buildCommandResult( + AssertionVerificationResultCode.ERROR_RETRIEVING_ASSERTION.name(), message); } catch (AssertionPeriodException e) { - String message = String.format("Assertion validation failed on verifying period with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); - return buildCommandResult(AssertionVerificationResultCode.PERIOD_VALIDATION_ERROR.name(), message); + String message = + String.format( + "Assertion validation failed on verifying period with error code %s" + + " and message: %s", + e.getErrorCode(), e.getMessage()); + return buildCommandResult( + AssertionVerificationResultCode.PERIOD_VALIDATION_ERROR.name(), message); } catch (AssertionThumbprintException e) { - String message = String.format("Assertion validation failed on verifying thumbprint with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); - return buildCommandResult(AssertionVerificationResultCode.THUMBPRINT_VALIDATION_ERROR.name(), message); + String message = + String.format( + "Assertion validation failed on verifying thumbprint with error code" + + " %s and message: %s", + e.getErrorCode(), e.getMessage()); + return buildCommandResult( + AssertionVerificationResultCode.THUMBPRINT_VALIDATION_ERROR.name(), message); } catch (AssertionUserIdException e) { - String message = String.format("Assertion validation failed on verifying user id with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); - return buildCommandResult(AssertionVerificationResultCode.USER_ID_VALIDATION_ERROR.name(), message); + String message = + String.format( + "Assertion validation failed on verifying user id with error code %s" + + " and message: %s", + e.getErrorCode(), e.getMessage()); + return buildCommandResult( + AssertionVerificationResultCode.USER_ID_VALIDATION_ERROR.name(), message); } if (!result) { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index 4cb1ab4f..d746503b 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -10,7 +10,7 @@ public class LollipopConsumerRequestConfig { @Builder.Default private boolean strictDigestVerify = false; - //request headers + // request headers @Builder.Default private String signatureHeader = "signature"; @Builder.Default private String signatureInputHeader = "signature-input"; @Builder.Default private String contentEncodingHeader = "content-encoding"; @@ -24,16 +24,18 @@ public class LollipopConsumerRequestConfig { @Builder.Default private String authJWTHeader = "x-pagopa-lollipop-auth-jwt"; @Builder.Default private String expectedFirstLcOriginalMethod = "POST"; - @Builder.Default private String expectedFirstLcOriginalUrl = "https://api-app.io.pagopa.it/first-lollipop/sign"; + + @Builder.Default + private String expectedFirstLcOriginalUrl = "https://api-app.io.pagopa.it/first-lollipop/sign"; // assertion validation parameters @Builder.Default private int assertionExpireInDays = 30; @Builder.Default private String assertionNotBeforeDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; - @Builder.Default private String samlNamespaceAssertion = "urn:oasis:names:tc:SAML:2.0:assertion"; + + @Builder.Default + private String samlNamespaceAssertion = "urn:oasis:names:tc:SAML:2.0:assertion"; + @Builder.Default private String assertionNotBeforeTag = "Conditions"; @Builder.Default private String assertionFiscalCodeTag = "Attribute"; @Builder.Default private String assertionInResponseToTag = "SubjectConfirmationData"; - - - } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java index fe5a5b30..cbe1adb8 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionRefAlgorithms.java @@ -1,12 +1,10 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.enumeration; import java.util.regex.Pattern; -/** - * Supported AssertionRef algorithms - */ +/** Supported AssertionRef algorithms */ public enum AssertionRefAlgorithms { - SHA256("sha256", AlgorithmName.SHA_256, Pattern.compile("^(sha256-[A-Za-z0-9-_=]{1,44})$")), SHA384("sha384", AlgorithmName.SHA_384, Pattern.compile("^(sha384-[A-Za-z0-9-_=]{1,66})$")), SHA512("sha512", AlgorithmName.SHA_512, Pattern.compile("^(sha512-[A-Za-z0-9-_=]{1,88})$")); @@ -35,10 +33,14 @@ public String getAlgorithmName() { public static AssertionRefAlgorithms getAlgorithmFromHash(String algorithmName) { switch (algorithmName) { - case AlgorithmName.SHA_256: return SHA256; - case AlgorithmName.SHA_384: return SHA384; - case AlgorithmName.SHA_512: return SHA512; - default: throw new UnsupportedOperationException("Unsupported algorithm: " + algorithmName); + case AlgorithmName.SHA_256: + return SHA256; + case AlgorithmName.SHA_384: + return SHA384; + case AlgorithmName.SHA_512: + return SHA512; + default: + throw new UnsupportedOperationException("Unsupported algorithm: " + algorithmName); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java index 7a47cd22..e9f6f4d0 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java @@ -1,10 +1,9 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.enumeration; -/** - * Supported assertion type - */ +/** Supported assertion type */ public enum AssertionType { SAML, - //TODO: OIDC + // TODO: OIDC } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java index e7cd1d0b..d3b505f0 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java @@ -4,24 +4,16 @@ /** Result codes to classify Saml assertion validation */ public enum AssertionVerificationResultCode { - /** - * Saml assertion validation failed on retrieving the assertion - */ + /** Saml assertion validation failed on retrieving the assertion */ ERROR_RETRIEVING_ASSERTION, - /** - * Saml assertion validation failed on period validation - */ + /** Saml assertion validation failed on period validation */ PERIOD_VALIDATION_ERROR, - /** - * Saml assertion validation failed on user id validation - */ + /** Saml assertion validation failed on user id validation */ USER_ID_VALIDATION_ERROR, - /** - * Saml assertion validation failed on thumbpriint validation - */ + /** Saml assertion validation failed on thumbpriint validation */ THUMBPRINT_VALIDATION_ERROR, /** Saml assertion validation failed without throwing an exception */ diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopRequestMethod.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopRequestMethod.java index ed098922..fe1b87a8 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopRequestMethod.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/LollipopRequestMethod.java @@ -1,8 +1,7 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.enumeration; -/** - * Supported Lollipop request methods - */ +/** Supported Lollipop request methods */ public enum LollipopRequestMethod { GET, POST, diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionPeriodException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionPeriodException.java index c9c6dfc6..1ecce2f9 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionPeriodException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionPeriodException.java @@ -1,10 +1,9 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.exception; import java.util.Objects; -/** - * Thrown in case of problems when verifying assertion period - */ +/** Thrown in case of problems when verifying assertion period */ public class AssertionPeriodException extends Exception { /** Error code of this exception */ diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java index 37a12bb0..bfd28080 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionThumbprintException.java @@ -1,10 +1,9 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.exception; import java.util.Objects; -/** - * Thrown in case of problems when verifying assertion thumbprint - */ +/** Thrown in case of problems when verifying assertion thumbprint */ public class AssertionThumbprintException extends Exception { /** Error code of this exception */ diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionUserIdException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionUserIdException.java index 106b8384..1c334b98 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionUserIdException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/AssertionUserIdException.java @@ -1,13 +1,11 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.exception; import java.util.Objects; -/** - * Thrown in case of problems when verifying assertion user id - */ +/** Thrown in case of problems when verifying assertion user id */ public class AssertionUserIdException extends Exception { - /** Error code of this exception */ private final ErrorCode errorCode; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingAssertionException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingAssertionException.java index 7cd1f385..f8476d6d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingAssertionException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingAssertionException.java @@ -1,10 +1,9 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.exception; import java.util.Objects; -/** - * Thrown in case of problems on retrieving the assertion - */ +/** Thrown in case of problems on retrieving the assertion */ public class ErrorRetrievingAssertionException extends Exception { /** Error code of this exception */ @@ -48,4 +47,4 @@ public enum ErrorCode { OIDC_TYPE_NOT_SUPPORTED, ERROR_PARSING_ASSERTION } -} \ No newline at end of file +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java index 5e6516ad..833e3bd4 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopRequestContentValidationException.java @@ -1,13 +1,11 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.exception; import java.util.Objects; -/** - * Thrown in case of problem during Lollipop request header and body validation - */ +/** Thrown in case of problem during Lollipop request header and body validation */ public class LollipopRequestContentValidationException extends Exception { - /** Error code of this exception */ private final ErrorCode errorCode; @@ -29,7 +27,8 @@ public LollipopRequestContentValidationException(ErrorCode errorCode, String mes * @param message Detail message * @param cause Exception causing the constructed one */ - public LollipopRequestContentValidationException(ErrorCode errorCode, String message, Throwable cause) { + public LollipopRequestContentValidationException( + ErrorCode errorCode, String message, Throwable cause) { super(message, cause); this.errorCode = Objects.requireNonNull(errorCode); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index 76a66ff5..7fee7de2 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -11,7 +11,6 @@ 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 */ @@ -38,9 +37,7 @@ public LollipopConsumerFactoryHelper( */ public HttpMessageVerifierService getHttpMessageVerifierService() { return new HttpMessageVerifierServiceImpl( - getHttpMessageVerifierFactory().create(), - getLollipopConsumerRequestConfig() - ); + getHttpMessageVerifierFactory().create(), getLollipopConsumerRequestConfig()); } /** @@ -52,8 +49,7 @@ public AssertionVerifierService getAssertionVerifierService() { return new AssertionVerifierServiceImpl( getIdpCertProviderFactory().create(), getAssertionServiceFactory().create(), - getLollipopConsumerRequestConfig() - ); + getLollipopConsumerRequestConfig()); } public HttpMessageVerifierFactory getHttpMessageVerifierFactory() { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java index e3581111..8610b7dc 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java @@ -1,10 +1,9 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.model; import lombok.Data; -/** - * EC public key model - */ +/** EC public key model */ @Data public class ECPublicKey { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java index 628d327a..60e103e2 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java @@ -1,10 +1,9 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.model; import lombok.Data; -/** - * RSA public key model - */ +/** RSA public key model */ @Data public class RSAPublicKey { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java index b5cb0a1b..92df175d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java @@ -19,10 +19,13 @@ public interface AssertionVerifierService { * * @param request the Lollipop request * @return true if the assertion is valid - * @throws ErrorRetrievingAssertionException thrown for general errors in the verification process + * @throws ErrorRetrievingAssertionException thrown for general errors in the verification + * process * @throws AssertionPeriodException thrown for error in assertion period validation * @throws AssertionThumbprintException thrown for error in assertion thumbprint validation * @throws AssertionUserIdException thrown for error in user id validation */ - boolean validateLollipop(LollipopConsumerRequest request) throws ErrorRetrievingAssertionException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException; + boolean validateLollipop(LollipopConsumerRequest request) + throws ErrorRetrievingAssertionException, AssertionPeriodException, + AssertionThumbprintException, AssertionUserIdException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java index 67da2603..0c479f1b 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/LollipopConsumerRequestValidationService.java @@ -1,11 +1,10 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service; import it.pagopa.tech.lollipop.consumer.exception.LollipopRequestContentValidationException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; -/** - * Interface of the service used to verify Lollipop request header params - */ +/** Interface of the service used to verify Lollipop request header params */ public interface LollipopConsumerRequestValidationService { /** @@ -14,5 +13,6 @@ public interface LollipopConsumerRequestValidationService { * @param request the Lollipop request * @throws LollipopRequestContentValidationException if some error occurred during validation */ - void validateLollipopRequest(LollipopConsumerRequest request) throws LollipopRequestContentValidationException; + void validateLollipopRequest(LollipopConsumerRequest request) + throws LollipopRequestContentValidationException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index b562c0aa..14161ccf 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -14,16 +14,6 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; -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; - -import javax.inject.Inject; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.io.StringReader; import java.text.ParseException; @@ -31,10 +21,17 @@ import java.util.Date; import java.util.Map; import java.util.concurrent.TimeUnit; +import javax.inject.Inject; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +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; -/** - * Standard implementation of {@link AssertionVerifierService} - */ +/** Standard implementation of {@link AssertionVerifierService} */ public class AssertionVerifierServiceImpl implements AssertionVerifierService { private final IdpCertProvider idpCertProvider; @@ -44,7 +41,10 @@ public class AssertionVerifierServiceImpl implements AssertionVerifierService { private static final String IN_RESPONSE_TO = "InResponseTo"; @Inject - public AssertionVerifierServiceImpl(IdpCertProvider idpCertProvider, AssertionService assertionService, LollipopConsumerRequestConfig lollipopRequestConfig) { + public AssertionVerifierServiceImpl( + IdpCertProvider idpCertProvider, + AssertionService assertionService, + LollipopConsumerRequestConfig lollipopRequestConfig) { this.idpCertProvider = idpCertProvider; this.assertionService = assertionService; this.lollipopRequestConfig = lollipopRequestConfig; @@ -52,88 +52,128 @@ public AssertionVerifierServiceImpl(IdpCertProvider idpCertProvider, AssertionSe /** * @see AssertionVerifierService#validateLollipop(LollipopConsumerRequest) - * */ @Override - public boolean validateLollipop(LollipopConsumerRequest request) throws ErrorRetrievingAssertionException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException { + public boolean validateLollipop(LollipopConsumerRequest request) + throws ErrorRetrievingAssertionException, AssertionPeriodException, + AssertionThumbprintException, AssertionUserIdException { Map headerParams = request.getHeaderParams(); - SamlAssertion assertion = getAssertion(headerParams.get(lollipopRequestConfig.getAuthJWTHeader()), headerParams.get(lollipopRequestConfig.getAssertionRefHeader())); + SamlAssertion assertion = + getAssertion( + headerParams.get(lollipopRequestConfig.getAuthJWTHeader()), + headerParams.get(lollipopRequestConfig.getAssertionRefHeader())); Document assertionDoc = buildDocumentFromAssertion(assertion); boolean isAssertionPeriodValid = validateAssertionPeriod(assertionDoc); if (!isAssertionPeriodValid) { - throw new AssertionPeriodException(AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, "The assertion has expired"); + throw new AssertionPeriodException( + AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, + "The assertion has expired"); } boolean isUserIdValid = validateUserId(request, assertionDoc); if (!isUserIdValid) { - throw new AssertionUserIdException(AssertionUserIdException.ErrorCode.INVALID_USER_ID, "The user id in the assertion does not match the request header"); + throw new AssertionUserIdException( + AssertionUserIdException.ErrorCode.INVALID_USER_ID, + "The user id in the assertion does not match the request header"); } boolean isInResponseToValid = validateInResponseTo(request, assertionDoc); if (!isInResponseToValid) { - throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.INVALID_IN_RESPONSE_TO, "The hash of provided public key do not match the InResponseTo in the assertion"); + throw new AssertionThumbprintException( + AssertionThumbprintException.ErrorCode.INVALID_IN_RESPONSE_TO, + "The hash of provided public key do not match the InResponseTo in the" + + " assertion"); } return true; } - private SamlAssertion getAssertion(String jwt, String assertionRef) throws ErrorRetrievingAssertionException { + private SamlAssertion getAssertion(String jwt, String assertionRef) + throws ErrorRetrievingAssertionException { try { return assertionService.getAssertion(jwt, assertionRef); } catch (OidcAssertionNotSupported e) { - throw new ErrorRetrievingAssertionException(ErrorRetrievingAssertionException.ErrorCode.OIDC_TYPE_NOT_SUPPORTED, e.getMessage(), e); + throw new ErrorRetrievingAssertionException( + ErrorRetrievingAssertionException.ErrorCode.OIDC_TYPE_NOT_SUPPORTED, + e.getMessage(), + e); } catch (LollipopAssertionNotFoundException e) { - throw new ErrorRetrievingAssertionException(ErrorRetrievingAssertionException.ErrorCode.SAML_ASSERTION_NOT_FOUND, e.getMessage(), e); + throw new ErrorRetrievingAssertionException( + ErrorRetrievingAssertionException.ErrorCode.SAML_ASSERTION_NOT_FOUND, + e.getMessage(), + e); } - } private boolean validateAssertionPeriod(Document assertionDoc) throws AssertionPeriodException { - NodeList listElements = assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionNotBeforeTag()); + NodeList listElements = + assertionDoc.getElementsByTagNameNS( + lollipopRequestConfig.getSamlNamespaceAssertion(), + lollipopRequestConfig.getAssertionNotBeforeTag()); if (listElements == null || listElements.getLength() <= 0) { return false; } - String notBefore = listElements.item(0).getAttributes().getNamedItem("NotBefore").getNodeValue(); + String notBefore = + listElements.item(0).getAttributes().getNamedItem("NotBefore").getNodeValue(); long notBeforeMilliseconds; try { - notBeforeMilliseconds = new SimpleDateFormat(lollipopRequestConfig.getAssertionNotBeforeDateFormat()).parse(notBefore).getTime(); + notBeforeMilliseconds = + new SimpleDateFormat(lollipopRequestConfig.getAssertionNotBeforeDateFormat()) + .parse(notBefore) + .getTime(); } catch (ParseException e) { - throw new AssertionPeriodException(AssertionPeriodException.ErrorCode.ERROR_PARSING_ASSERTION_NOT_BEFORE_DATE, e.getMessage(), e); + throw new AssertionPeriodException( + AssertionPeriodException.ErrorCode.ERROR_PARSING_ASSERTION_NOT_BEFORE_DATE, + e.getMessage(), + e); } long dateNowMilliseconds = new Date().getTime(); - long expiresAfterMilliseconds = TimeUnit.DAYS.toMillis(lollipopRequestConfig.getAssertionExpireInDays()); + long expiresAfterMilliseconds = + TimeUnit.DAYS.toMillis(lollipopRequestConfig.getAssertionExpireInDays()); long dateNowLessNotBefore = (dateNowMilliseconds - notBeforeMilliseconds); return 0 <= dateNowLessNotBefore && (dateNowLessNotBefore <= expiresAfterMilliseconds); } - private boolean validateUserId(LollipopConsumerRequest request, Document assertionDoc) throws AssertionUserIdException { - String userIdHeader = request.getHeaderParams().get(lollipopRequestConfig.getUserIdHeader()); + private boolean validateUserId(LollipopConsumerRequest request, Document assertionDoc) + throws AssertionUserIdException { + String userIdHeader = + request.getHeaderParams().get(lollipopRequestConfig.getUserIdHeader()); String userIdFromAssertion = getUserIdFromAssertion(assertionDoc); if (userIdFromAssertion == null) { - throw new AssertionUserIdException(AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, "Missing or invalid Fiscal Code in the retrieved saml assertion."); + throw new AssertionUserIdException( + AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, + "Missing or invalid Fiscal Code in the retrieved saml assertion."); } return userIdFromAssertion.equals(userIdHeader); } - private boolean validateInResponseTo(LollipopConsumerRequest request, Document assertionDoc) throws AssertionThumbprintException { - NodeList listElements = assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionInResponseToTag()); + private boolean validateInResponseTo(LollipopConsumerRequest request, Document assertionDoc) + throws AssertionThumbprintException { + NodeList listElements = + assertionDoc.getElementsByTagNameNS( + lollipopRequestConfig.getSamlNamespaceAssertion(), + lollipopRequestConfig.getAssertionInResponseToTag()); if (isInResponseToFieldFound(listElements)) { - throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_FIELD_NOT_FOUND, "Missing request id in the retrieved saml assertion"); + throw new AssertionThumbprintException( + AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_FIELD_NOT_FOUND, + "Missing request id in the retrieved saml assertion"); } - String inResponseTo = listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO).getNodeValue(); + String inResponseTo = + listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO).getNodeValue(); String inResponseToAlgorithm = retrieveInResponseToAlgorithm(inResponseTo); - - String publicKey = request.getHeaderParams().get(lollipopRequestConfig.getPublicKeyHeader()); + String publicKey = + request.getHeaderParams().get(lollipopRequestConfig.getPublicKeyHeader()); String calculatedThumbprint = calculateThumbprint(inResponseToAlgorithm, publicKey); - String assertionRefHeader = request.getHeaderParams().get(lollipopRequestConfig.getAssertionRefHeader()); + String assertionRefHeader = + request.getHeaderParams().get(lollipopRequestConfig.getAssertionRefHeader()); return inResponseTo.equals(calculatedThumbprint) && inResponseTo.equals(assertionRefHeader); } @@ -146,7 +186,8 @@ private boolean validateSignature(SamlAssertion assertion, IdpCertData idpCertDa return false; } - private static Document buildDocumentFromAssertion(SamlAssertion assertion) throws ErrorRetrievingAssertionException { + private static Document buildDocumentFromAssertion(SamlAssertion assertion) + throws ErrorRetrievingAssertionException { String stringXml = assertion.getAssertionData(); try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); @@ -157,7 +198,10 @@ private static Document buildDocumentFromAssertion(SamlAssertion assertion) thro DocumentBuilder builder = factory.newDocumentBuilder(); return builder.parse(new InputSource(new StringReader(stringXml))); } catch (ParserConfigurationException | SAXException | IOException e) { - throw new ErrorRetrievingAssertionException(ErrorRetrievingAssertionException.ErrorCode.ERROR_PARSING_ASSERTION, e.getMessage(), e); + throw new ErrorRetrievingAssertionException( + ErrorRetrievingAssertionException.ErrorCode.ERROR_PARSING_ASSERTION, + e.getMessage(), + e); } } @@ -167,14 +211,19 @@ private boolean isInResponseToFieldFound(NodeList listElements) { || listElements.item(0) == null || listElements.item(0).getAttributes() == null || listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO) == null - || listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO).getNodeValue() == null; + || listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO).getNodeValue() + == null; } private String getUserIdFromAssertion(Document assertionDoc) throws AssertionUserIdException { - NodeList listElements = assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionFiscalCodeTag()); + NodeList listElements = + assertionDoc.getElementsByTagNameNS( + lollipopRequestConfig.getSamlNamespaceAssertion(), + lollipopRequestConfig.getAssertionFiscalCodeTag()); if (listElements == null || listElements.getLength() <= 0) { - throw new AssertionUserIdException(AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, "Missing or invalid Fiscal Code in the retrieved saml assertion."); - + throw new AssertionUserIdException( + AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, + "Missing or invalid Fiscal Code in the retrieved saml assertion."); } for (int i = 0; i < listElements.getLength(); i++) { @@ -183,17 +232,23 @@ private String getUserIdFromAssertion(Document assertionDoc) throws AssertionUse continue; } Node name = item.getAttributes().getNamedItem("Name"); - if (name != null && name.getNodeValue().equals("fiscalNumber") && item.getTextContent() != null) { + if (name != null + && name.getNodeValue().equals("fiscalNumber") + && item.getTextContent() != null) { return item.getTextContent().trim().replace("TINIT-", ""); } } return null; } - private String retrieveInResponseToAlgorithm(String inResponseTo) throws AssertionThumbprintException { - boolean matchesSHA256 = AssertionRefAlgorithms.SHA256.getPattern().matcher(inResponseTo).matches(); - boolean matchesSHA384 = AssertionRefAlgorithms.SHA384.getPattern().matcher(inResponseTo).matches(); - boolean matchesSHA512 = AssertionRefAlgorithms.SHA512.getPattern().matcher(inResponseTo).matches(); + private String retrieveInResponseToAlgorithm(String inResponseTo) + throws AssertionThumbprintException { + boolean matchesSHA256 = + AssertionRefAlgorithms.SHA256.getPattern().matcher(inResponseTo).matches(); + boolean matchesSHA384 = + AssertionRefAlgorithms.SHA384.getPattern().matcher(inResponseTo).matches(); + boolean matchesSHA512 = + AssertionRefAlgorithms.SHA512.getPattern().matcher(inResponseTo).matches(); if (matchesSHA256) { return AssertionRefAlgorithms.SHA256.getHashAlgorithm(); @@ -204,22 +259,32 @@ private String retrieveInResponseToAlgorithm(String inResponseTo) throws Asserti if (matchesSHA512) { return AssertionRefAlgorithms.SHA512.getHashAlgorithm(); } - throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_ALGORITHM_NOT_VALID, "InResponseTo in the assertion do not contains a valid Assertion Ref or it contains an invalid algorithm."); - + throw new AssertionThumbprintException( + AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_ALGORITHM_NOT_VALID, + "InResponseTo in the assertion do not contains a valid Assertion Ref or it contains" + + " an invalid algorithm."); } - private String calculateThumbprint(String inResponseToAlgorithm, String publicKey) throws AssertionThumbprintException { + private String calculateThumbprint(String inResponseToAlgorithm, String publicKey) + throws AssertionThumbprintException { Base64URL thumbprint; try { - thumbprint = ThumbprintUtils.compute(inResponseToAlgorithm, JWK.parse(publicKey)); + thumbprint = ThumbprintUtils.compute(inResponseToAlgorithm, JWK.parse(publicKey)); } catch (JOSEException | ParseException e) { String errMsg = String.format("Can not calculate JwkThumbprint: %S", e.getMessage()); - throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, errMsg, e); + throw new AssertionThumbprintException( + AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, + errMsg, + e); } - AssertionRefAlgorithms algo = AssertionRefAlgorithms.getAlgorithmFromHash(inResponseToAlgorithm); + AssertionRefAlgorithms algo = + AssertionRefAlgorithms.getAlgorithmFromHash(inResponseToAlgorithm); String calculatedThumbprint = String.format("%s-%s", algo.getAlgorithmName(), thumbprint); if (!algo.getPattern().matcher(calculatedThumbprint).matches()) { - throw new AssertionThumbprintException(AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, "The calculated thumbprint does not match the expected pattern: " + calculatedThumbprint); + throw new AssertionThumbprintException( + AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, + "The calculated thumbprint does not match the expected pattern: " + + calculatedThumbprint); } return calculatedThumbprint; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java index b4908609..810b795c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service.impl; import com.fasterxml.jackson.core.JsonProcessingException; @@ -11,11 +12,11 @@ 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.Map; import java.util.regex.Pattern; -public class LollipopConsumerRequestValidationServiceImpl implements LollipopConsumerRequestValidationService { +public class LollipopConsumerRequestValidationServiceImpl + implements LollipopConsumerRequestValidationService { private final LollipopConsumerRequestConfig config; @@ -24,7 +25,8 @@ public LollipopConsumerRequestValidationServiceImpl(LollipopConsumerRequestConfi } @Override - public void validateLollipopRequest(LollipopConsumerRequest request) throws LollipopRequestContentValidationException { + public void validateLollipopRequest(LollipopConsumerRequest request) + throws LollipopRequestContentValidationException { Map headerParams = request.getHeaderParams(); validatePublicKey(headerParams.get(this.config.getPublicKeyHeader())); @@ -39,13 +41,19 @@ public void validateLollipopRequest(LollipopConsumerRequest request) throws Loll validateSignatureHeader(headerParams.get(this.config.getSignatureHeader())); } - private void validatePublicKey(String publicKey) throws LollipopRequestContentValidationException { - if (publicKey == null ) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_PUBLIC_KEY, "Missing Public Key Header"); + private void validatePublicKey(String publicKey) + throws LollipopRequestContentValidationException { + if (publicKey == null) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.MISSING_PUBLIC_KEY, + "Missing Public Key Header"); } - if (isNotValidPublicKey(publicKey, ECPublicKey.class) && isNotValidPublicKey(publicKey, RSAPublicKey.class)) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_PUBLIC_KEY, "Invalid Public Key Header value"); + if (isNotValidPublicKey(publicKey, ECPublicKey.class) + && isNotValidPublicKey(publicKey, RSAPublicKey.class)) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.INVALID_PUBLIC_KEY, + "Invalid Public Key Header value"); } } @@ -59,30 +67,43 @@ private boolean isNotValidPublicKey(String publicKey, Class clazz) { return false; } - private void validateAssertionRefHeader(String assertionRef) throws LollipopRequestContentValidationException { - if (assertionRef == null ) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_REF, "Missing AssertionRef Header"); + private void validateAssertionRefHeader(String assertionRef) + throws LollipopRequestContentValidationException { + if (assertionRef == null) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_REF, + "Missing AssertionRef Header"); } if (isNotValidAssertionRef(assertionRef)) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_REF, "Invalid AssertionRef Header value"); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_REF, + "Invalid AssertionRef Header value"); } } private boolean isNotValidAssertionRef(String signature) { - boolean matchesSHA256 = AssertionRefAlgorithms.SHA256.getPattern().matcher(signature).matches(); - boolean matchesSHA384 = AssertionRefAlgorithms.SHA384.getPattern().matcher(signature).matches(); - boolean matchesSHA512 = AssertionRefAlgorithms.SHA512.getPattern().matcher(signature).matches(); + boolean matchesSHA256 = + AssertionRefAlgorithms.SHA256.getPattern().matcher(signature).matches(); + boolean matchesSHA384 = + AssertionRefAlgorithms.SHA384.getPattern().matcher(signature).matches(); + boolean matchesSHA512 = + AssertionRefAlgorithms.SHA512.getPattern().matcher(signature).matches(); return !matchesSHA256 && !matchesSHA384 && !matchesSHA512; } - private void validateAssertionTypeHeader(String assertionType) throws LollipopRequestContentValidationException { - if (assertionType == null ) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_TYPE, "Missing Assertion Type Header"); + private void validateAssertionTypeHeader(String assertionType) + throws LollipopRequestContentValidationException { + if (assertionType == null) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_TYPE, + "Missing Assertion Type Header"); } if ((!isAssertionTypeSupported(assertionType))) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_TYPE, "Invalid Assertion Type Header value, type not supported"); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_TYPE, + "Invalid Assertion Type Header value, type not supported"); } } @@ -95,42 +116,62 @@ private boolean isAssertionTypeSupported(String assertionType) { return false; } - private void validateUserIdHeader(String userId) throws LollipopRequestContentValidationException { - if (userId == null ) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_USER_ID, "Missing User Id Header"); + private void validateUserIdHeader(String userId) + throws LollipopRequestContentValidationException { + if (userId == null) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.MISSING_USER_ID, + "Missing User Id Header"); } if ((isNotValidFiscalCode(userId))) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_USER_ID, "Invalid User Id Header value, type not supported"); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.INVALID_USER_ID, + "Invalid User Id Header value, type not supported"); } } private boolean isNotValidFiscalCode(String userId) { - return !Pattern.compile("^[A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]$").matcher(userId).matches(); + return !Pattern.compile( + "^[A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]$") + .matcher(userId) + .matches(); } - private void validateAuthJWTHeader(String authJWT) throws LollipopRequestContentValidationException { - if (authJWT == null ) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_AUTH_JWT, "Missing Auth JWT Header"); + private void validateAuthJWTHeader(String authJWT) + throws LollipopRequestContentValidationException { + if (authJWT == null) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.MISSING_AUTH_JWT, + "Missing Auth JWT Header"); } if (authJWT.isBlank()) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_AUTH_JWT, "Invalid Auth JWT Header value, cannot be empty"); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.INVALID_AUTH_JWT, + "Invalid Auth JWT Header value, cannot be empty"); } } - private void validateOriginalMethodHeader(String originalMethod) throws LollipopRequestContentValidationException { - if (originalMethod == null ) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_METHOD, "Missing Original Method Header"); + private void validateOriginalMethodHeader(String originalMethod) + throws LollipopRequestContentValidationException { + if (originalMethod == null) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_METHOD, + "Missing Original Method Header"); } if (!isRequestMethodSupported(originalMethod)) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_METHOD, "Invalid Original Method Header value, method not supported"); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_METHOD, + "Invalid Original Method Header value, method not supported"); } if (!originalMethod.equals(this.config.getExpectedFirstLcOriginalMethod())) { String errMsg = String.format("Unexpected original method: %s", originalMethod); - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_METHOD, errMsg); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_METHOD, + errMsg); } } @@ -143,18 +184,25 @@ private boolean isRequestMethodSupported(String originalMethod) { return false; } - private void validateOriginalURLHeader(String originalURL) throws LollipopRequestContentValidationException { - if (originalURL == null ) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_URL, "Missing Original URL Header"); + private void validateOriginalURLHeader(String originalURL) + throws LollipopRequestContentValidationException { + if (originalURL == null) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_URL, + "Missing Original URL Header"); } if (isNotValidOriginalURL(originalURL)) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_URL, "Invalid Original URL Header value"); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_URL, + "Invalid Original URL Header value"); } if (!originalURL.equals(this.config.getExpectedFirstLcOriginalUrl())) { String errMsg = String.format("Unexpected original url: %s", originalURL); - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_URL, errMsg); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_URL, + errMsg); } } @@ -162,31 +210,45 @@ private boolean isNotValidOriginalURL(String originalURL) { return !Pattern.compile("^https://\\S+").matcher(originalURL).matches(); } - private void validateSignatureInputHeader(String signatureInput) throws LollipopRequestContentValidationException { - if (signatureInput == null ) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE_INPUT, "Missing Signature Input Header"); + private void validateSignatureInputHeader(String signatureInput) + throws LollipopRequestContentValidationException { + if (signatureInput == null) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE_INPUT, + "Missing Signature Input Header"); } if (isNotValidSignatureInput(signatureInput)) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE_INPUT, "Invalid Signature Input Header value"); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE_INPUT, + "Invalid Signature Input Header value"); } } private boolean isNotValidSignatureInput(String signatureInput) { - return !Pattern.compile("^(((sig[0-9]+)=[^,]*?)(, ?)?)+$").matcher(signatureInput).matches(); + return !Pattern.compile("^(((sig[0-9]+)=[^,]*?)(, ?)?)+$") + .matcher(signatureInput) + .matches(); } - private void validateSignatureHeader(String signature) throws LollipopRequestContentValidationException { - if (signature == null ) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE, "Missing Signature Header"); + private void validateSignatureHeader(String signature) + throws LollipopRequestContentValidationException { + if (signature == null) { + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE, + "Missing Signature Header"); } if (isNotValidSignature(signature)) { - throw new LollipopRequestContentValidationException(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE, "Invalid Signature Header value"); + throw new LollipopRequestContentValidationException( + LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE, + "Invalid Signature Header value"); } } private boolean isNotValidSignature(String signature) { - return !Pattern.compile("^((sig[0-9]+)=:[A-Za-z0-9+/=]*:(, ?)?)+$").matcher(signature).matches(); + return !Pattern.compile("^((sig[0-9]+)=:[A-Za-z0-9+/=]*:(, ?)?)+$") + .matcher(signature) + .matches(); } } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java index 68276d4d..f4dfd512 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -12,9 +12,8 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; -import java.io.UnsupportedEncodingException; - import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; +import java.io.UnsupportedEncodingException; import lombok.SneakyThrows; import org.junit.jupiter.api.*; import org.mockito.*; @@ -36,18 +35,20 @@ void beforeAll() { new LollipopConsumerCommandImpl( messageVerifierServiceMock, assertionVerifierServiceMock, - requestValidationServiceMock - )); + requestValidationServiceMock)); } @Test void failedHttpMessageValidationThrowDigestException() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException, + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException, LollipopSignatureException { - doThrow(new LollipopDigestException( - LollipopDigestException.ErrorCode.INCORRECT_DIGEST, "error")) + doThrow( + new LollipopDigestException( + LollipopDigestException.ErrorCode.INCORRECT_DIGEST, "error")) .when(messageVerifierServiceMock) .verifyHttpMessage(any(LollipopConsumerRequest.class)); @@ -57,6 +58,8 @@ void failedHttpMessageValidationThrowDigestException() HttpMessageVerificationResultCode.DIGEST_VALIDATION_ERROR.name(), commandResult.getResultCode()); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock, never()) .validateLollipop(any(LollipopConsumerRequest.class)); @@ -65,11 +68,11 @@ void failedHttpMessageValidationThrowDigestException() @Test void failedHttpMessageValidationThrowSignatureException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, - LollipopSignatureException { + LollipopSignatureException { doThrow( - new LollipopSignatureException( - LollipopSignatureException.ErrorCode.INVALID_SIGNATURE, "error")) + new LollipopSignatureException( + LollipopSignatureException.ErrorCode.INVALID_SIGNATURE, "error")) .when(messageVerifierServiceMock) .verifyHttpMessage(any(LollipopConsumerRequest.class)); @@ -99,7 +102,8 @@ void failedHttpMessageValidationThrowUnsupportedEncodingException() { HttpMessageVerificationResultCode.UNSUPPORTED_ENCODING.name(), commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock, never()) .validateLollipop(any(LollipopConsumerRequest.class)); @@ -107,8 +111,10 @@ void failedHttpMessageValidationThrowUnsupportedEncodingException() { @Test void failedHttpMessageValidationWithoutThrowingException() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException, LollipopSignatureException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException, LollipopSignatureException { doReturn(false) .when(messageVerifierServiceMock) @@ -120,7 +126,8 @@ void failedHttpMessageValidationWithoutThrowingException() HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_FAILED.name(), commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock, never()) .validateLollipop(any(LollipopConsumerRequest.class)); @@ -128,8 +135,10 @@ void failedHttpMessageValidationWithoutThrowingException() @Test void failedAssertionValidationWithoutThrowingException() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException, LollipopSignatureException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException, LollipopSignatureException { doReturn(true) .when(messageVerifierServiceMock) @@ -144,15 +153,18 @@ void failedAssertionValidationWithoutThrowingException() AssertionVerificationResultCode.ASSERTION_VERIFICATION_FAILED.name(), commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } @Test void successLollipopRequestValidation() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException, LollipopSignatureException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException, LollipopSignatureException { doReturn(true) .when(messageVerifierServiceMock) @@ -165,31 +177,40 @@ void successLollipopRequestValidation() Assertions.assertEquals("SUCCESS", commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } @Test void failedLollipopRequestValidation() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { - + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException { - doThrow(LollipopRequestContentValidationException.class).when(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + doThrow(LollipopRequestContentValidationException.class) + .when(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); Assertions.assertEquals("REQUEST PARAMS VALIDATION FAILED", commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); - verify(messageVerifierServiceMock, never()).verifyHttpMessage(any(LollipopConsumerRequest.class)); - verify(assertionVerifierServiceMock, never()).validateLollipop(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(messageVerifierServiceMock, never()) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock, never()) + .validateLollipop(any(LollipopConsumerRequest.class)); } @Test void failedAssertionValidationThrowErrorRetrievingAssertionException() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException { doReturn(true) .when(messageVerifierServiceMock) @@ -204,15 +225,18 @@ void failedAssertionValidationThrowErrorRetrievingAssertionException() AssertionVerificationResultCode.ERROR_RETRIEVING_ASSERTION.name(), commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } @Test void failedAssertionValidationThrowAssertionPeriodException() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException { doReturn(true) .when(messageVerifierServiceMock) @@ -227,15 +251,18 @@ void failedAssertionValidationThrowAssertionPeriodException() AssertionVerificationResultCode.PERIOD_VALIDATION_ERROR.name(), commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } @Test void failedAssertionValidationThrowAssertionThumbprintException() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException { doReturn(true) .when(messageVerifierServiceMock) @@ -250,15 +277,18 @@ void failedAssertionValidationThrowAssertionThumbprintException() AssertionVerificationResultCode.THUMBPRINT_VALIDATION_ERROR.name(), commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } @Test void failedAssertionValidationThrowAssertionUserIdException() - throws LollipopDigestException, UnsupportedEncodingException, - LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, LollipopRequestContentValidationException { + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException { doReturn(true) .when(messageVerifierServiceMock) @@ -273,7 +303,8 @@ void failedAssertionValidationThrowAssertionUserIdException() AssertionVerificationResultCode.USER_ID_VALIDATION_ERROR.name(), commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java index a31f63ed..402782c5 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java @@ -1,5 +1,9 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service.impl; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.*; @@ -7,18 +11,14 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; class AssertionVerifierServiceImplTest { @@ -29,14 +29,43 @@ class AssertionVerifierServiceImplTest { private AssertionVerifierService sut; private static final String VALID_FISCAL_CODE = "AAAAAA89S20I111X"; - private static final String VALID_JWK = "{ \"kty\": \"EC\", \"crv\": \"P-256\", \"x\": \"SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74\", \"y\": \"lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI\"}"; - private static final String VALID_SHA_256_ASSERTION_REF = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; - private static final String VALID_SHA_384_ASSERTION_REF = "sha384-lqxC_2kqMdwiBWoD-Us63Fha6e3bE1Y3yUz8G6IJTldohJCIBVDfvS8acB3GJBhw"; - private static final String VALID_SHA_512_ASSERTION_REF = "sha512-nX5CfUc5R-FoYKYZwvQMuc4Tt-heb7vHi_O-AMUSqHNVCw9kNaN2SVuN-DXtGXyUhrcVcQdCyY6FVzl_vyWXNA"; - - private static final String EMPTY_ASSERTION_XML = ""; - private static final String ASSERTION_XML_WITH_INVALID_PERIOD_DATE_FORMAT = "https://app-backend.io.italia.it"; - private static final String ASSERTION_XML_WITH_EXPIRED_PERIOD = "https://app-backend.io.italia.it"; + private static final String VALID_JWK = + "{ \"kty\": \"EC\", \"crv\": \"P-256\", \"x\":" + + " \"SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74\", \"y\":" + + " \"lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI\"}"; + private static final String VALID_SHA_256_ASSERTION_REF = + "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; + private static final String VALID_SHA_384_ASSERTION_REF = + "sha384-lqxC_2kqMdwiBWoD-Us63Fha6e3bE1Y3yUz8G6IJTldohJCIBVDfvS8acB3GJBhw"; + private static final String VALID_SHA_512_ASSERTION_REF = + "sha512-nX5CfUc5R-FoYKYZwvQMuc4Tt-heb7vHi_O-AMUSqHNVCw9kNaN2SVuN-DXtGXyUhrcVcQdCyY6FVzl_vyWXNA"; + + private static final String EMPTY_ASSERTION_XML = + ""; + private static final String ASSERTION_XML_WITH_INVALID_PERIOD_DATE_FORMAT = + "https://app-backend.io.italia.it"; + private static final String ASSERTION_XML_WITH_EXPIRED_PERIOD = + "https://app-backend.io.italia.it"; private static String ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG; private static String ASSERTION_XML_WITHOUT_FISCAL_CODE; private static String ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG; @@ -49,14 +78,196 @@ class AssertionVerifierServiceImplTest { static void prepareInput() { lollipopRequestConfigMock = spy(LollipopConsumerRequestConfig.builder().build()); - String todayTimestamp = new SimpleDateFormat(lollipopRequestConfigMock.getAssertionNotBeforeDateFormat()).format(new Date()); - ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG = "https://app-backend.io.italia.it"; - ASSERTION_XML_WITHOUT_FISCAL_CODE = " https://app-backend.io.italia.it \t "; - ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG = " https://app-backend.io.italia.it \t TINIT-AAAAAA89S20I111X "; - ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM = " \t\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thttps://app-backend.io.italia.it\t\t\t\t\t\t\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t\t\t\t\t"; - ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM = " \t\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thttps://app-backend.io.italia.it\t\t\t\t\t\t\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t\t\t\t\t"; - ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM = " \t\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thttps://app-backend.io.italia.it\t\t\t\t\t\t\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t\t\t\t\t"; - ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM = " \t\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thttps://app-backend.io.italia.it\t\t\t\t\t\t\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t\t\t\t\t"; + String todayTimestamp = + new SimpleDateFormat(lollipopRequestConfigMock.getAssertionNotBeforeDateFormat()) + .format(new Date()); + ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG = + "https://app-backend.io.italia.it"; + ASSERTION_XML_WITHOUT_FISCAL_CODE = + " " + + " " + + " " + + " " + + " https://app-backend.io.italia.it " + + " \t " + + " " + + " " + + " "; + ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG = + " " + + " " + + " " + + " " + + " https://app-backend.io.italia.it " + + " \t " + + " " + + " TINIT-AAAAAA89S20I111X " + + " " + + " "; + ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM = + " " + + " \t" + + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t" + + "\t\t\t\t\t\t\t\t\t" + + "\t\t\t\t" + + "\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t" + + "\t\t\t\t" + + "\t"; + ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM = + " " + + " \t" + + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t" + + "\t\t\t\t\t\t\t\t\t" + + "\t\t\t\t" + + "\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t" + + "\t\t\t\t" + + "\t"; + ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM = + " " + + " \t" + + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t" + + "\t\t\t\t\t\t\t\t\t" + + "\t\t\t\t" + + "\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t" + + "\t\t\t\t" + + "\t"; + ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM = + " " + + " \t" + + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t" + + "\t\t\t\t\t\t\t\t\t" + + "\t\t\t\t" + + "\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t" + + "\t\t\t\t" + + "\t"; } @BeforeEach @@ -64,35 +275,54 @@ void setUp() { idpCertProviderMock = mock(IdpCertProvider.class); assertionServiceMock = mock(AssertionService.class); - sut = new AssertionVerifierServiceImpl(idpCertProviderMock, assertionServiceMock, lollipopRequestConfigMock); + sut = + new AssertionVerifierServiceImpl( + idpCertProviderMock, assertionServiceMock, lollipopRequestConfigMock); } @Test - void validateLollipopGetAssertionFailureWithOidcAssertionException() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopGetAssertionFailureWithOidcAssertionException() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); - doThrow(OidcAssertionNotSupported.class).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doThrow(OidcAssertionNotSupported.class) + .when(assertionServiceMock) + .getAssertion(anyString(), anyString()); - ErrorRetrievingAssertionException e = assertThrows(ErrorRetrievingAssertionException.class, () -> sut.validateLollipop(request)); + ErrorRetrievingAssertionException e = + assertThrows( + ErrorRetrievingAssertionException.class, + () -> sut.validateLollipop(request)); Assertions.assertTrue(e.getCause() instanceof OidcAssertionNotSupported); - Assertions.assertEquals(ErrorRetrievingAssertionException.ErrorCode.OIDC_TYPE_NOT_SUPPORTED, e.getErrorCode()); + Assertions.assertEquals( + ErrorRetrievingAssertionException.ErrorCode.OIDC_TYPE_NOT_SUPPORTED, + e.getErrorCode()); } @Test - void validateLollipopGetAssertionFailureWithAssertionNotFoundException() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopGetAssertionFailureWithAssertionNotFoundException() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); - doThrow(LollipopAssertionNotFoundException.class).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doThrow(LollipopAssertionNotFoundException.class) + .when(assertionServiceMock) + .getAssertion(anyString(), anyString()); - ErrorRetrievingAssertionException e = assertThrows(ErrorRetrievingAssertionException.class, () -> sut.validateLollipop(request)); + ErrorRetrievingAssertionException e = + assertThrows( + ErrorRetrievingAssertionException.class, + () -> sut.validateLollipop(request)); Assertions.assertTrue(e.getCause() instanceof LollipopAssertionNotFoundException); - Assertions.assertEquals(ErrorRetrievingAssertionException.ErrorCode.SAML_ASSERTION_NOT_FOUND, e.getErrorCode()); + Assertions.assertEquals( + ErrorRetrievingAssertionException.ErrorCode.SAML_ASSERTION_NOT_FOUND, + e.getErrorCode()); } @Test - void validateLollipopBuildAssertionDocFailure() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopBuildAssertionDocFailure() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -100,13 +330,19 @@ void validateLollipopBuildAssertionDocFailure() throws OidcAssertionNotSupported doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - ErrorRetrievingAssertionException e = assertThrows(ErrorRetrievingAssertionException.class, () -> sut.validateLollipop(request)); + ErrorRetrievingAssertionException e = + assertThrows( + ErrorRetrievingAssertionException.class, + () -> sut.validateLollipop(request)); - Assertions.assertEquals(ErrorRetrievingAssertionException.ErrorCode.ERROR_PARSING_ASSERTION, e.getErrorCode()); + Assertions.assertEquals( + ErrorRetrievingAssertionException.ErrorCode.ERROR_PARSING_ASSERTION, + e.getErrorCode()); } @Test - void validateLollipopValidatePeriodFailureWithFieldNotFoundInAssertionDoc() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidatePeriodFailureWithFieldNotFoundInAssertionDoc() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -114,13 +350,16 @@ void validateLollipopValidatePeriodFailureWithFieldNotFoundInAssertionDoc() thro doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionPeriodException e = assertThrows(AssertionPeriodException.class, () -> sut.validateLollipop(request)); + AssertionPeriodException e = + assertThrows(AssertionPeriodException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, e.getErrorCode()); + Assertions.assertEquals( + AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, e.getErrorCode()); } @Test - void validateLollipopValidatePeriodFailureWithInvalidDateFormat() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidatePeriodFailureWithInvalidDateFormat() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -128,13 +367,17 @@ void validateLollipopValidatePeriodFailureWithInvalidDateFormat() throws OidcAss doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionPeriodException e = assertThrows(AssertionPeriodException.class, () -> sut.validateLollipop(request)); + AssertionPeriodException e = + assertThrows(AssertionPeriodException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionPeriodException.ErrorCode.ERROR_PARSING_ASSERTION_NOT_BEFORE_DATE, e.getErrorCode()); + Assertions.assertEquals( + AssertionPeriodException.ErrorCode.ERROR_PARSING_ASSERTION_NOT_BEFORE_DATE, + e.getErrorCode()); } @Test - void validateLollipopValidatePeriodFailureWithExpiredAssertion() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidatePeriodFailureWithExpiredAssertion() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -142,13 +385,16 @@ void validateLollipopValidatePeriodFailureWithExpiredAssertion() throws OidcAsse doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionPeriodException e = assertThrows(AssertionPeriodException.class, () -> sut.validateLollipop(request)); + AssertionPeriodException e = + assertThrows(AssertionPeriodException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, e.getErrorCode()); + Assertions.assertEquals( + AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, e.getErrorCode()); } @Test - void validateLollipopValidateUserIdFailureWithoutAttributeTagInAssertionDoc() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateUserIdFailureWithoutAttributeTagInAssertionDoc() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -156,13 +402,16 @@ void validateLollipopValidateUserIdFailureWithoutAttributeTagInAssertionDoc() th doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionUserIdException e = assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); + AssertionUserIdException e = + assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, e.getErrorCode()); + Assertions.assertEquals( + AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, e.getErrorCode()); } @Test - void validateLollipopValidateUserIdFailureWithoutFiscalCodeInAssertionDoc() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateUserIdFailureWithoutFiscalCodeInAssertionDoc() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -170,13 +419,16 @@ void validateLollipopValidateUserIdFailureWithoutFiscalCodeInAssertionDoc() thro doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionUserIdException e = assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); + AssertionUserIdException e = + assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, e.getErrorCode()); + Assertions.assertEquals( + AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, e.getErrorCode()); } @Test - void validateLollipopValidateUserIdFailureWithInvalidUserIdHeader() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateUserIdFailureWithInvalidUserIdHeader() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -184,13 +436,16 @@ void validateLollipopValidateUserIdFailureWithInvalidUserIdHeader() throws OidcA doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionUserIdException e = assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); + AssertionUserIdException e = + assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionUserIdException.ErrorCode.INVALID_USER_ID, e.getErrorCode()); + Assertions.assertEquals( + AssertionUserIdException.ErrorCode.INVALID_USER_ID, e.getErrorCode()); } @Test - void validateLollipopValidateThumbprintFailureWithoutSubjectConfirmationDataTagInAssertionDoc() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateThumbprintFailureWithoutSubjectConfirmationDataTagInAssertionDoc() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", VALID_FISCAL_CODE); SamlAssertion assertion = new SamlAssertion(); @@ -198,28 +453,37 @@ void validateLollipopValidateThumbprintFailureWithoutSubjectConfirmationDataTagI doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionThumbprintException e = assertThrows(AssertionThumbprintException.class, () -> sut.validateLollipop(request)); + AssertionThumbprintException e = + assertThrows( + AssertionThumbprintException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_FIELD_NOT_FOUND, e.getErrorCode()); + Assertions.assertEquals( + AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_FIELD_NOT_FOUND, + e.getErrorCode()); } @Test - void validateLollipopValidateThumbprintFailureWithInvalidInResponseToAlgorithm() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateThumbprintFailureWithInvalidInResponseToAlgorithm() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", VALID_FISCAL_CODE); - SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionThumbprintException e = assertThrows(AssertionThumbprintException.class, () -> sut.validateLollipop(request)); + AssertionThumbprintException e = + assertThrows( + AssertionThumbprintException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_ALGORITHM_NOT_VALID, e.getErrorCode()); + Assertions.assertEquals( + AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_ALGORITHM_NOT_VALID, + e.getErrorCode()); } @Test - void validateLollipopValidateThumbprintFailureWithErrorCalculatingThumbprint() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateThumbprintFailureWithErrorCalculatingThumbprint() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", VALID_FISCAL_CODE); SamlAssertion assertion = new SamlAssertion(); @@ -227,29 +491,43 @@ void validateLollipopValidateThumbprintFailureWithErrorCalculatingThumbprint() t doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionThumbprintException e = assertThrows(AssertionThumbprintException.class, () -> sut.validateLollipop(request)); + AssertionThumbprintException e = + assertThrows( + AssertionThumbprintException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, e.getErrorCode()); + Assertions.assertEquals( + AssertionThumbprintException.ErrorCode.ERROR_CALCULATING_ASSERTION_THUMBPRINT, + e.getErrorCode()); Assertions.assertTrue(e.getCause() instanceof ParseException); } @Test - void validateLollipopValidateThumbprintFailureWithDifferentAssertionRefAndCalculatedThumbprint() throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { - LollipopConsumerRequest request = getLollipopConsumerRequest("", VALID_JWK, VALID_FISCAL_CODE); + void validateLollipopValidateThumbprintFailureWithDifferentAssertionRefAndCalculatedThumbprint() + throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + LollipopConsumerRequest request = + getLollipopConsumerRequest("", VALID_JWK, VALID_FISCAL_CODE); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); - AssertionThumbprintException e = assertThrows(AssertionThumbprintException.class, () -> sut.validateLollipop(request)); + AssertionThumbprintException e = + assertThrows( + AssertionThumbprintException.class, () -> sut.validateLollipop(request)); - Assertions.assertEquals(AssertionThumbprintException.ErrorCode.INVALID_IN_RESPONSE_TO, e.getErrorCode()); + Assertions.assertEquals( + AssertionThumbprintException.ErrorCode.INVALID_IN_RESPONSE_TO, e.getErrorCode()); } @Test - void validateLollipopSuccessWithSHA256Algorithm() throws LollipopAssertionNotFoundException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, OidcAssertionNotSupported { - LollipopConsumerRequest request = getLollipopConsumerRequest(VALID_SHA_256_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); + void validateLollipopSuccessWithSHA256Algorithm() + throws LollipopAssertionNotFoundException, AssertionPeriodException, + AssertionThumbprintException, AssertionUserIdException, + ErrorRetrievingAssertionException, OidcAssertionNotSupported { + LollipopConsumerRequest request = + getLollipopConsumerRequest( + VALID_SHA_256_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); @@ -262,8 +540,13 @@ void validateLollipopSuccessWithSHA256Algorithm() throws LollipopAssertionNotFou } @Test - void validateLollipopSuccessWithSHA384Algorithm() throws LollipopAssertionNotFoundException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, OidcAssertionNotSupported { - LollipopConsumerRequest request = getLollipopConsumerRequest(VALID_SHA_384_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); + void validateLollipopSuccessWithSHA384Algorithm() + throws LollipopAssertionNotFoundException, AssertionPeriodException, + AssertionThumbprintException, AssertionUserIdException, + ErrorRetrievingAssertionException, OidcAssertionNotSupported { + LollipopConsumerRequest request = + getLollipopConsumerRequest( + VALID_SHA_384_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM); @@ -276,8 +559,13 @@ void validateLollipopSuccessWithSHA384Algorithm() throws LollipopAssertionNotFou } @Test - void validateLollipopSuccessWithSHA512Algorithm() throws LollipopAssertionNotFoundException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, OidcAssertionNotSupported { - LollipopConsumerRequest request = getLollipopConsumerRequest(VALID_SHA_512_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); + void validateLollipopSuccessWithSHA512Algorithm() + throws LollipopAssertionNotFoundException, AssertionPeriodException, + AssertionThumbprintException, AssertionUserIdException, + ErrorRetrievingAssertionException, OidcAssertionNotSupported { + LollipopConsumerRequest request = + getLollipopConsumerRequest( + VALID_SHA_512_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM); @@ -289,15 +577,14 @@ void validateLollipopSuccessWithSHA512Algorithm() throws LollipopAssertionNotFou Assertions.assertTrue(result); } - private LollipopConsumerRequest getLollipopConsumerRequest(String assertionRef, String publicKey, String userId) { + private LollipopConsumerRequest getLollipopConsumerRequest( + String assertionRef, String publicKey, String userId) { HashMap headers = new HashMap<>(); headers.put(lollipopRequestConfigMock.getAuthJWTHeader(), ""); headers.put(lollipopRequestConfigMock.getAssertionRefHeader(), assertionRef); headers.put(lollipopRequestConfigMock.getUserIdHeader(), userId); headers.put(lollipopRequestConfigMock.getPublicKeyHeader(), publicKey); - return LollipopConsumerRequest.builder() - .headerParams(headers) - .build(); + return LollipopConsumerRequest.builder().headerParams(headers).build(); } -} \ No newline at end of file +} diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java index 0e921866..8a380f98 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java @@ -1,27 +1,35 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service.impl; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.spy; + import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionType; import it.pagopa.tech.lollipop.consumer.exception.LollipopRequestContentValidationException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; +import java.util.HashMap; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.HashMap; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.spy; - class LollipopConsumerRequestValidationServiceImplTest { - public static final String VALID_EC_PUBLIC_KEY = "{ \"kty\": \"EC\", \"x\": \"FqFDuwEgu4MUXERPMVL-85pGv2D3YmL4J1gfMkdbc24\", \"y\": \"hdV0oxmWFSxMoJUDpdihr76rS8VRBEqMFebYyAfK9-k\", \"crv\": \"P-256\"}"; - public static final String VALID_RSA_PUBLIC_KEY = "{ \"alg\": \"RS256\", \"e\": \"AQAB\", \"kty\": \"RSA\", \"n\": \"yeNlzlub94YgerT030codqEztjfU_S6X4DbDA_iVKkjAWtYfPHDzz_sPCT1Axz6isZdf3lHpq_gYX4Sz\"}"; - public static final String VALID_ASSERTION_REF = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; + public static final String VALID_EC_PUBLIC_KEY = + "{ \"kty\": \"EC\", \"x\": \"FqFDuwEgu4MUXERPMVL-85pGv2D3YmL4J1gfMkdbc24\", \"y\":" + + " \"hdV0oxmWFSxMoJUDpdihr76rS8VRBEqMFebYyAfK9-k\", \"crv\": \"P-256\"}"; + public static final String VALID_RSA_PUBLIC_KEY = + "{ \"alg\": \"RS256\", \"e\": \"AQAB\", \"kty\": \"RSA\", \"n\":" + + " \"yeNlzlub94YgerT030codqEztjfU_S6X4DbDA_iVKkjAWtYfPHDzz_sPCT1Axz6isZdf3lHpq_gYX4Sz\"}"; + public static final String VALID_ASSERTION_REF = + "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; public static final String VALID_FISCAL_CODE = "AAAAAA89S20I111X"; public static final String VALID_JWT = "aValidJWT"; - public static final String VALID_SIGNATURE_INPUT = "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\" \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; - public static final String VALID_SIGNATURE = "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + public static final String VALID_SIGNATURE_INPUT = + "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + public static final String VALID_SIGNATURE = + "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; public static final String RANDOM_STRING = ""; private LollipopConsumerRequestConfig config; @@ -36,33 +44,51 @@ void setUp() { @Test void validatePublicKeyFailureHeaderNotPresent() { HashMap headers = new HashMap<>(); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_PUBLIC_KEY, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.MISSING_PUBLIC_KEY, + e.getErrorCode()); } @Test void validatePublicKeyFailureHeaderInvalidFormat() { HashMap headers = new HashMap<>(); headers.put(config.getPublicKeyHeader(), RANDOM_STRING); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_PUBLIC_KEY, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.INVALID_PUBLIC_KEY, + e.getErrorCode()); } @Test void validateAssertionRefFailureHeaderNotPresent() { HashMap headers = new HashMap<>(); headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_REF, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_REF, + e.getErrorCode()); } @Test @@ -70,11 +96,17 @@ void validateAssertionRefFailureInvalidFormat() { HashMap headers = new HashMap<>(); headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); headers.put(config.getAssertionRefHeader(), RANDOM_STRING); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_REF, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_REF, + e.getErrorCode()); } @Test @@ -82,11 +114,17 @@ void validateAssertionTypeFailureHeaderNotPresent() { HashMap headers = new HashMap<>(); headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_TYPE, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.MISSING_ASSERTION_TYPE, + e.getErrorCode()); } @Test @@ -95,11 +133,17 @@ void validateAssertionTypeFailureInvalidFormat() { headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); headers.put(config.getAssertionTypeHeader(), RANDOM_STRING); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_TYPE, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.INVALID_ASSERTION_TYPE, + e.getErrorCode()); } @Test @@ -108,11 +152,17 @@ void validateUserIdFailureHeaderNotPresent() { headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_USER_ID, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.MISSING_USER_ID, + e.getErrorCode()); } @Test @@ -122,11 +172,17 @@ void validateUserIdFailureInvalidFormat() { headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); headers.put(config.getUserIdHeader(), RANDOM_STRING); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_USER_ID, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.INVALID_USER_ID, + e.getErrorCode()); } @Test @@ -136,11 +192,17 @@ void validateAuthJWKFailureHeaderNotPresent() { headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_AUTH_JWT, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.MISSING_AUTH_JWT, + e.getErrorCode()); } @Test @@ -151,11 +213,17 @@ void validateAuthJWKFailureInvalidFormat() { headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); headers.put(config.getAuthJWTHeader(), RANDOM_STRING); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_AUTH_JWT, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.INVALID_AUTH_JWT, + e.getErrorCode()); } @Test @@ -166,11 +234,17 @@ void validateOriginalMethodFailureHeaderNotPresent() { headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); headers.put(config.getAuthJWTHeader(), VALID_JWT); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_METHOD, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_METHOD, + e.getErrorCode()); } @Test @@ -182,11 +256,17 @@ void validateOriginalMethodFailureNotSupported() { headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); headers.put(config.getAuthJWTHeader(), VALID_JWT); headers.put(config.getOriginalMethodHeader(), "INVALID_METHOD"); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_METHOD, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_METHOD, + e.getErrorCode()); } @Test @@ -198,12 +278,19 @@ void validateOriginalMethodFailureDifferentFromExpectedMethod() { headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); headers.put(config.getAuthJWTHeader(), VALID_JWT); headers.put(config.getOriginalMethodHeader(), "PUT"); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_METHOD, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_METHOD, + e.getErrorCode()); } + @Test void validateOriginalURLFailureHeaderNotPresent() { HashMap headers = new HashMap<>(); @@ -213,11 +300,17 @@ void validateOriginalURLFailureHeaderNotPresent() { headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); headers.put(config.getAuthJWTHeader(), VALID_JWT); headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_URL, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.MISSING_ORIGINAL_URL, + e.getErrorCode()); } @Test @@ -230,11 +323,17 @@ void validateOriginalURLFailureInvalidFormat() { headers.put(config.getAuthJWTHeader(), VALID_JWT); headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); headers.put(config.getOriginalURLHeader(), RANDOM_STRING); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_URL, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.INVALID_ORIGINAL_URL, + e.getErrorCode()); } @Test @@ -247,11 +346,17 @@ void validateOriginalURLFailureDifferentFromExpectedMethod() { headers.put(config.getAuthJWTHeader(), VALID_JWT); headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); headers.put(config.getOriginalURLHeader(), "https://pagopa.it"); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_URL, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.UNEXPECTED_ORIGINAL_URL, + e.getErrorCode()); } @Test @@ -264,11 +369,17 @@ void validateSignatureInputFailureHeaderNotPresent() { headers.put(config.getAuthJWTHeader(), VALID_JWT); headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE_INPUT, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE_INPUT, + e.getErrorCode()); } @Test @@ -282,11 +393,17 @@ void validateSignatureInputFailureInvalidFormat() { headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); headers.put(config.getSignatureInputHeader(), RANDOM_STRING); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE_INPUT, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE_INPUT, + e.getErrorCode()); } @Test @@ -300,11 +417,17 @@ void validateSignatureFailureHeaderNotPresent() { headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); headers.put(config.getSignatureInputHeader(), VALID_SIGNATURE_INPUT); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.MISSING_SIGNATURE, + e.getErrorCode()); } @Test @@ -319,11 +442,17 @@ void validateSignatureFailureInvalidFormat() { headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); headers.put(config.getSignatureInputHeader(), VALID_SIGNATURE_INPUT); headers.put(config.getSignatureHeader(), RANDOM_STRING); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); - LollipopRequestContentValidationException e = assertThrows(LollipopRequestContentValidationException.class, () -> sut.validateLollipopRequest(request)); + LollipopRequestContentValidationException e = + assertThrows( + LollipopRequestContentValidationException.class, + () -> sut.validateLollipopRequest(request)); - assertEquals(LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE, e.getErrorCode()); + assertEquals( + LollipopRequestContentValidationException.ErrorCode.INVALID_SIGNATURE, + e.getErrorCode()); } @Test @@ -338,7 +467,8 @@ void validateRequestSuccessWithECPublicKey() { headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); headers.put(config.getSignatureInputHeader(), VALID_SIGNATURE_INPUT); headers.put(config.getSignatureHeader(), VALID_SIGNATURE); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); assertDoesNotThrow(() -> sut.validateLollipopRequest(request)); } @@ -355,8 +485,9 @@ void validateRequestSuccessWithRSAPublicKey() { headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); headers.put(config.getSignatureInputHeader(), VALID_SIGNATURE_INPUT); headers.put(config.getSignatureHeader(), VALID_SIGNATURE); - LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); + LollipopConsumerRequest request = + LollipopConsumerRequest.builder().headerParams(headers).build(); assertDoesNotThrow(() -> sut.validateLollipopRequest(request)); } -} \ No newline at end of file +} From 341f379ff90ec0d060110f3b2063985b26cb744e Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 17 Apr 2023 09:38:32 +0200 Subject: [PATCH 204/403] [SLS-21] updated verification-metadata.xml. --- gradle/verification-metadata.xml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index a255d04b..3d3df40f 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -253,6 +253,14 @@ + + + + + + + + @@ -337,6 +345,14 @@ + + + + + + + + @@ -934,9 +950,11 @@ + + @@ -2255,6 +2273,7 @@ + @@ -2320,6 +2339,7 @@ + @@ -2741,6 +2761,7 @@ + @@ -2764,6 +2785,7 @@ + @@ -2787,6 +2809,7 @@ + @@ -2810,6 +2833,7 @@ + @@ -2833,6 +2857,7 @@ + @@ -2852,9 +2877,11 @@ + + @@ -2874,6 +2901,7 @@ + @@ -2893,9 +2921,11 @@ + + @@ -2911,9 +2941,11 @@ + + From 45f20f0950ef57700663a0064d2bd5b83a6f95ad Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 17 Apr 2023 09:40:06 +0200 Subject: [PATCH 205/403] [SLS-21] updated comment. --- .../tech/lollipop/consumer/enumeration/AssertionType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java index e9f6f4d0..71701573 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionType.java @@ -4,6 +4,6 @@ /** Supported assertion type */ public enum AssertionType { SAML, - // TODO: OIDC + // Not supported yet: OIDC } From e63854f5f7c188864c7272b6b04fbf423d248bc8 Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 17 Apr 2023 11:04:34 +0200 Subject: [PATCH 206/403] [SLS-21] updated verification-metadata.xml and fix some merge errors. --- .../impl/LollipopConsumerCommandImplTest.java | 24 ++++++++++--------- gradle/verification-metadata.xml | 20 +++------------- .../visma/VismaHttpMessageVerifier.java | 2 +- 3 files changed, 17 insertions(+), 29 deletions(-) diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java index f4dfd512..2b03d62c 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -43,8 +43,7 @@ void failedHttpMessageValidationThrowDigestException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, - LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException { doThrow( new LollipopDigestException( @@ -68,11 +67,13 @@ void failedHttpMessageValidationThrowDigestException() @Test void failedHttpMessageValidationThrowSignatureException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, - LollipopSignatureException { + LollipopSignatureException, LollipopRequestContentValidationException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException { doThrow( - new LollipopSignatureException( - LollipopSignatureException.ErrorCode.INVALID_SIGNATURE, "error")) + new LollipopSignatureException( + LollipopSignatureException.ErrorCode.INVALID_SIGNATURE, "error")) .when(messageVerifierServiceMock) .verifyHttpMessage(any(LollipopConsumerRequest.class)); @@ -82,7 +83,8 @@ void failedHttpMessageValidationThrowSignatureException() HttpMessageVerificationResultCode.SIGNATURE_VALIDATION_ERROR.name(), commandResult.getResultCode()); - verify(requestValidationServiceMock).validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock, never()) .validateLollipop(any(LollipopConsumerRequest.class)); @@ -188,7 +190,7 @@ void failedLollipopRequestValidation() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException { + LollipopRequestContentValidationException, LollipopSignatureException { doThrow(LollipopRequestContentValidationException.class) .when(requestValidationServiceMock) @@ -210,7 +212,7 @@ void failedAssertionValidationThrowErrorRetrievingAssertionException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException { + LollipopRequestContentValidationException, LollipopSignatureException { doReturn(true) .when(messageVerifierServiceMock) @@ -236,7 +238,7 @@ void failedAssertionValidationThrowAssertionPeriodException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException { + LollipopRequestContentValidationException, LollipopSignatureException { doReturn(true) .when(messageVerifierServiceMock) @@ -262,7 +264,7 @@ void failedAssertionValidationThrowAssertionThumbprintException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException { + LollipopRequestContentValidationException, LollipopSignatureException { doReturn(true) .when(messageVerifierServiceMock) @@ -288,7 +290,7 @@ void failedAssertionValidationThrowAssertionUserIdException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException { + LollipopRequestContentValidationException, LollipopSignatureException { doReturn(true) .when(messageVerifierServiceMock) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 3d3df40f..948ab80f 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1,5 +1,5 @@ - + true false @@ -253,14 +253,6 @@ - - - - - - - - @@ -345,14 +337,6 @@ - - - - - - - - @@ -1681,9 +1665,11 @@ + + diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java index 54635b32..296ecc76 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java @@ -72,7 +72,7 @@ public boolean verifyHttpSignature( parameters.remove(lollipopConsumerRequestConfig.getSignatureInputHeader()); parameters.remove(lollipopConsumerRequestConfig.getSignatureHeader()); - String lollipopKey = parameters.get(lollipopConsumerRequestConfig.getLollipopKeyHeader()); + String lollipopKey = parameters.get(lollipopConsumerRequestConfig.getPublicKeyHeader()); if (lollipopKey == null) { throw new LollipopSignatureException( LollipopSignatureException.ErrorCode.MISSING_PUBLIC_KEY, From bf3500b1b869256269b75ff693ad0239533da6a3 Mon Sep 17 00:00:00 2001 From: svariant Date: Mon, 17 Apr 2023 11:07:28 +0200 Subject: [PATCH 207/403] [SLS-29] Introduced pre-commit hooks --- .pre-commit-config.yaml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..7a8b872f --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,7 @@ +# 1. `pip install pre-commit` +# 2. `pre-commit install` +repos: + - repo: https://github.com/maltzj/google-style-precommit-hook + rev: b7e9e7fcba4a5aea463e72fe9964c14877bd8130 + hooks: + - id: google-style-java \ No newline at end of file From 1e75109211cc6b749532aea48d2c50f32d2f5a63 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Mon, 17 Apr 2023 12:36:51 +0200 Subject: [PATCH 208/403] [SLS-29] Updated pre-commit config to include gradle checks and metadata-update, standard pre-commit hooks, and gitleaks --- .github/workflows/pr_scan.yml | 8 +++---- .pre-commit-config.yaml | 23 ++++++++++++++++--- .../openapi/openapi-spec.yml | 2 +- build.gradle | 2 +- gradle/verification-metadata.xml | 4 ++++ 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index c61cdd6d..bae1e45f 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -2,10 +2,10 @@ name: Check Build and Anchore on PR on: pull_request: - + env: DOCKERFILE: Dockerfile.test-only - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_ACTOR: ${{ secrets.GITHUB_ACTOR }} jobs: @@ -18,11 +18,11 @@ jobs: - name: Checkout project sources uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 with: - fetch-depth: 0 + fetch-depth: 0 - name: Setup Gradle uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 - name: Make gradlew executable - run: chmod +x ./gradlew + run: chmod +x ./gradlew - name: Run build with Gradle Wrapper run: ./gradlew build - name: Build the Docker image diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7a8b872f..d35b1c2c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,24 @@ # 1. `pip install pre-commit` # 2. `pre-commit install` repos: - - repo: https://github.com/maltzj/google-style-precommit-hook - rev: b7e9e7fcba4a5aea463e72fe9964c14877bd8130 + - repo: https://github.com/jguttman94/pre-commit-gradle + rev: v0.2.1 hooks: - - id: google-style-java \ No newline at end of file + - id: gradle-task + name: update-verification-metadata-sha256 + args: [ '-w', '--write-verification-metadata sha256 help'] + - id: gradle-spotless + args: [ '-w'] + - id: gradle-check + args: [ '-w' ] + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v3.2.0 + hooks: + - id: trailing-whitespace + - id: check-yaml + - id: check-added-large-files + - id: check-merge-conflict + - repo: https://github.com/gitleaks/gitleaks + rev: v8.16.1 + hooks: + - id: gitleaks \ No newline at end of file diff --git a/assertion-rest-client-native/openapi/openapi-spec.yml b/assertion-rest-client-native/openapi/openapi-spec.yml index 97f30e2b..c8baeba4 100644 --- a/assertion-rest-client-native/openapi/openapi-spec.yml +++ b/assertion-rest-client-native/openapi/openapi-spec.yml @@ -4,7 +4,7 @@ info: version: $npm_package_version x-logo: url: https://io.italia.it/assets/img/io-logo-blue.svg - description: |- + description: |- Client used to get the assertion from the identity provider servers: - url: http://localhost:3000 diff --git a/build.gradle b/build.gradle index 75f4874d..6b2c5eea 100644 --- a/build.gradle +++ b/build.gradle @@ -18,7 +18,7 @@ allprojects { targetCompatibility = '11' apply plugin: 'com.diffplug.spotless' apply plugin: 'nebula.lint' - gradleLint.rules = ['all-dependency'] + gradleLint.rules = [] configurations { spotless { diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index a255d04b..b3045e43 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -934,9 +934,11 @@ + + @@ -1663,9 +1665,11 @@ + + From e9f81b39db81d8eaec136a3b9770b64628a0d622 Mon Sep 17 00:00:00 2001 From: svariant Date: Mon, 17 Apr 2023 15:44:20 +0200 Subject: [PATCH 209/403] [SLS-26] Implemented idpCertData provider and storage --- .../consumer/idp/IdpCertProvider.java | 8 +- .../idp/impl/IdpCertProviderFactoryImpl.java | 42 +++++++ .../impl/IdpCertProviderFactoryImplStub.java | 18 --- .../idp/impl/IdpCertProviderImpl.java | 70 ++++++++++++ .../idp/impl/IdpCertProviderImplStub.java | 17 --- .../consumer/idp/storage/IdpCertStorage.java | 24 +++- .../idp/storage/IdpCertStorageConfig.java | 14 +++ .../idp/storage/IdpCertStorageProvider.java | 6 +- .../idp/storage/SimpleIdpCertStorage.java | 104 ++++++++++++++++++ .../storage/SimpleIdpCertStorageProvider.java | 19 ++++ gradle/verification-metadata.xml | 18 +-- 11 files changed, 280 insertions(+), 60 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImpl.java delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageConfig.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorage.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorageProvider.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java index 7aaed7a2..f2969e74 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java @@ -1,7 +1,13 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp; +import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import java.util.List; + public interface IdpCertProvider { - boolean getIdpCertData(String assertionInstant, String entityId); + List getIdpCertData(String assertionInstant, String entityId) + throws CertDataTagListNotFoundException, CertDataNotFoundException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImpl.java new file mode 100644 index 00000000..82ace7bf --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImpl.java @@ -0,0 +1,42 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.impl; + +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageProvider; +import javax.inject.Inject; + +/** + * Implementation of {@link IdpCertProviderFactory}, used to create instances of {@link + * IdpCertProviderImpl} + */ +public class IdpCertProviderFactoryImpl implements IdpCertProviderFactory { + + private IdpCertClientProvider idpCertClientProvider; + private IdpCertStorageProvider idpCertStorageProvider; + private final IdpCertStorageConfig storageConfig; + + @Inject + public IdpCertProviderFactoryImpl( + IdpCertStorageProvider idpCertStorageProvider, + IdpCertClientProvider idpCertClientProvider, + IdpCertStorageConfig storageConfig) { + this.idpCertClientProvider = idpCertClientProvider; + this.idpCertStorageProvider = idpCertStorageProvider; + this.storageConfig = storageConfig; + } + + /** + * Factory for creating an instance of {@link IdpCertProvider} + * + * @return an instance of {@link IdpCertProviderImpl} + */ + @Override + public IdpCertProvider create() { + return new IdpCertProviderImpl( + idpCertClientProvider.provideClient(), + idpCertStorageProvider.provideStorage(storageConfig)); + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java deleted file mode 100644 index c72c7da6..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java +++ /dev/null @@ -1,18 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.idp.impl; - -import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; -import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; -import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; -import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageProvider; - -public class IdpCertProviderFactoryImplStub implements IdpCertProviderFactory { - - private IdpCertClientProvider idpCertClientProvider; - private IdpCertStorageProvider idpCertStorageProvider; - - @Override - public IdpCertProvider create() { - return null; - } -} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java new file mode 100644 index 00000000..e993f96d --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java @@ -0,0 +1,70 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.impl; + +import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import java.util.List; +import javax.inject.Inject; + +public class IdpCertProviderImpl implements IdpCertProvider { + + private IdpCertClient idpCertClient; + private IdpCertStorage idpCertStorage; + + @Inject + public IdpCertProviderImpl(IdpCertClient idpCertClient, IdpCertStorage idpCertStorage) { + this.idpCertClient = idpCertClient; + this.idpCertStorage = idpCertStorage; + } + + /** + * {@inheritDoc} + * + *

Retrieve the Identity Provider Certification Data, first looking in the storage if enabled + * ({@link IdpCertStorageConfig}) and then, if not found, through the client {@link + * IdpCertClient}. If the storage is enabled ({@link IdpCertStorageConfig}) the IdpCertData will + * be stored, after being retrieved by the client. + * + * @param assertionInstant Assertion Issue Instant found in the xml + * @param entityId Entity ID of the identity provider found in the assertion + * @return List a list of idp cert data + * @throws CertDataTagListNotFoundException + * @throws CertDataNotFoundException + */ + @Override + public List getIdpCertData(String assertionInstant, String entityId) + throws CertDataTagListNotFoundException, CertDataNotFoundException { + if (assertionInstant == null + || assertionInstant.isBlank() + || entityId == null + || entityId.isBlank()) { + String errMsg = + String.format( + "Cannot retrieve the identity provider cert data, assertion instant" + + " [%s] or entity id [%s] missing", + assertionInstant, entityId); + throw new IllegalArgumentException(errMsg); + } + + List listIdpCertData = idpCertStorage.getIdpCertData(assertionInstant); + + if (listIdpCertData != null && listIdpCertData.size() > 0) { + return listIdpCertData; + } + + listIdpCertData = idpCertClient.getCertData(entityId, assertionInstant); + + if (listIdpCertData == null || listIdpCertData.size() > 0) { + return null; + } + + idpCertStorage.saveIdpCertData(assertionInstant, listIdpCertData); + + return listIdpCertData; + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java deleted file mode 100644 index b6df7d6f..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java +++ /dev/null @@ -1,17 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.idp.impl; - -import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; -import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; -import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; - -public class IdpCertProviderImplStub implements IdpCertProvider { - - private IdpCertClient idpCertClient; - private IdpCertStorage idpCertStorage; - - @Override - public boolean getIdpCertData(String assertionInstant, String entityId) { - return false; - } -} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java index 6226daf2..aa4425b6 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java @@ -4,13 +4,25 @@ import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import java.util.List; +/** + * Interface of the storage used for storing the identity provider certification data retrieved for + * validation + */ public interface IdpCertStorage { - List getTagList(); + /** + * Retrieve the idp cert data associated with the provided tag + * + * @param tag + * @return the list of idpCertData found + */ + List getIdpCertData(String tag); - void saveTagList(List tagList); - - IdpCertData getIdpCertData(String tag); - - void saveIdpCertData(String tag); + /** + * Store the provided idpCertData + * + * @param tag the idpCertData issue instance + * @param idpCertData + */ + void saveIdpCertData(String tag, List idpCertData); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageConfig.java new file mode 100644 index 00000000..f6fe13a4 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageConfig.java @@ -0,0 +1,14 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.storage; + +import java.util.concurrent.TimeUnit; +import lombok.Data; + +/** Configuration class for the idpCertData storage */ +@Data +public class IdpCertStorageConfig { + + private boolean idpCertDataStorageEnabled = true; + private long storageEvictionDelay = 1L; + private TimeUnit storageEvictionDelayTimeUnit = TimeUnit.MINUTES; +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageProvider.java index 3f045332..c73d835a 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageProvider.java @@ -1,7 +1,11 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.storage; +/** Interface for the provider used to create instances of {@link IdpCertStorage} */ public interface IdpCertStorageProvider { - IdpCertStorage provideStorage(); + /** + * @return instance of {@link IdpCertStorage} + */ + IdpCertStorage provideStorage(IdpCertStorageConfig storageConfig); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorage.java new file mode 100644 index 00000000..f26d8184 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorage.java @@ -0,0 +1,104 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.storage; + +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import javax.inject.Inject; + +/** + * Implementation of the {@link IdpCertStorage} interface as a simple in memory storage. + * + *

The storage can be configured via the {@link IdpCertStorageConfig} configuration class. + * + *

It store in a in memory {@link java.util.HashMap} the assertions and the associated scheduled + * eviction operations, every time an assertion is accessed the associated eviction operation is + * rescheduled. + */ +public class SimpleIdpCertStorage implements IdpCertStorage { + + private final Map> idpCertDataMap; + private final Map> scheduledEvictionsMap; + private final IdpCertStorageConfig storageConfig; + + @Inject + public SimpleIdpCertStorage( + Map> idpCertDataMap, + Map> scheduledEvictionsMap, + IdpCertStorageConfig storageConfig) { + this.idpCertDataMap = idpCertDataMap; + this.scheduledEvictionsMap = scheduledEvictionsMap; + this.storageConfig = storageConfig; + } + + /** + * Retrieve the idpCertData associated with the provided tag if the storage is enabled {@link + * IdpCertStorageConfig}, otherwise no operation is performed. + * + *

Before the list of idpCertData is returned the associated eviction operation is + * rescheduled with the delay configured via {@link IdpCertStorageConfig} + * + * @param tag the idpCertData issue instant + * @return the list of cert data if found, null if no cert data are present in the storage or + * the storage is disabled + */ + @Override + public List getIdpCertData(String tag) { + if (!storageConfig.isIdpCertDataStorageEnabled()) { + return null; + } + + List listIdpCertData = idpCertDataMap.get(tag); + if (listIdpCertData != null) { + delayEviction(tag); + } + return listIdpCertData; + } + + /** + * Store the idpCertData if the storage is enabled {@link IdpCertStorageConfig}, otherwise no + * operation is performed. + * + *

Once the idpCertData is stored an eviction operation is scheduled with a delay configured + * via {@link IdpCertStorageConfig} + * + * @param tag the idpCertData issue instant + * @param idpCertData + */ + @Override + public void saveIdpCertData(String tag, List idpCertData) { + if (!storageConfig.isIdpCertDataStorageEnabled()) { + return; + } + + idpCertDataMap.put(tag, idpCertData); + scheduleEviction(tag); + } + + private void scheduleEviction(String assertionRef) { + ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); + ScheduledFuture schedule = + executorService.schedule( + getEvictionTask(assertionRef), + storageConfig.getStorageEvictionDelay(), + storageConfig.getStorageEvictionDelayTimeUnit()); + scheduledEvictionsMap.put(assertionRef, schedule); + } + + private void delayEviction(String tag) { + ScheduledFuture schedule = scheduledEvictionsMap.get(tag); + schedule.cancel(false); + scheduledEvictionsMap.remove(tag); + scheduleEviction(tag); + } + + private Runnable getEvictionTask(String tag) { + return () -> { + idpCertDataMap.remove(tag); + scheduledEvictionsMap.remove(tag); + }; + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorageProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorageProvider.java new file mode 100644 index 00000000..632ea668 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorageProvider.java @@ -0,0 +1,19 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.storage; + +import java.util.HashMap; + +/** Implementation of {@link IdpCertStorageProvider} interface. It provides an instance of the */ +public class SimpleIdpCertStorageProvider implements IdpCertStorageProvider { + + /** + * {@inheritDoc} + * + * @param storageConfig the storage configuration + * @return an instance of {@link SimpleIdpCertStorage} + */ + @Override + public IdpCertStorage provideStorage(IdpCertStorageConfig storageConfig) { + return new SimpleIdpCertStorage(new HashMap<>(), new HashMap<>(), storageConfig); + } +} diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 5337fc06..2ce666da 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -245,14 +245,6 @@ - - - - - - - - @@ -345,14 +337,6 @@ - - - - - - - - @@ -377,9 +361,9 @@ + - From 2a2981132c43af5f5f8eb37cd75887006361cf03 Mon Sep 17 00:00:00 2001 From: svariant Date: Mon, 17 Apr 2023 17:25:15 +0200 Subject: [PATCH 210/403] [SLS-26] Moved identity provider storage implementation from core module to identity-service-rest-client-native --- .../idp/impl/IdpCertProviderImpl.java | 37 +++++++------------ .../consumer/idp/storage/IdpCertStorage.java | 5 +-- .../client/simple/IdpCertSimpleClient.java | 33 +++++++++++++++-- .../simple/IdpCertSimpleClientProvider.java | 8 +++- .../simple}/storage/SimpleIdpCertStorage.java | 19 +++++----- .../storage/SimpleIdpCertStorageProvider.java | 5 ++- .../java/simple/IdpCertSimpleClientTest.java | 9 ++++- 7 files changed, 73 insertions(+), 43 deletions(-) rename {core/src/main/java/it/pagopa/tech/lollipop/consumer/idp => identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple}/storage/SimpleIdpCertStorage.java (85%) rename {core/src/main/java/it/pagopa/tech/lollipop/consumer/idp => identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple}/storage/SimpleIdpCertStorageProvider.java (66%) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java index e993f96d..3c952905 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java @@ -25,16 +25,19 @@ public IdpCertProviderImpl(IdpCertClient idpCertClient, IdpCertStorage idpCertSt /** * {@inheritDoc} * - *

Retrieve the Identity Provider Certification Data, first looking in the storage if enabled - * ({@link IdpCertStorageConfig}) and then, if not found, through the client {@link - * IdpCertClient}. If the storage is enabled ({@link IdpCertStorageConfig}) the IdpCertData will - * be stored, after being retrieved by the client. + *

Retrieve the certification data of the given entityId issued in the same timeframe as the + * issue instant of the SAML assertion, first looking in the storage if enabled ({@link + * IdpCertStorageConfig}) and then, if not found, through the client {@link IdpCertClient}. If + * the storage is enabled ({@link IdpCertStorageConfig}) the IdpCertData will be stored, after + * being retrieved by the client. * - * @param assertionInstant Assertion Issue Instant found in the xml - * @param entityId Entity ID of the identity provider found in the assertion - * @return List a list of idp cert data - * @throws CertDataTagListNotFoundException - * @throws CertDataNotFoundException + * @param entityId Identity Provider ID + * @param assertionInstant Assertion Issue Instant + * @return the certifications issued before and after the timestamp instant + * @throws CertDataTagListNotFoundException if an error occurred retrieving the list of tags or + * filtering the tags with the instant + * @throws CertDataNotFoundException if an error occurred retrieving the certification XML or if + * data for the given entityId were not found */ @Override public List getIdpCertData(String assertionInstant, String entityId) @@ -51,20 +54,6 @@ public List getIdpCertData(String assertionInstant, String entityId throw new IllegalArgumentException(errMsg); } - List listIdpCertData = idpCertStorage.getIdpCertData(assertionInstant); - - if (listIdpCertData != null && listIdpCertData.size() > 0) { - return listIdpCertData; - } - - listIdpCertData = idpCertClient.getCertData(entityId, assertionInstant); - - if (listIdpCertData == null || listIdpCertData.size() > 0) { - return null; - } - - idpCertStorage.saveIdpCertData(assertionInstant, listIdpCertData); - - return listIdpCertData; + return idpCertClient.getCertData(assertionInstant, entityId); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java index aa4425b6..ef2f827a 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java @@ -2,7 +2,6 @@ package it.pagopa.tech.lollipop.consumer.idp.storage; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; -import java.util.List; /** * Interface of the storage used for storing the identity provider certification data retrieved for @@ -16,7 +15,7 @@ public interface IdpCertStorage { * @param tag * @return the list of idpCertData found */ - List getIdpCertData(String tag); + IdpCertData getIdpCertData(String tag); /** * Store the provided idpCertData @@ -24,5 +23,5 @@ public interface IdpCertStorage { * @param tag the idpCertData issue instance * @param idpCertData */ - void saveIdpCertData(String tag, List idpCertData); + void saveIdpCertData(String tag, IdpCertData idpCertData); } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 1b62a68c..1c2ee31d 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -9,6 +9,8 @@ import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.CertData; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.EntitiesDescriptor; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.EntityDescriptor; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import java.util.ArrayList; import java.util.Collections; @@ -20,16 +22,22 @@ public class IdpCertSimpleClient implements IdpCertClient { private final DefaultApi defaultApi; private final IdpCertSimpleClientConfig entityConfig; + private IdpCertStorage storage; @Inject - public IdpCertSimpleClient(ApiClient client, IdpCertSimpleClientConfig entityConfig) { + public IdpCertSimpleClient( + ApiClient client, IdpCertSimpleClientConfig entityConfig, IdpCertStorage storage) { this.defaultApi = new DefaultApi(client); this.entityConfig = entityConfig; + this.storage = storage; } /** * Retrieve the certification data of the given entityId issued in the same timeframe as the - * issue instant of the SAML assertion + * issue instant of the SAML assertion, first looking in the storage if enabled ({@link + * IdpCertStorageConfig}) and then, if not found, through the client {@link IdpCertClient}. If + * the storage is enabled ({@link IdpCertStorageConfig}) the IdpCertData will be stored, after + * being retrieved by the client. * * @param entityId Identity Provider ID * @param instant Assertion Issue Instant @@ -61,7 +69,14 @@ public List getCertData(String entityId, String instant) for (String tag : tagList) { try { - IdpCertData certData = getCIECertData(tag, entityId); + String storageTag = codifyStorageTag(tag, entityId); + IdpCertData certData = storage.getIdpCertData(storageTag); + + if (certData == null) { + certData = getCIECertData(tag, entityId); + } else { + storage.saveIdpCertData(storageTag, certData); + } listCertData.add(certData); } catch (ApiException | EntityIdNotFoundException e) { @@ -85,8 +100,14 @@ public List getCertData(String entityId, String instant) for (String tag : tagList) { try { - IdpCertData certData = getSPIDCertData(tag, entityId); + String storageTag = codifyStorageTag(tag, entityId); + IdpCertData certData = storage.getIdpCertData(codifyStorageTag(tag, entityId)); + if (certData == null) { + certData = getSPIDCertData(tag, entityId); + } else { + storage.saveIdpCertData(storageTag, certData); + } listCertData.add(certData); } catch (ApiException | EntityIdNotFoundException e) { throw new CertDataNotFoundException( @@ -211,4 +232,8 @@ private List getTagsFromInstant(List tagList, String instant) return newTagList; } + + private String codifyStorageTag(String tag, String entityId) { + return tag + entityId; + } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java index 6a292a71..6a9f5ba1 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java @@ -4,6 +4,8 @@ import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.storage.SimpleIdpCertStorageProvider; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; import javax.inject.Inject; /** Provider class for retrieving an instance of {@link IdpCertSimpleClient} */ @@ -22,6 +24,10 @@ public IdpCertSimpleClientProvider(IdpCertSimpleClientConfig config) { */ @Override public IdpCertClient provideClient() { - return new IdpCertSimpleClient(new ApiClient(this.idpClientConfig), this.idpClientConfig); + SimpleIdpCertStorageProvider storageProvider = new SimpleIdpCertStorageProvider(); + return new IdpCertSimpleClient( + new ApiClient(this.idpClientConfig), + this.idpClientConfig, + storageProvider.provideStorage(new IdpCertStorageConfig())); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorage.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorage.java similarity index 85% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorage.java rename to identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorage.java index f26d8184..69cc2826 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorage.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorage.java @@ -1,8 +1,9 @@ /* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.idp.storage; +package it.pagopa.tech.lollipop.consumer.idp.client.simple.storage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; -import java.util.List; import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -20,13 +21,13 @@ */ public class SimpleIdpCertStorage implements IdpCertStorage { - private final Map> idpCertDataMap; + private final Map idpCertDataMap; private final Map> scheduledEvictionsMap; private final IdpCertStorageConfig storageConfig; @Inject public SimpleIdpCertStorage( - Map> idpCertDataMap, + Map idpCertDataMap, Map> scheduledEvictionsMap, IdpCertStorageConfig storageConfig) { this.idpCertDataMap = idpCertDataMap; @@ -46,16 +47,16 @@ public SimpleIdpCertStorage( * the storage is disabled */ @Override - public List getIdpCertData(String tag) { + public IdpCertData getIdpCertData(String tag) { if (!storageConfig.isIdpCertDataStorageEnabled()) { return null; } - List listIdpCertData = idpCertDataMap.get(tag); - if (listIdpCertData != null) { + IdpCertData idpCertData = idpCertDataMap.get(tag); + if (idpCertData != null) { delayEviction(tag); } - return listIdpCertData; + return idpCertData; } /** @@ -69,7 +70,7 @@ public List getIdpCertData(String tag) { * @param idpCertData */ @Override - public void saveIdpCertData(String tag, List idpCertData) { + public void saveIdpCertData(String tag, IdpCertData idpCertData) { if (!storageConfig.isIdpCertDataStorageEnabled()) { return; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorageProvider.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorageProvider.java similarity index 66% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorageProvider.java rename to identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorageProvider.java index 632ea668..710f5787 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorageProvider.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorageProvider.java @@ -1,6 +1,9 @@ /* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.idp.storage; +package it.pagopa.tech.lollipop.consumer.idp.client.simple.storage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageProvider; import java.util.HashMap; /** Implementation of {@link IdpCertStorageProvider} interface. It provides an instance of the */ diff --git a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java index 20a12462..eee7c6a6 100644 --- a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java @@ -6,6 +6,8 @@ import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.storage.SimpleIdpCertStorageProvider; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import java.time.Instant; import java.util.List; @@ -31,7 +33,12 @@ class IdpCertSimpleClientTest { public static void startServer() { entityConfig = Mockito.spy(IdpCertSimpleClientConfig.builder().build()); ApiClient client = new ApiClient(entityConfig); - idpCertSimpleClient = new IdpCertSimpleClient(client, entityConfig); + SimpleIdpCertStorageProvider storageProvider = new SimpleIdpCertStorageProvider(); + idpCertSimpleClient = + new IdpCertSimpleClient( + client, + entityConfig, + storageProvider.provideStorage(new IdpCertStorageConfig())); } @Test From e9936ca669f8b7d1f149f4ddfb3c979cb461afcc Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Mon, 17 Apr 2023 20:07:34 +0200 Subject: [PATCH 211/403] [SLS-12] Introducing implementation of a spring interceptor using the lollipop verification function. Implemented skeleton for integration testing --- .../command/LollipopConsumerCommand.java | 4 +- .../LollipopConsumerCommandBuilder.java | 4 +- .../LollipopConsumerCommandBuilderImpl.java | 6 +- .../impl/LollipopConsumerCommandImpl.java | 9 +- .../config/LollipopConsumerRequestConfig.java | 4 + .../helper/LollipopConsumerFactoryHelper.java | 65 +- .../impl/LollipopConsumerCommandImplTest.java | 25 +- gradle/verification-metadata.xml | 1113 ++++++++++++++++- settings.gradle | 2 +- spring-impl/build.gradle | 33 + .../HttpVerifierHandlerInterceptor.java | 45 + .../config/HttpVerifierConfiguration.java | 50 + .../SpringLollipopConsumerRequestConfig.java | 12 + .../LollipopConsumerRequestConverter.java | 29 + ...fierHandlerInterceptorIntegrationTest.java | 114 ++ 15 files changed, 1472 insertions(+), 43 deletions(-) create mode 100644 spring-impl/build.gradle create mode 100644 spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java create mode 100644 spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java create mode 100644 spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java create mode 100644 spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java create mode 100644 spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java index 9bb161a6..bb8662c9 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java @@ -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 { @@ -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(); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java index 3031657a..eed04f74 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java @@ -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 { @@ -9,5 +11,5 @@ public interface LollipopConsumerCommandBuilder { * * @return an instance of {@link LollipopConsumerCommand} */ - LollipopConsumerCommand createCommand(); + LollipopConsumerCommand createCommand(LollipopConsumerRequest lollipopConsumerRequest); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java index 6c10346c..b1d0ee2e 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java @@ -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; /** @@ -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); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index 1ff773c0..fc56f264 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -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"; @@ -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); diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index d746503b..74ae215f 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -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; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index 7fee7de2..87434aa9 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -1,16 +1,17 @@ /* (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 */ @@ -18,16 +19,25 @@ 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; } /** @@ -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()); } /** @@ -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() { @@ -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; } } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java index 2b03d62c..18c673eb 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -35,7 +35,8 @@ void beforeAll() { new LollipopConsumerCommandImpl( messageVerifierServiceMock, assertionVerifierServiceMock, - requestValidationServiceMock)); + requestValidationServiceMock, + LollipopConsumerRequest.builder().build())); } @Test @@ -51,7 +52,7 @@ void failedHttpMessageValidationThrowDigestException() .when(messageVerifierServiceMock) .verifyHttpMessage(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( HttpMessageVerificationResultCode.DIGEST_VALIDATION_ERROR.name(), @@ -77,7 +78,7 @@ void failedHttpMessageValidationThrowSignatureException() .when(messageVerifierServiceMock) .verifyHttpMessage(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( HttpMessageVerificationResultCode.SIGNATURE_VALIDATION_ERROR.name(), @@ -98,7 +99,7 @@ void failedHttpMessageValidationThrowUnsupportedEncodingException() { .when(messageVerifierServiceMock) .verifyHttpMessage(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( HttpMessageVerificationResultCode.UNSUPPORTED_ENCODING.name(), @@ -122,7 +123,7 @@ void failedHttpMessageValidationWithoutThrowingException() .when(messageVerifierServiceMock) .verifyHttpMessage(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_FAILED.name(), @@ -149,7 +150,7 @@ void failedAssertionValidationWithoutThrowingException() .when(assertionVerifierServiceMock) .validateLollipop(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( AssertionVerificationResultCode.ASSERTION_VERIFICATION_FAILED.name(), @@ -175,7 +176,7 @@ void successLollipopRequestValidation() .when(assertionVerifierServiceMock) .validateLollipop(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals("SUCCESS", commandResult.getResultCode()); @@ -195,7 +196,7 @@ void failedLollipopRequestValidation() doThrow(LollipopRequestContentValidationException.class) .when(requestValidationServiceMock) .validateLollipopRequest(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals("REQUEST PARAMS VALIDATION FAILED", commandResult.getResultCode()); @@ -221,7 +222,7 @@ void failedAssertionValidationThrowErrorRetrievingAssertionException() .when(assertionVerifierServiceMock) .validateLollipop(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( AssertionVerificationResultCode.ERROR_RETRIEVING_ASSERTION.name(), @@ -247,7 +248,7 @@ void failedAssertionValidationThrowAssertionPeriodException() .when(assertionVerifierServiceMock) .validateLollipop(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( AssertionVerificationResultCode.PERIOD_VALIDATION_ERROR.name(), @@ -273,7 +274,7 @@ void failedAssertionValidationThrowAssertionThumbprintException() .when(assertionVerifierServiceMock) .validateLollipop(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( AssertionVerificationResultCode.THUMBPRINT_VALIDATION_ERROR.name(), @@ -299,7 +300,7 @@ void failedAssertionValidationThrowAssertionUserIdException() .when(assertionVerifierServiceMock) .validateLollipop(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( AssertionVerificationResultCode.USER_ID_VALIDATION_ERROR.name(), diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 5337fc06..8aeef21f 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -9,6 +9,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -113,6 +139,11 @@ + + + + + @@ -145,6 +176,11 @@ + + + + + @@ -183,6 +219,11 @@ + + + + + @@ -245,12 +286,15 @@ - - - + + + - - + + + + + @@ -299,6 +343,17 @@ + + + + + + + + + + + @@ -345,12 +400,15 @@ - - - + + + - - + + + + + @@ -377,9 +435,9 @@ + - @@ -388,6 +446,17 @@ + + + + + + + + + + + @@ -406,6 +475,17 @@ + + + + + + + + + + + @@ -429,6 +509,11 @@ + + + + + @@ -447,6 +532,17 @@ + + + + + + + + + + + @@ -455,6 +551,17 @@ + + + + + + + + + + + @@ -481,6 +588,22 @@ + + + + + + + + + + + + + + + + @@ -507,6 +630,14 @@ + + + + + + + + @@ -958,6 +1089,16 @@ + + + + + + + + + + @@ -978,6 +1119,14 @@ + + + + + + + + @@ -999,6 +1148,11 @@ + + + + + @@ -1079,6 +1233,14 @@ + + + + + + + + @@ -1163,6 +1325,16 @@ + + + + + + + + + + @@ -1205,6 +1377,16 @@ + + + + + + + + + + @@ -1215,6 +1397,14 @@ + + + + + + + + @@ -1225,6 +1415,14 @@ + + + + + + + + @@ -1235,6 +1433,14 @@ + + + + + + + + @@ -1245,6 +1451,14 @@ + + + + + + + + @@ -1255,6 +1469,14 @@ + + + + + + + + @@ -1265,6 +1487,14 @@ + + + + + + + + @@ -1275,6 +1505,14 @@ + + + + + + + + @@ -1285,12 +1523,25 @@ + + + + + + + + + + + + + @@ -1301,6 +1552,14 @@ + + + + + + + + @@ -1311,6 +1570,14 @@ + + + + + + + + @@ -1321,12 +1588,25 @@ + + + + + + + + + + + + + @@ -1337,6 +1617,14 @@ + + + + + + + + @@ -1347,12 +1635,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1363,6 +1680,19 @@ + + + + + + + + + + + + + @@ -1373,6 +1703,14 @@ + + + + + + + + @@ -1383,12 +1721,25 @@ + + + + + + + + + + + + + @@ -1399,6 +1750,14 @@ + + + + + + + + @@ -1409,6 +1768,14 @@ + + + + + + + + @@ -1419,6 +1786,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1697,6 +2092,14 @@ + + + + + + + + @@ -1707,6 +2110,19 @@ + + + + + + + + + + + + + @@ -1725,6 +2141,14 @@ + + + + + + + + @@ -1750,6 +2174,11 @@ + + + + + @@ -1854,6 +2283,14 @@ + + + + + + + + @@ -1864,6 +2301,14 @@ + + + + + + + + @@ -1880,6 +2325,11 @@ + + + + + @@ -1906,6 +2356,22 @@ + + + + + + + + + + + + + + + + @@ -1932,6 +2398,22 @@ + + + + + + + + + + + + + + + + @@ -1962,6 +2444,19 @@ + + + + + + + + + + + + + @@ -1997,6 +2492,11 @@ + + + + + @@ -2015,6 +2515,14 @@ + + + + + + + + @@ -2106,18 +2614,36 @@ + + + + + + + + + + + + + + + + + + @@ -2134,6 +2660,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2222,6 +2787,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -2290,6 +2879,14 @@ + + + + + + + + @@ -2306,6 +2903,11 @@ + + + + + @@ -2376,6 +2978,11 @@ + + + + + @@ -2480,6 +3087,11 @@ + + + + + @@ -2528,6 +3140,11 @@ + + + + + @@ -2609,6 +3226,21 @@ + + + + + + + + + + + + + + + @@ -2619,6 +3251,11 @@ + + + + + @@ -2691,6 +3328,11 @@ + + + + + @@ -2711,6 +3353,11 @@ + + + + + @@ -2720,6 +3367,11 @@ + + + + + @@ -2758,6 +3410,17 @@ + + + + + + + + + + + @@ -2806,6 +3469,17 @@ + + + + + + + + + + + @@ -2830,6 +3504,17 @@ + + + + + + + + + + + @@ -2854,6 +3539,17 @@ + + + + + + + + + + + @@ -2878,6 +3574,17 @@ + + + + + + + + + + + @@ -2898,6 +3605,17 @@ + + + + + + + + + + + @@ -2922,6 +3640,17 @@ + + + + + + + + + + + @@ -2942,6 +3671,17 @@ + + + + + + + + + + + @@ -3026,6 +3766,19 @@ + + + + + + + + + + + + + @@ -3036,6 +3789,14 @@ + + + + + + + + @@ -3072,6 +3833,14 @@ + + + + + + + + @@ -3082,6 +3851,11 @@ + + + + + @@ -3158,6 +3932,14 @@ + + + + + + + + @@ -3168,6 +3950,22 @@ + + + + + + + + + + + + + + + + @@ -3252,6 +4050,283 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3260,6 +4335,14 @@ + + + + + + + + @@ -3296,6 +4379,14 @@ + + + + + + + + diff --git a/settings.gradle b/settings.gradle index 8e918fab..0c7b9d75 100644 --- a/settings.gradle +++ b/settings.gradle @@ -29,4 +29,4 @@ gradleEnterprise { } rootProject.name = 'eng-lollipop-consumer-java-sdk' -include 'core', 'assertion-rest-client-native', 'http-verifier', 'identity-service-rest-client-native', 'redis-storage' +include 'core', 'assertion-rest-client-native', 'http-verifier', 'identity-service-rest-client-native', 'redis-storage', 'spring-impl' diff --git a/spring-impl/build.gradle b/spring-impl/build.gradle new file mode 100644 index 00000000..39bb999e --- /dev/null +++ b/spring-impl/build.gradle @@ -0,0 +1,33 @@ +plugins { + id 'java-library' + id("io.freefair.lombok") version "8.0.0" + id 'org.springframework.boot' version '2.7.10' + id 'io.spring.dependency-management' version '1.0.15.RELEASE' +} + +repositories { + mavenLocal() + mavenCentral() + maven { + url = uri("https://maven.pkg.github.com/pagopa/eng-http-signatures") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + } + } +} + +dependencies { + implementation project(':core') + implementation 'org.springframework.boot:spring-boot-starter-web:2.7.10' + testImplementation 'org.springframework.boot:spring-boot-starter-test:2.7.10' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2' + testImplementation project(':http-verifier') + testImplementation project(':assertion-rest-client-native') + testImplementation project(':identity-service-rest-client-native') +} + +tasks.named('test') { + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java new file mode 100644 index 00000000..14b796d8 --- /dev/null +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java @@ -0,0 +1,45 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring; + +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; +import it.pagopa.tech.lollipop.consumer.model.CommandResult; +import it.pagopa.tech.lollipop.consumer.spring.converter.LollipopConsumerRequestConverter; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.AllArgsConstructor; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.web.servlet.HandlerInterceptor; + +@AllArgsConstructor +public class HttpVerifierHandlerInterceptor implements HandlerInterceptor { + + private final LollipopConsumerCommandBuilder consumerCommandBuilder; + private static final Log log = LogFactory.getLog(HttpVerifierHandlerInterceptor.class); + + @Override + public boolean preHandle( + HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + + LollipopConsumerCommand lollipopConsumerCommand = + consumerCommandBuilder.createCommand( + LollipopConsumerRequestConverter.convert(request)); + + try { + CommandResult commandResult = lollipopConsumerCommand.doExecute(); + + if (commandResult.getResultCode().equals("KO")) { + response.sendError(401, commandResult.getResultMessage()); + } else { + return true; + } + + } catch (Exception e) { + log.error("Error verifying request", e); + } + + return false; + } +} diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java new file mode 100644 index 00000000..dd04f6e6 --- /dev/null +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java @@ -0,0 +1,50 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring.config; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; +import it.pagopa.tech.lollipop.consumer.command.impl.LollipopConsumerCommandBuilderImpl; +import it.pagopa.tech.lollipop.consumer.helper.LollipopConsumerFactoryHelper; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; +import it.pagopa.tech.lollipop.consumer.service.impl.LollipopConsumerRequestValidationServiceImpl; +import it.pagopa.tech.lollipop.consumer.spring.HttpVerifierHandlerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class HttpVerifierConfiguration { + + private SpringLollipopConsumerRequestConfig springLollipopConsumerRequestConfig; + + @Bean + public LollipopConsumerFactoryHelper lollipopConsumerFactoryHelper( + HttpMessageVerifierFactory httpMessageVerifierFactory, + IdpCertProviderFactory idpCertProviderFactory, + AssertionServiceFactory assertionServiceFactory) { + return new LollipopConsumerFactoryHelper( + httpMessageVerifierFactory, + idpCertProviderFactory, + assertionServiceFactory, + getLollipopConsumerRequestValidationService()); + } + + @Bean + public LollipopConsumerRequestValidationService getLollipopConsumerRequestValidationService() { + return new LollipopConsumerRequestValidationServiceImpl( + springLollipopConsumerRequestConfig); + } + + @Bean + public LollipopConsumerCommandBuilder lollipopConsumerCommandBuilder( + LollipopConsumerFactoryHelper lollipopConsumerFactoryHelper) { + return new LollipopConsumerCommandBuilderImpl(lollipopConsumerFactoryHelper); + } + + @Bean + public HttpVerifierHandlerInterceptor httpVerifierHandlerInterceptor( + LollipopConsumerCommandBuilder lollipopConsumerCommandBuilder) { + return new HttpVerifierHandlerInterceptor(lollipopConsumerCommandBuilder); + } +} diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java new file mode 100644 index 00000000..d8e2fa89 --- /dev/null +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java @@ -0,0 +1,12 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring.config; + +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import lombok.NoArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; + +@ConfigurationProperties(prefix = "lollipop.core.config") +@ConfigurationPropertiesScan +@NoArgsConstructor +public class SpringLollipopConsumerRequestConfig extends LollipopConsumerRequestConfig {} diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java new file mode 100644 index 00000000..2c26722e --- /dev/null +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java @@ -0,0 +1,29 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring.converter; + +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletRequest; +import org.springframework.util.StreamUtils; + +public class LollipopConsumerRequestConverter { + + public static LollipopConsumerRequest convert(HttpServletRequest httpServletRequest) + throws IOException { + + byte[] requestBody; + + InputStream requestInputStream = httpServletRequest.getInputStream(); + requestBody = StreamUtils.copyToByteArray(requestInputStream); + + return LollipopConsumerRequest.builder() + .requestBody(new String(requestBody)) + .headerParams( + Collections.list(httpServletRequest.getHeaderNames()).stream() + .collect(Collectors.toMap(h -> h, httpServletRequest::getHeader))) + .build(); + } +} diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java new file mode 100644 index 00000000..5976a207 --- /dev/null +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java @@ -0,0 +1,114 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientConfig; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.assertion.impl.AssertionServiceFactoryImpl; +import it.pagopa.tech.lollipop.consumer.assertion.storage.SimpleAssertionStorageProvider; +import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.http_verifier.visma.VismaHttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImplStub; +import it.pagopa.tech.lollipop.consumer.spring.config.HttpVerifierConfiguration; +import it.pagopa.tech.lollipop.consumer.spring.config.SpringLollipopConsumerRequestConfig; +import java.security.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.web.filter.CommonsRequestLoggingFilter; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration( + classes = { + HttpVerifierHandlerInterceptor.class, + SpringLollipopConsumerRequestConfig.class, + HttpVerifierConfiguration.class, + HttpVerifierHandlerInterceptorIntegrationTest.DemoServicesConfig.class + }) +public class HttpVerifierHandlerInterceptorIntegrationTest { + + // @Autowired + // private DemoController controller; + // + // @LocalServerPort + // private int port; + // + // @Controller + // public static class DemoController { + // + // @PostMapping("/") + // public @ResponseBody + // String testMethod() { + // return "Test!"; + // } + // + // } + + @Autowired private HttpVerifierHandlerInterceptor interceptor; + + @Configuration + public static class DemoServicesConfig { + + @Bean + public SpringLollipopConsumerRequestConfig verifierConfiguration() { + return new SpringLollipopConsumerRequestConfig(); + } + + @Bean + public HttpMessageVerifierFactory httpMessageVerifierFactory() throws Exception { + return new VismaHttpMessageVerifierFactory("UTF-8", verifierConfiguration()); + } + + @Bean + public IdpCertProviderFactory idpCertProviderFactory() { + return new IdpCertProviderFactoryImplStub(); + } + + @Bean + public AssertionServiceFactory assertionServiceFactory() { + return new AssertionServiceFactoryImpl( + new SimpleAssertionStorageProvider(), + new AssertionSimpleClientProvider( + AssertionSimpleClientConfig.builder().build()), + storageConfig()); + } + + @Bean + public StorageConfig storageConfig() { + return new StorageConfig(); + } + } + + @Component + public static class DemoWebConfigurer implements WebMvcConfigurer { + + @Autowired private HttpVerifierHandlerInterceptor interceptor; + + @Bean + public CommonsRequestLoggingFilter loggingFilter() { + CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter(); + filter.setIncludeQueryString(true); + filter.setIncludeClientInfo(true); + filter.setIncludeHeaders(true); + filter.setIncludePayload(true); + return filter; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(interceptor); + } + } + + @Test + public void something() {} +} From 6f363c114a1dfd659200e4f60d492b3008c79355 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 18 Apr 2023 10:11:44 +0200 Subject: [PATCH 212/403] [SLS-26] Defined unit tests for SimpleIdpCertStorage - added 2 tests to IdpCertSimpleClientTest --- .../simple/IdpCertSimpleClientTest.java | 18 ++- .../storage/SimpleIdpCertStorageTest.java | 135 ++++++++++++++++++ 2 files changed, 150 insertions(+), 3 deletions(-) rename identity-service-rest-client-native/src/test/java/{ => it/pagopa/tech/lollipop/consumer/idp/client}/simple/IdpCertSimpleClientTest.java (86%) create mode 100644 identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorageTest.java diff --git a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java similarity index 86% rename from identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java rename to identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java index eee7c6a6..79427af9 100644 --- a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java @@ -1,10 +1,8 @@ /* (C)2023 */ -package simple; +package it.pagopa.tech.lollipop.consumer.idp.client.simple; import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; -import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClient; -import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.storage.SimpleIdpCertStorageProvider; import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; @@ -75,4 +73,18 @@ void getCIECertDataWrongInstant() { CertDataTagListNotFoundException.class, () -> idpCertSimpleClient.getCertData(CIE_ENTITY_ID, WRONG_INSTANT)); } + + @Test + void entityIdNull() { + Assertions.assertThrows( + IllegalArgumentException.class, + () -> idpCertSimpleClient.getCertData(null, WRONG_INSTANT)); + } + + @Test + void instantNull() { + Assertions.assertThrows( + IllegalArgumentException.class, + () -> idpCertSimpleClient.getCertData(CIE_ENTITY_ID, null)); + } } diff --git a/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorageTest.java b/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorageTest.java new file mode 100644 index 00000000..e189d7eb --- /dev/null +++ b/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorageTest.java @@ -0,0 +1,135 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.storage; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.*; +import lombok.SneakyThrows; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class SimpleIdpCertStorageTest { + + private static final long EVICTION_DELAY = 5000L; + private static IdpCertStorageConfig storageConfigMock; + private IdpCertStorage sut; + private static final String IDPCERTDATA_1 = "1680691737https://posteid.poste.it"; + + @BeforeEach + void setUp() { + storageConfigMock = mock(IdpCertStorageConfig.class); + doReturn(EVICTION_DELAY).when(storageConfigMock).getStorageEvictionDelay(); + doReturn(TimeUnit.MILLISECONDS).when(storageConfigMock).getStorageEvictionDelayTimeUnit(); + } + + @Test + void getExistingAssertionAndResetScheduleEvictionWithStorageEnabled() + throws InterruptedException, ExecutionException { + doReturn(true).when(storageConfigMock).isIdpCertDataStorageEnabled(); + + Map idpCertDataMap = new HashMap<>(); + IdpCertData idpCertData = new IdpCertData(); + idpCertDataMap.put(IDPCERTDATA_1, idpCertData); + Map> scheduledEvictionsMap = new HashMap<>(); + ScheduledFuture scheduledFutureMock = mock(ScheduledFuture.class); + scheduledEvictionsMap.put(IDPCERTDATA_1, scheduledFutureMock); + + sut = new SimpleIdpCertStorage(idpCertDataMap, scheduledEvictionsMap, storageConfigMock); + + IdpCertData result = sut.getIdpCertData(IDPCERTDATA_1); + + assertNotNull(result); + assertEquals(idpCertData, result); + assertEquals(1, scheduledEvictionsMap.size()); + + CompletableFuture future = waitEvictionEnd(scheduledEvictionsMap); + assertEquals(true, future.get()); + assertEquals(0, idpCertDataMap.size()); + assertEquals(0, scheduledEvictionsMap.size()); + } + + @Test + void getNotExistingAssertionWithStorageEnabled() { + doReturn(true).when(storageConfigMock).isIdpCertDataStorageEnabled(); + + sut = new SimpleIdpCertStorage(new HashMap<>(), new HashMap<>(), storageConfigMock); + + IdpCertData result = sut.getIdpCertData(IDPCERTDATA_1); + + assertNull(result); + } + + @Test + void saveAssertionAndScheduleEvictionWithStorageEnabled() + throws InterruptedException, ExecutionException { + doReturn(true).when(storageConfigMock).isIdpCertDataStorageEnabled(); + + Map idpCertDataMap = new HashMap<>(); + Map> scheduledEvictionsMap = new HashMap<>(); + + sut = new SimpleIdpCertStorage(idpCertDataMap, scheduledEvictionsMap, storageConfigMock); + IdpCertData idpCertData = new IdpCertData(); + + sut.saveIdpCertData(IDPCERTDATA_1, idpCertData); + + assertEquals(1, idpCertDataMap.size()); + assertEquals(1, scheduledEvictionsMap.size()); + assertEquals(idpCertData, idpCertDataMap.get(IDPCERTDATA_1)); + + CompletableFuture future = waitEvictionEnd(scheduledEvictionsMap); + assertEquals(true, future.get()); + assertEquals(0, idpCertDataMap.size()); + assertEquals(0, scheduledEvictionsMap.size()); + } + + @Test + void getAssertionWithStorageDisabled() { + doReturn(false).when(storageConfigMock).isIdpCertDataStorageEnabled(); + + sut = new SimpleIdpCertStorage(new HashMap<>(), new HashMap<>(), storageConfigMock); + + IdpCertData result = sut.getIdpCertData(IDPCERTDATA_1); + + assertNull(result); + } + + @Test + void savaAssertionWithStorageDisabled() { + doReturn(false).when(storageConfigMock).isIdpCertDataStorageEnabled(); + + Map idpCertDataMap = new HashMap<>(); + Map> scheduledEvictionsMap = new HashMap<>(); + + sut = new SimpleIdpCertStorage(idpCertDataMap, scheduledEvictionsMap, storageConfigMock); + + sut.saveIdpCertData(IDPCERTDATA_1, new IdpCertData()); + + assertEquals(0, idpCertDataMap.size()); + assertEquals(0, scheduledEvictionsMap.size()); + } + + private CompletableFuture waitEvictionEnd( + Map> scheduledEvictionsMap) { + CompletableFuture future = new CompletableFuture<>(); + ExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); + executorService.submit( + new Runnable() { + @SneakyThrows + @Override + public void run() { + ScheduledFuture scheduledFuture = + scheduledEvictionsMap.get(IDPCERTDATA_1); + scheduledFuture.get(); + future.complete(true); + } + }); + return future; + } +} From 06c493bac4b6d63d29898f20afd1b038ca8af1f9 Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Tue, 18 Apr 2023 15:13:37 +0200 Subject: [PATCH 213/403] Update pr_scan.yml --- .github/workflows/pr_scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 5cdac27b..6b9379a3 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -8,7 +8,7 @@ env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_ACTOR: ${{ secrets.GITHUB_ACTOR }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - PROJECT_KEY: 'pagopa.eng-lollipop-consumer-java-sdk' + PROJECT_KEY: 'pagopa_eng-lollipop-consumer-java-sdk' jobs: pr_scan: From 9de2940a8b37d80210c24b28541bdb0071d03255 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 18 Apr 2023 16:05:53 +0200 Subject: [PATCH 214/403] [SLS-26] Removed storage injection from IdpCertProvider --- .../idp/impl/IdpCertProviderFactoryImpl.java | 17 +++-------------- .../consumer/idp/impl/IdpCertProviderImpl.java | 5 +---- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImpl.java index 82ace7bf..121da224 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImpl.java @@ -4,8 +4,6 @@ import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; -import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; -import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageProvider; import javax.inject.Inject; /** @@ -14,18 +12,11 @@ */ public class IdpCertProviderFactoryImpl implements IdpCertProviderFactory { - private IdpCertClientProvider idpCertClientProvider; - private IdpCertStorageProvider idpCertStorageProvider; - private final IdpCertStorageConfig storageConfig; + private final IdpCertClientProvider idpCertClientProvider; @Inject - public IdpCertProviderFactoryImpl( - IdpCertStorageProvider idpCertStorageProvider, - IdpCertClientProvider idpCertClientProvider, - IdpCertStorageConfig storageConfig) { + public IdpCertProviderFactoryImpl(IdpCertClientProvider idpCertClientProvider) { this.idpCertClientProvider = idpCertClientProvider; - this.idpCertStorageProvider = idpCertStorageProvider; - this.storageConfig = storageConfig; } /** @@ -35,8 +26,6 @@ public IdpCertProviderFactoryImpl( */ @Override public IdpCertProvider create() { - return new IdpCertProviderImpl( - idpCertClientProvider.provideClient(), - idpCertStorageProvider.provideStorage(storageConfig)); + return new IdpCertProviderImpl(idpCertClientProvider.provideClient()); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java index 3c952905..8e269ca3 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java @@ -5,7 +5,6 @@ import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; -import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import java.util.List; @@ -14,12 +13,10 @@ public class IdpCertProviderImpl implements IdpCertProvider { private IdpCertClient idpCertClient; - private IdpCertStorage idpCertStorage; @Inject - public IdpCertProviderImpl(IdpCertClient idpCertClient, IdpCertStorage idpCertStorage) { + public IdpCertProviderImpl(IdpCertClient idpCertClient) { this.idpCertClient = idpCertClient; - this.idpCertStorage = idpCertStorage; } /** From 53b2fc7235da49755532e69a837f2c38f3f763dd Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 18 Apr 2023 16:40:21 +0200 Subject: [PATCH 215/403] [SLS-12] Updated spring interceptor --- assertion-rest-client-native/build.gradle | 1 + .../simple/AssertionSimpleClientTest.java | 281 +---------------- .../AssertionSimpleClientTestUtils.java | 284 ++++++++++++++++++ .../impl/AssertionVerifierServiceImpl.java | 9 + ...pConsumerRequestValidationServiceImpl.java | 8 +- spring-impl/build.gradle | 4 +- .../HttpVerifierHandlerInterceptor.java | 2 +- .../config/HttpVerifierConfiguration.java | 3 +- .../AssertionSimpleClientTestUtils.java | 170 +++++++++++ .../consumer/spring/DemoApplication.java | 13 + ...fierHandlerInterceptorIntegrationTest.java | 150 ++++----- .../spring/config/DemoServicesConfig.java | 47 +++ .../spring/config/DemoWebConfigurer.java | 31 ++ .../spring/controller/DemoController.java | 15 + 14 files changed, 652 insertions(+), 366 deletions(-) create mode 100644 assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTestUtils.java create mode 100644 spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/AssertionSimpleClientTestUtils.java create mode 100644 spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/DemoApplication.java create mode 100644 spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java create mode 100644 spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoWebConfigurer.java create mode 100644 spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/controller/DemoController.java diff --git a/assertion-rest-client-native/build.gradle b/assertion-rest-client-native/build.gradle index b71cc6f4..37a69bc4 100644 --- a/assertion-rest-client-native/build.gradle +++ b/assertion-rest-client-native/build.gradle @@ -10,6 +10,7 @@ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' + id "java-test-fixtures" id("io.freefair.lombok") version "8.0.0" /*id("org.openapi.generator") version "6.5.0"*/ } diff --git a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java index de42da14..d887ed96 100644 --- a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java +++ b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java @@ -1,8 +1,8 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple; +import static it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientTestUtils.*; import static org.mockserver.integration.ClientAndServer.startClientAndServer; -import static org.mockserver.model.HttpRequest.request; import static org.mockserver.model.HttpResponse.response; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiClient; @@ -14,262 +14,13 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.mockito.Mockito; -import org.mockserver.client.MockServerClient; import org.mockserver.integration.ClientAndServer; -import org.mockserver.model.Header; class AssertionSimpleClientTest { private static AssertionSimpleClient assertionSimpleClient; private static AssertionSimpleClientConfig assertionConfig; private static ClientAndServer mockServer; - private static final String XML_STRING = - " https://posteid.poste.it" - + " " - + " " - + " " - + " " - + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" - + " " - + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" - + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" - + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" - + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" - + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " - + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" - + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" - + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" - + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" - + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" - + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" - + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" - + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" - + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" - + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" - + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" - + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" - + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" - + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" - + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" - + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" - + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" - + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" - + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" - + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" - + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" - + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" - + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" - + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" - + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" - + " " - + " " - + " https://posteid.poste.it " - + " " - + " " - + " " - + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" - + " " - + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" - + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" - + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" - + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" - + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " - + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" - + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" - + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" - + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" - + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" - + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" - + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" - + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" - + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" - + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" - + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" - + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" - + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" - + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" - + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" - + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" - + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" - + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" - + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" - + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" - + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" - + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" - + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" - + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" - + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" - + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" - + " " - + " " - + " " - + " https://app-backend.io.italia.it" - + " " - + " https://www.spid.gov.it/SpidL2" - + " " - + " " - + " " - + " TINIT-AAAAAA89S20I111X " - + " "; - private static final String RESPONSE_STRING = - "{\"response_xml\": \" " - + " https://posteid.poste.it" - + " " - + " " - + " " - + " " - + " " - + " " - + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" - + " " - + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" - + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" - + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" - + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" - + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " - + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" - + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" - + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" - + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" - + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" - + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" - + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" - + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" - + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" - + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" - + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" - + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" - + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" - + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" - + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" - + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" - + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" - + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" - + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" - + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" - + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" - + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" - + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" - + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" - + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" - + " " - + " " - + " " - + " https://posteid.poste.it " - + " " - + " " - + " " - + " " - + " " - + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" - + " " - + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" - + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" - + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" - + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" - + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " - + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" - + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" - + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" - + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" - + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" - + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" - + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" - + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" - + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" - + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" - + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" - + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" - + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" - + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" - + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" - + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" - + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" - + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" - + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" - + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" - + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" - + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" - + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" - + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" - + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" - + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" - + " " - + " " - + " " - + " https://app-backend.io.italia.it" - + " " - + " https://www.spid.gov.it/SpidL2" - + " " - + " " - + " TINIT-AAAAAA89S20I111X" - + " " - + " \"}"; - private static final String ASSERTION_REF = - "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; - private static final String WRONG_ASSERTION_REF = - "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfXXXXX"; - private static final String JWT = "Bearer aValidJWT"; @BeforeAll public static void startServer() { @@ -282,7 +33,7 @@ public static void startServer() { @Test void samlAssertionFound() throws LollipopAssertionNotFoundException, OidcAssertionNotSupported { - createExpectationAssertionFound(); + AssertionSimpleClientTestUtils.createExpectationAssertionFound(); SamlAssertion response = assertionSimpleClient.getAssertion(JWT, ASSERTION_REF); Assertions.assertNotNull(response); @@ -294,39 +45,13 @@ void samlAssertionFound() throws LollipopAssertionNotFoundException, OidcAsserti @Test void assertionNotFound() { - createExpectationAssertionNotFound(); + AssertionSimpleClientTestUtils.createExpectationAssertionNotFound(); // setup Assertions.assertThrows( LollipopAssertionNotFoundException.class, () -> assertionSimpleClient.getAssertion(JWT, WRONG_ASSERTION_REF)); } - private void createExpectationAssertionFound() { - new MockServerClient("localhost", 2000) - .when( - request() - .withMethod("GET") - .withPath("/assertions/{assertion}") - .withPathParameter("assertion", ASSERTION_REF) - .withHeaders( - new Header("Accept", "application/json"), - new Header("x-pagopa-lollipop-auth", JWT))) - .respond(response().withStatusCode(200).withBody(RESPONSE_STRING)); - } - - private void createExpectationAssertionNotFound() { - new MockServerClient("localhost", 2000) - .when( - request() - .withMethod("GET") - .withPath("/assertions/{assertion}") - .withPathParameter("assertion", WRONG_ASSERTION_REF) - .withHeaders( - new Header("Accept", "application/json"), - new Header("x-pagopa-lollipop-auth", JWT))) - .respond(response().withStatusCode(404).withBody("{}")); - } - @AfterAll public static void stopServer() { mockServer.stop(); diff --git a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTestUtils.java b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTestUtils.java new file mode 100644 index 00000000..48b2ef3d --- /dev/null +++ b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTestUtils.java @@ -0,0 +1,284 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.assertion.client.simple; + +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +import org.mockserver.client.MockServerClient; +import org.mockserver.model.Header; + +public class AssertionSimpleClientTestUtils { + + public static final String XML_STRING = + " https://posteid.poste.it" + + " " + + " " + + " " + + " " + + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" + + " " + + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" + + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" + + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" + + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" + + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " " + + " " + + " https://posteid.poste.it " + + " " + + " " + + " " + + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" + + " " + + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" + + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" + + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" + + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" + + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + " " + + " " + + " " + + " https://app-backend.io.italia.it" + + " " + + " https://www.spid.gov.it/SpidL2" + + " " + + " " + + " " + + " TINIT-AAAAAA89S20I111X " + + " "; + public static final String RESPONSE_STRING = + "{\"response_xml\": \" " + + " https://posteid.poste.it" + + " " + + " " + + " " + + " " + + " " + + " " + + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" + + " " + + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" + + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" + + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" + + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" + + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " " + + " " + + " " + + " https://posteid.poste.it " + + " " + + " " + + " " + + " " + + " " + + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" + + " " + + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" + + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" + + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" + + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" + + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + " " + + " " + + " " + + " https://app-backend.io.italia.it" + + " " + + " https://www.spid.gov.it/SpidL2" + + " " + + " " + + " TINIT-AAAAAA89S20I111X" + + " " + + " \"}"; + public static final String ASSERTION_REF = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; + public static final String WRONG_ASSERTION_REF = + "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfXXXXX"; + public static final String JWT = "Bearer aValidJWT"; + + public static void createExpectationAssertionFound() { + new MockServerClient("localhost", 2000) + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", JWT))) + .respond(response().withStatusCode(200).withBody(RESPONSE_STRING)); + } + + public static void createExpectationAssertionNotFound() { + new MockServerClient("localhost", 2000) + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", WRONG_ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", JWT))) + .respond(response().withStatusCode(404).withBody("{}")); + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index 14161ccf..c53e6c5b 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -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 { @@ -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()); diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java index 810b795c..e4712b83 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java @@ -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; @@ -30,7 +31,6 @@ public void validateLollipopRequest(LollipopConsumerRequest request) Map 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())); @@ -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( diff --git a/spring-impl/build.gradle b/spring-impl/build.gradle index 39bb999e..24995c0d 100644 --- a/spring-impl/build.gradle +++ b/spring-impl/build.gradle @@ -22,8 +22,10 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web:2.7.10' testImplementation 'org.springframework.boot:spring-boot-starter-test:2.7.10' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2' + //Mockserver for testing api + testImplementation 'org.mock-server:mockserver-netty:5.15.0' testImplementation project(':http-verifier') - testImplementation project(':assertion-rest-client-native') + testImplementation testFixtures(project(':assertion-rest-client-native')) testImplementation project(':identity-service-rest-client-native') } diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java index 14b796d8..6fa6871e 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java @@ -30,7 +30,7 @@ public boolean preHandle( try { CommandResult commandResult = lollipopConsumerCommand.doExecute(); - if (commandResult.getResultCode().equals("KO")) { + if (!commandResult.getResultCode().equals("SUCCESS")) { response.sendError(401, commandResult.getResultMessage()); } else { return true; diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java index dd04f6e6..faf81cc2 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java @@ -10,13 +10,14 @@ import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; import it.pagopa.tech.lollipop.consumer.service.impl.LollipopConsumerRequestValidationServiceImpl; import it.pagopa.tech.lollipop.consumer.spring.HttpVerifierHandlerInterceptor; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class HttpVerifierConfiguration { - private SpringLollipopConsumerRequestConfig springLollipopConsumerRequestConfig; + @Autowired private SpringLollipopConsumerRequestConfig springLollipopConsumerRequestConfig; @Bean public LollipopConsumerFactoryHelper lollipopConsumerFactoryHelper( diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/AssertionSimpleClientTestUtils.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/AssertionSimpleClientTestUtils.java new file mode 100644 index 00000000..baa87018 --- /dev/null +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/AssertionSimpleClientTestUtils.java @@ -0,0 +1,170 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring; + +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +import java.text.SimpleDateFormat; +import java.util.Date; +import org.mockserver.client.MockServerClient; +import org.mockserver.model.Header; + +public class AssertionSimpleClientTestUtils { + + public static final String RESPONSE_STRING = + "{\"response_xml\": \" " + + " https://posteid.poste.it" + + " " + + " " + + " " + + " " + + " " + + " " + + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" + + " " + + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" + + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" + + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" + + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" + + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " " + + " " + + " " + + " https://posteid.poste.it " + + " " + + " " + + " " + + " " + + " " + + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" + + " " + + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" + + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" + + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" + + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" + + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + " " + + " " + + " " + + " " + + " https://app-backend.io.italia.it" + + " " + + " https://www.spid.gov.it/SpidL2" + + " " + + " TINIT-AAAAAA89S20I111X" + + " " + + " \"}"; + public static final String ASSERTION_REF = "sha256-_ZzL8qeuAM5kQ9pbMB4tn7IDSQZCVXAkW9fm4P7ULPI"; + public static final String WRONG_ASSERTION_REF = + "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfXXXXX"; + public static final String JWT = "aValidJWT"; + + public static void createExpectationAssertionFound() { + new MockServerClient("localhost", 3000) + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", JWT))) + .respond(response().withStatusCode(200).withBody(RESPONSE_STRING)); + } + + public static void createExpectationAssertionNotFound() { + new MockServerClient("localhost", 2000) + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", WRONG_ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", JWT))) + .respond(response().withStatusCode(404).withBody("{}")); + } +} diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/DemoApplication.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/DemoApplication.java new file mode 100644 index 00000000..2608818e --- /dev/null +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/DemoApplication.java @@ -0,0 +1,13 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication(scanBasePackages = "it.pagopa.tech") +public class DemoApplication { + + public static void main(String[] args) { + SpringApplication.run(DemoApplication.class, args); + } +} diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java index 5976a207..2df74957 100644 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java @@ -1,114 +1,96 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.spring; -import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; -import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientConfig; -import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientProvider; -import it.pagopa.tech.lollipop.consumer.assertion.impl.AssertionServiceFactoryImpl; -import it.pagopa.tech.lollipop.consumer.assertion.storage.SimpleAssertionStorageProvider; -import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; -import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; -import it.pagopa.tech.lollipop.consumer.http_verifier.visma.VismaHttpMessageVerifierFactory; -import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; -import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImplStub; +import static org.mockserver.integration.ClientAndServer.startClientAndServer; + import it.pagopa.tech.lollipop.consumer.spring.config.HttpVerifierConfiguration; import it.pagopa.tech.lollipop.consumer.spring.config.SpringLollipopConsumerRequestConfig; -import java.security.*; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockserver.integration.ClientAndServer; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.stereotype.Component; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.web.filter.CommonsRequestLoggingFilter; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.client.RestTemplate; @ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ContextConfiguration( classes = { - HttpVerifierHandlerInterceptor.class, + DemoApplication.class, SpringLollipopConsumerRequestConfig.class, HttpVerifierConfiguration.class, - HttpVerifierHandlerInterceptorIntegrationTest.DemoServicesConfig.class }) public class HttpVerifierHandlerInterceptorIntegrationTest { - // @Autowired - // private DemoController controller; - // - // @LocalServerPort - // private int port; - // - // @Controller - // public static class DemoController { - // - // @PostMapping("/") - // public @ResponseBody - // String testMethod() { - // return "Test!"; - // } - // - // } + @LocalServerPort private int port; + @Autowired private TestRestTemplate restTemplate; - @Autowired private HttpVerifierHandlerInterceptor interceptor; + @BeforeAll + public static void startServer() { + mockServer = startClientAndServer(3000); + } - @Configuration - public static class DemoServicesConfig { + private static ClientAndServer mockServer; - @Bean - public SpringLollipopConsumerRequestConfig verifierConfiguration() { - return new SpringLollipopConsumerRequestConfig(); - } + @Autowired private HttpVerifierHandlerInterceptor interceptor; - @Bean - public HttpMessageVerifierFactory httpMessageVerifierFactory() throws Exception { - return new VismaHttpMessageVerifierFactory("UTF-8", verifierConfiguration()); - } + @Test + public void test() { + AssertionSimpleClientTestUtils.createExpectationAssertionFound(); - @Bean - public IdpCertProviderFactory idpCertProviderFactory() { - return new IdpCertProviderFactoryImplStub(); - } + String signatureInput = + "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + var signature = + "sig123=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; - @Bean - public AssertionServiceFactory assertionServiceFactory() { - return new AssertionServiceFactoryImpl( - new SimpleAssertionStorageProvider(), - new AssertionSimpleClientProvider( - AssertionSimpleClientConfig.builder().build()), - storageConfig()); - } + RestTemplate exec = restTemplate.getRestTemplate(); + exec.getClientHttpRequestInitializers() + .add( + request -> { + request.getHeaders() + .add( + "Content-Digest", + "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"); + request.getHeaders() + .add( + "x-pagopa-lollipop-original-url", + "https://api-app.io.pagopa.it/first-lollipop/sign"); + request.getHeaders().add("x-pagopa-lollipop-original-method", "POST"); + request.getHeaders() + .add( + "x-pagopa-lollipop-public-key", + "eyJrdHkiOiJFQyIsIngiOiJGcUZEd" + + "XdFZ3U0TVVYRVJQTVZMLTg1cEd2MkQzWW1MNEoxZ2ZNa2RiYzI0IiwieSI6Im" + + "hkVjBveG1XRlN4TW9KVURwZGlocjc2clM4VlJCRXFNRmViWXlBZks5LWsiLCJjcnYiO" + + "iJQLTI1NiJ9"); + request.getHeaders() + .add( + "x-pagopa-lollipop-assertion-ref", + "sha256-_ZzL8qeuAM5kQ9pbMB4tn7IDSQZCVXAkW9fm4P7ULPI"); + request.getHeaders().add("x-pagopa-lollipop-assertion-type", "SAML"); + request.getHeaders().add("x-pagopa-lollipop-auth-jwt", "aValidJWT"); + request.getHeaders() + .add("x-pagopa-lollipop-user-id", "AAAAAA89S20I111X"); + request.getHeaders().add("Signature-Input", signatureInput); + request.getHeaders().add("Signature", signature); + }); - @Bean - public StorageConfig storageConfig() { - return new StorageConfig(); - } + String response = + exec.postForObject( + "http://localhost:" + port, + "{\"message\":\"a valid message payload\"}", + String.class); } - @Component - public static class DemoWebConfigurer implements WebMvcConfigurer { - - @Autowired private HttpVerifierHandlerInterceptor interceptor; - - @Bean - public CommonsRequestLoggingFilter loggingFilter() { - CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter(); - filter.setIncludeQueryString(true); - filter.setIncludeClientInfo(true); - filter.setIncludeHeaders(true); - filter.setIncludePayload(true); - return filter; - } - - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(interceptor); - } + @AfterAll + public static void stopServer() { + mockServer.stop(); } - - @Test - public void something() {} } diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java new file mode 100644 index 00000000..e61a3308 --- /dev/null +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java @@ -0,0 +1,47 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring.config; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientConfig; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.assertion.impl.AssertionServiceFactoryImpl; +import it.pagopa.tech.lollipop.consumer.assertion.storage.SimpleAssertionStorageProvider; +import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.http_verifier.visma.VismaHttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImplStub; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class DemoServicesConfig { + + @Bean + public SpringLollipopConsumerRequestConfig verifierConfiguration() { + return new SpringLollipopConsumerRequestConfig(); + } + + @Bean + public HttpMessageVerifierFactory httpMessageVerifierFactory() throws Exception { + return new VismaHttpMessageVerifierFactory("UTF-8", verifierConfiguration()); + } + + @Bean + public IdpCertProviderFactory idpCertProviderFactory() { + return new IdpCertProviderFactoryImplStub(); + } + + @Bean + public AssertionServiceFactory assertionServiceFactory() { + return new AssertionServiceFactoryImpl( + new SimpleAssertionStorageProvider(), + new AssertionSimpleClientProvider(AssertionSimpleClientConfig.builder().build()), + storageConfig()); + } + + @Bean + public StorageConfig storageConfig() { + return new StorageConfig(); + } +} diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoWebConfigurer.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoWebConfigurer.java new file mode 100644 index 00000000..c45f4d01 --- /dev/null +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoWebConfigurer.java @@ -0,0 +1,31 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring.config; + +import it.pagopa.tech.lollipop.consumer.spring.HttpVerifierHandlerInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.CommonsRequestLoggingFilter; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Component +public class DemoWebConfigurer implements WebMvcConfigurer { + + @Autowired private HttpVerifierHandlerInterceptor interceptor; + + @Bean + public CommonsRequestLoggingFilter loggingFilter() { + CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter(); + filter.setIncludeQueryString(true); + filter.setIncludeClientInfo(true); + filter.setIncludeHeaders(true); + filter.setIncludePayload(true); + return filter; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(interceptor); + } +} diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/controller/DemoController.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/controller/DemoController.java new file mode 100644 index 00000000..3b8cb50d --- /dev/null +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/controller/DemoController.java @@ -0,0 +1,15 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class DemoController { + + @RequestMapping("/") + public @ResponseBody String test() { + return "Test"; + } +} From 89f1bd81190b82b03454acd921786cc4900c2cbf Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 18 Apr 2023 16:44:48 +0200 Subject: [PATCH 216/403] [SLS-26] Handled multiple idp certificate signatures - added unit test --- .../lollipop/consumer/model/IdpCertData.java | 3 +- .../client/simple/IdpCertSimpleClient.java | 2 +- .../internal/model/EntityDescriptor.java | 66 +++++++++++++------ .../simple/IdpCertSimpleClientTest.java | 11 ++++ 4 files changed, 60 insertions(+), 22 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java index 6c0aaa2e..12d0c7ab 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java @@ -1,6 +1,7 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.model; +import java.util.List; import lombok.Getter; import lombok.Setter; @@ -10,5 +11,5 @@ public class IdpCertData { private String entityId; private String tag; - private String certData; + private List certData; } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 1c2ee31d..e30a4a4a 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -168,7 +168,7 @@ private IdpCertData getEntityData(EntitiesDescriptor data, String tag, String en if (entity.getEntityID().equals(entityId)) { newData.setEntityId(entityId); newData.setTag(tag); - newData.setCertData(entity.getSignature()); + newData.setCertData(entity.getSignatureList()); return newData; } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java index f54361ce..8e8b7d1d 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java @@ -3,10 +3,8 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; +import java.util.stream.Collectors; import lombok.Getter; /** EntityDescriptor */ @@ -21,7 +19,7 @@ public class EntityDescriptor { @JsonProperty("entityID") private String entityID; - private String signature; + private List signatureList; /** * Methods that obtains the signature used for verify the user's assertion from a series of @@ -32,24 +30,52 @@ public class EntityDescriptor { @SuppressWarnings("unchecked") @JsonProperty("IDPSSODescriptor") private void unpackNestedSignature(Map signature) { - Map keyDescriptor = new HashMap<>(); + List> keyDescriptorsList = new ArrayList<>(); if (signature.get(KEY_DESCRIPTOR) instanceof List) { - List> listDescriptors = - (List>) signature.get(KEY_DESCRIPTOR); - Optional> optionalFirst = - listDescriptors.stream() - .filter(el -> el.get("use").equals("signing")) - .findFirst(); - - if (optionalFirst.isPresent()) { - keyDescriptor = optionalFirst.get(); - } + + keyDescriptorsList = + ((List>) signature.get(KEY_DESCRIPTOR)) + .stream() + .filter(el -> el.get("use").equals("signing")) + .collect(Collectors.toList()); } else { - keyDescriptor = (Map) signature.get(KEY_DESCRIPTOR); + Map keyDescriptorFound = + (Map) signature.get(KEY_DESCRIPTOR); + + if (keyDescriptorFound.get("use").equals("signing")) { + keyDescriptorsList.add(keyDescriptorFound); + } + } + + List> keyInfosList = new ArrayList<>(); + for (Map keyDescriptor : keyDescriptorsList) { + if (keyDescriptor.get(KEY_INFO) instanceof List) { + keyInfosList = (List>) keyDescriptor.get(KEY_INFO); + } else { + Map keyInfo = (Map) keyDescriptor.get(KEY_INFO); + + keyInfosList.add(keyInfo); + } + } + + List> listX509Data = new ArrayList<>(); + for (Map keyInfo : keyInfosList) { + if (keyInfo.get(X_509_DATA) instanceof List) { + listX509Data = (List>) keyInfo.get(X_509_DATA); + } else { + listX509Data.add((Map) keyInfo.get(X_509_DATA)); + } + } + + List signatureList = new ArrayList<>(); + for (Map x509Data : listX509Data) { + if (x509Data.get(X_509_CERTIFICATE) instanceof List) { + signatureList = (List) x509Data.get(X_509_CERTIFICATE); + } else { + signatureList.add((String) x509Data.get(X_509_CERTIFICATE)); + } } - Map keyInfo = (Map) keyDescriptor.get(KEY_INFO); - Map x509Data = (Map) keyInfo.get(X_509_DATA); - this.signature = (String) x509Data.get(X_509_CERTIFICATE); + this.signatureList = signatureList; } } diff --git a/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java index 79427af9..e4617299 100644 --- a/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java @@ -21,6 +21,7 @@ class IdpCertSimpleClientTest { private static final String INSTANT = String.valueOf(Instant.now().getEpochSecond()); private static final String SPID_ENTITY_ID = "https://posteid.poste.it"; + private static final String SPID_ENTITY_ID_MULTIPLE_SIGNATURE = "https://loginspid.aruba.it"; private static final String CIE_ENTITY_ID = "https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"; @@ -46,6 +47,16 @@ void certSPIDDataFound() throws CertDataTagListNotFoundException, CertDataNotFou Assertions.assertNotNull(response); } + @Test + void certSPIDDataFoundMultipleSignature() + throws CertDataTagListNotFoundException, CertDataNotFoundException { + List response = + idpCertSimpleClient.getCertData(SPID_ENTITY_ID_MULTIPLE_SIGNATURE, INSTANT); + + Assertions.assertNotNull(response); + Assertions.assertTrue(response.get(0).getCertData().size() > 1); + } + @Test void certCIEDataFound() throws CertDataTagListNotFoundException, CertDataNotFoundException { List response = idpCertSimpleClient.getCertData(CIE_ENTITY_ID, INSTANT); From e659146c1bfdc378f0eab79ec01d90e47adfb43d Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 18 Apr 2023 16:46:23 +0200 Subject: [PATCH 217/403] [SLS-33] Updated build.gradle --- build.gradle | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 28173590..24fffe1e 100644 --- a/build.gradle +++ b/build.gradle @@ -141,14 +141,14 @@ subprojects { } } } - subprojects { - sonar { - properties { - property "sonar.sources", "src" - } + + sonar { + properties { + property "sonar.sources", "src" } } + test { finalizedBy jacocoTestReport // report is always generated after tests run jacoco { From 1f6c275fa176c972c9f7198ef8080b2df6b66c1e Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 18 Apr 2023 17:01:32 +0200 Subject: [PATCH 218/403] [SLS-33] Updated pr_scan.yml --- .github/workflows/pr_scan.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 6b9379a3..7c4664c6 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -60,6 +60,8 @@ jobs: run: ./gradlew sonar -Dsonar.organization=pagopa -Dsonar.projectKey=${{ env.PROJECT_KEY }} + -Dsonar.coverage.jacoco.xmlReportPaths=./test-coverage/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml + -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*" -Dsonar.host.url=https://sonarcloud.io -Dsonar.login=${{ env.SONAR_TOKEN }} -Dsonar.pullrequest.key=${{ github.event.pull_request.number }} From aad00c2b35b797f490c89bbe310ab4b0dc40c560 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 18 Apr 2023 17:10:14 +0200 Subject: [PATCH 219/403] [SLS-33] Updated build.gradle --- redis-storage/build.gradle | 1 + test-coverage/build.gradle | 1 + 2 files changed, 2 insertions(+) diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle index dcab70e8..7b652d07 100644 --- a/redis-storage/build.gradle +++ b/redis-storage/build.gradle @@ -11,6 +11,7 @@ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' id("io.freefair.lombok") version "8.0.0" + id "org.sonarqube" version "3.5.0.2730" apply false } repositories { diff --git a/test-coverage/build.gradle b/test-coverage/build.gradle index 8a804e88..f8f830c1 100644 --- a/test-coverage/build.gradle +++ b/test-coverage/build.gradle @@ -1,6 +1,7 @@ plugins { id 'base' id 'jacoco-report-aggregation' + id "org.sonarqube" version "3.5.0.2730" apply false } repositories { From a2a41715c65ee37254b3feb16a1d80d46180c3a0 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 18 Apr 2023 17:23:00 +0200 Subject: [PATCH 220/403] [SLS-33] Updated build.gradle --- redis-storage/build.gradle | 1 - test-coverage/build.gradle | 1 - 2 files changed, 2 deletions(-) diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle index 7b652d07..dcab70e8 100644 --- a/redis-storage/build.gradle +++ b/redis-storage/build.gradle @@ -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.sonarqube" version "3.5.0.2730" apply false } repositories { diff --git a/test-coverage/build.gradle b/test-coverage/build.gradle index f8f830c1..8a804e88 100644 --- a/test-coverage/build.gradle +++ b/test-coverage/build.gradle @@ -1,7 +1,6 @@ plugins { id 'base' id 'jacoco-report-aggregation' - id "org.sonarqube" version "3.5.0.2730" apply false } repositories { From 6f6a100c04e870c7bac048a2e09a384b4a4daca2 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 18 Apr 2023 17:34:21 +0200 Subject: [PATCH 221/403] [SLS-33] Updated with src content for sonar scanner --- redis-storage/src/main/resources/dummydata | 0 test-coverage/src/main/resources/dummydata | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 redis-storage/src/main/resources/dummydata create mode 100644 test-coverage/src/main/resources/dummydata diff --git a/redis-storage/src/main/resources/dummydata b/redis-storage/src/main/resources/dummydata new file mode 100644 index 00000000..e69de29b diff --git a/test-coverage/src/main/resources/dummydata b/test-coverage/src/main/resources/dummydata new file mode 100644 index 00000000..e69de29b From 91d94b07d36d037ae1ed4c72f870487f07de195c Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 18 Apr 2023 17:43:03 +0200 Subject: [PATCH 222/403] [SLS-33] Updated build.gradle --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 24fffe1e..4b2615b9 100644 --- a/build.gradle +++ b/build.gradle @@ -144,7 +144,7 @@ subprojects { sonar { properties { - property "sonar.sources", "src" + property "sonar.sources", "src/main" } } From e30dec7d66dbf5ab1c1b23cfceb208fc2f8b7760 Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Tue, 18 Apr 2023 18:05:15 +0200 Subject: [PATCH 223/403] Update pr_scan.yml --- .github/workflows/pr_scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 7c4664c6..639b126c 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -57,7 +57,7 @@ jobs: with: sarif_file: ${{ steps.scan.outputs.sarif }} - name: Run Sonar Scanner - run: ./gradlew sonar + run: ./gradlew build sonarqube --info -Dsonar.organization=pagopa -Dsonar.projectKey=${{ env.PROJECT_KEY }} -Dsonar.coverage.jacoco.xmlReportPaths=./test-coverage/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml From a9214a1f56fe257a8776020ad529facdaa64d31b Mon Sep 17 00:00:00 2001 From: Alessio Cialini <63233981+alessio-cialini@users.noreply.github.com> Date: Tue, 18 Apr 2023 18:05:50 +0200 Subject: [PATCH 224/403] Update pr_scan.yml --- .github/workflows/pr_scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 639b126c..e6d85b15 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -60,7 +60,7 @@ jobs: run: ./gradlew build sonarqube --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/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*" -Dsonar.host.url=https://sonarcloud.io -Dsonar.login=${{ env.SONAR_TOKEN }} From a375fe17cb21a1689dbbd25e0c3a66573a4b9103 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 18 Apr 2023 19:17:40 +0200 Subject: [PATCH 225/403] [SLS-12] Updated tests an docs --- .../HttpVerifierHandlerInterceptor.java | 17 +++++- .../config/HttpVerifierConfiguration.java | 4 ++ .../SpringLollipopConsumerRequestConfig.java | 3 + .../LollipopConsumerRequestConverter.java | 21 +++++-- ...fierHandlerInterceptorIntegrationTest.java | 60 ++++++++++++++++++- 5 files changed, 96 insertions(+), 9 deletions(-) diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java index 6fa6871e..a79282be 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java @@ -12,16 +12,29 @@ import org.apache.commons.logging.LogFactory; import org.springframework.web.servlet.HandlerInterceptor; +import java.io.IOException; + +/** + * Instance of a Spring Http {@link HandlerInterceptor}, to be used for Lollipop Request validations + */ @AllArgsConstructor public class HttpVerifierHandlerInterceptor implements HandlerInterceptor { private final LollipopConsumerCommandBuilder consumerCommandBuilder; private static final Log log = LogFactory.getLog(HttpVerifierHandlerInterceptor.class); + /** + * + * @param request current HTTP request + * @param response current HTTP response + * @param handler chosen handler to execute, for type and/or instance evaluation + * @return boolean to determine if the handle completes successfully + * @throws IOException throws exception if the conversion of a http request fails + */ @Override public boolean preHandle( - HttpServletRequest request, HttpServletResponse response, Object handler) - throws Exception { + HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { + LollipopConsumerCommand lollipopConsumerCommand = consumerCommandBuilder.createCommand( diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java index faf81cc2..80ef1008 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java @@ -14,6 +14,10 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +/** + * Instance of Spring configuration of the core elements, the implementations of the related services + * are delegated to external configurations + */ @Configuration public class HttpVerifierConfiguration { diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java index d8e2fa89..d3a41677 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java @@ -6,6 +6,9 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationPropertiesScan; +/** + * Spring instance of the {@link LollipopConsumerRequestConfig} + */ @ConfigurationProperties(prefix = "lollipop.core.config") @ConfigurationPropertiesScan @NoArgsConstructor diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java index 2c26722e..d284a207 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java @@ -9,18 +9,31 @@ import javax.servlet.http.HttpServletRequest; import org.springframework.util.StreamUtils; +/** + * Class to be used for conversion of the http requests to be validated + */ public class LollipopConsumerRequestConverter { + /** + * Utility method to be used to generate a LollipopConsumerRequest + * @param httpServletRequest http request to be converted into a lollipop request + * @return instance of {@link LollipopConsumerRequest} produced from the httpServletRequest + * @throws IOException exception return if body extraction fails + */ public static LollipopConsumerRequest convert(HttpServletRequest httpServletRequest) throws IOException { - byte[] requestBody; + byte[] requestBody = null; - InputStream requestInputStream = httpServletRequest.getInputStream(); - requestBody = StreamUtils.copyToByteArray(requestInputStream); + String method = httpServletRequest.getMethod(); + + if (method != null && (!method.equals("GET") && !method.equals("DELETE"))) { + InputStream requestInputStream = httpServletRequest.getInputStream(); + requestBody = StreamUtils.copyToByteArray(requestInputStream); + } return LollipopConsumerRequest.builder() - .requestBody(new String(requestBody)) + .requestBody(requestBody != null ? new String(requestBody) : null) .headerParams( Collections.list(httpServletRequest.getHeaderNames()).stream() .collect(Collectors.toMap(h -> h, httpServletRequest::getHeader))) diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java index 2df74957..d15035b6 100644 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java @@ -6,6 +6,7 @@ import it.pagopa.tech.lollipop.consumer.spring.config.HttpVerifierConfiguration; import it.pagopa.tech.lollipop.consumer.spring.config.SpringLollipopConsumerRequestConfig; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -14,6 +15,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.http.ResponseEntity; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.web.client.RestTemplate; @@ -41,7 +43,7 @@ public static void startServer() { @Autowired private HttpVerifierHandlerInterceptor interceptor; @Test - public void test() { + public void testWithValidRequestReturnsSuccess() { AssertionSimpleClientTestUtils.createExpectationAssertionFound(); String signatureInput = @@ -82,11 +84,63 @@ public void test() { request.getHeaders().add("Signature", signature); }); - String response = - exec.postForObject( + ResponseEntity response = + exec.postForEntity( "http://localhost:" + port, "{\"message\":\"a valid message payload\"}", String.class); + Assertions.assertNotNull(response); + Assertions.assertEquals(200, response.getStatusCodeValue()); + } + + public void testWithinvalidPayloadRequestReturnsUnauthorized() { + AssertionSimpleClientTestUtils.createExpectationAssertionFound(); + + String signatureInput = + "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + var signature = + "sig123=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + + RestTemplate exec = restTemplate.getRestTemplate(); + exec.getClientHttpRequestInitializers() + .add( + request -> { + request.getHeaders() + .add( + "Content-Digest", + "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"); + request.getHeaders() + .add( + "x-pagopa-lollipop-original-url", + "https://api-app.io.pagopa.it/first-lollipop/sign"); + request.getHeaders().add("x-pagopa-lollipop-original-method", "POST"); + request.getHeaders() + .add( + "x-pagopa-lollipop-public-key", + "eyJrdHkiOiJFQyIsIngiOiJGcUZEd" + + "XdFZ3U0TVVYRVJQTVZMLTg1cEd2MkQzWW1MNEoxZ2ZNa2RiYzI0IiwieSI6Im" + + "hkVjBveG1XRlN4TW9KVURwZGlocjc2clM4VlJCRXFNRmViWXlBZks5LWsiLCJjcnYiO" + + "iJQLTI1NiJ9"); + request.getHeaders() + .add( + "x-pagopa-lollipop-assertion-ref", + "sha256-_ZzL8qeuAM5kQ9pbMB4tn7IDSQZCVXAkW9fm4P7ULPI"); + request.getHeaders().add("x-pagopa-lollipop-assertion-type", "SAML"); + request.getHeaders().add("x-pagopa-lollipop-auth-jwt", "aValidJWT"); + request.getHeaders() + .add("x-pagopa-lollipop-user-id", "AAAAAA89S20I111X"); + request.getHeaders().add("Signature-Input", signatureInput); + request.getHeaders().add("Signature", signature); + }); + + ResponseEntity response = + exec.postForEntity( + "http://localhost:" + port, + "{\"message\":\"an invalid message payload\"}", + String.class); + Assertions.assertNotNull(response); + Assertions.assertEquals(401, response.getStatusCodeValue()); } @AfterAll From e0d860cc84242df62cfbb9088630a3f7d1a460d9 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Mon, 17 Apr 2023 20:07:34 +0200 Subject: [PATCH 226/403] [SLS-12] Introducing implementation of a spring interceptor using the lollipop verification function. Implemented skeleton for integration testing --- .../command/LollipopConsumerCommand.java | 4 +- .../LollipopConsumerCommandBuilder.java | 4 +- .../LollipopConsumerCommandBuilderImpl.java | 6 +- .../impl/LollipopConsumerCommandImpl.java | 9 +- .../config/LollipopConsumerRequestConfig.java | 4 + .../helper/LollipopConsumerFactoryHelper.java | 65 +- .../impl/LollipopConsumerCommandImplTest.java | 25 +- gradle/verification-metadata.xml | 1109 ++++++++++++++++- settings.gradle | 2 +- spring-impl/build.gradle | 33 + .../HttpVerifierHandlerInterceptor.java | 45 + .../config/HttpVerifierConfiguration.java | 50 + .../SpringLollipopConsumerRequestConfig.java | 12 + .../LollipopConsumerRequestConverter.java | 29 + ...fierHandlerInterceptorIntegrationTest.java | 114 ++ 15 files changed, 1474 insertions(+), 37 deletions(-) create mode 100644 spring-impl/build.gradle create mode 100644 spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java create mode 100644 spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java create mode 100644 spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java create mode 100644 spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java create mode 100644 spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java index 9bb161a6..bb8662c9 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommand.java @@ -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 { @@ -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(); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java index 3031657a..eed04f74 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/LollipopConsumerCommandBuilder.java @@ -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 { @@ -9,5 +11,5 @@ public interface LollipopConsumerCommandBuilder { * * @return an instance of {@link LollipopConsumerCommand} */ - LollipopConsumerCommand createCommand(); + LollipopConsumerCommand createCommand(LollipopConsumerRequest lollipopConsumerRequest); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java index 6c10346c..b1d0ee2e 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java @@ -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; /** @@ -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); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index 1ff773c0..fc56f264 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -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"; @@ -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); diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index d746503b..74ae215f 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -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; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index 7fee7de2..87434aa9 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -1,16 +1,17 @@ /* (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 */ @@ -18,16 +19,25 @@ 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; } /** @@ -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()); } /** @@ -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() { @@ -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; } } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java index 2b03d62c..18c673eb 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -35,7 +35,8 @@ void beforeAll() { new LollipopConsumerCommandImpl( messageVerifierServiceMock, assertionVerifierServiceMock, - requestValidationServiceMock)); + requestValidationServiceMock, + LollipopConsumerRequest.builder().build())); } @Test @@ -51,7 +52,7 @@ void failedHttpMessageValidationThrowDigestException() .when(messageVerifierServiceMock) .verifyHttpMessage(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( HttpMessageVerificationResultCode.DIGEST_VALIDATION_ERROR.name(), @@ -77,7 +78,7 @@ void failedHttpMessageValidationThrowSignatureException() .when(messageVerifierServiceMock) .verifyHttpMessage(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( HttpMessageVerificationResultCode.SIGNATURE_VALIDATION_ERROR.name(), @@ -98,7 +99,7 @@ void failedHttpMessageValidationThrowUnsupportedEncodingException() { .when(messageVerifierServiceMock) .verifyHttpMessage(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( HttpMessageVerificationResultCode.UNSUPPORTED_ENCODING.name(), @@ -122,7 +123,7 @@ void failedHttpMessageValidationWithoutThrowingException() .when(messageVerifierServiceMock) .verifyHttpMessage(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_FAILED.name(), @@ -149,7 +150,7 @@ void failedAssertionValidationWithoutThrowingException() .when(assertionVerifierServiceMock) .validateLollipop(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( AssertionVerificationResultCode.ASSERTION_VERIFICATION_FAILED.name(), @@ -175,7 +176,7 @@ void successLollipopRequestValidation() .when(assertionVerifierServiceMock) .validateLollipop(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals("SUCCESS", commandResult.getResultCode()); @@ -195,7 +196,7 @@ void failedLollipopRequestValidation() doThrow(LollipopRequestContentValidationException.class) .when(requestValidationServiceMock) .validateLollipopRequest(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals("REQUEST PARAMS VALIDATION FAILED", commandResult.getResultCode()); @@ -221,7 +222,7 @@ void failedAssertionValidationThrowErrorRetrievingAssertionException() .when(assertionVerifierServiceMock) .validateLollipop(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( AssertionVerificationResultCode.ERROR_RETRIEVING_ASSERTION.name(), @@ -247,7 +248,7 @@ void failedAssertionValidationThrowAssertionPeriodException() .when(assertionVerifierServiceMock) .validateLollipop(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( AssertionVerificationResultCode.PERIOD_VALIDATION_ERROR.name(), @@ -273,7 +274,7 @@ void failedAssertionValidationThrowAssertionThumbprintException() .when(assertionVerifierServiceMock) .validateLollipop(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( AssertionVerificationResultCode.THUMBPRINT_VALIDATION_ERROR.name(), @@ -299,7 +300,7 @@ void failedAssertionValidationThrowAssertionUserIdException() .when(assertionVerifierServiceMock) .validateLollipop(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( AssertionVerificationResultCode.USER_ID_VALIDATION_ERROR.name(), diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 19d17857..fb2e5eed 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -9,6 +9,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -113,6 +139,11 @@ + + + + + @@ -145,6 +176,11 @@ + + + + + @@ -183,6 +219,11 @@ + + + + + @@ -245,6 +286,17 @@ + + + + + + + + + + + @@ -291,6 +343,17 @@ + + + + + + + + + + + @@ -329,12 +392,15 @@ - - - + + + + + + - - + + @@ -372,6 +438,17 @@ + + + + + + + + + + + @@ -390,6 +467,17 @@ + + + + + + + + + + + @@ -413,6 +501,11 @@ + + + + + @@ -431,6 +524,17 @@ + + + + + + + + + + + @@ -439,6 +543,17 @@ + + + + + + + + + + + @@ -465,6 +580,22 @@ + + + + + + + + + + + + + + + + @@ -491,6 +622,14 @@ + + + + + + + + @@ -942,6 +1081,16 @@ + + + + + + + + + + @@ -962,6 +1111,14 @@ + + + + + + + + @@ -983,6 +1140,11 @@ + + + + + @@ -1063,6 +1225,14 @@ + + + + + + + + @@ -1147,6 +1317,16 @@ + + + + + + + + + + @@ -1189,6 +1369,16 @@ + + + + + + + + + + @@ -1199,6 +1389,14 @@ + + + + + + + + @@ -1209,6 +1407,14 @@ + + + + + + + + @@ -1219,6 +1425,14 @@ + + + + + + + + @@ -1229,6 +1443,14 @@ + + + + + + + + @@ -1239,6 +1461,14 @@ + + + + + + + + @@ -1249,6 +1479,14 @@ + + + + + + + + @@ -1259,6 +1497,14 @@ + + + + + + + + @@ -1269,12 +1515,25 @@ + + + + + + + + + + + + + @@ -1285,6 +1544,14 @@ + + + + + + + + @@ -1295,6 +1562,14 @@ + + + + + + + + @@ -1305,12 +1580,25 @@ + + + + + + + + + + + + + @@ -1321,6 +1609,14 @@ + + + + + + + + @@ -1331,12 +1627,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1347,6 +1672,19 @@ + + + + + + + + + + + + + @@ -1357,6 +1695,14 @@ + + + + + + + + @@ -1367,12 +1713,25 @@ + + + + + + + + + + + + + @@ -1383,6 +1742,14 @@ + + + + + + + + @@ -1393,6 +1760,14 @@ + + + + + + + + @@ -1403,6 +1778,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1681,6 +2084,14 @@ + + + + + + + + @@ -1691,6 +2102,19 @@ + + + + + + + + + + + + + @@ -1709,6 +2133,14 @@ + + + + + + + + @@ -1734,6 +2166,11 @@ + + + + + @@ -1838,6 +2275,14 @@ + + + + + + + + @@ -1848,6 +2293,14 @@ + + + + + + + + @@ -1864,6 +2317,11 @@ + + + + + @@ -1890,6 +2348,22 @@ + + + + + + + + + + + + + + + + @@ -1916,6 +2390,22 @@ + + + + + + + + + + + + + + + + @@ -1946,6 +2436,19 @@ + + + + + + + + + + + + + @@ -1981,6 +2484,11 @@ + + + + + @@ -1999,6 +2507,14 @@ + + + + + + + + @@ -2090,18 +2606,36 @@ + + + + + + + + + + + + + + + + + + @@ -2118,6 +2652,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2206,6 +2779,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -2274,6 +2871,14 @@ + + + + + + + + @@ -2290,6 +2895,11 @@ + + + + + @@ -2360,6 +2970,11 @@ + + + + + @@ -2464,6 +3079,11 @@ + + + + + @@ -2512,6 +3132,11 @@ + + + + + @@ -2630,6 +3255,21 @@ + + + + + + + + + + + + + + + @@ -2640,6 +3280,11 @@ + + + + + @@ -2712,6 +3357,11 @@ + + + + + @@ -2732,6 +3382,11 @@ + + + + + @@ -2741,6 +3396,11 @@ + + + + + @@ -2779,6 +3439,17 @@ + + + + + + + + + + + @@ -2827,6 +3498,17 @@ + + + + + + + + + + + @@ -2851,6 +3533,17 @@ + + + + + + + + + + + @@ -2875,6 +3568,17 @@ + + + + + + + + + + + @@ -2899,6 +3603,17 @@ + + + + + + + + + + + @@ -2919,6 +3634,17 @@ + + + + + + + + + + + @@ -2943,6 +3669,17 @@ + + + + + + + + + + + @@ -2963,6 +3700,17 @@ + + + + + + + + + + + @@ -3047,6 +3795,19 @@ + + + + + + + + + + + + + @@ -3057,6 +3818,14 @@ + + + + + + + + @@ -3093,6 +3862,14 @@ + + + + + + + + @@ -3103,6 +3880,11 @@ + + + + + @@ -3203,6 +3985,14 @@ + + + + + + + + @@ -3213,6 +4003,22 @@ + + + + + + + + + + + + + + + + @@ -3328,6 +4134,283 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3336,6 +4419,14 @@ + + + + + + + + @@ -3372,6 +4463,14 @@ + + + + + + + + diff --git a/settings.gradle b/settings.gradle index d9f15bbf..844793d0 100644 --- a/settings.gradle +++ b/settings.gradle @@ -29,4 +29,4 @@ gradleEnterprise { } rootProject.name = 'eng-lollipop-consumer-java-sdk' -include 'core', 'assertion-rest-client-native', 'http-verifier', 'identity-service-rest-client-native', 'redis-storage', 'test-coverage' +include 'core', 'assertion-rest-client-native', 'http-verifier', 'identity-service-rest-client-native', 'redis-storage', 'test-coverage', 'spring-impl' diff --git a/spring-impl/build.gradle b/spring-impl/build.gradle new file mode 100644 index 00000000..39bb999e --- /dev/null +++ b/spring-impl/build.gradle @@ -0,0 +1,33 @@ +plugins { + id 'java-library' + id("io.freefair.lombok") version "8.0.0" + id 'org.springframework.boot' version '2.7.10' + id 'io.spring.dependency-management' version '1.0.15.RELEASE' +} + +repositories { + mavenLocal() + mavenCentral() + maven { + url = uri("https://maven.pkg.github.com/pagopa/eng-http-signatures") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + } + } +} + +dependencies { + implementation project(':core') + implementation 'org.springframework.boot:spring-boot-starter-web:2.7.10' + testImplementation 'org.springframework.boot:spring-boot-starter-test:2.7.10' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2' + testImplementation project(':http-verifier') + testImplementation project(':assertion-rest-client-native') + testImplementation project(':identity-service-rest-client-native') +} + +tasks.named('test') { + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java new file mode 100644 index 00000000..14b796d8 --- /dev/null +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java @@ -0,0 +1,45 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring; + +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; +import it.pagopa.tech.lollipop.consumer.model.CommandResult; +import it.pagopa.tech.lollipop.consumer.spring.converter.LollipopConsumerRequestConverter; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.AllArgsConstructor; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.web.servlet.HandlerInterceptor; + +@AllArgsConstructor +public class HttpVerifierHandlerInterceptor implements HandlerInterceptor { + + private final LollipopConsumerCommandBuilder consumerCommandBuilder; + private static final Log log = LogFactory.getLog(HttpVerifierHandlerInterceptor.class); + + @Override + public boolean preHandle( + HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + + LollipopConsumerCommand lollipopConsumerCommand = + consumerCommandBuilder.createCommand( + LollipopConsumerRequestConverter.convert(request)); + + try { + CommandResult commandResult = lollipopConsumerCommand.doExecute(); + + if (commandResult.getResultCode().equals("KO")) { + response.sendError(401, commandResult.getResultMessage()); + } else { + return true; + } + + } catch (Exception e) { + log.error("Error verifying request", e); + } + + return false; + } +} diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java new file mode 100644 index 00000000..dd04f6e6 --- /dev/null +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java @@ -0,0 +1,50 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring.config; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; +import it.pagopa.tech.lollipop.consumer.command.impl.LollipopConsumerCommandBuilderImpl; +import it.pagopa.tech.lollipop.consumer.helper.LollipopConsumerFactoryHelper; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; +import it.pagopa.tech.lollipop.consumer.service.impl.LollipopConsumerRequestValidationServiceImpl; +import it.pagopa.tech.lollipop.consumer.spring.HttpVerifierHandlerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class HttpVerifierConfiguration { + + private SpringLollipopConsumerRequestConfig springLollipopConsumerRequestConfig; + + @Bean + public LollipopConsumerFactoryHelper lollipopConsumerFactoryHelper( + HttpMessageVerifierFactory httpMessageVerifierFactory, + IdpCertProviderFactory idpCertProviderFactory, + AssertionServiceFactory assertionServiceFactory) { + return new LollipopConsumerFactoryHelper( + httpMessageVerifierFactory, + idpCertProviderFactory, + assertionServiceFactory, + getLollipopConsumerRequestValidationService()); + } + + @Bean + public LollipopConsumerRequestValidationService getLollipopConsumerRequestValidationService() { + return new LollipopConsumerRequestValidationServiceImpl( + springLollipopConsumerRequestConfig); + } + + @Bean + public LollipopConsumerCommandBuilder lollipopConsumerCommandBuilder( + LollipopConsumerFactoryHelper lollipopConsumerFactoryHelper) { + return new LollipopConsumerCommandBuilderImpl(lollipopConsumerFactoryHelper); + } + + @Bean + public HttpVerifierHandlerInterceptor httpVerifierHandlerInterceptor( + LollipopConsumerCommandBuilder lollipopConsumerCommandBuilder) { + return new HttpVerifierHandlerInterceptor(lollipopConsumerCommandBuilder); + } +} diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java new file mode 100644 index 00000000..d8e2fa89 --- /dev/null +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java @@ -0,0 +1,12 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring.config; + +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import lombok.NoArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; + +@ConfigurationProperties(prefix = "lollipop.core.config") +@ConfigurationPropertiesScan +@NoArgsConstructor +public class SpringLollipopConsumerRequestConfig extends LollipopConsumerRequestConfig {} diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java new file mode 100644 index 00000000..2c26722e --- /dev/null +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java @@ -0,0 +1,29 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring.converter; + +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletRequest; +import org.springframework.util.StreamUtils; + +public class LollipopConsumerRequestConverter { + + public static LollipopConsumerRequest convert(HttpServletRequest httpServletRequest) + throws IOException { + + byte[] requestBody; + + InputStream requestInputStream = httpServletRequest.getInputStream(); + requestBody = StreamUtils.copyToByteArray(requestInputStream); + + return LollipopConsumerRequest.builder() + .requestBody(new String(requestBody)) + .headerParams( + Collections.list(httpServletRequest.getHeaderNames()).stream() + .collect(Collectors.toMap(h -> h, httpServletRequest::getHeader))) + .build(); + } +} diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java new file mode 100644 index 00000000..5976a207 --- /dev/null +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java @@ -0,0 +1,114 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientConfig; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.assertion.impl.AssertionServiceFactoryImpl; +import it.pagopa.tech.lollipop.consumer.assertion.storage.SimpleAssertionStorageProvider; +import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.http_verifier.visma.VismaHttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImplStub; +import it.pagopa.tech.lollipop.consumer.spring.config.HttpVerifierConfiguration; +import it.pagopa.tech.lollipop.consumer.spring.config.SpringLollipopConsumerRequestConfig; +import java.security.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.web.filter.CommonsRequestLoggingFilter; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration( + classes = { + HttpVerifierHandlerInterceptor.class, + SpringLollipopConsumerRequestConfig.class, + HttpVerifierConfiguration.class, + HttpVerifierHandlerInterceptorIntegrationTest.DemoServicesConfig.class + }) +public class HttpVerifierHandlerInterceptorIntegrationTest { + + // @Autowired + // private DemoController controller; + // + // @LocalServerPort + // private int port; + // + // @Controller + // public static class DemoController { + // + // @PostMapping("/") + // public @ResponseBody + // String testMethod() { + // return "Test!"; + // } + // + // } + + @Autowired private HttpVerifierHandlerInterceptor interceptor; + + @Configuration + public static class DemoServicesConfig { + + @Bean + public SpringLollipopConsumerRequestConfig verifierConfiguration() { + return new SpringLollipopConsumerRequestConfig(); + } + + @Bean + public HttpMessageVerifierFactory httpMessageVerifierFactory() throws Exception { + return new VismaHttpMessageVerifierFactory("UTF-8", verifierConfiguration()); + } + + @Bean + public IdpCertProviderFactory idpCertProviderFactory() { + return new IdpCertProviderFactoryImplStub(); + } + + @Bean + public AssertionServiceFactory assertionServiceFactory() { + return new AssertionServiceFactoryImpl( + new SimpleAssertionStorageProvider(), + new AssertionSimpleClientProvider( + AssertionSimpleClientConfig.builder().build()), + storageConfig()); + } + + @Bean + public StorageConfig storageConfig() { + return new StorageConfig(); + } + } + + @Component + public static class DemoWebConfigurer implements WebMvcConfigurer { + + @Autowired private HttpVerifierHandlerInterceptor interceptor; + + @Bean + public CommonsRequestLoggingFilter loggingFilter() { + CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter(); + filter.setIncludeQueryString(true); + filter.setIncludeClientInfo(true); + filter.setIncludeHeaders(true); + filter.setIncludePayload(true); + return filter; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(interceptor); + } + } + + @Test + public void something() {} +} From d8eac94b28fd221879fba3395d472ca6085ce02b Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 18 Apr 2023 16:40:21 +0200 Subject: [PATCH 227/403] [SLS-12] Updated spring interceptor --- assertion-rest-client-native/build.gradle | 1 + .../simple/AssertionSimpleClientTest.java | 281 +---------------- .../AssertionSimpleClientTestUtils.java | 284 ++++++++++++++++++ .../impl/AssertionVerifierServiceImpl.java | 9 + ...pConsumerRequestValidationServiceImpl.java | 8 +- spring-impl/build.gradle | 4 +- .../HttpVerifierHandlerInterceptor.java | 2 +- .../config/HttpVerifierConfiguration.java | 3 +- .../AssertionSimpleClientTestUtils.java | 170 +++++++++++ .../consumer/spring/DemoApplication.java | 13 + ...fierHandlerInterceptorIntegrationTest.java | 150 ++++----- .../spring/config/DemoServicesConfig.java | 47 +++ .../spring/config/DemoWebConfigurer.java | 31 ++ .../spring/controller/DemoController.java | 15 + 14 files changed, 652 insertions(+), 366 deletions(-) create mode 100644 assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTestUtils.java create mode 100644 spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/AssertionSimpleClientTestUtils.java create mode 100644 spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/DemoApplication.java create mode 100644 spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java create mode 100644 spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoWebConfigurer.java create mode 100644 spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/controller/DemoController.java diff --git a/assertion-rest-client-native/build.gradle b/assertion-rest-client-native/build.gradle index b71cc6f4..37a69bc4 100644 --- a/assertion-rest-client-native/build.gradle +++ b/assertion-rest-client-native/build.gradle @@ -10,6 +10,7 @@ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' + id "java-test-fixtures" id("io.freefair.lombok") version "8.0.0" /*id("org.openapi.generator") version "6.5.0"*/ } diff --git a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java index de42da14..d887ed96 100644 --- a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java +++ b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java @@ -1,8 +1,8 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple; +import static it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientTestUtils.*; import static org.mockserver.integration.ClientAndServer.startClientAndServer; -import static org.mockserver.model.HttpRequest.request; import static org.mockserver.model.HttpResponse.response; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiClient; @@ -14,262 +14,13 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.mockito.Mockito; -import org.mockserver.client.MockServerClient; import org.mockserver.integration.ClientAndServer; -import org.mockserver.model.Header; class AssertionSimpleClientTest { private static AssertionSimpleClient assertionSimpleClient; private static AssertionSimpleClientConfig assertionConfig; private static ClientAndServer mockServer; - private static final String XML_STRING = - " https://posteid.poste.it" - + " " - + " " - + " " - + " " - + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" - + " " - + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" - + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" - + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" - + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" - + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " - + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" - + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" - + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" - + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" - + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" - + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" - + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" - + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" - + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" - + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" - + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" - + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" - + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" - + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" - + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" - + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" - + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" - + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" - + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" - + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" - + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" - + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" - + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" - + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" - + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" - + " " - + " " - + " https://posteid.poste.it " - + " " - + " " - + " " - + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" - + " " - + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" - + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" - + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" - + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" - + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " - + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" - + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" - + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" - + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" - + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" - + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" - + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" - + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" - + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" - + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" - + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" - + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" - + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" - + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" - + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" - + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" - + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" - + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" - + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" - + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" - + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" - + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" - + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" - + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" - + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" - + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" - + " " - + " " - + " " - + " https://app-backend.io.italia.it" - + " " - + " https://www.spid.gov.it/SpidL2" - + " " - + " " - + " " - + " TINIT-AAAAAA89S20I111X " - + " "; - private static final String RESPONSE_STRING = - "{\"response_xml\": \" " - + " https://posteid.poste.it" - + " " - + " " - + " " - + " " - + " " - + " " - + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" - + " " - + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" - + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" - + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" - + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" - + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " - + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" - + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" - + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" - + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" - + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" - + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" - + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" - + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" - + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" - + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" - + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" - + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" - + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" - + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" - + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" - + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" - + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" - + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" - + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" - + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" - + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" - + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" - + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" - + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" - + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" - + " " - + " " - + " " - + " https://posteid.poste.it " - + " " - + " " - + " " - + " " - + " " - + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" - + " " - + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" - + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" - + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" - + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" - + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " - + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" - + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" - + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" - + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" - + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" - + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" - + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" - + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" - + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" - + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" - + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" - + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" - + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" - + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" - + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" - + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" - + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" - + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" - + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" - + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" - + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" - + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" - + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" - + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" - + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" - + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" - + " " - + " " - + " " - + " https://app-backend.io.italia.it" - + " " - + " https://www.spid.gov.it/SpidL2" - + " " - + " " - + " TINIT-AAAAAA89S20I111X" - + " " - + " \"}"; - private static final String ASSERTION_REF = - "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; - private static final String WRONG_ASSERTION_REF = - "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfXXXXX"; - private static final String JWT = "Bearer aValidJWT"; @BeforeAll public static void startServer() { @@ -282,7 +33,7 @@ public static void startServer() { @Test void samlAssertionFound() throws LollipopAssertionNotFoundException, OidcAssertionNotSupported { - createExpectationAssertionFound(); + AssertionSimpleClientTestUtils.createExpectationAssertionFound(); SamlAssertion response = assertionSimpleClient.getAssertion(JWT, ASSERTION_REF); Assertions.assertNotNull(response); @@ -294,39 +45,13 @@ void samlAssertionFound() throws LollipopAssertionNotFoundException, OidcAsserti @Test void assertionNotFound() { - createExpectationAssertionNotFound(); + AssertionSimpleClientTestUtils.createExpectationAssertionNotFound(); // setup Assertions.assertThrows( LollipopAssertionNotFoundException.class, () -> assertionSimpleClient.getAssertion(JWT, WRONG_ASSERTION_REF)); } - private void createExpectationAssertionFound() { - new MockServerClient("localhost", 2000) - .when( - request() - .withMethod("GET") - .withPath("/assertions/{assertion}") - .withPathParameter("assertion", ASSERTION_REF) - .withHeaders( - new Header("Accept", "application/json"), - new Header("x-pagopa-lollipop-auth", JWT))) - .respond(response().withStatusCode(200).withBody(RESPONSE_STRING)); - } - - private void createExpectationAssertionNotFound() { - new MockServerClient("localhost", 2000) - .when( - request() - .withMethod("GET") - .withPath("/assertions/{assertion}") - .withPathParameter("assertion", WRONG_ASSERTION_REF) - .withHeaders( - new Header("Accept", "application/json"), - new Header("x-pagopa-lollipop-auth", JWT))) - .respond(response().withStatusCode(404).withBody("{}")); - } - @AfterAll public static void stopServer() { mockServer.stop(); diff --git a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTestUtils.java b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTestUtils.java new file mode 100644 index 00000000..48b2ef3d --- /dev/null +++ b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTestUtils.java @@ -0,0 +1,284 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.assertion.client.simple; + +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +import org.mockserver.client.MockServerClient; +import org.mockserver.model.Header; + +public class AssertionSimpleClientTestUtils { + + public static final String XML_STRING = + " https://posteid.poste.it" + + " " + + " " + + " " + + " " + + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" + + " " + + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" + + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" + + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" + + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" + + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " " + + " " + + " https://posteid.poste.it " + + " " + + " " + + " " + + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" + + " " + + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" + + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" + + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" + + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" + + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + " " + + " " + + " " + + " https://app-backend.io.italia.it" + + " " + + " https://www.spid.gov.it/SpidL2" + + " " + + " " + + " " + + " TINIT-AAAAAA89S20I111X " + + " "; + public static final String RESPONSE_STRING = + "{\"response_xml\": \" " + + " https://posteid.poste.it" + + " " + + " " + + " " + + " " + + " " + + " " + + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" + + " " + + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" + + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" + + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" + + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" + + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " " + + " " + + " " + + " https://posteid.poste.it " + + " " + + " " + + " " + + " " + + " " + + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" + + " " + + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" + + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" + + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" + + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" + + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + " " + + " " + + " " + + " https://app-backend.io.italia.it" + + " " + + " https://www.spid.gov.it/SpidL2" + + " " + + " " + + " TINIT-AAAAAA89S20I111X" + + " " + + " \"}"; + public static final String ASSERTION_REF = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; + public static final String WRONG_ASSERTION_REF = + "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfXXXXX"; + public static final String JWT = "Bearer aValidJWT"; + + public static void createExpectationAssertionFound() { + new MockServerClient("localhost", 2000) + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", JWT))) + .respond(response().withStatusCode(200).withBody(RESPONSE_STRING)); + } + + public static void createExpectationAssertionNotFound() { + new MockServerClient("localhost", 2000) + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", WRONG_ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", JWT))) + .respond(response().withStatusCode(404).withBody("{}")); + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index 14161ccf..c53e6c5b 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -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 { @@ -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()); diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java index 810b795c..e4712b83 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java @@ -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; @@ -30,7 +31,6 @@ public void validateLollipopRequest(LollipopConsumerRequest request) Map 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())); @@ -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( diff --git a/spring-impl/build.gradle b/spring-impl/build.gradle index 39bb999e..24995c0d 100644 --- a/spring-impl/build.gradle +++ b/spring-impl/build.gradle @@ -22,8 +22,10 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web:2.7.10' testImplementation 'org.springframework.boot:spring-boot-starter-test:2.7.10' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2' + //Mockserver for testing api + testImplementation 'org.mock-server:mockserver-netty:5.15.0' testImplementation project(':http-verifier') - testImplementation project(':assertion-rest-client-native') + testImplementation testFixtures(project(':assertion-rest-client-native')) testImplementation project(':identity-service-rest-client-native') } diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java index 14b796d8..6fa6871e 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java @@ -30,7 +30,7 @@ public boolean preHandle( try { CommandResult commandResult = lollipopConsumerCommand.doExecute(); - if (commandResult.getResultCode().equals("KO")) { + if (!commandResult.getResultCode().equals("SUCCESS")) { response.sendError(401, commandResult.getResultMessage()); } else { return true; diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java index dd04f6e6..faf81cc2 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java @@ -10,13 +10,14 @@ import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; import it.pagopa.tech.lollipop.consumer.service.impl.LollipopConsumerRequestValidationServiceImpl; import it.pagopa.tech.lollipop.consumer.spring.HttpVerifierHandlerInterceptor; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class HttpVerifierConfiguration { - private SpringLollipopConsumerRequestConfig springLollipopConsumerRequestConfig; + @Autowired private SpringLollipopConsumerRequestConfig springLollipopConsumerRequestConfig; @Bean public LollipopConsumerFactoryHelper lollipopConsumerFactoryHelper( diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/AssertionSimpleClientTestUtils.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/AssertionSimpleClientTestUtils.java new file mode 100644 index 00000000..baa87018 --- /dev/null +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/AssertionSimpleClientTestUtils.java @@ -0,0 +1,170 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring; + +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +import java.text.SimpleDateFormat; +import java.util.Date; +import org.mockserver.client.MockServerClient; +import org.mockserver.model.Header; + +public class AssertionSimpleClientTestUtils { + + public static final String RESPONSE_STRING = + "{\"response_xml\": \" " + + " https://posteid.poste.it" + + " " + + " " + + " " + + " " + + " " + + " " + + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" + + " " + + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" + + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" + + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" + + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" + + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " " + + " " + + " " + + " https://posteid.poste.it " + + " " + + " " + + " " + + " " + + " " + + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" + + " " + + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" + + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" + + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" + + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" + + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + " " + + " " + + " " + + " " + + " https://app-backend.io.italia.it" + + " " + + " https://www.spid.gov.it/SpidL2" + + " " + + " TINIT-AAAAAA89S20I111X" + + " " + + " \"}"; + public static final String ASSERTION_REF = "sha256-_ZzL8qeuAM5kQ9pbMB4tn7IDSQZCVXAkW9fm4P7ULPI"; + public static final String WRONG_ASSERTION_REF = + "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfXXXXX"; + public static final String JWT = "aValidJWT"; + + public static void createExpectationAssertionFound() { + new MockServerClient("localhost", 3000) + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", JWT))) + .respond(response().withStatusCode(200).withBody(RESPONSE_STRING)); + } + + public static void createExpectationAssertionNotFound() { + new MockServerClient("localhost", 2000) + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", WRONG_ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", JWT))) + .respond(response().withStatusCode(404).withBody("{}")); + } +} diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/DemoApplication.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/DemoApplication.java new file mode 100644 index 00000000..2608818e --- /dev/null +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/DemoApplication.java @@ -0,0 +1,13 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication(scanBasePackages = "it.pagopa.tech") +public class DemoApplication { + + public static void main(String[] args) { + SpringApplication.run(DemoApplication.class, args); + } +} diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java index 5976a207..2df74957 100644 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java @@ -1,114 +1,96 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.spring; -import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; -import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientConfig; -import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientProvider; -import it.pagopa.tech.lollipop.consumer.assertion.impl.AssertionServiceFactoryImpl; -import it.pagopa.tech.lollipop.consumer.assertion.storage.SimpleAssertionStorageProvider; -import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; -import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; -import it.pagopa.tech.lollipop.consumer.http_verifier.visma.VismaHttpMessageVerifierFactory; -import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; -import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImplStub; +import static org.mockserver.integration.ClientAndServer.startClientAndServer; + import it.pagopa.tech.lollipop.consumer.spring.config.HttpVerifierConfiguration; import it.pagopa.tech.lollipop.consumer.spring.config.SpringLollipopConsumerRequestConfig; -import java.security.*; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockserver.integration.ClientAndServer; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.stereotype.Component; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.web.filter.CommonsRequestLoggingFilter; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.client.RestTemplate; @ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ContextConfiguration( classes = { - HttpVerifierHandlerInterceptor.class, + DemoApplication.class, SpringLollipopConsumerRequestConfig.class, HttpVerifierConfiguration.class, - HttpVerifierHandlerInterceptorIntegrationTest.DemoServicesConfig.class }) public class HttpVerifierHandlerInterceptorIntegrationTest { - // @Autowired - // private DemoController controller; - // - // @LocalServerPort - // private int port; - // - // @Controller - // public static class DemoController { - // - // @PostMapping("/") - // public @ResponseBody - // String testMethod() { - // return "Test!"; - // } - // - // } + @LocalServerPort private int port; + @Autowired private TestRestTemplate restTemplate; - @Autowired private HttpVerifierHandlerInterceptor interceptor; + @BeforeAll + public static void startServer() { + mockServer = startClientAndServer(3000); + } - @Configuration - public static class DemoServicesConfig { + private static ClientAndServer mockServer; - @Bean - public SpringLollipopConsumerRequestConfig verifierConfiguration() { - return new SpringLollipopConsumerRequestConfig(); - } + @Autowired private HttpVerifierHandlerInterceptor interceptor; - @Bean - public HttpMessageVerifierFactory httpMessageVerifierFactory() throws Exception { - return new VismaHttpMessageVerifierFactory("UTF-8", verifierConfiguration()); - } + @Test + public void test() { + AssertionSimpleClientTestUtils.createExpectationAssertionFound(); - @Bean - public IdpCertProviderFactory idpCertProviderFactory() { - return new IdpCertProviderFactoryImplStub(); - } + String signatureInput = + "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + var signature = + "sig123=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; - @Bean - public AssertionServiceFactory assertionServiceFactory() { - return new AssertionServiceFactoryImpl( - new SimpleAssertionStorageProvider(), - new AssertionSimpleClientProvider( - AssertionSimpleClientConfig.builder().build()), - storageConfig()); - } + RestTemplate exec = restTemplate.getRestTemplate(); + exec.getClientHttpRequestInitializers() + .add( + request -> { + request.getHeaders() + .add( + "Content-Digest", + "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"); + request.getHeaders() + .add( + "x-pagopa-lollipop-original-url", + "https://api-app.io.pagopa.it/first-lollipop/sign"); + request.getHeaders().add("x-pagopa-lollipop-original-method", "POST"); + request.getHeaders() + .add( + "x-pagopa-lollipop-public-key", + "eyJrdHkiOiJFQyIsIngiOiJGcUZEd" + + "XdFZ3U0TVVYRVJQTVZMLTg1cEd2MkQzWW1MNEoxZ2ZNa2RiYzI0IiwieSI6Im" + + "hkVjBveG1XRlN4TW9KVURwZGlocjc2clM4VlJCRXFNRmViWXlBZks5LWsiLCJjcnYiO" + + "iJQLTI1NiJ9"); + request.getHeaders() + .add( + "x-pagopa-lollipop-assertion-ref", + "sha256-_ZzL8qeuAM5kQ9pbMB4tn7IDSQZCVXAkW9fm4P7ULPI"); + request.getHeaders().add("x-pagopa-lollipop-assertion-type", "SAML"); + request.getHeaders().add("x-pagopa-lollipop-auth-jwt", "aValidJWT"); + request.getHeaders() + .add("x-pagopa-lollipop-user-id", "AAAAAA89S20I111X"); + request.getHeaders().add("Signature-Input", signatureInput); + request.getHeaders().add("Signature", signature); + }); - @Bean - public StorageConfig storageConfig() { - return new StorageConfig(); - } + String response = + exec.postForObject( + "http://localhost:" + port, + "{\"message\":\"a valid message payload\"}", + String.class); } - @Component - public static class DemoWebConfigurer implements WebMvcConfigurer { - - @Autowired private HttpVerifierHandlerInterceptor interceptor; - - @Bean - public CommonsRequestLoggingFilter loggingFilter() { - CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter(); - filter.setIncludeQueryString(true); - filter.setIncludeClientInfo(true); - filter.setIncludeHeaders(true); - filter.setIncludePayload(true); - return filter; - } - - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(interceptor); - } + @AfterAll + public static void stopServer() { + mockServer.stop(); } - - @Test - public void something() {} } diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java new file mode 100644 index 00000000..e61a3308 --- /dev/null +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java @@ -0,0 +1,47 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring.config; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientConfig; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.assertion.impl.AssertionServiceFactoryImpl; +import it.pagopa.tech.lollipop.consumer.assertion.storage.SimpleAssertionStorageProvider; +import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.http_verifier.visma.VismaHttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImplStub; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class DemoServicesConfig { + + @Bean + public SpringLollipopConsumerRequestConfig verifierConfiguration() { + return new SpringLollipopConsumerRequestConfig(); + } + + @Bean + public HttpMessageVerifierFactory httpMessageVerifierFactory() throws Exception { + return new VismaHttpMessageVerifierFactory("UTF-8", verifierConfiguration()); + } + + @Bean + public IdpCertProviderFactory idpCertProviderFactory() { + return new IdpCertProviderFactoryImplStub(); + } + + @Bean + public AssertionServiceFactory assertionServiceFactory() { + return new AssertionServiceFactoryImpl( + new SimpleAssertionStorageProvider(), + new AssertionSimpleClientProvider(AssertionSimpleClientConfig.builder().build()), + storageConfig()); + } + + @Bean + public StorageConfig storageConfig() { + return new StorageConfig(); + } +} diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoWebConfigurer.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoWebConfigurer.java new file mode 100644 index 00000000..c45f4d01 --- /dev/null +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoWebConfigurer.java @@ -0,0 +1,31 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring.config; + +import it.pagopa.tech.lollipop.consumer.spring.HttpVerifierHandlerInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.CommonsRequestLoggingFilter; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Component +public class DemoWebConfigurer implements WebMvcConfigurer { + + @Autowired private HttpVerifierHandlerInterceptor interceptor; + + @Bean + public CommonsRequestLoggingFilter loggingFilter() { + CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter(); + filter.setIncludeQueryString(true); + filter.setIncludeClientInfo(true); + filter.setIncludeHeaders(true); + filter.setIncludePayload(true); + return filter; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(interceptor); + } +} diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/controller/DemoController.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/controller/DemoController.java new file mode 100644 index 00000000..3b8cb50d --- /dev/null +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/controller/DemoController.java @@ -0,0 +1,15 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class DemoController { + + @RequestMapping("/") + public @ResponseBody String test() { + return "Test"; + } +} From 6136d393c9bff8efff935b755efd87e54c4ecffe Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 18 Apr 2023 19:17:40 +0200 Subject: [PATCH 228/403] [SLS-12] Updated tests an docs --- .../HttpVerifierHandlerInterceptor.java | 17 +++++- .../config/HttpVerifierConfiguration.java | 4 ++ .../SpringLollipopConsumerRequestConfig.java | 3 + .../LollipopConsumerRequestConverter.java | 21 +++++-- ...fierHandlerInterceptorIntegrationTest.java | 60 ++++++++++++++++++- 5 files changed, 96 insertions(+), 9 deletions(-) diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java index 6fa6871e..a79282be 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java @@ -12,16 +12,29 @@ import org.apache.commons.logging.LogFactory; import org.springframework.web.servlet.HandlerInterceptor; +import java.io.IOException; + +/** + * Instance of a Spring Http {@link HandlerInterceptor}, to be used for Lollipop Request validations + */ @AllArgsConstructor public class HttpVerifierHandlerInterceptor implements HandlerInterceptor { private final LollipopConsumerCommandBuilder consumerCommandBuilder; private static final Log log = LogFactory.getLog(HttpVerifierHandlerInterceptor.class); + /** + * + * @param request current HTTP request + * @param response current HTTP response + * @param handler chosen handler to execute, for type and/or instance evaluation + * @return boolean to determine if the handle completes successfully + * @throws IOException throws exception if the conversion of a http request fails + */ @Override public boolean preHandle( - HttpServletRequest request, HttpServletResponse response, Object handler) - throws Exception { + HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { + LollipopConsumerCommand lollipopConsumerCommand = consumerCommandBuilder.createCommand( diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java index faf81cc2..80ef1008 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java @@ -14,6 +14,10 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +/** + * Instance of Spring configuration of the core elements, the implementations of the related services + * are delegated to external configurations + */ @Configuration public class HttpVerifierConfiguration { diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java index d8e2fa89..d3a41677 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java @@ -6,6 +6,9 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationPropertiesScan; +/** + * Spring instance of the {@link LollipopConsumerRequestConfig} + */ @ConfigurationProperties(prefix = "lollipop.core.config") @ConfigurationPropertiesScan @NoArgsConstructor diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java index 2c26722e..d284a207 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java @@ -9,18 +9,31 @@ import javax.servlet.http.HttpServletRequest; import org.springframework.util.StreamUtils; +/** + * Class to be used for conversion of the http requests to be validated + */ public class LollipopConsumerRequestConverter { + /** + * Utility method to be used to generate a LollipopConsumerRequest + * @param httpServletRequest http request to be converted into a lollipop request + * @return instance of {@link LollipopConsumerRequest} produced from the httpServletRequest + * @throws IOException exception return if body extraction fails + */ public static LollipopConsumerRequest convert(HttpServletRequest httpServletRequest) throws IOException { - byte[] requestBody; + byte[] requestBody = null; - InputStream requestInputStream = httpServletRequest.getInputStream(); - requestBody = StreamUtils.copyToByteArray(requestInputStream); + String method = httpServletRequest.getMethod(); + + if (method != null && (!method.equals("GET") && !method.equals("DELETE"))) { + InputStream requestInputStream = httpServletRequest.getInputStream(); + requestBody = StreamUtils.copyToByteArray(requestInputStream); + } return LollipopConsumerRequest.builder() - .requestBody(new String(requestBody)) + .requestBody(requestBody != null ? new String(requestBody) : null) .headerParams( Collections.list(httpServletRequest.getHeaderNames()).stream() .collect(Collectors.toMap(h -> h, httpServletRequest::getHeader))) diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java index 2df74957..d15035b6 100644 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java @@ -6,6 +6,7 @@ import it.pagopa.tech.lollipop.consumer.spring.config.HttpVerifierConfiguration; import it.pagopa.tech.lollipop.consumer.spring.config.SpringLollipopConsumerRequestConfig; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -14,6 +15,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.http.ResponseEntity; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.web.client.RestTemplate; @@ -41,7 +43,7 @@ public static void startServer() { @Autowired private HttpVerifierHandlerInterceptor interceptor; @Test - public void test() { + public void testWithValidRequestReturnsSuccess() { AssertionSimpleClientTestUtils.createExpectationAssertionFound(); String signatureInput = @@ -82,11 +84,63 @@ public void test() { request.getHeaders().add("Signature", signature); }); - String response = - exec.postForObject( + ResponseEntity response = + exec.postForEntity( "http://localhost:" + port, "{\"message\":\"a valid message payload\"}", String.class); + Assertions.assertNotNull(response); + Assertions.assertEquals(200, response.getStatusCodeValue()); + } + + public void testWithinvalidPayloadRequestReturnsUnauthorized() { + AssertionSimpleClientTestUtils.createExpectationAssertionFound(); + + String signatureInput = + "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + var signature = + "sig123=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + + RestTemplate exec = restTemplate.getRestTemplate(); + exec.getClientHttpRequestInitializers() + .add( + request -> { + request.getHeaders() + .add( + "Content-Digest", + "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"); + request.getHeaders() + .add( + "x-pagopa-lollipop-original-url", + "https://api-app.io.pagopa.it/first-lollipop/sign"); + request.getHeaders().add("x-pagopa-lollipop-original-method", "POST"); + request.getHeaders() + .add( + "x-pagopa-lollipop-public-key", + "eyJrdHkiOiJFQyIsIngiOiJGcUZEd" + + "XdFZ3U0TVVYRVJQTVZMLTg1cEd2MkQzWW1MNEoxZ2ZNa2RiYzI0IiwieSI6Im" + + "hkVjBveG1XRlN4TW9KVURwZGlocjc2clM4VlJCRXFNRmViWXlBZks5LWsiLCJjcnYiO" + + "iJQLTI1NiJ9"); + request.getHeaders() + .add( + "x-pagopa-lollipop-assertion-ref", + "sha256-_ZzL8qeuAM5kQ9pbMB4tn7IDSQZCVXAkW9fm4P7ULPI"); + request.getHeaders().add("x-pagopa-lollipop-assertion-type", "SAML"); + request.getHeaders().add("x-pagopa-lollipop-auth-jwt", "aValidJWT"); + request.getHeaders() + .add("x-pagopa-lollipop-user-id", "AAAAAA89S20I111X"); + request.getHeaders().add("Signature-Input", signatureInput); + request.getHeaders().add("Signature", signature); + }); + + ResponseEntity response = + exec.postForEntity( + "http://localhost:" + port, + "{\"message\":\"an invalid message payload\"}", + String.class); + Assertions.assertNotNull(response); + Assertions.assertEquals(401, response.getStatusCodeValue()); } @AfterAll From 3a9ccd64bcfe334b4e8d550db065c047a2367710 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 18 Apr 2023 19:35:28 +0200 Subject: [PATCH 229/403] [SLS-12] Updated after rebase --- .github/workflows/pr_scan.yml | 4 +- build.gradle | 16 +- gradle/verification-metadata.xml | 479 +----------------- .../HttpVerifierHandlerInterceptor.java | 8 +- .../config/HttpVerifierConfiguration.java | 4 +- .../SpringLollipopConsumerRequestConfig.java | 4 +- .../LollipopConsumerRequestConverter.java | 5 +- ...fierHandlerInterceptorIntegrationTest.java | 8 +- .../spring/config/DemoServicesConfig.java | 7 +- 9 files changed, 42 insertions(+), 493 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 0035ac28..1fd11afb 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -57,10 +57,10 @@ jobs: with: sarif_file: ${{ steps.scan.outputs.sarif }} - name: Run Sonar Scanner - run: ./gradlew build sonarqube --info + run: ./gradlew sonarqube --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.login=${{ env.SONAR_TOKEN }} diff --git a/build.gradle b/build.gradle index 4b2615b9..794c60ff 100644 --- a/build.gradle +++ b/build.gradle @@ -144,7 +144,9 @@ subprojects { sonar { properties { - property "sonar.sources", "src/main" + property "sonar.sources", "src/main/java" + property "sonar.tests", "src/test/java" + property "sonar.java.binaries" "build/classes/java/main" } } @@ -163,6 +165,18 @@ subprojects { } +project(":test-coverage") { + sonarqube { + skipProject = true + } +} + +project(":redis-storage") { + sonarqube { + skipProject = true + } +} + graalvmNative { binaries { main { diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index dbb01431..ba9b6699 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -144,11 +144,6 @@ - - - - - @@ -397,14 +392,6 @@ - - - - - - - - @@ -548,17 +535,6 @@ - - - - - - - - - - - @@ -578,17 +554,6 @@ - - - - - - - - - - - @@ -631,22 +596,6 @@ - - - - - - - - - - - - - - - - @@ -1142,16 +1091,6 @@ - - - - - - - - - - @@ -1180,14 +1119,6 @@ - - - - - - - - @@ -1214,11 +1145,6 @@ - - - - - @@ -1307,14 +1233,6 @@ - - - - - - - - @@ -1479,14 +1397,6 @@ - - - - - - - - @@ -1505,14 +1415,6 @@ - - - - - - - - @@ -1549,14 +1451,6 @@ - - - - - - - - @@ -1575,14 +1469,6 @@ - - - - - - - - @@ -1601,14 +1487,6 @@ - - - - - - - - @@ -1645,14 +1523,6 @@ - - - - - - - - @@ -1682,14 +1552,6 @@ - - - - - - - - @@ -1726,14 +1588,6 @@ - - - - - - - - @@ -1808,14 +1662,6 @@ - - - - - - - - @@ -1857,14 +1703,6 @@ - - - - - - - - @@ -1880,11 +1718,6 @@ - - - - - @@ -1899,14 +1732,6 @@ - - - - - - - - @@ -1925,14 +1750,6 @@ - - - - - - - - @@ -1951,14 +1768,6 @@ - - - - - - - - @@ -2283,14 +2092,6 @@ - - - - - - - - @@ -2314,19 +2115,6 @@ - - - - - - - - - - - - - @@ -2576,22 +2364,6 @@ - - - - - - - - - - - - - - - - @@ -2677,19 +2449,6 @@ - - - - - - - - - - - - - @@ -2730,11 +2489,6 @@ - - - - - @@ -2761,14 +2515,6 @@ - - - - - - - - @@ -2890,11 +2636,6 @@ - - - - - @@ -2950,45 +2691,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -3101,30 +2803,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - @@ -3201,14 +2879,6 @@ - - - - - - - - @@ -3558,11 +3228,6 @@ - - - - - @@ -3600,16 +3265,6 @@ - - - - - - - - - - @@ -3707,11 +3362,6 @@ - - - - - @@ -3751,11 +3401,6 @@ - - - - - @@ -3805,17 +3450,6 @@ - - - - - - - - - - - @@ -3875,17 +3509,6 @@ - - - - - - - - - - - @@ -3921,17 +3544,6 @@ - - - - - - - - - - - @@ -3967,17 +3579,6 @@ - - - - - - - - - - - @@ -4013,17 +3614,6 @@ - - - - - - - - - - - @@ -4218,19 +3808,6 @@ - - - - - - - - - - - - - @@ -4293,14 +3870,6 @@ - - - - - - - - @@ -4392,6 +3961,14 @@ + + + + + + + + @@ -4416,22 +3993,6 @@ - - - - - - - - - - - - - - - - @@ -4458,22 +4019,6 @@ - - - - - - - - - - - - - - - - @@ -4882,14 +4427,6 @@ - - - - - - - - diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java index a79282be..dd594344 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java @@ -5,6 +5,7 @@ import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; import it.pagopa.tech.lollipop.consumer.model.CommandResult; import it.pagopa.tech.lollipop.consumer.spring.converter.LollipopConsumerRequestConverter; +import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.AllArgsConstructor; @@ -12,8 +13,6 @@ import org.apache.commons.logging.LogFactory; import org.springframework.web.servlet.HandlerInterceptor; -import java.io.IOException; - /** * Instance of a Spring Http {@link HandlerInterceptor}, to be used for Lollipop Request validations */ @@ -24,7 +23,6 @@ public class HttpVerifierHandlerInterceptor implements HandlerInterceptor { private static final Log log = LogFactory.getLog(HttpVerifierHandlerInterceptor.class); /** - * * @param request current HTTP request * @param response current HTTP response * @param handler chosen handler to execute, for type and/or instance evaluation @@ -33,8 +31,8 @@ public class HttpVerifierHandlerInterceptor implements HandlerInterceptor { */ @Override public boolean preHandle( - HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { - + HttpServletRequest request, HttpServletResponse response, Object handler) + throws IOException { LollipopConsumerCommand lollipopConsumerCommand = consumerCommandBuilder.createCommand( diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java index 80ef1008..a860d76e 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java @@ -15,8 +15,8 @@ import org.springframework.context.annotation.Configuration; /** - * Instance of Spring configuration of the core elements, the implementations of the related services - * are delegated to external configurations + * Instance of Spring configuration of the core elements, the implementations of the related + * services are delegated to external configurations */ @Configuration public class HttpVerifierConfiguration { diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java index d3a41677..4e5a8017 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java @@ -6,9 +6,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationPropertiesScan; -/** - * Spring instance of the {@link LollipopConsumerRequestConfig} - */ +/** Spring instance of the {@link LollipopConsumerRequestConfig} */ @ConfigurationProperties(prefix = "lollipop.core.config") @ConfigurationPropertiesScan @NoArgsConstructor diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java index d284a207..5245c351 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java @@ -9,13 +9,12 @@ import javax.servlet.http.HttpServletRequest; import org.springframework.util.StreamUtils; -/** - * Class to be used for conversion of the http requests to be validated - */ +/** Class to be used for conversion of the http requests to be validated */ public class LollipopConsumerRequestConverter { /** * Utility method to be used to generate a LollipopConsumerRequest + * * @param httpServletRequest http request to be converted into a lollipop request * @return instance of {@link LollipopConsumerRequest} produced from the httpServletRequest * @throws IOException exception return if body extraction fails diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java index d15035b6..4be6c840 100644 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java @@ -98,7 +98,7 @@ public void testWithinvalidPayloadRequestReturnsUnauthorized() { String signatureInput = "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" - + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; var signature = "sig123=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; @@ -119,9 +119,9 @@ public void testWithinvalidPayloadRequestReturnsUnauthorized() { .add( "x-pagopa-lollipop-public-key", "eyJrdHkiOiJFQyIsIngiOiJGcUZEd" - + "XdFZ3U0TVVYRVJQTVZMLTg1cEd2MkQzWW1MNEoxZ2ZNa2RiYzI0IiwieSI6Im" - + "hkVjBveG1XRlN4TW9KVURwZGlocjc2clM4VlJCRXFNRmViWXlBZks5LWsiLCJjcnYiO" - + "iJQLTI1NiJ9"); + + "XdFZ3U0TVVYRVJQTVZMLTg1cEd2MkQzWW1MNEoxZ2ZNa2RiYzI0IiwieSI6Im" + + "hkVjBveG1XRlN4TW9KVURwZGlocjc2clM4VlJCRXFNRmViWXlBZks5LWsiLCJjcnYiO" + + "iJQLTI1NiJ9"); request.getHeaders() .add( "x-pagopa-lollipop-assertion-ref", diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java index e61a3308..d483c543 100644 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java @@ -10,7 +10,9 @@ import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; import it.pagopa.tech.lollipop.consumer.http_verifier.visma.VismaHttpMessageVerifierFactory; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; -import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImplStub; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImpl; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -29,7 +31,8 @@ public HttpMessageVerifierFactory httpMessageVerifierFactory() throws Exception @Bean public IdpCertProviderFactory idpCertProviderFactory() { - return new IdpCertProviderFactoryImplStub(); + return new IdpCertProviderFactoryImpl( + new IdpCertSimpleClientProvider(IdpCertSimpleClientConfig.builder().build())); } @Bean From 79f5978bc24a4127dab3b2515ee48acd37829058 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 18 Apr 2023 19:46:15 +0200 Subject: [PATCH 230/403] [SLS-12] Updated verification-metadata.xml --- gradle/verification-metadata.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index ba9b6699..47338276 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -3397,6 +3397,9 @@ + + + From 311b90d673e5a1f85ae8cb140c1b2717864d1371 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 18 Apr 2023 19:56:40 +0200 Subject: [PATCH 231/403] [SLS-12] Updated build.gradle --- assertion-rest-client-native/build.gradle | 2 -- spring-impl/build.gradle | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/assertion-rest-client-native/build.gradle b/assertion-rest-client-native/build.gradle index 37a69bc4..cd735ddd 100644 --- a/assertion-rest-client-native/build.gradle +++ b/assertion-rest-client-native/build.gradle @@ -10,9 +10,7 @@ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' - id "java-test-fixtures" id("io.freefair.lombok") version "8.0.0" -/*id("org.openapi.generator") version "6.5.0"*/ } group 'it.pagopa.tech' diff --git a/spring-impl/build.gradle b/spring-impl/build.gradle index 24995c0d..626784c7 100644 --- a/spring-impl/build.gradle +++ b/spring-impl/build.gradle @@ -25,7 +25,7 @@ dependencies { //Mockserver for testing api testImplementation 'org.mock-server:mockserver-netty:5.15.0' testImplementation project(':http-verifier') - testImplementation testFixtures(project(':assertion-rest-client-native')) + testImplementation project(':assertion-rest-client-native') testImplementation project(':identity-service-rest-client-native') } From 3ecdc4ea53503671209a6c1a5f6b701466e11fc0 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 18 Apr 2023 20:05:32 +0200 Subject: [PATCH 232/403] [SLS-12] Updated build.gradle --- gradle/verification-metadata.xml | 113 +++++++++++++++++++++++++++++++ spring-impl/build.gradle | 1 - 2 files changed, 113 insertions(+), 1 deletion(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 47338276..5267a29c 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -191,6 +191,11 @@ + + + + + @@ -234,6 +239,11 @@ + + + + + @@ -305,6 +315,14 @@ + + + + + + + + @@ -362,6 +380,14 @@ + + + + + + + + @@ -417,6 +443,14 @@ + + + + + + + + @@ -460,6 +494,7 @@ + @@ -495,6 +530,9 @@ + + + @@ -514,6 +552,7 @@ + @@ -535,6 +574,22 @@ + + + + + + + + + + + + + + + + @@ -591,6 +646,22 @@ + + + + + + + + + + + + + + + + @@ -604,6 +675,7 @@ + @@ -2283,6 +2355,14 @@ + + + + + + + + @@ -2301,6 +2381,14 @@ + + + + + + + + @@ -2322,6 +2410,11 @@ + + + + + @@ -4028,6 +4121,16 @@ + + + + + + + + + + @@ -4062,6 +4165,16 @@ + + + + + + + + + + diff --git a/spring-impl/build.gradle b/spring-impl/build.gradle index 626784c7..ee1d2f7f 100644 --- a/spring-impl/build.gradle +++ b/spring-impl/build.gradle @@ -1,7 +1,6 @@ plugins { id 'java-library' id("io.freefair.lombok") version "8.0.0" - id 'org.springframework.boot' version '2.7.10' id 'io.spring.dependency-management' version '1.0.15.RELEASE' } From 6a979c46081766cd15eb129b7f9e289c07ecdae2 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 19 Apr 2023 09:48:50 +0200 Subject: [PATCH 233/403] [SLS-12] Updated build.gradle --- gradle/verification-metadata.xml | 205 +++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 5267a29c..0e779214 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -11,22 +11,27 @@ + + + + + @@ -178,6 +183,7 @@ + @@ -193,6 +199,7 @@ + @@ -226,11 +233,13 @@ + + @@ -241,6 +250,7 @@ + @@ -298,9 +308,11 @@ + + @@ -317,9 +329,11 @@ + + @@ -363,9 +377,11 @@ + + @@ -382,9 +398,11 @@ + + @@ -420,9 +438,11 @@ + + @@ -445,9 +465,11 @@ + + @@ -515,9 +537,11 @@ + + @@ -531,6 +555,7 @@ + @@ -565,30 +590,40 @@ + + + + + + + + + + @@ -600,20 +635,25 @@ + + + + + @@ -637,33 +677,44 @@ + + + + + + + + + + + @@ -1214,6 +1265,7 @@ + @@ -1299,9 +1351,11 @@ + + @@ -1867,14 +1921,17 @@ + + + @@ -2161,6 +2218,7 @@ + @@ -2176,14 +2234,17 @@ + + + @@ -2210,6 +2271,7 @@ + @@ -2240,6 +2302,7 @@ + @@ -2357,9 +2420,11 @@ + + @@ -2383,9 +2448,11 @@ + + @@ -2412,6 +2479,7 @@ + @@ -2579,6 +2647,7 @@ + @@ -2755,19 +2824,23 @@ + + + + @@ -2778,9 +2851,11 @@ + + @@ -2874,25 +2949,31 @@ + + + + + + @@ -2966,9 +3047,11 @@ + + @@ -2990,6 +3073,7 @@ + @@ -3250,6 +3334,7 @@ + @@ -3323,38 +3408,47 @@ + + + + + + + + + @@ -3477,6 +3571,7 @@ + @@ -3486,6 +3581,7 @@ + @@ -3494,6 +3590,7 @@ + @@ -3537,12 +3634,15 @@ + + + @@ -3596,12 +3696,15 @@ + + + @@ -3631,12 +3734,15 @@ + + + @@ -3701,12 +3807,15 @@ + + + @@ -3732,12 +3841,15 @@ + + + @@ -3767,12 +3879,15 @@ + + + @@ -3798,12 +3913,15 @@ + + + @@ -3898,9 +4016,11 @@ + + @@ -3916,9 +4036,11 @@ + + @@ -3960,9 +4082,11 @@ + + @@ -3978,6 +4102,7 @@ + @@ -4067,25 +4192,31 @@ + + + + + + @@ -4101,17 +4232,21 @@ + + + + @@ -4123,11 +4258,13 @@ + + @@ -4167,11 +4304,13 @@ + + @@ -4197,32 +4336,39 @@ + + + + + + + @@ -4252,56 +4398,71 @@ + + + + + + + + + + + + + + + @@ -4315,45 +4476,57 @@ + + + + + + + + + + + + @@ -4364,23 +4537,29 @@ + + + + + + @@ -4415,89 +4594,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -4581,9 +4784,11 @@ + + From 1044e28e799492aab7011bef71ab5110dfb023c4 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 19 Apr 2023 10:28:11 +0200 Subject: [PATCH 234/403] [SLS-12] Updated build.gradle --- gradle/verification-metadata.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 0e779214..71aae894 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -332,6 +332,9 @@ + + + @@ -401,6 +404,9 @@ + + + @@ -3570,6 +3576,9 @@ + + + @@ -3828,6 +3837,9 @@ + + + @@ -3900,6 +3912,9 @@ + + + @@ -3934,6 +3949,9 @@ + + + From c13910b1a076c26932896820a23372807f60a2a3 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 19 Apr 2023 11:02:58 +0200 Subject: [PATCH 235/403] [SLS-12] Updated build.gradle --- gradle/verification-metadata.xml | 751 +++++++++++++++++++++++++++++++ 1 file changed, 751 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 71aae894..2861e753 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -11,26 +11,31 @@ + + + + + @@ -42,92 +47,110 @@ + + + + + + + + + + + + + + + + + + @@ -140,6 +163,7 @@ + @@ -151,12 +175,14 @@ + + @@ -183,6 +209,7 @@ + @@ -199,12 +226,14 @@ + + @@ -222,6 +251,7 @@ + @@ -233,12 +263,14 @@ + + @@ -250,12 +282,14 @@ + + @@ -267,12 +301,14 @@ + + @@ -290,10 +326,12 @@ + + @@ -308,10 +346,12 @@ + + @@ -329,6 +369,7 @@ + @@ -336,12 +377,14 @@ + + @@ -350,6 +393,7 @@ + @@ -362,10 +406,12 @@ + + @@ -380,10 +426,12 @@ + + @@ -401,6 +449,7 @@ + @@ -408,12 +457,14 @@ + + @@ -422,6 +473,7 @@ + @@ -434,20 +486,24 @@ + + + + @@ -471,16 +527,22 @@ + + + + + + @@ -513,14 +575,17 @@ + + + @@ -543,24 +608,41 @@ + + + + + + + + + + + + + + + + + @@ -580,8 +662,16 @@ + + + + + + + + @@ -596,34 +686,51 @@ + + + + + + + + + + + + + + + + + @@ -641,34 +748,53 @@ + + + + + + + + + + + + + + + + + + + @@ -683,34 +809,51 @@ + + + + + + + + + + + + + + + + + @@ -720,6 +863,7 @@ + @@ -729,6 +873,13 @@ + + + + + + + @@ -737,10 +888,12 @@ + + @@ -761,10 +914,12 @@ + + @@ -779,10 +934,12 @@ + + @@ -797,80 +954,96 @@ + + + + + + + + + + + + + + + + @@ -914,30 +1087,36 @@ + + + + + + @@ -960,6 +1139,7 @@ + @@ -1002,10 +1182,12 @@ + + @@ -1028,16 +1210,19 @@ + + + @@ -1054,158 +1239,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1222,20 +1438,24 @@ + + + + @@ -1250,16 +1470,19 @@ + + + @@ -1271,106 +1494,126 @@ + + + + + + + + + + + + + + + + + + + + @@ -1393,50 +1636,60 @@ + + + + + + + + + + @@ -1461,42 +1714,50 @@ + + + + + + + + @@ -1513,10 +1774,12 @@ + + @@ -1531,10 +1794,12 @@ + + @@ -1549,10 +1814,12 @@ + + @@ -1567,10 +1834,12 @@ + + @@ -1585,10 +1854,12 @@ + + @@ -1603,10 +1874,12 @@ + + @@ -1621,10 +1894,12 @@ + + @@ -1639,10 +1914,12 @@ + + @@ -1657,6 +1934,7 @@ + @@ -1668,10 +1946,12 @@ + + @@ -1686,10 +1966,12 @@ + + @@ -1704,10 +1986,12 @@ + + @@ -1722,6 +2006,7 @@ + @@ -1733,10 +2018,12 @@ + + @@ -1751,10 +2038,12 @@ + + @@ -1782,6 +2071,7 @@ + @@ -1796,10 +2086,12 @@ + + @@ -1819,10 +2111,12 @@ + + @@ -1837,10 +2131,12 @@ + + @@ -1852,6 +2148,7 @@ + @@ -1866,10 +2163,12 @@ + + @@ -1884,10 +2183,12 @@ + + @@ -1902,10 +2203,12 @@ + + @@ -1927,16 +2230,19 @@ + + + @@ -1951,10 +2257,12 @@ + + @@ -1969,10 +2277,12 @@ + + @@ -1987,10 +2297,12 @@ + + @@ -2005,10 +2317,12 @@ + + @@ -2023,10 +2337,12 @@ + + @@ -2038,6 +2354,7 @@ + @@ -2049,6 +2366,7 @@ + @@ -2063,10 +2381,12 @@ + + @@ -2081,10 +2401,12 @@ + + @@ -2099,10 +2421,12 @@ + + @@ -2114,16 +2438,19 @@ + + + @@ -2138,10 +2465,12 @@ + + @@ -2156,6 +2485,7 @@ + @@ -2167,10 +2497,12 @@ + + @@ -2185,10 +2517,12 @@ + + @@ -2203,10 +2537,12 @@ + + @@ -2221,45 +2557,54 @@ + + + + + + + + + @@ -2274,29 +2619,35 @@ + + + + + + @@ -2308,48 +2659,57 @@ + + + + + + + + + @@ -2364,10 +2724,12 @@ + + @@ -2392,26 +2754,31 @@ + + + + + @@ -2426,20 +2793,24 @@ + + + + @@ -2454,26 +2825,31 @@ + + + + + @@ -2485,24 +2861,28 @@ + + + + @@ -2533,26 +2913,31 @@ + + + + + @@ -2575,20 +2960,24 @@ + + + + @@ -2618,12 +3007,14 @@ + + @@ -2635,42 +3026,49 @@ + + + + + + + @@ -2685,48 +3083,57 @@ + + + + + + + + + @@ -2738,38 +3145,45 @@ + + + + + + + @@ -2784,6 +3198,7 @@ + @@ -2795,6 +3210,7 @@ + @@ -2806,16 +3222,19 @@ + + + @@ -2830,22 +3249,26 @@ + + + + @@ -2857,182 +3280,216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3041,80 +3498,95 @@ + + + + + + + + + + + + + + + @@ -3123,6 +3595,7 @@ + @@ -3145,10 +3618,12 @@ + + @@ -3160,52 +3635,62 @@ + + + + + + + + + + @@ -3225,16 +3710,19 @@ + + + @@ -3246,18 +3734,21 @@ + + + @@ -3269,48 +3760,57 @@ + + + + + + + + + @@ -3322,82 +3822,98 @@ + + + + + + + + + + + + + + + + @@ -3414,46 +3930,55 @@ + + + + + + + + + @@ -3465,10 +3990,12 @@ + + @@ -3488,10 +4015,12 @@ + + @@ -3506,10 +4035,12 @@ + + @@ -3524,10 +4055,12 @@ + + @@ -3542,10 +4075,12 @@ + + @@ -3561,6 +4096,7 @@ + @@ -3571,6 +4107,7 @@ + @@ -3580,16 +4117,19 @@ + + + @@ -3599,6 +4139,7 @@ + @@ -3608,6 +4149,7 @@ + @@ -3617,46 +4159,55 @@ + + + + + + + + + @@ -3665,22 +4216,26 @@ + + + + @@ -3689,36 +4244,43 @@ + + + + + + + @@ -3727,36 +4289,43 @@ + + + + + + + @@ -3765,16 +4334,19 @@ + + + @@ -3792,6 +4364,7 @@ + @@ -3800,30 +4373,36 @@ + + + + + + @@ -3843,30 +4422,36 @@ + + + + + + @@ -3875,30 +4460,36 @@ + + + + + + @@ -3918,24 +4509,29 @@ + + + + + @@ -3955,74 +4551,88 @@ + + + + + + + + + + + + + + @@ -4034,98 +4644,117 @@ + + + + + + + + + + + + + + + + + + + @@ -4137,10 +4766,12 @@ + + @@ -4176,26 +4807,31 @@ + + + + + @@ -4210,98 +4846,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + @@ -4316,30 +4977,41 @@ + + + + + + + + + + + @@ -4354,132 +5026,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -4494,56 +5192,68 @@ + + + + + + + + + + + + @@ -4555,28 +5265,34 @@ + + + + + + @@ -4612,112 +5328,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -4766,56 +5506,67 @@ + + + + + + + + + + + From ffdd4913ccce66fd824e0c1440b7f10fc218a5f7 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 19 Apr 2023 11:12:51 +0200 Subject: [PATCH 236/403] [SLS-12] Updated build.gradle --- gradle/verification-metadata.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 2861e753..f43203c9 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -718,6 +718,9 @@ + + + @@ -781,6 +784,9 @@ + + + @@ -841,6 +847,9 @@ + + + From e334dd5097d70319d35c4177027aff9b52c59566 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 19 Apr 2023 11:22:59 +0200 Subject: [PATCH 237/403] [SLS-12] Updated build.gradle --- .github/workflows/pr_scan.yml | 1 + build.gradle | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 1fd11afb..fbbff157 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -63,6 +63,7 @@ jobs: -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 }} diff --git a/build.gradle b/build.gradle index 794c60ff..1ea508d3 100644 --- a/build.gradle +++ b/build.gradle @@ -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 @@ -146,7 +155,6 @@ subprojects { properties { property "sonar.sources", "src/main/java" property "sonar.tests", "src/test/java" - property "sonar.java.binaries" "build/classes/java/main" } } From e51c27501899eb17627e39b2f263c5c43ce3752f Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 19 Apr 2023 11:33:29 +0200 Subject: [PATCH 238/403] [SLS-12] Updated build.gradle --- gradle/verification-metadata.xml | 56 ++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index f43203c9..58dfbef5 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1094,6 +1094,20 @@ + + + + + + + + + + + + + + @@ -4214,6 +4228,12 @@ + + + + + + @@ -4287,6 +4307,12 @@ + + + + + + @@ -4332,6 +4358,12 @@ + + + + + + @@ -4416,6 +4448,12 @@ + + + + + + @@ -4458,6 +4496,12 @@ + + + + + + @@ -4503,6 +4547,12 @@ + + + + + + @@ -4545,6 +4595,12 @@ + + + + + + From a3706835f7adf2fdd0e44816ee57651a8d0c6b15 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 19 Apr 2023 11:45:56 +0200 Subject: [PATCH 239/403] [SLS-12] Updated build.gradle --- .github/workflows/pr_scan.yml | 2 +- build.gradle | 7 +++++++ redis-storage/src/test/resources/dummydata | 0 test-coverage/src/test/resources/dummydata | 0 4 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 redis-storage/src/test/resources/dummydata create mode 100644 test-coverage/src/test/resources/dummydata diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index fbbff157..dfd77b43 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -57,7 +57,7 @@ jobs: with: sarif_file: ${{ steps.scan.outputs.sarif }} - name: Run Sonar Scanner - run: ./gradlew sonarqube --info + run: ./gradlew sonar --info -Dsonar.organization=pagopa -Dsonar.projectKey=${{ env.PROJECT_KEY }} -Dsonar.coverage.jacoco.xmlReportPaths=test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml diff --git a/build.gradle b/build.gradle index 1ea508d3..e2a8cbcb 100644 --- a/build.gradle +++ b/build.gradle @@ -163,6 +163,7 @@ subprojects { finalizedBy jacocoTestReport // report is always generated after tests run jacoco { excludes = ["**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*"] + } } jacocoTestReport { @@ -174,12 +175,18 @@ subprojects { } project(":test-coverage") { + sonar { + skipProject = true + } sonarqube { skipProject = true } } project(":redis-storage") { + sonar { + skipProject = true + } sonarqube { skipProject = true } diff --git a/redis-storage/src/test/resources/dummydata b/redis-storage/src/test/resources/dummydata new file mode 100644 index 00000000..e69de29b diff --git a/test-coverage/src/test/resources/dummydata b/test-coverage/src/test/resources/dummydata new file mode 100644 index 00000000..e69de29b From f84b65fdbb36587ecf42fbad411db4ba42dce9e5 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 19 Apr 2023 12:16:21 +0200 Subject: [PATCH 240/403] [core-sprint3-fixes] Updated build.gradle and pr_scan.yml --- .github/workflows/pr_scan.yml | 2 +- build.gradle | 3 +++ test-coverage/build.gradle | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index dfd77b43..b7cf167a 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -60,7 +60,7 @@ jobs: run: ./gradlew sonar --info -Dsonar.organization=pagopa -Dsonar.projectKey=${{ env.PROJECT_KEY }} - -Dsonar.coverage.jacoco.xmlReportPaths=test-coverage/build/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" diff --git a/build.gradle b/build.gradle index e2a8cbcb..bcee8be2 100644 --- a/build.gradle +++ b/build.gradle @@ -168,6 +168,9 @@ subprojects { } jacocoTestReport { dependsOn test // tests are required to run before generating the report + reports { + xml.enabled true + } } } diff --git a/test-coverage/build.gradle b/test-coverage/build.gradle index 8a804e88..894f7759 100644 --- a/test-coverage/build.gradle +++ b/test-coverage/build.gradle @@ -18,6 +18,7 @@ dependencies { jacocoAggregation project(':http-verifier') jacocoAggregation project(':identity-service-rest-client-native') jacocoAggregation project(':assertion-rest-client-native') + jacocoAggregation project(':spring-impl') } reporting { @@ -37,7 +38,8 @@ testCodeCoverageReport { [project(':http-verifier'), project(':identity-service-rest-client-native'), project(':assertion-rest-client-native'), - project(':core') + project(':core'), + project(':spring-impl') ].collect { it.fileTree(dir: "${it.buildDir}/classes", exclude: [ "**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*" From 3b3f13d7b7755df71a5c73b4d3280f19e2d2ea59 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 19 Apr 2023 12:46:37 +0200 Subject: [PATCH 241/403] [core-sprint3-fixes] Updated pr_scan.yml --- .github/workflows/pr_scan.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index b7cf167a..c5d14fc4 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -2,6 +2,8 @@ name: Check Build and Anchore on PR on: pull_request: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: env: DOCKERFILE: Dockerfile.test-only @@ -56,7 +58,8 @@ jobs: if: always() with: sarif_file: ${{ steps.scan.outputs.sarif }} - - name: Run Sonar Scanner + - name: Run Sonar Scanner on Pull Request + if: ${{ github.event_name == 'pull_request' }} run: ./gradlew sonar --info -Dsonar.organization=pagopa -Dsonar.projectKey=${{ env.PROJECT_KEY }} @@ -68,3 +71,14 @@ jobs: -Dsonar.pullrequest.key=${{ github.event.pull_request.number }} -Dsonar.pullrequest.branch=${{ github.head_ref }} -Dsonar.pullrequest.base=${{ github.base_ref }} + - name: Run Sonar Scanner + if: ${{ github.event_name != 'pull_request' }} + run: ./gradlew sonar --info + -Dsonar.organization=pagopa + -Dsonar.projectKey=${{ env.PROJECT_KEY }} + -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.branch.name=${{ github.head_ref }} From 31bece5178fa5125e2492004a48f765ed302ea8c Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 19 Apr 2023 13:04:09 +0200 Subject: [PATCH 242/403] [core-sprint3-fixes] Fixing sonar smells --- .../impl/AssertionVerifierServiceImpl.java | 15 ++++++++++----- ...lipopConsumerRequestValidationServiceImpl.java | 5 ++++- .../spring/config/HttpVerifierConfiguration.java | 11 +++++------ .../LollipopConsumerRequestConverter.java | 2 ++ ...VerifierHandlerInterceptorIntegrationTest.java | 5 +++-- 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index c53e6c5b..37fc3ffc 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -273,11 +273,7 @@ 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"); - } + publicKey = getPublicKey(publicKey); thumbprint = ThumbprintUtils.compute(inResponseToAlgorithm, JWK.parse(publicKey)); } catch (JOSEException | ParseException e) { String errMsg = String.format("Can not calculate JwkThumbprint: %S", e.getMessage()); @@ -297,4 +293,13 @@ private String calculateThumbprint(String inResponseToAlgorithm, String publicKe } return calculatedThumbprint; } + + private String getPublicKey(String publicKey) { + try { + publicKey = new String(Base64.getDecoder().decode(publicKey)); + } catch (Exception e) { + log.log(Level.FINE, "Key not in Base64"); + } + return publicKey; + } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java index e4712b83..9aeed6e2 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java @@ -14,8 +14,11 @@ import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; import java.util.Base64; import java.util.Map; +import java.util.logging.Level; import java.util.regex.Pattern; +import lombok.extern.java.Log; +@Log public class LollipopConsumerRequestValidationServiceImpl implements LollipopConsumerRequestValidationService { @@ -52,7 +55,7 @@ private void validatePublicKey(String publicKey) try { publicKey = new String(Base64.getDecoder().decode(publicKey.getBytes())); } catch (Exception e) { - // + log.log(Level.FINE, "Key not in Base64"); } if (isNotValidPublicKey(publicKey, ECPublicKey.class) diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java index a860d76e..a95dfa1b 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java @@ -10,7 +10,6 @@ import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; import it.pagopa.tech.lollipop.consumer.service.impl.LollipopConsumerRequestValidationServiceImpl; import it.pagopa.tech.lollipop.consumer.spring.HttpVerifierHandlerInterceptor; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -21,22 +20,22 @@ @Configuration public class HttpVerifierConfiguration { - @Autowired private SpringLollipopConsumerRequestConfig springLollipopConsumerRequestConfig; - @Bean public LollipopConsumerFactoryHelper lollipopConsumerFactoryHelper( HttpMessageVerifierFactory httpMessageVerifierFactory, IdpCertProviderFactory idpCertProviderFactory, - AssertionServiceFactory assertionServiceFactory) { + AssertionServiceFactory assertionServiceFactory, + LollipopConsumerRequestValidationService lollipopConsumerRequestValidationService) { return new LollipopConsumerFactoryHelper( httpMessageVerifierFactory, idpCertProviderFactory, assertionServiceFactory, - getLollipopConsumerRequestValidationService()); + lollipopConsumerRequestValidationService); } @Bean - public LollipopConsumerRequestValidationService getLollipopConsumerRequestValidationService() { + public LollipopConsumerRequestValidationService getLollipopConsumerRequestValidationService( + SpringLollipopConsumerRequestConfig springLollipopConsumerRequestConfig) { return new LollipopConsumerRequestValidationServiceImpl( springLollipopConsumerRequestConfig); } diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java index 5245c351..ec517183 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java @@ -12,6 +12,8 @@ /** Class to be used for conversion of the http requests to be validated */ public class LollipopConsumerRequestConverter { + private LollipopConsumerRequestConverter() {} + /** * Utility method to be used to generate a LollipopConsumerRequest * diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java index 4be6c840..c89d6ea3 100644 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java @@ -43,7 +43,7 @@ public static void startServer() { @Autowired private HttpVerifierHandlerInterceptor interceptor; @Test - public void testWithValidRequestReturnsSuccess() { + void testWithValidRequestReturnsSuccess() { AssertionSimpleClientTestUtils.createExpectationAssertionFound(); String signatureInput = @@ -93,7 +93,8 @@ public void testWithValidRequestReturnsSuccess() { Assertions.assertEquals(200, response.getStatusCodeValue()); } - public void testWithinvalidPayloadRequestReturnsUnauthorized() { + @Test + void testWithinvalidPayloadRequestReturnsUnauthorized() { AssertionSimpleClientTestUtils.createExpectationAssertionFound(); String signatureInput = From efbe46548e1a6a80405e03d549649a738d5fd528 Mon Sep 17 00:00:00 2001 From: giomella Date: Wed, 19 Apr 2023 10:04:45 +0200 Subject: [PATCH 243/403] [SLS-25] added signature validation to the assertion verification flow. --- core/build.gradle | 5 + .../config/LollipopConsumerRequestConfig.java | 2 + .../ErrorRetrievingIdpCertDataException.java | 49 ++++++++ .../ErrorValidatingAssertionSignature.java | 49 ++++++++ .../service/AssertionVerifierService.java | 12 +- .../impl/AssertionVerifierServiceImpl.java | 115 +++++++++++++++--- 6 files changed, 207 insertions(+), 25 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingIdpCertDataException.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java diff --git a/core/build.gradle b/core/build.gradle index 0660be4d..76515282 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -45,6 +45,11 @@ dependencies { implementation 'javax.inject:javax.inject:1' implementation 'com.nimbusds:nimbus-jose-jwt:9.31' implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.2' + implementation 'org.opensaml:opensaml-core:4.0.1' + implementation 'org.opensaml:opensaml-saml-api:4.0.1' + implementation 'org.opensaml:opensaml-saml-impl:4.0.1' + implementation 'org.apache.wss4j:wss4j-ws-security-common:2.4.1' + // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.mockito:mockito-core:5.2.0' diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index 74ae215f..ee6e7515 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -42,4 +42,6 @@ public class LollipopConsumerRequestConfig { @Builder.Default private String assertionNotBeforeTag = "Conditions"; @Builder.Default private String assertionFiscalCodeTag = "Attribute"; @Builder.Default private String assertionInResponseToTag = "SubjectConfirmationData"; + @Builder.Default private String assertionEntityIdTag = "Issuer"; + @Builder.Default private String assertionInstantTag = "Assertion"; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingIdpCertDataException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingIdpCertDataException.java new file mode 100644 index 00000000..a77f0776 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingIdpCertDataException.java @@ -0,0 +1,49 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +import java.util.Objects; + +/** Thrown in case of problems on retrieving the IDP data */ +public class ErrorRetrievingIdpCertDataException extends Exception { + + /** Error code of this exception */ + private final ErrorCode errorCode; + + /** + * Constructs new exception with provided error code and message + * + * @param errorCode Error code + * @param message Detail message + */ + public ErrorRetrievingIdpCertDataException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Constructs new exception with provided error code, message and cause + * + * @param errorCode Error code + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public ErrorRetrievingIdpCertDataException(ErrorCode errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Returns error code + * + * @return Error code of this exception + */ + public ErrorCode getErrorCode() { + return errorCode; + } + + /** Error codes to classify Lollipop Request Exceptions */ + public enum ErrorCode { + ENTITY_ID_FIELD_NOT_FOUND, + INSTANT_FIELD_NOT_FOUND, + IDP_CERT_DATA_NOT_FOUND + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java new file mode 100644 index 00000000..5368ba68 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java @@ -0,0 +1,49 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +import java.util.Objects; + +/** Thrown in case of problems when validating assertion signature */ +public class ErrorValidatingAssertionSignature extends Exception { + + /** Error code of this exception */ + private final ErrorCode errorCode; + + /** + * Constructs new exception with provided error code and message + * + * @param errorCode Error code + * @param message Detail message + */ + public ErrorValidatingAssertionSignature(ErrorCode errorCode, String message) { + super(message); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Constructs new exception with provided error code, message and cause + * + * @param errorCode Error code + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public ErrorValidatingAssertionSignature(ErrorCode errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Returns error code + * + * @return Error code of this exception + */ + public ErrorCode getErrorCode() { + return errorCode; + } + + /** Error codes to classify Lollipop Request Exceptions */ + public enum ErrorCode { + ERROR_GENERATING_X509_CERTIFICATE, + ERROR_RETRIEVING_ASSERTION_SIGNATURE + + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java index 92df175d..2949d656 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java @@ -1,10 +1,7 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service; -import it.pagopa.tech.lollipop.consumer.exception.AssertionPeriodException; -import it.pagopa.tech.lollipop.consumer.exception.AssertionThumbprintException; -import it.pagopa.tech.lollipop.consumer.exception.AssertionUserIdException; -import it.pagopa.tech.lollipop.consumer.exception.ErrorRetrievingAssertionException; +import it.pagopa.tech.lollipop.consumer.exception.*; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; /** @@ -19,13 +16,14 @@ public interface AssertionVerifierService { * * @param request the Lollipop request * @return true if the assertion is valid - * @throws ErrorRetrievingAssertionException thrown for general errors in the verification - * process + * @throws ErrorRetrievingAssertionException thrown for errors when retrieving the assertion * @throws AssertionPeriodException thrown for error in assertion period validation * @throws AssertionThumbprintException thrown for error in assertion thumbprint validation * @throws AssertionUserIdException thrown for error in user id validation + * @throws ErrorRetrievingIdpCertDataException thrown for errors when retrieving the IDP data + * @throws ErrorValidatingAssertionSignature thrown for error in signature validation */ boolean validateLollipop(LollipopConsumerRequest request) throws ErrorRetrievingAssertionException, AssertionPeriodException, - AssertionThumbprintException, AssertionUserIdException; + AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingIdpCertDataException, ErrorValidatingAssertionSignature; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index 37fc3ffc..e8d7a563 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -14,6 +14,9 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; +import org.apache.wss4j.common.ext.WSSecurityException; +import org.apache.wss4j.common.saml.SAMLKeyInfo; +import org.apache.wss4j.common.saml.SamlAssertionWrapper; import java.io.IOException; import java.io.StringReader; import java.text.ParseException; @@ -22,20 +25,27 @@ 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.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; -@Log +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.*; + /** Standard implementation of {@link AssertionVerifierService} */ +@Log public class AssertionVerifierServiceImpl implements AssertionVerifierService { private final IdpCertProvider idpCertProvider; @@ -43,6 +53,8 @@ public class AssertionVerifierServiceImpl implements AssertionVerifierService { private final LollipopConsumerRequestConfig lollipopRequestConfig; private static final String IN_RESPONSE_TO = "InResponseTo"; + private static final String ISSUE_INSTANT = "IssueInstant"; + private static final String NOT_BEFORE = "NotBefore"; @Inject public AssertionVerifierServiceImpl( @@ -60,7 +72,7 @@ public AssertionVerifierServiceImpl( @Override public boolean validateLollipop(LollipopConsumerRequest request) throws ErrorRetrievingAssertionException, AssertionPeriodException, - AssertionThumbprintException, AssertionUserIdException { + AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingIdpCertDataException, ErrorValidatingAssertionSignature { Map headerParams = request.getHeaderParams(); SamlAssertion assertion = @@ -91,7 +103,8 @@ public boolean validateLollipop(LollipopConsumerRequest request) + " assertion"); } - return true; + List idpCertDataList = getIdpCertData(assertionDoc); + return validateSignature(assertionDoc, idpCertDataList); } private SamlAssertion getAssertion(String jwt, String assertionRef) @@ -111,16 +124,16 @@ private SamlAssertion getAssertion(String jwt, String assertionRef) } } - private boolean validateAssertionPeriod(Document assertionDoc) throws AssertionPeriodException { + protected boolean validateAssertionPeriod(Document assertionDoc) throws AssertionPeriodException { NodeList listElements = assertionDoc.getElementsByTagNameNS( lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionNotBeforeTag()); - if (listElements == null || listElements.getLength() <= 0) { + if (isElementNotFound(listElements, NOT_BEFORE)) { return false; } String notBefore = - listElements.item(0).getAttributes().getNamedItem("NotBefore").getNodeValue(); + listElements.item(0).getAttributes().getNamedItem(NOT_BEFORE).getNodeValue(); long notBeforeMilliseconds; try { @@ -142,7 +155,7 @@ private boolean validateAssertionPeriod(Document assertionDoc) throws AssertionP return 0 <= dateNowLessNotBefore && (dateNowLessNotBefore <= expiresAfterMilliseconds); } - private boolean validateUserId(LollipopConsumerRequest request, Document assertionDoc) + protected boolean validateUserId(LollipopConsumerRequest request, Document assertionDoc) throws AssertionUserIdException { String userIdHeader = request.getHeaderParams().get(lollipopRequestConfig.getUserIdHeader()); @@ -157,13 +170,13 @@ private boolean validateUserId(LollipopConsumerRequest request, Document asserti return userIdFromAssertion.equals(userIdHeader); } - private boolean validateInResponseTo(LollipopConsumerRequest request, Document assertionDoc) + protected boolean validateInResponseTo(LollipopConsumerRequest request, Document assertionDoc) throws AssertionThumbprintException { NodeList listElements = assertionDoc.getElementsByTagNameNS( lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionInResponseToTag()); - if (isInResponseToFieldFound(listElements)) { + if (isElementNotFound(listElements, IN_RESPONSE_TO)) { throw new AssertionThumbprintException( AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_FIELD_NOT_FOUND, "Missing request id in the retrieved saml assertion"); @@ -182,14 +195,64 @@ private boolean validateInResponseTo(LollipopConsumerRequest request, Document a return inResponseTo.equals(calculatedThumbprint) && inResponseTo.equals(assertionRefHeader); } - private IdpCertData getIdpCertData(SamlAssertion assertion) { - return null; + private List getIdpCertData(Document assertionDoc) throws ErrorRetrievingIdpCertDataException { + NodeList listElements = + assertionDoc.getElementsByTagNameNS( + lollipopRequestConfig.getSamlNamespaceAssertion(), + lollipopRequestConfig.getAssertionInstantTag()); + if (isElementNotFound(listElements, ISSUE_INSTANT)) { + throw new ErrorRetrievingIdpCertDataException(ErrorRetrievingIdpCertDataException.ErrorCode.INSTANT_FIELD_NOT_FOUND, "Missing instant field in the retrieved saml assertion"); + } + String instant = + listElements.item(0).getAttributes().getNamedItem(ISSUE_INSTANT).getNodeValue(); + + String entityId = getEntityId(listElements.item(0).getChildNodes()); + if (entityId == null) { + throw new ErrorRetrievingIdpCertDataException(ErrorRetrievingIdpCertDataException.ErrorCode.ENTITY_ID_FIELD_NOT_FOUND, "Missing entity id field in the retrieved saml assertion"); + } + try { + return idpCertProvider.getIdpCertData(instant, entityId); + } catch (CertDataNotFoundException e) { + throw new ErrorRetrievingIdpCertDataException(ErrorRetrievingIdpCertDataException.ErrorCode.IDP_CERT_DATA_NOT_FOUND, "Some error occurred in retrieving certification data from IDP", e); + } + } + + protected boolean validateSignature(Document assertionDoc, List idpCertDataList) throws ErrorValidatingAssertionSignature { + SamlAssertionWrapper wrapper; + try { + wrapper = new SamlAssertionWrapper((Element) assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionInstantTag()).item(0)); + } catch (WSSecurityException e) { + throw new ErrorValidatingAssertionSignature(ErrorValidatingAssertionSignature.ErrorCode.ERROR_RETRIEVING_ASSERTION_SIGNATURE, "Failed to retrieve signature from assertion", e); + } + + return validateSignature(idpCertDataList, wrapper); } - private boolean validateSignature(SamlAssertion assertion, IdpCertData idpCertData) { + private boolean validateSignature(List idpCertDataList, SamlAssertionWrapper wrapper) { + for (IdpCertData idpCertData : idpCertDataList) { + for (String certData : idpCertData.getCertData()) { + try { + X509Certificate x509Certificate = getX509Certificate(certData); + wrapper.verifySignature(new SAMLKeyInfo(new X509Certificate[] {x509Certificate})); + } catch (CertificateException | WSSecurityException e) { + // CertificateException: Failed to generate X509 certificate from IDP metadata + // or + // WSSecurityException: Failed to validate assertion signature + // TODO: se l'assertion non ha signature la validazione va in successo, corretto? + continue; + } + return true; + } + } return false; } + private X509Certificate getX509Certificate(String idpCertificate) throws CertificateException { + CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); + InputStream fileStream = new ByteArrayInputStream(Base64.getMimeDecoder().decode(idpCertificate)); + return (X509Certificate) certificateFactory.generateCertificate(fileStream); + } + private static Document buildDocumentFromAssertion(SamlAssertion assertion) throws ErrorRetrievingAssertionException { String stringXml = assertion.getAssertionData(); @@ -209,14 +272,13 @@ private static Document buildDocumentFromAssertion(SamlAssertion assertion) } } - private boolean isInResponseToFieldFound(NodeList listElements) { + private boolean isElementNotFound(NodeList listElements, String elementName) { return listElements == null || listElements.getLength() <= 0 || listElements.item(0) == null - || listElements.item(0).getAttributes() == null - || listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO) == null - || listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO).getNodeValue() - == null; + || !listElements.item(0).hasAttributes() + || listElements.item(0).getAttributes().getNamedItem(elementName) == null + || listElements.item(0).getAttributes().getNamedItem(elementName).getNodeValue() == null; } private String getUserIdFromAssertion(Document assertionDoc) throws AssertionUserIdException { @@ -294,6 +356,22 @@ private String calculateThumbprint(String inResponseToAlgorithm, String publicKe return calculatedThumbprint; } + private String getEntityId(NodeList listElements) { + if (listElements == null) { + return null; + } + for (int i = 0; i < listElements.getLength(); i++) { + Node item = listElements.item(i); + if (item != null + && item.getLocalName() != null + && item.getLocalName().equals(lollipopRequestConfig.getAssertionEntityIdTag()) + && item.getTextContent() != null) { + return item.getTextContent(); + } + } + return null; + } + private String getPublicKey(String publicKey) { try { publicKey = new String(Base64.getDecoder().decode(publicKey)); @@ -303,3 +381,4 @@ private String getPublicKey(String publicKey) { return publicKey; } } + From cf416ca85d082546e7bf1c97468d0163d426f576 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 19 Apr 2023 10:47:57 +0200 Subject: [PATCH 244/403] [SLS-25] Removed tag list exception - applied spotless - update metadata --- .../impl/LollipopConsumerCommandImpl.java | 4 + .../CertDataTagListNotFoundException.java | 15 - .../ErrorRetrievingIdpCertDataException.java | 4 +- .../ErrorValidatingAssertionSignature.java | 2 +- .../consumer/idp/IdpCertProvider.java | 3 +- .../consumer/idp/client/IdpCertClient.java | 4 +- .../idp/impl/IdpCertProviderImpl.java | 5 +- .../service/AssertionVerifierService.java | 3 +- .../impl/AssertionVerifierServiceImpl.java | 56 ++- .../impl/LollipopConsumerCommandImplTest.java | 30 +- .../AssertionVerifierServiceImplTest.java | 13 +- gradle/verification-metadata.xml | 415 ++++++++++++++++++ .../client/simple/IdpCertSimpleClient.java | 8 +- .../simple/IdpCertSimpleClientTest.java | 12 +- 14 files changed, 506 insertions(+), 68 deletions(-) delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index fc56f264..1aac9cb5 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -109,6 +109,10 @@ private CommandResult getAssertionVerificationResult(LollipopConsumerRequest req e.getErrorCode(), e.getMessage()); return buildCommandResult( AssertionVerificationResultCode.USER_ID_VALIDATION_ERROR.name(), message); + } catch (ErrorValidatingAssertionSignature e) { + throw new RuntimeException(e); // TODO + } catch (ErrorRetrievingIdpCertDataException e) { + throw new RuntimeException(e); // TODO } if (!result) { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java deleted file mode 100644 index 36739a40..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java +++ /dev/null @@ -1,15 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.exception; - -/** Thrown in case of problems retrieving idp certification tag list */ -public class CertDataTagListNotFoundException extends Exception { - /** - * Constructs new exception with provided message and cause - * - * @param message Detail message - * @param cause Exception causing the constructed one - */ - public CertDataTagListNotFoundException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingIdpCertDataException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingIdpCertDataException.java index a77f0776..bc0a5ca9 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingIdpCertDataException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingIdpCertDataException.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.exception; import java.util.Objects; @@ -26,7 +27,8 @@ public ErrorRetrievingIdpCertDataException(ErrorCode errorCode, String message) * @param message Detail message * @param cause Exception causing the constructed one */ - public ErrorRetrievingIdpCertDataException(ErrorCode errorCode, String message, Throwable cause) { + public ErrorRetrievingIdpCertDataException( + ErrorCode errorCode, String message, Throwable cause) { super(message, cause); this.errorCode = Objects.requireNonNull(errorCode); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java index 5368ba68..bd83065a 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.exception; import java.util.Objects; @@ -44,6 +45,5 @@ public ErrorCode getErrorCode() { public enum ErrorCode { ERROR_GENERATING_X509_CERTIFICATE, ERROR_RETRIEVING_ASSERTION_SIGNATURE - } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java index f2969e74..c977a5a8 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java @@ -2,12 +2,11 @@ package it.pagopa.tech.lollipop.consumer.idp; import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import java.util.List; public interface IdpCertProvider { List getIdpCertData(String assertionInstant, String entityId) - throws CertDataTagListNotFoundException, CertDataNotFoundException; + throws CertDataNotFoundException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java index 00f9c5b8..330af5bf 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java @@ -2,12 +2,10 @@ package it.pagopa.tech.lollipop.consumer.idp.client; import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import java.util.List; public interface IdpCertClient { - List getCertData(String entityId, String instant) - throws CertDataNotFoundException, CertDataTagListNotFoundException; + List getCertData(String entityId, String instant) throws CertDataNotFoundException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java index 8e269ca3..a5c5d04a 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java @@ -2,7 +2,6 @@ package it.pagopa.tech.lollipop.consumer.idp.impl; import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; @@ -31,14 +30,12 @@ public IdpCertProviderImpl(IdpCertClient idpCertClient) { * @param entityId Identity Provider ID * @param assertionInstant Assertion Issue Instant * @return the certifications issued before and after the timestamp instant - * @throws CertDataTagListNotFoundException if an error occurred retrieving the list of tags or - * filtering the tags with the instant * @throws CertDataNotFoundException if an error occurred retrieving the certification XML or if * data for the given entityId were not found */ @Override public List getIdpCertData(String assertionInstant, String entityId) - throws CertDataTagListNotFoundException, CertDataNotFoundException { + throws CertDataNotFoundException { if (assertionInstant == null || assertionInstant.isBlank() || entityId == null diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java index 2949d656..691c32b2 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java @@ -25,5 +25,6 @@ public interface AssertionVerifierService { */ boolean validateLollipop(LollipopConsumerRequest request) throws ErrorRetrievingAssertionException, AssertionPeriodException, - AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingIdpCertDataException, ErrorValidatingAssertionSignature; + AssertionThumbprintException, AssertionUserIdException, + ErrorRetrievingIdpCertDataException, ErrorValidatingAssertionSignature; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index e8d7a563..4fdc0b20 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -72,7 +72,8 @@ public AssertionVerifierServiceImpl( @Override public boolean validateLollipop(LollipopConsumerRequest request) throws ErrorRetrievingAssertionException, AssertionPeriodException, - AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingIdpCertDataException, ErrorValidatingAssertionSignature { + AssertionThumbprintException, AssertionUserIdException, + ErrorRetrievingIdpCertDataException, ErrorValidatingAssertionSignature { Map headerParams = request.getHeaderParams(); SamlAssertion assertion = @@ -124,7 +125,8 @@ private SamlAssertion getAssertion(String jwt, String assertionRef) } } - protected boolean validateAssertionPeriod(Document assertionDoc) throws AssertionPeriodException { + protected boolean validateAssertionPeriod(Document assertionDoc) + throws AssertionPeriodException { NodeList listElements = assertionDoc.getElementsByTagNameNS( lollipopRequestConfig.getSamlNamespaceAssertion(), @@ -195,50 +197,74 @@ protected boolean validateInResponseTo(LollipopConsumerRequest request, Document return inResponseTo.equals(calculatedThumbprint) && inResponseTo.equals(assertionRefHeader); } - private List getIdpCertData(Document assertionDoc) throws ErrorRetrievingIdpCertDataException { + private List getIdpCertData(Document assertionDoc) + throws ErrorRetrievingIdpCertDataException { NodeList listElements = assertionDoc.getElementsByTagNameNS( lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionInstantTag()); if (isElementNotFound(listElements, ISSUE_INSTANT)) { - throw new ErrorRetrievingIdpCertDataException(ErrorRetrievingIdpCertDataException.ErrorCode.INSTANT_FIELD_NOT_FOUND, "Missing instant field in the retrieved saml assertion"); + throw new ErrorRetrievingIdpCertDataException( + ErrorRetrievingIdpCertDataException.ErrorCode.INSTANT_FIELD_NOT_FOUND, + "Missing instant field in the retrieved saml assertion"); } String instant = listElements.item(0).getAttributes().getNamedItem(ISSUE_INSTANT).getNodeValue(); String entityId = getEntityId(listElements.item(0).getChildNodes()); if (entityId == null) { - throw new ErrorRetrievingIdpCertDataException(ErrorRetrievingIdpCertDataException.ErrorCode.ENTITY_ID_FIELD_NOT_FOUND, "Missing entity id field in the retrieved saml assertion"); + throw new ErrorRetrievingIdpCertDataException( + ErrorRetrievingIdpCertDataException.ErrorCode.ENTITY_ID_FIELD_NOT_FOUND, + "Missing entity id field in the retrieved saml assertion"); } try { return idpCertProvider.getIdpCertData(instant, entityId); } catch (CertDataNotFoundException e) { - throw new ErrorRetrievingIdpCertDataException(ErrorRetrievingIdpCertDataException.ErrorCode.IDP_CERT_DATA_NOT_FOUND, "Some error occurred in retrieving certification data from IDP", e); + throw new ErrorRetrievingIdpCertDataException( + ErrorRetrievingIdpCertDataException.ErrorCode.IDP_CERT_DATA_NOT_FOUND, + "Some error occurred in retrieving certification data from IDP", + e); } } - protected boolean validateSignature(Document assertionDoc, List idpCertDataList) throws ErrorValidatingAssertionSignature { + protected boolean validateSignature(Document assertionDoc, List idpCertDataList) + throws ErrorValidatingAssertionSignature { SamlAssertionWrapper wrapper; try { - wrapper = new SamlAssertionWrapper((Element) assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionInstantTag()).item(0)); + wrapper = + new SamlAssertionWrapper( + (Element) + assertionDoc + .getElementsByTagNameNS( + lollipopRequestConfig + .getSamlNamespaceAssertion(), + lollipopRequestConfig.getAssertionInstantTag()) + .item(0)); } catch (WSSecurityException e) { - throw new ErrorValidatingAssertionSignature(ErrorValidatingAssertionSignature.ErrorCode.ERROR_RETRIEVING_ASSERTION_SIGNATURE, "Failed to retrieve signature from assertion", e); + throw new ErrorValidatingAssertionSignature( + ErrorValidatingAssertionSignature.ErrorCode + .ERROR_RETRIEVING_ASSERTION_SIGNATURE, + "Failed to retrieve signature from assertion", + e); } return validateSignature(idpCertDataList, wrapper); } - private boolean validateSignature(List idpCertDataList, SamlAssertionWrapper wrapper) { + private boolean validateSignature( + List idpCertDataList, SamlAssertionWrapper wrapper) { for (IdpCertData idpCertData : idpCertDataList) { for (String certData : idpCertData.getCertData()) { try { X509Certificate x509Certificate = getX509Certificate(certData); - wrapper.verifySignature(new SAMLKeyInfo(new X509Certificate[] {x509Certificate})); + wrapper.verifySignature( + new SAMLKeyInfo(new X509Certificate[] {x509Certificate})); } catch (CertificateException | WSSecurityException e) { // CertificateException: Failed to generate X509 certificate from IDP metadata // or // WSSecurityException: Failed to validate assertion signature - // TODO: se l'assertion non ha signature la validazione va in successo, corretto? + // TODO: se l'assertion non ha signature la validazione va in successo, + // corretto? continue; } return true; @@ -249,7 +275,8 @@ private boolean validateSignature(List idpCertDataList, SamlAsserti private X509Certificate getX509Certificate(String idpCertificate) throws CertificateException { CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); - InputStream fileStream = new ByteArrayInputStream(Base64.getMimeDecoder().decode(idpCertificate)); + InputStream fileStream = + new ByteArrayInputStream(Base64.getMimeDecoder().decode(idpCertificate)); return (X509Certificate) certificateFactory.generateCertificate(fileStream); } @@ -278,7 +305,8 @@ private boolean isElementNotFound(NodeList listElements, String elementName) { || listElements.item(0) == null || !listElements.item(0).hasAttributes() || listElements.item(0).getAttributes().getNamedItem(elementName) == null - || listElements.item(0).getAttributes().getNamedItem(elementName).getNodeValue() == null; + || listElements.item(0).getAttributes().getNamedItem(elementName).getNodeValue() + == null; } private String getUserIdFromAssertion(Document assertionDoc) throws AssertionUserIdException { diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java index 18c673eb..1ed59441 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -44,7 +44,8 @@ void failedHttpMessageValidationThrowDigestException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doThrow( new LollipopDigestException( @@ -70,7 +71,8 @@ void failedHttpMessageValidationThrowSignatureException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, LollipopSignatureException, LollipopRequestContentValidationException, AssertionPeriodException, AssertionThumbprintException, - AssertionUserIdException, ErrorRetrievingAssertionException { + AssertionUserIdException, ErrorRetrievingAssertionException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doThrow( new LollipopSignatureException( @@ -117,7 +119,8 @@ void failedHttpMessageValidationWithoutThrowingException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doReturn(false) .when(messageVerifierServiceMock) @@ -141,7 +144,8 @@ void failedAssertionValidationWithoutThrowingException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doReturn(true) .when(messageVerifierServiceMock) @@ -167,7 +171,8 @@ void successLollipopRequestValidation() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doReturn(true) .when(messageVerifierServiceMock) @@ -191,7 +196,8 @@ void failedLollipopRequestValidation() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doThrow(LollipopRequestContentValidationException.class) .when(requestValidationServiceMock) @@ -213,7 +219,8 @@ void failedAssertionValidationThrowErrorRetrievingAssertionException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doReturn(true) .when(messageVerifierServiceMock) @@ -239,7 +246,8 @@ void failedAssertionValidationThrowAssertionPeriodException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doReturn(true) .when(messageVerifierServiceMock) @@ -265,7 +273,8 @@ void failedAssertionValidationThrowAssertionThumbprintException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doReturn(true) .when(messageVerifierServiceMock) @@ -291,7 +300,8 @@ void failedAssertionValidationThrowAssertionUserIdException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doReturn(true) .when(messageVerifierServiceMock) diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java index 402782c5..c4aa12ae 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java @@ -520,11 +520,12 @@ void validateLollipopValidateThumbprintFailureWithDifferentAssertionRefAndCalcul AssertionThumbprintException.ErrorCode.INVALID_IN_RESPONSE_TO, e.getErrorCode()); } - @Test + /*@Test void validateLollipopSuccessWithSHA256Algorithm() throws LollipopAssertionNotFoundException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, - ErrorRetrievingAssertionException, OidcAssertionNotSupported { + ErrorRetrievingAssertionException, OidcAssertionNotSupported, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { LollipopConsumerRequest request = getLollipopConsumerRequest( VALID_SHA_256_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); @@ -543,7 +544,8 @@ void validateLollipopSuccessWithSHA256Algorithm() void validateLollipopSuccessWithSHA384Algorithm() throws LollipopAssertionNotFoundException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, - ErrorRetrievingAssertionException, OidcAssertionNotSupported { + ErrorRetrievingAssertionException, OidcAssertionNotSupported, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { LollipopConsumerRequest request = getLollipopConsumerRequest( VALID_SHA_384_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); @@ -562,7 +564,8 @@ void validateLollipopSuccessWithSHA384Algorithm() void validateLollipopSuccessWithSHA512Algorithm() throws LollipopAssertionNotFoundException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, - ErrorRetrievingAssertionException, OidcAssertionNotSupported { + ErrorRetrievingAssertionException, OidcAssertionNotSupported, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { LollipopConsumerRequest request = getLollipopConsumerRequest( VALID_SHA_512_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); @@ -575,7 +578,7 @@ void validateLollipopSuccessWithSHA512Algorithm() boolean result = sut.validateLollipop(request); Assertions.assertTrue(result); - } + }*/ private LollipopConsumerRequest getLollipopConsumerRequest( String assertionRef, String publicKey, String userId) { diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 58dfbef5..1b8fa4e7 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -908,6 +908,9 @@ + + + @@ -1144,6 +1147,14 @@ + + + + + + + + @@ -1167,6 +1178,11 @@ + + + + + @@ -1215,6 +1231,19 @@ + + + + + + + + + + + + + @@ -1250,6 +1279,16 @@ + + + + + + + + + + @@ -1657,6 +1696,11 @@ + + + + + @@ -1725,6 +1769,24 @@ + + + + + + + + + + + + + + + + + + @@ -2745,6 +2807,14 @@ + + + + + + + + @@ -3005,6 +3075,29 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -3075,6 +3168,11 @@ + + + + + @@ -3089,6 +3187,11 @@ + + + + + @@ -3140,6 +3243,14 @@ + + + + + + + + @@ -3173,6 +3284,16 @@ + + + + + + + + + + @@ -3199,6 +3320,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3219,6 +3376,11 @@ + + + + + @@ -3453,6 +3615,27 @@ + + + + + + + + + + + + + + + + + + + + + @@ -3465,6 +3648,11 @@ + + + + + @@ -3484,6 +3672,11 @@ + + + + + @@ -3510,6 +3703,24 @@ + + + + + + + + + + + + + + + + + + @@ -3564,6 +3775,14 @@ + + + + + + + + @@ -3583,6 +3802,14 @@ + + + + + + + + @@ -3631,6 +3858,14 @@ + + + + + + + + @@ -3731,6 +3966,14 @@ + + + + + + + + @@ -3941,6 +4184,14 @@ + + + + + + + + @@ -4870,6 +5121,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5162,6 +5551,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index e30a4a4a..54c57d15 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -42,14 +42,12 @@ public IdpCertSimpleClient( * @param entityId Identity Provider ID * @param instant Assertion Issue Instant * @return the certifications issued before and after the timestamp instant - * @throws CertDataTagListNotFoundException if an error occurred retrieving the list of tags or - * filtering the tags with the instant * @throws CertDataNotFoundException if an error occurred retrieving the certification XML or if * data for the given entityId were not found */ @Override public List getCertData(String entityId, String instant) - throws CertDataNotFoundException, CertDataTagListNotFoundException { + throws CertDataNotFoundException { List listCertData = new ArrayList<>(); List tagList; @@ -63,7 +61,7 @@ public List getCertData(String entityId, String instant) } catch (ApiException | TagListSearchOutOfBoundException | InvalidInstantFormatException e) { - throw new CertDataTagListNotFoundException( + throw new CertDataNotFoundException( "Error retrieving certificate's tag list: " + e.getMessage(), e); } @@ -94,7 +92,7 @@ public List getCertData(String entityId, String instant) } catch (ApiException | TagListSearchOutOfBoundException | InvalidInstantFormatException e) { - throw new CertDataTagListNotFoundException( + throw new CertDataNotFoundException( "Error retrieving certificate's tag list: " + e.getMessage(), e); } diff --git a/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java index e4617299..2aaef53c 100644 --- a/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java @@ -2,7 +2,6 @@ package it.pagopa.tech.lollipop.consumer.idp.client.simple; import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.storage.SimpleIdpCertStorageProvider; import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; @@ -41,15 +40,14 @@ public static void startServer() { } @Test - void certSPIDDataFound() throws CertDataTagListNotFoundException, CertDataNotFoundException { + void certSPIDDataFound() throws CertDataNotFoundException { List response = idpCertSimpleClient.getCertData(SPID_ENTITY_ID, INSTANT); Assertions.assertNotNull(response); } @Test - void certSPIDDataFoundMultipleSignature() - throws CertDataTagListNotFoundException, CertDataNotFoundException { + void certSPIDDataFoundMultipleSignature() throws CertDataNotFoundException { List response = idpCertSimpleClient.getCertData(SPID_ENTITY_ID_MULTIPLE_SIGNATURE, INSTANT); @@ -58,7 +56,7 @@ void certSPIDDataFoundMultipleSignature() } @Test - void certCIEDataFound() throws CertDataTagListNotFoundException, CertDataNotFoundException { + void certCIEDataFound() throws CertDataNotFoundException { List response = idpCertSimpleClient.getCertData(CIE_ENTITY_ID, INSTANT); Assertions.assertNotNull(response); @@ -74,14 +72,14 @@ void getCertDataWrongEntityID() { @Test void getSPIDCertDataWrongInstant() { Assertions.assertThrows( - CertDataTagListNotFoundException.class, + CertDataNotFoundException.class, () -> idpCertSimpleClient.getCertData(SPID_ENTITY_ID, WRONG_INSTANT)); } @Test void getCIECertDataWrongInstant() { Assertions.assertThrows( - CertDataTagListNotFoundException.class, + CertDataNotFoundException.class, () -> idpCertSimpleClient.getCertData(CIE_ENTITY_ID, WRONG_INSTANT)); } From f4ee8d4e3082ea7097682295b338ddef6482ad2e Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 19 Apr 2023 11:01:45 +0200 Subject: [PATCH 245/403] [SLS-25] Added error messages to define ErrorValidatingAssertionSignature & ErrorRetrievingIdpCertDataException --- .../impl/LollipopConsumerCommandImpl.java | 20 +++++++++++++++---- .../AssertionVerificationResultCode.java | 8 +++++++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index 1aac9cb5..baa392d0 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -96,7 +96,7 @@ private CommandResult getAssertionVerificationResult(LollipopConsumerRequest req } catch (AssertionThumbprintException e) { String message = String.format( - "Assertion validation failed on verifying thumbprint with error code" + "Assertion validation failed on verifying thumbprint with error code" + " %s and message: %s", e.getErrorCode(), e.getMessage()); return buildCommandResult( @@ -104,15 +104,27 @@ private CommandResult getAssertionVerificationResult(LollipopConsumerRequest req } catch (AssertionUserIdException e) { String message = String.format( - "Assertion validation failed on verifying user id with error code %s" + "Assertion validation failed on verifying user id with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); return buildCommandResult( AssertionVerificationResultCode.USER_ID_VALIDATION_ERROR.name(), message); } catch (ErrorValidatingAssertionSignature e) { - throw new RuntimeException(e); // TODO + String message = + String.format( + "Assertion validation failed on verifying signature with error code %s" + + " and message: %s", + e.getErrorCode(), e.getMessage()); + return buildCommandResult( + AssertionVerificationResultCode.SIGNATURE_VALIDATION_ERROR.name(), message); } catch (ErrorRetrievingIdpCertDataException e) { - throw new RuntimeException(e); // TODO + String message = + String.format( + "Assertion validation failed on retrieving identity provider's" + + " certification data with error code %s and message: %s", + e.getErrorCode(), e.getMessage()); + return buildCommandResult( + AssertionVerificationResultCode.IDP_CERT_DATA_RETRIEVING_ERROR.name(), message); } if (!result) { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java index d3b505f0..9c88baad 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java @@ -13,9 +13,15 @@ public enum AssertionVerificationResultCode { /** Saml assertion validation failed on user id validation */ USER_ID_VALIDATION_ERROR, - /** Saml assertion validation failed on thumbpriint validation */ + /** Saml assertion validation failed on thumbprint validation */ THUMBPRINT_VALIDATION_ERROR, + /** Saml assertion validation failed on signature validation */ + SIGNATURE_VALIDATION_ERROR, + + /** Saml assertion validation failed on retrieving identity provider's certification data */ + IDP_CERT_DATA_RETRIEVING_ERROR, + /** Saml assertion validation failed without throwing an exception */ ASSERTION_VERIFICATION_FAILED, From 4c1178fe5c53050655c5204afe39372f7cef274c Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 19 Apr 2023 11:14:06 +0200 Subject: [PATCH 246/403] [SLS-25] Added tests to verify signature & idpCertData exception --- .../impl/LollipopConsumerCommandImplTest.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java index 1ed59441..b244bc04 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -321,4 +321,58 @@ void failedAssertionValidationThrowAssertionUserIdException() verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } + + @Test + void failedAssertionValidationThrowErrorValidatingAssertionSignature() + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { + + doReturn(true) + .when(messageVerifierServiceMock) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); + doThrow(ErrorValidatingAssertionSignature.class) + .when(assertionVerifierServiceMock) + .validateLollipop(any(LollipopConsumerRequest.class)); + + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + + Assertions.assertEquals( + AssertionVerificationResultCode.SIGNATURE_VALIDATION_ERROR.name(), + commandResult.getResultCode()); + + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); + } + + @Test + void failedAssertionValidationThrowErrorRetrievingIdpCertDataException() + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { + + doReturn(true) + .when(messageVerifierServiceMock) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); + doThrow(ErrorRetrievingIdpCertDataException.class) + .when(assertionVerifierServiceMock) + .validateLollipop(any(LollipopConsumerRequest.class)); + + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + + Assertions.assertEquals( + AssertionVerificationResultCode.IDP_CERT_DATA_RETRIEVING_ERROR.name(), + commandResult.getResultCode()); + + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); + } } From c85520893418bf1c20a7b8b680c5b80d51562302 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 19 Apr 2023 16:12:25 +0200 Subject: [PATCH 247/403] [SLS-12] Defining base for logback logging --- core/build.gradle | 1 + .../command/impl/LollipopConsumerCommandImpl.java | 2 +- .../consumer/logger/LollipopLoggerService.java | 9 +++++++++ .../logger/LollipopLoggerServiceFactory.java | 7 +++++++ .../logger/impl/LollipopLogbackLoggerService.java | 15 +++++++++++++++ .../impl/LollipopLogbackLoggerServiceFactory.java | 4 ++++ .../impl/AssertionVerifierServiceImpl.java | 5 +++-- 7 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerService.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerServiceFactory.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerService.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactory.java diff --git a/core/build.gradle b/core/build.gradle index 0660be4d..ca02f3f0 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -44,6 +44,7 @@ dependencies { implementation 'com.typesafe:config:1.4.2' implementation 'javax.inject:javax.inject:1' implementation 'com.nimbusds:nimbus-jose-jwt:9.31' + implementation 'ch.qos.logback:logback-classic:1.4.6' implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.2' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index fc56f264..55807f79 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -19,7 +19,6 @@ public class LollipopConsumerCommandImpl implements LollipopConsumerCommand { private final HttpMessageVerifierService messageVerifierService; private final AssertionVerifierService assertionVerifierService; private final LollipopConsumerRequestValidationService requestValidationService; - private final LollipopConsumerRequest request; public static final String VERIFICATION_SUCCESS_CODE = "SUCCESS"; @@ -47,6 +46,7 @@ public LollipopConsumerCommandImpl( @Override public CommandResult doExecute() { + try { requestValidationService.validateLollipopRequest(request); } catch (LollipopRequestContentValidationException e) { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerService.java new file mode 100644 index 00000000..ea5b8858 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerService.java @@ -0,0 +1,9 @@ +package it.pagopa.tech.lollipop.consumer.logger; + +import org.slf4j.event.Level; + +public interface LollipopLoggerService { + + public void log(Level level, String message, Object... args); + +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerServiceFactory.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerServiceFactory.java new file mode 100644 index 00000000..65534471 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerServiceFactory.java @@ -0,0 +1,7 @@ +package it.pagopa.tech.lollipop.consumer.logger; + +public interface LollipopLoggerServiceFactory { + + LollipopLoggerService create(); + +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerService.java new file mode 100644 index 00000000..cd224e40 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerService.java @@ -0,0 +1,15 @@ +package it.pagopa.tech.lollipop.consumer.logger.impl; + +import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerService; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.event.Level; + +@Slf4j +public class LollipopLogbackLoggerService implements LollipopLoggerService { + + @Override + public void log(Level level, String message, Object... args) { + log.atLevel(level).log(message, args); + } + +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactory.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactory.java new file mode 100644 index 00000000..fb0c4553 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactory.java @@ -0,0 +1,4 @@ +package it.pagopa.tech.lollipop.consumer.logger.impl; + +public class LollipopLogbackLoggerServiceFactory { +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index 37fc3ffc..c37a8a74 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -28,13 +28,14 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import lombok.extern.java.Log; +import lombok.extern.slf4j.Slf4j; 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 +@Slf4j /** Standard implementation of {@link AssertionVerifierService} */ public class AssertionVerifierServiceImpl implements AssertionVerifierService { @@ -298,7 +299,7 @@ private String getPublicKey(String publicKey) { try { publicKey = new String(Base64.getDecoder().decode(publicKey)); } catch (Exception e) { - log.log(Level.FINE, "Key not in Base64"); + log.debug("Key not in Base64"); } return publicKey; } From f2129f87a8546136b7df7f74539e6c990058a6ea Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 19 Apr 2023 18:40:00 +0200 Subject: [PATCH 248/403] [SLS-25] Introducing IDP Validation (Reupload from giomella commits) --- core/build.gradle | 3 - .../ErrorValidatingAssertionSignature.java | 4 +- .../helper/LollipopConsumerFactoryHelper.java | 4 + .../idp/impl/IdpCertProviderImpl.java | 3 +- .../impl/AssertionVerifierServiceImpl.java | 58 +- .../utils/LollipopSamlAssertionWrapper.java | 38 + .../tech/lollipop/consumer/TestUtils.java | 423 +++++++++++ .../impl/LollipopConsumerCommandImplTest.java | 4 +- .../AssertionVerifierServiceImplTest.java | 703 ++++++++++-------- gradle/verification-metadata.xml | 151 ++++ .../impl/MockAssertionVerifierService.java | 21 + ...fierHandlerInterceptorIntegrationTest.java | 7 + 12 files changed, 1079 insertions(+), 340 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopSamlAssertionWrapper.java create mode 100644 core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java create mode 100644 spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java diff --git a/core/build.gradle b/core/build.gradle index 76515282..9c07ba35 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -45,9 +45,6 @@ dependencies { implementation 'javax.inject:javax.inject:1' implementation 'com.nimbusds:nimbus-jose-jwt:9.31' implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.2' - implementation 'org.opensaml:opensaml-core:4.0.1' - implementation 'org.opensaml:opensaml-saml-api:4.0.1' - implementation 'org.opensaml:opensaml-saml-impl:4.0.1' implementation 'org.apache.wss4j:wss4j-ws-security-common:2.4.1' // Use JUnit Jupiter for testing. diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java index bd83065a..e8be1a94 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java @@ -43,7 +43,7 @@ public ErrorCode getErrorCode() { /** Error codes to classify Lollipop Request Exceptions */ public enum ErrorCode { - ERROR_GENERATING_X509_CERTIFICATE, - ERROR_RETRIEVING_ASSERTION_SIGNATURE + ERROR_PARSING_ASSERTION, + MISSING_ASSERTION_SIGNATURE } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index 87434aa9..969b37f1 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -116,4 +116,8 @@ private synchronized AssertionService createAssertionService() { public LollipopConsumerRequestValidationService getRequestValidationService() { return lollipopConsumerRequestValidationService; } + + public void setAssertionVerifierService(AssertionVerifierService assertionVerifierService) { + this.assertionVerifierService = assertionVerifierService; + } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java index a5c5d04a..eb428c1d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java @@ -48,6 +48,7 @@ public List getIdpCertData(String assertionInstant, String entityId throw new IllegalArgumentException(errMsg); } - return idpCertClient.getCertData(assertionInstant, entityId); + + return idpCertClient.getCertData(entityId, assertionInstant); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index 4fdc0b20..e6f74328 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -14,22 +14,29 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; -import org.apache.wss4j.common.ext.WSSecurityException; -import org.apache.wss4j.common.saml.SAMLKeyInfo; -import org.apache.wss4j.common.saml.SamlAssertionWrapper; +import it.pagopa.tech.lollipop.consumer.utils.LollipopSamlAssertionWrapper; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.io.StringReader; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.*; 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.apache.wss4j.common.ext.WSSecurityException; +import org.apache.wss4j.common.saml.SAMLKeyInfo; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -37,13 +44,6 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.*; - /** Standard implementation of {@link AssertionVerifierService} */ @Log public class AssertionVerifierServiceImpl implements AssertionVerifierService { @@ -76,11 +76,10 @@ public boolean validateLollipop(LollipopConsumerRequest request) ErrorRetrievingIdpCertDataException, ErrorValidatingAssertionSignature { Map headerParams = request.getHeaderParams(); - SamlAssertion assertion = + Document assertionDoc = getAssertion( headerParams.get(lollipopRequestConfig.getAuthJWTHeader()), headerParams.get(lollipopRequestConfig.getAssertionRefHeader())); - Document assertionDoc = buildDocumentFromAssertion(assertion); boolean isAssertionPeriodValid = validateAssertionPeriod(assertionDoc); if (!isAssertionPeriodValid) { @@ -108,10 +107,11 @@ public boolean validateLollipop(LollipopConsumerRequest request) return validateSignature(assertionDoc, idpCertDataList); } - private SamlAssertion getAssertion(String jwt, String assertionRef) + private Document getAssertion(String jwt, String assertionRef) throws ErrorRetrievingAssertionException { + SamlAssertion assertion; try { - return assertionService.getAssertion(jwt, assertionRef); + assertion = assertionService.getAssertion(jwt, assertionRef); } catch (OidcAssertionNotSupported e) { throw new ErrorRetrievingAssertionException( ErrorRetrievingAssertionException.ErrorCode.OIDC_TYPE_NOT_SUPPORTED, @@ -123,6 +123,7 @@ private SamlAssertion getAssertion(String jwt, String assertionRef) e.getMessage(), e); } + return buildDocumentFromAssertion(assertion); } protected boolean validateAssertionPeriod(Document assertionDoc) @@ -197,7 +198,7 @@ protected boolean validateInResponseTo(LollipopConsumerRequest request, Document return inResponseTo.equals(calculatedThumbprint) && inResponseTo.equals(assertionRefHeader); } - private List getIdpCertData(Document assertionDoc) + protected List getIdpCertData(Document assertionDoc) throws ErrorRetrievingIdpCertDataException { NodeList listElements = assertionDoc.getElementsByTagNameNS( @@ -218,7 +219,13 @@ private List getIdpCertData(Document assertionDoc) "Missing entity id field in the retrieved saml assertion"); } try { - return idpCertProvider.getIdpCertData(instant, entityId); + instant = Long.toString( + new SimpleDateFormat(lollipopRequestConfig.getAssertionNotBeforeDateFormat()) + .parse(instant).getTime()); + } catch (ParseException e) { + } + try { + return idpCertProvider.getIdpCertData(instant, entityId.trim()); } catch (CertDataNotFoundException e) { throw new ErrorRetrievingIdpCertDataException( ErrorRetrievingIdpCertDataException.ErrorCode.IDP_CERT_DATA_NOT_FOUND, @@ -229,10 +236,10 @@ private List getIdpCertData(Document assertionDoc) protected boolean validateSignature(Document assertionDoc, List idpCertDataList) throws ErrorValidatingAssertionSignature { - SamlAssertionWrapper wrapper; + LollipopSamlAssertionWrapper wrapper; try { wrapper = - new SamlAssertionWrapper( + new LollipopSamlAssertionWrapper( (Element) assertionDoc .getElementsByTagNameNS( @@ -242,9 +249,8 @@ protected boolean validateSignature(Document assertionDoc, List idp .item(0)); } catch (WSSecurityException e) { throw new ErrorValidatingAssertionSignature( - ErrorValidatingAssertionSignature.ErrorCode - .ERROR_RETRIEVING_ASSERTION_SIGNATURE, - "Failed to retrieve signature from assertion", + ErrorValidatingAssertionSignature.ErrorCode.ERROR_PARSING_ASSERTION, + "Failed to build SAML object from assertion", e); } @@ -252,19 +258,20 @@ protected boolean validateSignature(Document assertionDoc, List idp } private boolean validateSignature( - List idpCertDataList, SamlAssertionWrapper wrapper) { + List idpCertDataList, LollipopSamlAssertionWrapper wrapper) + throws ErrorValidatingAssertionSignature { for (IdpCertData idpCertData : idpCertDataList) { for (String certData : idpCertData.getCertData()) { try { X509Certificate x509Certificate = getX509Certificate(certData); - wrapper.verifySignature( + wrapper.verifySignatureLollipop( new SAMLKeyInfo(new X509Certificate[] {x509Certificate})); } catch (CertificateException | WSSecurityException e) { // CertificateException: Failed to generate X509 certificate from IDP metadata // or // WSSecurityException: Failed to validate assertion signature - // TODO: se l'assertion non ha signature la validazione va in successo, - // corretto? + // this exceptions are ignored because if the signature validation fail for one + // certificate it may pass with one of the other certificates continue; } return true; @@ -409,4 +416,3 @@ private String getPublicKey(String publicKey) { return publicKey; } } - diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopSamlAssertionWrapper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopSamlAssertionWrapper.java new file mode 100644 index 00000000..af56d2f9 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopSamlAssertionWrapper.java @@ -0,0 +1,38 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.utils; + +import it.pagopa.tech.lollipop.consumer.exception.ErrorValidatingAssertionSignature; +import org.apache.wss4j.common.ext.WSSecurityException; +import org.apache.wss4j.common.saml.SAMLKeyInfo; +import org.apache.wss4j.common.saml.SamlAssertionWrapper; +import org.opensaml.xmlsec.signature.Signature; +import org.w3c.dom.Element; + +/** + * Extension of the {@link SamlAssertionWrapper} class that add the check for the existence of + * signature in the assertion before its validation + */ +public class LollipopSamlAssertionWrapper extends SamlAssertionWrapper { + + public LollipopSamlAssertionWrapper(Element element) throws WSSecurityException { + super(element); + } + + /** + * If the assertion has a signature call the signature validation, otherwise it throws {@link + * ErrorValidatingAssertionSignature} + * + * @see SamlAssertionWrapper#verifySignature(SAMLKeyInfo) + * @throws ErrorValidatingAssertionSignature if the assertion does not have a signature + */ + public void verifySignatureLollipop(SAMLKeyInfo samlKeyInfo) + throws WSSecurityException, ErrorValidatingAssertionSignature { + Signature sig = getSignature(); + if (sig == null) { + throw new ErrorValidatingAssertionSignature( + ErrorValidatingAssertionSignature.ErrorCode.MISSING_ASSERTION_SIGNATURE, + "The given assertion does not have a signature"); + } + verifySignature(samlKeyInfo); + } +} diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java new file mode 100644 index 00000000..ce1bc163 --- /dev/null +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java @@ -0,0 +1,423 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer; + +public class TestUtils { + + public static final String VALID_FISCAL_CODE = "AAAAAA89S20I111X"; + public static final String VALID_JWK = + "{ \"kty\": \"EC\", \"crv\": \"P-256\", \"x\":" + + " \"SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74\", \"y\":" + + " \"lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI\"}"; + public static final String VALID_SHA_256_ASSERTION_REF = + "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; + public static final String VALID_SHA_384_ASSERTION_REF = + "sha384-lqxC_2kqMdwiBWoD-Us63Fha6e3bE1Y3yUz8G6IJTldohJCIBVDfvS8acB3GJBhw"; + public static final String VALID_SHA_512_ASSERTION_REF = + "sha512-nX5CfUc5R-FoYKYZwvQMuc4Tt-heb7vHi_O-AMUSqHNVCw9kNaN2SVuN-DXtGXyUhrcVcQdCyY6FVzl_vyWXNA"; + public static final String EMPTY_ASSERTION_XML = + ""; + public static final String ASSERTION_XML_WITH_INVALID_PERIOD_DATE_FORMAT = + "https://app-backend.io.italia.it"; + public static final String ASSERTION_XML_WITH_EXPIRED_PERIOD = + "https://app-backend.io.italia.it"; + public static final String ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG = + "https://app-backend.io.italia.it"; + + public static final String ASSERTION_XML_WITHOUT_FISCAL_CODE = + " " + + " " + + " https://app-backend.io.italia.it " + + " \t " + + " " + + " "; + public static final String ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG = + " " + + " " + + " https://app-backend.io.italia.it " + + " \t " + + " TINIT-AAAAAA89S20I111X " + + " " + + " "; + public static final String ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM = + " \t\t\t" + + "\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t\t\t" + + "\t\t\t\t\t\t\t\t\t\t" + + "\t\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t" + + "\t\t\t" + + "\t"; + public static final String ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM = + " \t\t\t" + + "\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t\t\t" + + "\t\t\t\t\t\t\t\t\t\t" + + "\t\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t" + + "\t\t\t" + + "\t"; + public static final String ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM = + " \t\t\t" + + "\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t\t\t" + + "\t\t\t\t\t\t\t\t\t\t" + + "\t\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t" + + "\t\t\t" + + "\t"; + public static final String ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM = + " \t\t\t" + + "\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t\t\t" + + "\t\t\t\t\t\t\t\t\t\t" + + "\t\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t" + + "\t\t\t" + + "\t"; + public static final String ASSERTION_XML_WITHOUT_INSTANT_FIELD = + " \t" + + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t\t\t" + + "\t\t\t\t\t\t\t\t\t\t" + + "\t\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t" + + "\t\t\t" + + "\t"; + public static final String ASSERTION_XML_WITHOUT_ENTITY_ID_FIELD = + " \t\t\t" + + "\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t\t\t" + + "\t\t\t\t\t\t\t\t\t\t" + + "\t\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t" + + "\t\t\t" + + "\t"; + public static final String ASSERTION_XML_WITH_VALID_ENTITY_ID_FIELD = + " \thttps://posteid.poste.it" + + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t\t\t" + + "\t\t\t\t\t\t\t\t\t\t" + + "\t\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t" + + "\t\t\t" + + "\t"; + public static final String ASSERTION_XML_WITH_INVALID_SIGNATURE = + " \thttps://posteid.poste.it\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=\n" + + " \n" + + " \n" + + " " + + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF\n" + + " " + + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio\n" + + " " + + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf\n" + + " " + + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4\n" + + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg==\n" + + " \n" + + " \n" + + " " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc\n" + + " " + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx\n" + + " " + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz\n" + + " " + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE\n" + + " " + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC\n" + + " " + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd\n" + + " " + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE\n" + + " " + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4\n" + + " " + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR\n" + + " " + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH\n" + + " " + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw\n" + + " " + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1\n" + + " " + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD\n" + + " " + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G\n" + + " " + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc\n" + + " " + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO\n" + + " " + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ\n" + + " " + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO\n" + + " " + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz\n" + + " " + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD\n" + + " " + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0\n" + + " " + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH\n" + + " " + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy\n" + + " " + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC\n" + + " " + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=\n" + + " \n" + + " \n" + + " \t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t\t\t" + + "\t\t\t\t\t\t\t\t\t\t" + + "\t\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t" + + "\t\t\t" + + "\t"; + public static final String CERTIFICATE_TIM_LATEST = + "MIID0jCCArqgAwIBAgIUXDUOKL3WuolxDw96Fk9es8rIt6kwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAklUMS4wLAYDVQQKDCVUZWxlY29tIEl0YWxpYSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMSgwJgYDVQQLDB9TZXJ2aXppIHBlciBsJ2lkZW50aXRhIGRpZ2l0YWxlMSIwIAYDVQQDDBlUSSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMB4XDTIxMTExMTE3MDMyMFoXDTI1MTExMDE3MDMyMFowgYsxCzAJBgNVBAYTAklUMS4wLAYDVQQKDCVUZWxlY29tIEl0YWxpYSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMSgwJgYDVQQLDB9TZXJ2aXppIHBlciBsJ2lkZW50aXRhIGRpZ2l0YWxlMSIwIAYDVQQDDBlUSSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6sIS3+3iZSaAIyVywahlbpua2uJ/XmpV68P1e1STJpHoaj32STdHhqZnnb4Y/FshP1NUolzNolPXAYDmDduW1OnGndJZ+G9Hjh1PCkdiRw+p0FjhQAsGJkn8NdgTIHLJjqN1qQwtOsVGab8ScyA3mtmj3xKYuBhUoweuATzC7f5r7FfIoc3cy6N5lgrpZpfeAChxLwoHVjoAVgIBuemi6HAzmd4/BI06KzOcR7+dBVi4+uiseldxrJ5bhnjZKIwgkX14y9UA84Y+e+rMtyT8cT3XXi9NazZl5Ej5/bQPqqVsbg6tXzQSfEJD6JEjuYeC0RUKMS/EJn3hL5VLzTJ1NwIDAQABoywwKjAdBgNVHQ4EFgQUfctFZ8bRtmEvXPRlqgVDuggY/ZwwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA0lszHadknPfE17IWGWsgvlXOdKMnWcl9H5rEYmsWwDB9FJG9XAZvPMcVv1kkWi6XZI/8N2Twhu1BdZkdvntDRscuck8wxxIpkRV7CwlcqNFZ/IwjDBxOBa8Q1J850p+qP8A9apsLLPUlu/oLygNDWIXzcOjMqnPkEP+XXUNYPto5iV+OyDzLLacCYqDDHcvDewWLmEjt35X967KcM+m7K2zGRLWfqcZPIjJJOkpNjgcs+MaisMrGDyOKiD16v0LpwVyIpTqXvDk7KHo8CUNXDxyLxZzB6WffgnOgjXTfU3vluweOx0qQy/VxIupDlNBKiZB4gnt1oAfnaMbqla9wcw=="; + public static final String ASSERTION_XML_TIM = + "PHNhbWwycDpSZXNwb25zZSB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgRGVzdGluYXRpb249Imh0dHBzOi8vYXBwLWJhY2tlbmQuaW8uaXRhbGlhLml0L2Fzc2VydGlvbkNvbnN1bWVyU2VydmljZSIgSUQ9Il85YzA0YTI4ZDkzNWViNmMyODg0Njc4OTc0ZjA0OWZhNiIgSW5SZXNwb25zZVRvPSJzaGEyNTYtTUpDOTZQZzFUdWZEN0FNMWdTTW0xZ3JRUExFOGI1UjFJcjFKSmJaQlExSSIgSXNzdWVJbnN0YW50PSIyMDIzLTA0LTA0VDE1OjAxOjQ1Ljk3M1oiIFZlcnNpb249IjIuMCI+PHNhbWwyOklzc3VlciB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlkLWZvcm1hdDplbnRpdHkiPmh0dHBzOi8vbG9naW4uaWQudGltLml0L2FmZndlYnNlcnZpY2VzL3B1YmxpYy9zYW1sMnNzbzwvc2FtbDI6SXNzdWVyPjxTaWduYXR1cmUgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxTaWduZWRJbmZvPjxDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PFNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZHNpZy1tb3JlI3JzYS1zaGEyNTYiLz48UmVmZXJlbmNlIFVSST0iI185YzA0YTI4ZDkzNWViNmMyODg0Njc4OTc0ZjA0OWZhNiI+PFRyYW5zZm9ybXM+PFRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8+PFRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjwvVHJhbnNmb3Jtcz48RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjc2hhMjU2Ii8+PERpZ2VzdFZhbHVlPk1kRjE4aTNRVC9pdnBrdjdubkdlWms4N3hzYWpFWlY3d3Jrdm9IUy9KZGs9PC9EaWdlc3RWYWx1ZT48L1JlZmVyZW5jZT48L1NpZ25lZEluZm8+PFNpZ25hdHVyZVZhbHVlPk5TWCtWWCtMaXJYNzROQ0lQbGVxelIxeTIwZW5rVS9IQ2tKWlJmOUFCNEQvSkFJRUhSdWRxbmhyckQyb05OZ3lRNnltcktsSFVvQnpnbVhGWmIvUE8wa0pXTzVwbGhLY1AxakFhNlF4NTRNaHFqUnA2cmdhcGk2SlJGTXErbDVXeVVLSnRXMHBCdkpQYUVpMngxeG1HUHZzZU81ZkNEbnVpZHZEdXYydFVqRm1jZTY4bzRGWjF2dGprd0w3TExMNUNNTHc4dVNnWFNwK1lhOUNNQzJaYVl5aDNOaExsUktvazNuakVpd2d2ZTRWUURQRGZ0RmhnektHb25zM0FHcTQra2xPODBzaWF4WUl1Y1FKMVdxUmJKL3NzRUV5N3NOZXU3cXlhSmsrekpzVnA5cU5OL0RhM3lxTXp1bVRUMmtSZnNIL0tuWFJmTC9NQnNHNFNEVHY0QT09PC9TaWduYXR1cmVWYWx1ZT48S2V5SW5mbz48WDUwOURhdGE+PFg1MDlDZXJ0aWZpY2F0ZT5NSUlEMGpDQ0FycWdBd0lCQWdJVVhEVU9LTDNXdW9seER3OTZGazllczhySXQ2a3dEUVlKS29aSWh2Y05BUUVMQlFBd2dZc3hDekFKQmdOVkJBWVRBa2xVTVM0d0xBWURWUVFLRENWVVpXeGxZMjl0SUVsMFlXeHBZU0JVY25WemRDQlVaV05vYm05c2IyZHBaWE1nYzNKc01TZ3dKZ1lEVlFRTERCOVRaWEoyYVhwcElIQmxjaUJzSjJsa1pXNTBhWFJoSUdScFoybDBZV3hsTVNJd0lBWURWUVFEREJsVVNTQlVjblZ6ZENCVVpXTm9ibTlzYjJkcFpYTWdjM0pzTUI0WERUSXhNVEV4TVRFM01ETXlNRm9YRFRJMU1URXhNREUzTURNeU1Gb3dnWXN4Q3pBSkJnTlZCQVlUQWtsVU1TNHdMQVlEVlFRS0RDVlVaV3hsWTI5dElFbDBZV3hwWVNCVWNuVnpkQ0JVWldOb2JtOXNiMmRwWlhNZ2MzSnNNU2d3SmdZRFZRUUxEQjlUWlhKMmFYcHBJSEJsY2lCc0oybGtaVzUwYVhSaElHUnBaMmwwWVd4bE1TSXdJQVlEVlFRRERCbFVTU0JVY25WemRDQlVaV05vYm05c2IyZHBaWE1nYzNKc01JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNnNJUzMrM2laU2FBSXlWeXdhaGxicHVhMnVKL1htcFY2OFAxZTFTVEpwSG9hajMyU1RkSGhxWm5uYjRZL0ZzaFAxTlVvbHpOb2xQWEFZRG1EZHVXMU9uR25kSlorRzlIamgxUENrZGlSdytwMEZqaFFBc0dKa244TmRnVElITEpqcU4xcVF3dE9zVkdhYjhTY3lBM210bWozeEtZdUJoVW93ZXVBVHpDN2Y1cjdGZklvYzNjeTZONWxncnBacGZlQUNoeEx3b0hWam9BVmdJQnVlbWk2SEF6bWQ0L0JJMDZLek9jUjcrZEJWaTQrdWlzZWxkeHJKNWJobmpaS0l3Z2tYMTR5OVVBODRZK2Urck10eVQ4Y1QzWFhpOU5helpsNUVqNS9iUVBxcVZzYmc2dFh6UVNmRUpENkpFanVZZUMwUlVLTVMvRUpuM2hMNVZMelRKMU53SURBUUFCb3l3d0tqQWRCZ05WSFE0RUZnUVVmY3RGWjhiUnRtRXZYUFJscWdWRHVnZ1kvWnd3Q1FZRFZSMFRCQUl3QURBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQTBsc3pIYWRrblBmRTE3SVdHV3NndmxYT2RLTW5XY2w5SDVyRVltc1d3REI5RkpHOVhBWnZQTWNWdjFra1dpNlhaSS84TjJUd2h1MUJkWmtkdm50RFJzY3Vjazh3eHhJcGtSVjdDd2xjcU5GWi9Jd2pEQnhPQmE4UTFKODUwcCtxUDhBOWFwc0xMUFVsdS9vTHlnTkRXSVh6Y09qTXFuUGtFUCtYWFVOWVB0bzVpVitPeUR6TExhY0NZcURESGN2RGV3V0xtRWp0MzVYOTY3S2NNK203SzJ6R1JMV2ZxY1pQSWpKSk9rcE5qZ2NzK01haXNNckdEeU9LaUQxNnYwTHB3VnlJcFRxWHZEazdLSG84Q1VOWER4eUx4WnpCNldmZmduT2dqWFRmVTN2bHV3ZU94MHFReS9WeEl1cERsTkJLaVpCNGdudDFvQWZuYU1icWxhOXdjdz09PC9YNTA5Q2VydGlmaWNhdGU+PC9YNTA5RGF0YT48L0tleUluZm8+PC9TaWduYXR1cmU+PHNhbWwycDpTdGF0dXM+PHNhbWwycDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz48L3NhbWwycDpTdGF0dXM+PHNhbWwyOkFzc2VydGlvbiB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9Il9jMjYwYjI2NzNlYzMwZjJjNzI0YjI5NDM2NTFiOWEyYiIgSXNzdWVJbnN0YW50PSIyMDIzLTA0LTA0VDE1OjAxOjQ1Ljk3M1oiIFZlcnNpb249IjIuMCI+PHNhbWwyOklzc3VlciBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpuYW1laWQtZm9ybWF0OmVudGl0eSI+aHR0cHM6Ly9sb2dpbi5pZC50aW0uaXQvYWZmd2Vic2VydmljZXMvcHVibGljL3NhbWwyc3NvPC9zYW1sMjpJc3N1ZXI+PFNpZ25hdHVyZSB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+PFNpZ25lZEluZm8+PENhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxkc2lnLW1vcmUjcnNhLXNoYTI1NiIvPjxSZWZlcmVuY2UgVVJJPSIjX2MyNjBiMjY3M2VjMzBmMmM3MjRiMjk0MzY1MWI5YTJiIj48VHJhbnNmb3Jtcz48VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz48VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PC9UcmFuc2Zvcm1zPjxEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNzaGEyNTYiLz48RGlnZXN0VmFsdWU+d2tlS0V1OWpFOGNaeFpVM3hWcWZEVURWVHpCUHZjL1FERXJRNXpRRWk3Yz08L0RpZ2VzdFZhbHVlPjwvUmVmZXJlbmNlPjwvU2lnbmVkSW5mbz48U2lnbmF0dXJlVmFsdWU+NWlUQ3o5WjdCT1d5QzBPZE56M2RNMXI1RG1yOTliamtvejZWMlJUVmJTNE5UUnB5UmVkb3ZqNHBhRmxXd0Z4Ris4eWNDNTJlUXRmVDk3Tk5HVExMRlJRYTMrODVWbHVqeFdWZmhDUks1aEJxV1VXZVFiUnl6YitmWlhJSEgxTE5ENTlkVUcrWHlDcDl1Z1lzbi9JZjJySGoxTUdxYnMvZnZaU25HeU16RzRrVXpSa0lXREl4eWdLSXNCYTREQUc0bms5MGNVRTBlQVRQdURDblhNbkEyWTMvWlJWN3lCalpXbUorZ3F1ZHExaWowUDJJL29FUVdIWW1yVTV1bkhIZTI0MmlmUTRpYkdydy93cWRpa1UvSDA1M0JHZEFFaFluTVByYWpPV1Z5SmhoYnlTdCsycmpDZ0xjeWZMWG5xV3FUVS9IdE5CSGNQWGhVK0RaL1Q5MzNBPT08L1NpZ25hdHVyZVZhbHVlPjxLZXlJbmZvPjxYNTA5RGF0YT48WDUwOUNlcnRpZmljYXRlPk1JSUQwakNDQXJxZ0F3SUJBZ0lVWERVT0tMM1d1b2x4RHc5NkZrOWVzOHJJdDZrd0RRWUpLb1pJaHZjTkFRRUxCUUF3Z1lzeEN6QUpCZ05WQkFZVEFrbFVNUzR3TEFZRFZRUUtEQ1ZVWld4bFkyOXRJRWwwWVd4cFlTQlVjblZ6ZENCVVpXTm9ibTlzYjJkcFpYTWdjM0pzTVNnd0pnWURWUVFMREI5VFpYSjJhWHBwSUhCbGNpQnNKMmxrWlc1MGFYUmhJR1JwWjJsMFlXeGxNU0l3SUFZRFZRUUREQmxVU1NCVWNuVnpkQ0JVWldOb2JtOXNiMmRwWlhNZ2MzSnNNQjRYRFRJeE1URXhNVEUzTURNeU1Gb1hEVEkxTVRFeE1ERTNNRE15TUZvd2dZc3hDekFKQmdOVkJBWVRBa2xVTVM0d0xBWURWUVFLRENWVVpXeGxZMjl0SUVsMFlXeHBZU0JVY25WemRDQlVaV05vYm05c2IyZHBaWE1nYzNKc01TZ3dKZ1lEVlFRTERCOVRaWEoyYVhwcElIQmxjaUJzSjJsa1pXNTBhWFJoSUdScFoybDBZV3hsTVNJd0lBWURWUVFEREJsVVNTQlVjblZ6ZENCVVpXTm9ibTlzYjJkcFpYTWdjM0pzTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE2c0lTMyszaVpTYUFJeVZ5d2FobGJwdWEydUovWG1wVjY4UDFlMVNUSnBIb2FqMzJTVGRIaHFabm5iNFkvRnNoUDFOVW9sek5vbFBYQVlEbURkdVcxT25HbmRKWitHOUhqaDFQQ2tkaVJ3K3AwRmpoUUFzR0prbjhOZGdUSUhMSmpxTjFxUXd0T3NWR2FiOFNjeUEzbXRtajN4S1l1QmhVb3dldUFUekM3ZjVyN0ZmSW9jM2N5Nk41bGdycFpwZmVBQ2h4THdvSFZqb0FWZ0lCdWVtaTZIQXptZDQvQkkwNkt6T2NSNytkQlZpNCt1aXNlbGR4cko1YmhualpLSXdna1gxNHk5VUE4NFkrZStyTXR5VDhjVDNYWGk5TmF6Wmw1RWo1L2JRUHFxVnNiZzZ0WHpRU2ZFSkQ2SkVqdVllQzBSVUtNUy9FSm4zaEw1Vkx6VEoxTndJREFRQUJveXd3S2pBZEJnTlZIUTRFRmdRVWZjdEZaOGJSdG1FdlhQUmxxZ1ZEdWdnWS9ad3dDUVlEVlIwVEJBSXdBREFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBMGxzekhhZGtuUGZFMTdJV0dXc2d2bFhPZEtNbldjbDlINXJFWW1zV3dEQjlGSkc5WEFadlBNY1Z2MWtrV2k2WFpJLzhOMlR3aHUxQmRaa2R2bnREUnNjdWNrOHd4eElwa1JWN0N3bGNxTkZaL0l3akRCeE9CYThRMUo4NTBwK3FQOEE5YXBzTExQVWx1L29MeWdORFdJWHpjT2pNcW5Qa0VQK1hYVU5ZUHRvNWlWK095RHpMTGFjQ1lxRERIY3ZEZXdXTG1FanQzNVg5NjdLY00rbTdLMnpHUkxXZnFjWlBJakpKT2twTmpnY3MrTWFpc01yR0R5T0tpRDE2djBMcHdWeUlwVHFYdkRrN0tIbzhDVU5YRHh5THhaekI2V2ZmZ25PZ2pYVGZVM3ZsdXdlT3gwcVF5L1Z4SXVwRGxOQktpWkI0Z250MW9BZm5hTWJxbGE5d2N3PT08L1g1MDlDZXJ0aWZpY2F0ZT48L1g1MDlEYXRhPjwvS2V5SW5mbz48L1NpZ25hdHVyZT48c2FtbDI6U3ViamVjdD48c2FtbDI6TmFtZUlEIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6dHJhbnNpZW50IiBOYW1lUXVhbGlmaWVyPSJodHRwczovL2xvZ2luLmlkLnRpbS5pdC9hZmZ3ZWJzZXJ2aWNlcy9wdWJsaWMvc2FtbDJzc28iPl80OTJlNDQyNGVjOTVjNzU5MWViMTY5MGJjOTk3ZDIwMzwvc2FtbDI6TmFtZUlEPjxzYW1sMjpTdWJqZWN0Q29uZmlybWF0aW9uIE1ldGhvZD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmNtOmJlYXJlciI+PHNhbWwyOlN1YmplY3RDb25maXJtYXRpb25EYXRhIEluUmVzcG9uc2VUbz0ic2hhMjU2LU1KQzk2UGcxVHVmRDdBTTFnU01tMWdyUVBMRThiNVIxSXIxSkpiWkJRMUkiIE5vdE9uT3JBZnRlcj0iMjAyMy0wNC0wNFQxNTowMjoxNS45NzNaIiBSZWNpcGllbnQ9Imh0dHBzOi8vYXBwLWJhY2tlbmQuaW8uaXRhbGlhLml0L2Fzc2VydGlvbkNvbnN1bWVyU2VydmljZSIvPjwvc2FtbDI6U3ViamVjdENvbmZpcm1hdGlvbj48L3NhbWwyOlN1YmplY3Q+PHNhbWwyOkNvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDIzLTA0LTA0VDE1OjAxOjQ0Ljk3M1oiIE5vdE9uT3JBZnRlcj0iMjAyMy0wNC0wNFQxNTowMjoxNS45NzNaIj48c2FtbDI6QXVkaWVuY2VSZXN0cmljdGlvbj48c2FtbDI6QXVkaWVuY2U+aHR0cHM6Ly9hcHAtYmFja2VuZC5pby5pdGFsaWEuaXQ8L3NhbWwyOkF1ZGllbmNlPjwvc2FtbDI6QXVkaWVuY2VSZXN0cmljdGlvbj48L3NhbWwyOkNvbmRpdGlvbnM+PHNhbWwyOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAyMy0wNC0wNFQxNTowMTo0NS45NzNaIj48c2FtbDI6QXV0aG5Db250ZXh0PjxzYW1sMjpBdXRobkNvbnRleHRDbGFzc1JlZj5odHRwczovL3d3dy5zcGlkLmdvdi5pdC9TcGlkTDI8L3NhbWwyOkF1dGhuQ29udGV4dENsYXNzUmVmPjwvc2FtbDI6QXV0aG5Db250ZXh0Pjwvc2FtbDI6QXV0aG5TdGF0ZW1lbnQ+PHNhbWwyOkF0dHJpYnV0ZVN0YXRlbWVudD48c2FtbDI6QXR0cmlidXRlIEZyaWVuZGx5TmFtZT0iRGF0YSBkaSBuYXNjaXRhIiBOYW1lPSJkYXRlT2ZCaXJ0aCI+PHNhbWwyOkF0dHJpYnV0ZVZhbHVlIHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnR5cGU9InhzOmRhdGUiPjE5ODctMDktMTQ8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjxzYW1sMjpBdHRyaWJ1dGUgRnJpZW5kbHlOYW1lPSJJbmRpcml6em8gZGkgcG9zdGEgZWxldHRyb25pY2EiIE5hbWU9ImVtYWlsIj48c2FtbDI6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hIiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4c2k6dHlwZT0ieHM6c3RyaW5nIj5waWV0cm8uc3Ryb2lhQGdtYWlsLmNvbTwvc2FtbDI6QXR0cmlidXRlVmFsdWU+PC9zYW1sMjpBdHRyaWJ1dGU+PHNhbWwyOkF0dHJpYnV0ZSBGcmllbmRseU5hbWU9IkNvZ25vbWUiIE5hbWU9ImZhbWlseU5hbWUiPjxzYW1sMjpBdHRyaWJ1dGVWYWx1ZSB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhzaTp0eXBlPSJ4czpzdHJpbmciPlN0cm9pYTwvc2FtbDI6QXR0cmlidXRlVmFsdWU+PC9zYW1sMjpBdHRyaWJ1dGU+PHNhbWwyOkF0dHJpYnV0ZSBGcmllbmRseU5hbWU9IkNvZGljZSBmaXNjYWxlIiBOYW1lPSJmaXNjYWxOdW1iZXIiPjxzYW1sMjpBdHRyaWJ1dGVWYWx1ZSB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhzaTp0eXBlPSJ4czpzdHJpbmciPlRJTklULVNUUlBUUjg3UDE0RTMzNVY8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjxzYW1sMjpBdHRyaWJ1dGUgRnJpZW5kbHlOYW1lPSJOb21lIiBOYW1lPSJuYW1lIj48c2FtbDI6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hIiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4c2k6dHlwZT0ieHM6c3RyaW5nIj5QaWV0cm88L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjwvc2FtbDI6QXR0cmlidXRlU3RhdGVtZW50Pjwvc2FtbDI6QXNzZXJ0aW9uPjwvc2FtbDJwOlJlc3BvbnNlPg=="; +} diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java index b244bc04..646627a3 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -337,7 +337,7 @@ void failedAssertionValidationThrowErrorValidatingAssertionSignature() .when(assertionVerifierServiceMock) .validateLollipop(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( AssertionVerificationResultCode.SIGNATURE_VALIDATION_ERROR.name(), @@ -364,7 +364,7 @@ void failedAssertionValidationThrowErrorRetrievingIdpCertDataException() .when(assertionVerifierServiceMock) .validateLollipop(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( AssertionVerificationResultCode.IDP_CERT_DATA_RETRIEVING_ERROR.name(), diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java index c4aa12ae..ccdd1d81 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java @@ -1,24 +1,28 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service.impl; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static it.pagopa.tech.lollipop.consumer.TestUtils.*; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.*; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; -import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; + +import java.nio.charset.StandardCharsets; import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.util.Collections; import java.util.HashMap; +import lombok.SneakyThrows; +import org.apache.geronimo.mail.util.Base64; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.w3c.dom.Document; class AssertionVerifierServiceImplTest { @@ -26,263 +30,25 @@ class AssertionVerifierServiceImplTest { private AssertionService assertionServiceMock; private static LollipopConsumerRequestConfig lollipopRequestConfigMock; - private AssertionVerifierService sut; - - private static final String VALID_FISCAL_CODE = "AAAAAA89S20I111X"; - private static final String VALID_JWK = - "{ \"kty\": \"EC\", \"crv\": \"P-256\", \"x\":" - + " \"SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74\", \"y\":" - + " \"lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI\"}"; - private static final String VALID_SHA_256_ASSERTION_REF = - "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; - private static final String VALID_SHA_384_ASSERTION_REF = - "sha384-lqxC_2kqMdwiBWoD-Us63Fha6e3bE1Y3yUz8G6IJTldohJCIBVDfvS8acB3GJBhw"; - private static final String VALID_SHA_512_ASSERTION_REF = - "sha512-nX5CfUc5R-FoYKYZwvQMuc4Tt-heb7vHi_O-AMUSqHNVCw9kNaN2SVuN-DXtGXyUhrcVcQdCyY6FVzl_vyWXNA"; - - private static final String EMPTY_ASSERTION_XML = - ""; - private static final String ASSERTION_XML_WITH_INVALID_PERIOD_DATE_FORMAT = - "https://app-backend.io.italia.it"; - private static final String ASSERTION_XML_WITH_EXPIRED_PERIOD = - "https://app-backend.io.italia.it"; - private static String ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG; - private static String ASSERTION_XML_WITHOUT_FISCAL_CODE; - private static String ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG; - private static String ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM; - private static String ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM; - private static String ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM; - private static String ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM; - - @BeforeAll - static void prepareInput() { - lollipopRequestConfigMock = spy(LollipopConsumerRequestConfig.builder().build()); - - String todayTimestamp = - new SimpleDateFormat(lollipopRequestConfigMock.getAssertionNotBeforeDateFormat()) - .format(new Date()); - ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG = - "https://app-backend.io.italia.it"; - ASSERTION_XML_WITHOUT_FISCAL_CODE = - " " - + " " - + " " - + " " - + " https://app-backend.io.italia.it " - + " \t " - + " " - + " " - + " "; - ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG = - " " - + " " - + " " - + " " - + " https://app-backend.io.italia.it " - + " \t " - + " " - + " TINIT-AAAAAA89S20I111X " - + " " - + " "; - ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM = - " " - + " \t" - + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" - + "\t\t\t\t\t\t" - + "\t" - + "\t\t\t\t\t\t\t\t\t" - + "\t\t\t\t" - + "\thttps://app-backend.io.italia.it\t\t" - + "\t\t\t\t" - + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t" - + "\t\t\t\t" - + "\t"; - ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM = - " " - + " \t" - + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" - + "\t\t\t\t\t\t" - + "\t" - + "\t\t\t\t\t\t\t\t\t" - + "\t\t\t\t" - + "\thttps://app-backend.io.italia.it\t\t" - + "\t\t\t\t" - + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t" - + "\t\t\t\t" - + "\t"; - ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM = - " " - + " \t" - + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" - + "\t\t\t\t\t\t" - + "\t" - + "\t\t\t\t\t\t\t\t\t" - + "\t\t\t\t" - + "\thttps://app-backend.io.italia.it\t\t" - + "\t\t\t\t" - + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t" - + "\t\t\t\t" - + "\t"; - ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM = - " " - + " \t" - + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" - + "\t\t\t\t\t\t" - + "\t" - + "\t\t\t\t\t\t\t\t\t" - + "\t\t\t\t" - + "\thttps://app-backend.io.italia.it\t\t" - + "\t\t\t\t" - + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t" - + "\t\t\t\t" - + "\t"; - } + private AssertionVerifierServiceImpl sut; @BeforeEach void setUp() { idpCertProviderMock = mock(IdpCertProvider.class); assertionServiceMock = mock(AssertionService.class); + lollipopRequestConfigMock = spy(LollipopConsumerRequestConfig.builder().build()); sut = - new AssertionVerifierServiceImpl( - idpCertProviderMock, assertionServiceMock, lollipopRequestConfigMock); + spy( + new AssertionVerifierServiceImpl( + idpCertProviderMock, + assertionServiceMock, + lollipopRequestConfigMock)); } + @SneakyThrows @Test - void validateLollipopGetAssertionFailureWithOidcAssertionException() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopGetAssertionFailureWithOidcAssertionException() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); doThrow(OidcAssertionNotSupported.class) @@ -300,9 +66,9 @@ void validateLollipopGetAssertionFailureWithOidcAssertionException() e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopGetAssertionFailureWithAssertionNotFoundException() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopGetAssertionFailureWithAssertionNotFoundException() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); doThrow(LollipopAssertionNotFoundException.class) @@ -320,9 +86,9 @@ void validateLollipopGetAssertionFailureWithAssertionNotFoundException() e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopBuildAssertionDocFailure() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopGetAssertionFailureForBuildAssertionDocError() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -340,9 +106,33 @@ void validateLollipopBuildAssertionDocFailure() e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopValidatePeriodFailureWithFieldNotFoundInAssertionDoc() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopGetAssertionSuccess() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(EMPTY_ASSERTION_XML); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.emptyList()).when(sut).getIdpCertData(any(Document.class)); + doReturn(true).when(sut).validateSignature(any(Document.class), anyList()); + + boolean result = sut.validateLollipop(request); + + assertTrue(result); + } + + @SneakyThrows + @Test + void validateLollipopValidatePeriodFailureWithFieldNotFoundInAssertionDoc() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -357,9 +147,9 @@ void validateLollipopValidatePeriodFailureWithFieldNotFoundInAssertionDoc() AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopValidatePeriodFailureWithInvalidDateFormat() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidatePeriodFailureWithInvalidDateFormat() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -375,9 +165,9 @@ void validateLollipopValidatePeriodFailureWithInvalidDateFormat() e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopValidatePeriodFailureWithExpiredAssertion() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidatePeriodFailureWithExpiredAssertion() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -392,15 +182,41 @@ void validateLollipopValidatePeriodFailureWithExpiredAssertion() AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, e.getErrorCode()); } + @SneakyThrows + @Test + void validateLollipopValidatePeriodSuccess() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(new String(Base64.decode(ASSERTION_XML_TIM.getBytes(StandardCharsets.UTF_8)))); + + doReturn(365 * 20).when(lollipopRequestConfigMock).getAssertionExpireInDays(); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.emptyList()).when(sut).getIdpCertData(any(Document.class)); + doReturn(true).when(sut).validateSignature(any(Document.class), anyList()); + + boolean result = sut.validateLollipop(request); + + assertTrue(result); + } + + @SneakyThrows @Test - void validateLollipopValidateUserIdFailureWithoutAttributeTagInAssertionDoc() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateUserIdFailureWithoutAttributeTagInAssertionDoc() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); AssertionUserIdException e = assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); @@ -409,15 +225,16 @@ void validateLollipopValidateUserIdFailureWithoutAttributeTagInAssertionDoc() AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopValidateUserIdFailureWithoutFiscalCodeInAssertionDoc() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateUserIdFailureWithoutFiscalCodeInAssertionDoc() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITHOUT_FISCAL_CODE); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); AssertionUserIdException e = assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); @@ -426,15 +243,16 @@ void validateLollipopValidateUserIdFailureWithoutFiscalCodeInAssertionDoc() AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopValidateUserIdFailureWithInvalidUserIdHeader() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateUserIdFailureWithInvalidUserIdHeader() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); AssertionUserIdException e = assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); @@ -443,15 +261,41 @@ void validateLollipopValidateUserIdFailureWithInvalidUserIdHeader() AssertionUserIdException.ErrorCode.INVALID_USER_ID, e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopValidateThumbprintFailureWithoutSubjectConfirmationDataTagInAssertionDoc() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateUserIdSuccess() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", VALID_FISCAL_CODE); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.emptyList()).when(sut).getIdpCertData(any(Document.class)); + doReturn(true).when(sut).validateSignature(any(Document.class), anyList()); + + boolean result = sut.validateLollipop(request); + + assertTrue(result); + } + + @SneakyThrows + @Test + void + validateLollipopValidateThumbprintFailureWithoutSubjectConfirmationDataTagInAssertionDoc() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); AssertionThumbprintException e = assertThrows( @@ -462,15 +306,19 @@ void validateLollipopValidateThumbprintFailureWithoutSubjectConfirmationDataTagI e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopValidateThumbprintFailureWithInvalidInResponseToAlgorithm() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { - LollipopConsumerRequest request = getLollipopConsumerRequest("", "", VALID_FISCAL_CODE); + void validateLollipopValidateThumbprintFailureWithInvalidInResponseToAlgorithm() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); AssertionThumbprintException e = assertThrows( @@ -481,15 +329,19 @@ void validateLollipopValidateThumbprintFailureWithInvalidInResponseToAlgorithm() e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopValidateThumbprintFailureWithErrorCalculatingThumbprint() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { - LollipopConsumerRequest request = getLollipopConsumerRequest("", "", VALID_FISCAL_CODE); + void validateLollipopValidateThumbprintFailureWithErrorCalculatingThumbprint() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); AssertionThumbprintException e = assertThrows( @@ -501,16 +353,20 @@ void validateLollipopValidateThumbprintFailureWithErrorCalculatingThumbprint() Assertions.assertTrue(e.getCause() instanceof ParseException); } + @SneakyThrows @Test - void validateLollipopValidateThumbprintFailureWithDifferentAssertionRefAndCalculatedThumbprint() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { - LollipopConsumerRequest request = - getLollipopConsumerRequest("", VALID_JWK, VALID_FISCAL_CODE); + void + validateLollipopValidateThumbprintFailureWithDifferentAssertionRefAndCalculatedThumbprint() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", VALID_JWK, ""); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); AssertionThumbprintException e = assertThrows( @@ -520,65 +376,300 @@ void validateLollipopValidateThumbprintFailureWithDifferentAssertionRefAndCalcul AssertionThumbprintException.ErrorCode.INVALID_IN_RESPONSE_TO, e.getErrorCode()); } - /*@Test - void validateLollipopSuccessWithSHA256Algorithm() - throws LollipopAssertionNotFoundException, AssertionPeriodException, - AssertionThumbprintException, AssertionUserIdException, - ErrorRetrievingAssertionException, OidcAssertionNotSupported, - ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { + @SneakyThrows + @Test + void validateLollipopValidateThumbprintSHA256Success() { LollipopConsumerRequest request = - getLollipopConsumerRequest( - VALID_SHA_256_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); + getLollipopConsumerRequest(VALID_SHA_256_ASSERTION_REF, VALID_JWK, ""); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.emptyList()).when(sut).getIdpCertData(any(Document.class)); + doReturn(true).when(sut).validateSignature(any(Document.class), anyList()); boolean result = sut.validateLollipop(request); - Assertions.assertTrue(result); + assertTrue(result); } + @SneakyThrows @Test - void validateLollipopSuccessWithSHA384Algorithm() - throws LollipopAssertionNotFoundException, AssertionPeriodException, - AssertionThumbprintException, AssertionUserIdException, - ErrorRetrievingAssertionException, OidcAssertionNotSupported, - ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { + void validateLollipopValidateThumbprintSHA384Success() { LollipopConsumerRequest request = - getLollipopConsumerRequest( - VALID_SHA_384_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); + getLollipopConsumerRequest(VALID_SHA_384_ASSERTION_REF, VALID_JWK, ""); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.emptyList()).when(sut).getIdpCertData(any(Document.class)); + doReturn(true).when(sut).validateSignature(any(Document.class), anyList()); boolean result = sut.validateLollipop(request); - Assertions.assertTrue(result); + assertTrue(result); } + @SneakyThrows @Test - void validateLollipopSuccessWithSHA512Algorithm() - throws LollipopAssertionNotFoundException, AssertionPeriodException, - AssertionThumbprintException, AssertionUserIdException, - ErrorRetrievingAssertionException, OidcAssertionNotSupported, - ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { + void validateLollipopValidateThumbprintSHA512Success() { LollipopConsumerRequest request = - getLollipopConsumerRequest( - VALID_SHA_512_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); + getLollipopConsumerRequest(VALID_SHA_512_ASSERTION_REF, VALID_JWK, ""); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.emptyList()).when(sut).getIdpCertData(any(Document.class)); + doReturn(true).when(sut).validateSignature(any(Document.class), anyList()); + + boolean result = sut.validateLollipop(request); + + assertTrue(result); + } + + @SneakyThrows + @Test + void validateLollipopGetIdpCertDataFailureForMissingInstantField() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITHOUT_INSTANT_FIELD); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + + ErrorRetrievingIdpCertDataException e = + assertThrows( + ErrorRetrievingIdpCertDataException.class, + () -> sut.validateLollipop(request)); + + Assertions.assertEquals( + ErrorRetrievingIdpCertDataException.ErrorCode.INSTANT_FIELD_NOT_FOUND, + e.getErrorCode()); + } + + @SneakyThrows + @Test + void validateLollipopGetIdpCertDataFailureForMissingEntityIdField() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITHOUT_ENTITY_ID_FIELD); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + + ErrorRetrievingIdpCertDataException e = + assertThrows( + ErrorRetrievingIdpCertDataException.class, + () -> sut.validateLollipop(request)); + + Assertions.assertEquals( + ErrorRetrievingIdpCertDataException.ErrorCode.ENTITY_ID_FIELD_NOT_FOUND, + e.getErrorCode()); + } + + @SneakyThrows + @Test + void validateLollipopGetIdpCertDataFailureForIdpCertDataNotFoundException() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_VALID_ENTITY_ID_FIELD); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doThrow(CertDataNotFoundException.class) + .when(idpCertProviderMock) + .getIdpCertData(anyString(), anyString()); + + ErrorRetrievingIdpCertDataException e = + assertThrows( + ErrorRetrievingIdpCertDataException.class, + () -> sut.validateLollipop(request)); + + Assertions.assertEquals( + ErrorRetrievingIdpCertDataException.ErrorCode.IDP_CERT_DATA_NOT_FOUND, + e.getErrorCode()); + } + + @SneakyThrows + @Test + void validateLollipopGetIdpCertDataSuccess() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_VALID_ENTITY_ID_FIELD); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true).when(sut).validateSignature(any(Document.class), anyList()); + + boolean result = sut.validateLollipop(request); + + assertTrue(result); + } + + @SneakyThrows + @Test + void validateLollipopValidateSignatureFailureForErrorUnmarshalAssertion() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(EMPTY_ASSERTION_XML); + + IdpCertData idpCertData = new IdpCertData(); + idpCertData.setCertData(Collections.singletonList(CERTIFICATE_TIM_LATEST)); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.singletonList(idpCertData)) + .when(sut) + .getIdpCertData(any(Document.class)); + + ErrorValidatingAssertionSignature e = + assertThrows( + ErrorValidatingAssertionSignature.class, + () -> sut.validateLollipop(request)); + + Assertions.assertEquals( + ErrorValidatingAssertionSignature.ErrorCode.ERROR_PARSING_ASSERTION, + e.getErrorCode()); + } + + @SneakyThrows + @Test + void validateLollipopValidateSignatureFailureForMissingSignature() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); + + IdpCertData idpCertData = new IdpCertData(); + idpCertData.setCertData(Collections.singletonList(CERTIFICATE_TIM_LATEST)); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.singletonList(idpCertData)) + .when(sut) + .getIdpCertData(any(Document.class)); + + ErrorValidatingAssertionSignature e = + assertThrows( + ErrorValidatingAssertionSignature.class, + () -> sut.validateLollipop(request)); + + Assertions.assertEquals( + ErrorValidatingAssertionSignature.ErrorCode.MISSING_ASSERTION_SIGNATURE, + e.getErrorCode()); + } + + @SneakyThrows + @Test + void validateLollipopValidateSignatureFailureForSignatureNotValid() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_INVALID_SIGNATURE); + + IdpCertData idpCertData = new IdpCertData(); + idpCertData.setCertData(Collections.singletonList(CERTIFICATE_TIM_LATEST)); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.singletonList(idpCertData)) + .when(sut) + .getIdpCertData(any(Document.class)); boolean result = sut.validateLollipop(request); - Assertions.assertTrue(result); - }*/ + assertFalse(result); + } + + @SneakyThrows + @Test + void validateLollipopSuccess() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(new String(Base64.decode(ASSERTION_XML_TIM.getBytes(StandardCharsets.UTF_8)))); + + IdpCertData idpCertData = new IdpCertData(); + idpCertData.setCertData(Collections.singletonList(CERTIFICATE_TIM_LATEST)); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.singletonList(idpCertData)) + .when(sut) + .getIdpCertData(any(Document.class)); + + boolean result = sut.validateLollipop(request); + + assertTrue(result); + } private LollipopConsumerRequest getLollipopConsumerRequest( String assertionRef, String publicKey, String userId) { diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 1b8fa4e7..74c5fb0e 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1713,6 +1713,14 @@ + + + + + + + + @@ -1737,6 +1745,14 @@ + + + + + + + + @@ -1774,6 +1790,14 @@ + + + + + + + + @@ -1782,6 +1806,11 @@ + + + + + @@ -3090,6 +3119,14 @@ + + + + + + + + @@ -3187,6 +3224,11 @@ + + + + + @@ -3308,6 +3350,11 @@ + + + + + @@ -3628,6 +3675,14 @@ + + + + + + + + @@ -5121,6 +5176,14 @@ + + + + + + + + @@ -5129,6 +5192,14 @@ + + + + + + + + @@ -5147,6 +5218,14 @@ + + + + + + + + @@ -5155,6 +5234,14 @@ + + + + + + + + @@ -5163,6 +5250,14 @@ + + + + + + + + @@ -5171,6 +5266,14 @@ + + + + + + + + @@ -5179,6 +5282,14 @@ + + + + + + + + @@ -5187,6 +5298,14 @@ + + + + + + + + @@ -5195,6 +5314,14 @@ + + + + + + + + @@ -5203,6 +5330,14 @@ + + + + + + + + @@ -5243,6 +5378,14 @@ + + + + + + + + @@ -5251,6 +5394,14 @@ + + + + + + + + diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java new file mode 100644 index 00000000..dfc123b5 --- /dev/null +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java @@ -0,0 +1,21 @@ +package it.pagopa.tech.lollipop.consumer.service.impl; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import org.w3c.dom.Document; + +import java.util.List; + +public class MockAssertionVerifierService extends AssertionVerifierServiceImpl { + + public MockAssertionVerifierService(IdpCertProvider idpCertProvider, AssertionService assertionService, LollipopConsumerRequestConfig lollipopRequestConfig) { + super(idpCertProvider, assertionService, lollipopRequestConfig); + } + + @Override + protected boolean validateSignature(Document assertionDoc, List idpCertDataList) { + return true; + } +} diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java index c89d6ea3..5ac53fa8 100644 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java @@ -3,6 +3,11 @@ import static org.mockserver.integration.ClientAndServer.startClientAndServer; +import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.helper.LollipopConsumerFactoryHelper; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.service.impl.MockAssertionVerifierService; import it.pagopa.tech.lollipop.consumer.spring.config.HttpVerifierConfiguration; import it.pagopa.tech.lollipop.consumer.spring.config.SpringLollipopConsumerRequestConfig; import org.junit.jupiter.api.AfterAll; @@ -32,6 +37,7 @@ public class HttpVerifierHandlerInterceptorIntegrationTest { @LocalServerPort private int port; @Autowired private TestRestTemplate restTemplate; + @Autowired private LollipopConsumerFactoryHelper factoryHelper; @BeforeAll public static void startServer() { @@ -45,6 +51,7 @@ public static void startServer() { @Test void testWithValidRequestReturnsSuccess() { AssertionSimpleClientTestUtils.createExpectationAssertionFound(); + factoryHelper.setAssertionVerifierService(new MockAssertionVerifierService(factoryHelper.getIdpCertProviderFactory().create(), factoryHelper.getAssertionServiceFactory().create(), LollipopConsumerRequestConfig.builder().build())); String signatureInput = "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" From 0fe1897e10446a51daf32e5c3b2dbe479fb269ec Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 19 Apr 2023 18:52:49 +0200 Subject: [PATCH 249/403] [SLS-25] Applied spotless, updated verification-metadata.xml --- .../idp/impl/IdpCertProviderImpl.java | 1 - .../impl/AssertionVerifierServiceImpl.java | 9 +- .../AssertionVerifierServiceImplTest.java | 7 +- gradle/verification-metadata.xml | 123 +++++++++--------- .../impl/MockAssertionVerifierService.java | 9 +- ...fierHandlerInterceptorIntegrationTest.java | 8 +- 6 files changed, 80 insertions(+), 77 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java index eb428c1d..08661097 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java @@ -48,7 +48,6 @@ public List getIdpCertData(String assertionInstant, String entityId throw new IllegalArgumentException(errMsg); } - return idpCertClient.getCertData(entityId, assertionInstant); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index e6f74328..76dab4bb 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -219,9 +219,12 @@ protected List getIdpCertData(Document assertionDoc) "Missing entity id field in the retrieved saml assertion"); } try { - instant = Long.toString( - new SimpleDateFormat(lollipopRequestConfig.getAssertionNotBeforeDateFormat()) - .parse(instant).getTime()); + instant = + Long.toString( + new SimpleDateFormat( + lollipopRequestConfig.getAssertionNotBeforeDateFormat()) + .parse(instant) + .getTime()); } catch (ParseException e) { } try { diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java index ccdd1d81..9c748b99 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java @@ -12,7 +12,6 @@ import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; - import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.Collections; @@ -188,7 +187,8 @@ void validateLollipopValidatePeriodSuccess() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); - assertion.setAssertionData(new String(Base64.decode(ASSERTION_XML_TIM.getBytes(StandardCharsets.UTF_8)))); + assertion.setAssertionData( + new String(Base64.decode(ASSERTION_XML_TIM.getBytes(StandardCharsets.UTF_8)))); doReturn(365 * 20).when(lollipopRequestConfigMock).getAssertionExpireInDays(); @@ -649,7 +649,8 @@ void validateLollipopSuccess() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); - assertion.setAssertionData(new String(Base64.decode(ASSERTION_XML_TIM.getBytes(StandardCharsets.UTF_8)))); + assertion.setAssertionData( + new String(Base64.decode(ASSERTION_XML_TIM.getBytes(StandardCharsets.UTF_8)))); IdpCertData idpCertData = new IdpCertData(); idpCertData.setCertData(Collections.singletonList(CERTIFICATE_TIM_LATEST)); diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 74c5fb0e..1b76ae42 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1790,6 +1790,11 @@ + + + + + @@ -1816,11 +1821,6 @@ - - - - - @@ -3205,11 +3205,6 @@ - - - - - @@ -3626,6 +3621,19 @@ + + + + + + + + + + + + + @@ -3662,19 +3670,6 @@ - - - - - - - - - - - - - @@ -3830,6 +3825,13 @@ + + + + + + + @@ -3838,13 +3840,6 @@ - - - - - - - @@ -4239,14 +4234,6 @@ - - - - - - - - @@ -4312,6 +4299,14 @@ + + + + + + + + @@ -5702,32 +5697,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -5779,6 +5748,14 @@ + + + + + + + + @@ -5813,6 +5790,16 @@ + + + + + + + + + + @@ -5821,6 +5808,14 @@ + + + + + + + + diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java index dfc123b5..56a6eaf6 100644 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java @@ -1,16 +1,19 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service.impl; import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; -import org.w3c.dom.Document; - import java.util.List; +import org.w3c.dom.Document; public class MockAssertionVerifierService extends AssertionVerifierServiceImpl { - public MockAssertionVerifierService(IdpCertProvider idpCertProvider, AssertionService assertionService, LollipopConsumerRequestConfig lollipopRequestConfig) { + public MockAssertionVerifierService( + IdpCertProvider idpCertProvider, + AssertionService assertionService, + LollipopConsumerRequestConfig lollipopRequestConfig) { super(idpCertProvider, assertionService, lollipopRequestConfig); } diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java index 5ac53fa8..e665b819 100644 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java @@ -3,10 +3,8 @@ import static org.mockserver.integration.ClientAndServer.startClientAndServer; -import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.helper.LollipopConsumerFactoryHelper; -import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; import it.pagopa.tech.lollipop.consumer.service.impl.MockAssertionVerifierService; import it.pagopa.tech.lollipop.consumer.spring.config.HttpVerifierConfiguration; import it.pagopa.tech.lollipop.consumer.spring.config.SpringLollipopConsumerRequestConfig; @@ -51,7 +49,11 @@ public static void startServer() { @Test void testWithValidRequestReturnsSuccess() { AssertionSimpleClientTestUtils.createExpectationAssertionFound(); - factoryHelper.setAssertionVerifierService(new MockAssertionVerifierService(factoryHelper.getIdpCertProviderFactory().create(), factoryHelper.getAssertionServiceFactory().create(), LollipopConsumerRequestConfig.builder().build())); + factoryHelper.setAssertionVerifierService( + new MockAssertionVerifierService( + factoryHelper.getIdpCertProviderFactory().create(), + factoryHelper.getAssertionServiceFactory().create(), + LollipopConsumerRequestConfig.builder().build())); String signatureInput = "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" From 40147d4e457317d525741397743931afe2a7e4a7 Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 20 Apr 2023 11:10:51 +0200 Subject: [PATCH 250/403] [SLS-25] resolved sonarqube code smell and added unit test for coverage. do some refactor. --- .../impl/LollipopConsumerCommandImpl.java | 59 +++++++++-------- .../config/LollipopConsumerRequestConfig.java | 1 + .../idp/impl/IdpCertProviderImpl.java | 2 +- .../impl/AssertionVerifierServiceImpl.java | 25 ++++--- .../tech/lollipop/consumer/TestUtils.java | 34 ++++++++++ .../idp/impl/IdpCertProviderImplTest.java | 66 +++++++++++++++++++ .../AssertionVerifierServiceImplTest.java | 23 +++++++ ...sumerRequestValidationServiceImplTest.java | 33 ++++++---- gradle/verification-metadata.xml | 15 ++++- .../client/simple/IdpCertSimpleClient.java | 1 + .../TagListSearchOutOfBoundException.java | 2 +- 11 files changed, 209 insertions(+), 52 deletions(-) create mode 100644 core/src/test/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImplTest.java rename {core/src/main/java/it/pagopa/tech/lollipop/consumer => identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple}/exception/TagListSearchOutOfBoundException.java (80%) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index baa392d0..43a6eb4c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -22,6 +22,7 @@ public class LollipopConsumerCommandImpl implements LollipopConsumerCommand { private final LollipopConsumerRequest request; + private static final String CODE_AND_MESSAGE = " with error code: %s and message: %s"; public static final String VERIFICATION_SUCCESS_CODE = "SUCCESS"; public static final String REQUEST_PARAMS_VALIDATION_FAILED = "REQUEST PARAMS VALIDATION FAILED"; @@ -53,8 +54,9 @@ public CommandResult doExecute() { String message = String.format( "Error validating Lollipop request header or body, validation failed" - + " with error code %s and message: %s", - e.getErrorCode(), e.getMessage()); + + CODE_AND_MESSAGE, + e.getErrorCode(), + e.getMessage()); return buildCommandResult(REQUEST_PARAMS_VALIDATION_FAILED, message); } @@ -80,49 +82,52 @@ private CommandResult getAssertionVerificationResult(LollipopConsumerRequest req } catch (ErrorRetrievingAssertionException e) { String message = String.format( - "Cannot obtain the assertion, validation failed with error code %s" - + " and message: %s", - e.getErrorCode(), e.getMessage()); + "Cannot obtain the assertion, validation failed" + CODE_AND_MESSAGE, + e.getErrorCode(), + e.getMessage()); return buildCommandResult( AssertionVerificationResultCode.ERROR_RETRIEVING_ASSERTION.name(), message); } catch (AssertionPeriodException e) { String message = String.format( - "Assertion validation failed on verifying period with error code %s" - + " and message: %s", - e.getErrorCode(), e.getMessage()); + "Assertion validation failed on verifying period" + CODE_AND_MESSAGE, + e.getErrorCode(), + e.getMessage()); return buildCommandResult( AssertionVerificationResultCode.PERIOD_VALIDATION_ERROR.name(), message); } catch (AssertionThumbprintException e) { String message = String.format( - "Assertion validation failed on verifying thumbprint with error code" - + " %s and message: %s", - e.getErrorCode(), e.getMessage()); + "Assertion validation failed on verifying thumbprint" + + CODE_AND_MESSAGE, + e.getErrorCode(), + e.getMessage()); return buildCommandResult( AssertionVerificationResultCode.THUMBPRINT_VALIDATION_ERROR.name(), message); } catch (AssertionUserIdException e) { String message = String.format( - "Assertion validation failed on verifying user id with error code %s" - + " and message: %s", - e.getErrorCode(), e.getMessage()); + "Assertion validation failed on verifying user id" + CODE_AND_MESSAGE, + e.getErrorCode(), + e.getMessage()); return buildCommandResult( AssertionVerificationResultCode.USER_ID_VALIDATION_ERROR.name(), message); } catch (ErrorValidatingAssertionSignature e) { String message = String.format( - "Assertion validation failed on verifying signature with error code %s" - + " and message: %s", - e.getErrorCode(), e.getMessage()); + "Assertion validation failed on verifying signature" + CODE_AND_MESSAGE, + e.getErrorCode(), + e.getMessage()); return buildCommandResult( AssertionVerificationResultCode.SIGNATURE_VALIDATION_ERROR.name(), message); } catch (ErrorRetrievingIdpCertDataException e) { String message = String.format( "Assertion validation failed on retrieving identity provider's" - + " certification data with error code %s and message: %s", - e.getErrorCode(), e.getMessage()); + + " certification data" + + CODE_AND_MESSAGE, + e.getErrorCode(), + e.getMessage()); return buildCommandResult( AssertionVerificationResultCode.IDP_CERT_DATA_RETRIEVING_ERROR.name(), message); } @@ -145,16 +150,17 @@ private CommandResult getHttpMessageVerificationResult(LollipopConsumerRequest r } catch (LollipopDigestException e) { String message = String.format( - "HTTP message validation failed on verifying digest with error code %s" - + " and message: %s", - e.getErrorCode(), e.getMessage()); + "HTTP message validation failed on verifying digest" + CODE_AND_MESSAGE, + e.getErrorCode(), + e.getMessage()); return buildCommandResult( HttpMessageVerificationResultCode.DIGEST_VALIDATION_ERROR.name(), message); } catch (LollipopSignatureException e) { String message = String.format( - "HTTP message validation failed on verifying signatures with message:" - + " %s", + "HTTP message validation failed on verifying signatures" + + CODE_AND_MESSAGE, + e.getErrorCode(), e.getMessage()); return buildCommandResult( HttpMessageVerificationResultCode.SIGNATURE_VALIDATION_ERROR.name(), message); @@ -169,8 +175,9 @@ private CommandResult getHttpMessageVerificationResult(LollipopConsumerRequest r } catch (LollipopVerifierException e) { String message = String.format( - "HTTP message validation failed on content validation with message:" - + " %s", + "HTTP message validation failed on content validation" + + CODE_AND_MESSAGE, + e.getErrorCode(), e.getMessage()); return buildCommandResult( HttpMessageVerificationResultCode.REQUEST_VALIDATION_ERROR.name(), message); diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index ee6e7515..28e69042 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -35,6 +35,7 @@ public class LollipopConsumerRequestConfig { // assertion validation parameters @Builder.Default private int assertionExpireInDays = 30; @Builder.Default private String assertionNotBeforeDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; + @Builder.Default private String assertionInstantDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; @Builder.Default private String samlNamespaceAssertion = "urn:oasis:names:tc:SAML:2.0:assertion"; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java index 08661097..e6cb40fa 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java @@ -11,7 +11,7 @@ public class IdpCertProviderImpl implements IdpCertProvider { - private IdpCertClient idpCertClient; + private final IdpCertClient idpCertClient; @Inject public IdpCertProviderImpl(IdpCertClient idpCertClient) { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index 76dab4bb..8ec2e116 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -218,15 +218,7 @@ protected List getIdpCertData(Document assertionDoc) ErrorRetrievingIdpCertDataException.ErrorCode.ENTITY_ID_FIELD_NOT_FOUND, "Missing entity id field in the retrieved saml assertion"); } - try { - instant = - Long.toString( - new SimpleDateFormat( - lollipopRequestConfig.getAssertionNotBeforeDateFormat()) - .parse(instant) - .getTime()); - } catch (ParseException e) { - } + instant = parseInstantToMillis(instant); try { return idpCertProvider.getIdpCertData(instant, entityId.trim()); } catch (CertDataNotFoundException e) { @@ -418,4 +410,19 @@ private String getPublicKey(String publicKey) { } return publicKey; } + + private String parseInstantToMillis(String instant) { + String instantDateFormat = lollipopRequestConfig.getAssertionInstantDateFormat(); + try { + instant = + Long.toString(new SimpleDateFormat(instantDateFormat).parse(instant).getTime()); + } catch (ParseException e) { + String msg = + String.format( + "Retrieved instant %s does not match expected format %s", + instant, instantDateFormat); + log.log(Level.WARNING, msg); + } + return instant; + } } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java index ce1bc163..19e9727f 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java @@ -270,6 +270,38 @@ public class TestUtils { + " xsi:type=\"xs:string\">TINIT-AAAAAA89S20I111X\t\t" + "\t\t\t" + "\t"; + public static final String ASSERTION_XML_WITH_INVALID_INSTANT_FORMAT = + " \thttps://posteid.poste.it" + + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t\t\t" + + "\t\t\t\t\t\t\t\t\t\t" + + "\t\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t" + + "\t\t\t" + + "\t"; public static final String ASSERTION_XML_WITH_VALID_ENTITY_ID_FIELD = " sut.getIdpCertData(randomString1, randomString2)); + } + + @Test + void getIdpCertDataErrorInvalidInstantNull() { + String randomString = generateRandomString(); + Assertions.assertThrows( + IllegalArgumentException.class, () -> sut.getIdpCertData(null, randomString)); + } + + @Test + void getIdpCertDataErrorInvalidInstantEmpty() { + String randomString = generateRandomString(); + Assertions.assertThrows( + IllegalArgumentException.class, () -> sut.getIdpCertData("", randomString)); + } + + @Test + void getIdpCertDataErrorInvalidEntityIdNull() { + String randomString = generateRandomString(); + Assertions.assertThrows( + IllegalArgumentException.class, () -> sut.getIdpCertData(randomString, null)); + } + + @Test + void getIdpCertDataErrorInvalidEntityIdEmpty() { + String randomString = generateRandomString(); + Assertions.assertThrows( + IllegalArgumentException.class, () -> sut.getIdpCertData(randomString, "")); + } + + private String generateRandomString() { + byte[] array = new byte[7]; + random.nextBytes(array); + return new String(array, StandardCharsets.UTF_8); + } +} diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java index 9c748b99..18221542 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java @@ -526,6 +526,29 @@ void validateLollipopGetIdpCertDataFailureForIdpCertDataNotFoundException() { e.getErrorCode()); } + @SneakyThrows + @Test + void validateLollipopGetIdpCertDataSuccessWithWarningForInvalidInstantDateFormat() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_INVALID_INSTANT_FORMAT); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true).when(sut).validateSignature(any(Document.class), anyList()); + + boolean result = sut.validateLollipop(request); + + assertTrue(result); + } + @SneakyThrows @Test void validateLollipopGetIdpCertDataSuccess() { diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java index 8a380f98..2130e5d3 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java @@ -9,12 +9,19 @@ import it.pagopa.tech.lollipop.consumer.exception.LollipopRequestContentValidationException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; +import java.nio.charset.StandardCharsets; import java.util.HashMap; +import java.util.Random; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; class LollipopConsumerRequestValidationServiceImplTest { + private LollipopConsumerRequestConfig config; + private LollipopConsumerRequestValidationService sut; + + private final Random random = new Random(); + public static final String VALID_EC_PUBLIC_KEY = "{ \"kty\": \"EC\", \"x\": \"FqFDuwEgu4MUXERPMVL-85pGv2D3YmL4J1gfMkdbc24\", \"y\":" + " \"hdV0oxmWFSxMoJUDpdihr76rS8VRBEqMFebYyAfK9-k\", \"crv\": \"P-256\"}"; @@ -30,10 +37,6 @@ class LollipopConsumerRequestValidationServiceImplTest { + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; public static final String VALID_SIGNATURE = "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; - public static final String RANDOM_STRING = ""; - private LollipopConsumerRequestConfig config; - - private LollipopConsumerRequestValidationService sut; @BeforeEach void setUp() { @@ -60,7 +63,7 @@ void validatePublicKeyFailureHeaderNotPresent() { @Test void validatePublicKeyFailureHeaderInvalidFormat() { HashMap headers = new HashMap<>(); - headers.put(config.getPublicKeyHeader(), RANDOM_STRING); + headers.put(config.getPublicKeyHeader(), generateRandomString()); LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); @@ -95,7 +98,7 @@ void validateAssertionRefFailureHeaderNotPresent() { void validateAssertionRefFailureInvalidFormat() { HashMap headers = new HashMap<>(); headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); - headers.put(config.getAssertionRefHeader(), RANDOM_STRING); + headers.put(config.getAssertionRefHeader(), generateRandomString()); LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); @@ -132,7 +135,7 @@ void validateAssertionTypeFailureInvalidFormat() { HashMap headers = new HashMap<>(); headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); - headers.put(config.getAssertionTypeHeader(), RANDOM_STRING); + headers.put(config.getAssertionTypeHeader(), generateRandomString()); LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); @@ -171,7 +174,7 @@ void validateUserIdFailureInvalidFormat() { headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); - headers.put(config.getUserIdHeader(), RANDOM_STRING); + headers.put(config.getUserIdHeader(), generateRandomString()); LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); @@ -212,7 +215,7 @@ void validateAuthJWKFailureInvalidFormat() { headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); - headers.put(config.getAuthJWTHeader(), RANDOM_STRING); + headers.put(config.getAuthJWTHeader(), ""); LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); @@ -322,7 +325,7 @@ void validateOriginalURLFailureInvalidFormat() { headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); headers.put(config.getAuthJWTHeader(), VALID_JWT); headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); - headers.put(config.getOriginalURLHeader(), RANDOM_STRING); + headers.put(config.getOriginalURLHeader(), generateRandomString()); LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); @@ -392,7 +395,7 @@ void validateSignatureInputFailureInvalidFormat() { headers.put(config.getAuthJWTHeader(), VALID_JWT); headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); - headers.put(config.getSignatureInputHeader(), RANDOM_STRING); + headers.put(config.getSignatureInputHeader(), generateRandomString()); LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); @@ -441,7 +444,7 @@ void validateSignatureFailureInvalidFormat() { headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); headers.put(config.getSignatureInputHeader(), VALID_SIGNATURE_INPUT); - headers.put(config.getSignatureHeader(), RANDOM_STRING); + headers.put(config.getSignatureHeader(), generateRandomString()); LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); @@ -490,4 +493,10 @@ void validateRequestSuccessWithRSAPublicKey() { assertDoesNotThrow(() -> sut.validateLollipopRequest(request)); } + + private String generateRandomString() { + byte[] array = new byte[7]; + random.nextBytes(array); + return new String(array, StandardCharsets.UTF_8); + } } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 1b76ae42..c7b84545 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -375,6 +375,7 @@ + @@ -455,6 +456,7 @@ + @@ -533,6 +535,7 @@ + @@ -720,6 +723,7 @@ + @@ -739,6 +743,7 @@ + @@ -786,6 +791,7 @@ + @@ -806,6 +812,7 @@ + @@ -849,6 +856,7 @@ + @@ -868,6 +876,7 @@ + @@ -4765,7 +4774,7 @@ - + @@ -4864,7 +4873,7 @@ - + @@ -4912,7 +4921,7 @@ - + diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 54c57d15..33dacf88 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -3,6 +3,7 @@ import it.pagopa.tech.lollipop.consumer.exception.*; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.exception.TagListSearchOutOfBoundException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.api.DefaultApi; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/TagListSearchOutOfBoundException.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/exception/TagListSearchOutOfBoundException.java similarity index 80% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/TagListSearchOutOfBoundException.java rename to identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/exception/TagListSearchOutOfBoundException.java index ed780469..1561bf7e 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/TagListSearchOutOfBoundException.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/exception/TagListSearchOutOfBoundException.java @@ -1,5 +1,5 @@ /* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.exception; +package it.pagopa.tech.lollipop.consumer.idp.client.simple.exception; public class TagListSearchOutOfBoundException extends Exception { From 42170694276abccfdbfaf89aa07c715509ec269c Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 20 Apr 2023 11:55:26 +0200 Subject: [PATCH 251/403] [SLS-18] Updating logger service. Defined skeleton for logback lollipop includes --- core/build.gradle | 1 + .../LollipopConsumerCommandBuilderImpl.java | 2 + .../impl/LollipopConsumerCommandImpl.java | 57 ++++++++++++---- .../config/LollipopConsumerRequestConfig.java | 5 ++ .../helper/LollipopConsumerFactoryHelper.java | 9 +++ .../logger/LollipopLoggerService.java | 5 +- .../impl/LollipopLogbackLoggerService.java | 5 +- .../LollipopLogbackLoggerServiceFactory.java | 10 ++- .../consumer/model/CommandResult.java | 2 + .../lollipop/consumer/model/IdpCertData.java | 2 + .../model/LollipopConsumerRequest.java | 2 + .../consumer/model/SamlAssertion.java | 3 + .../impl/AssertionVerifierServiceImpl.java | 38 +++++++---- .../logging/logback/includes/defaults.xml | 23 +++++++ .../tech/lollipop/logging/logback/logback.xml | 5 ++ .../impl/LollipopConsumerCommandImplTest.java | 4 ++ sample/build.gradle | 1 + .../tech/sample/LollipopConsumerSample.java | 68 ++++++++++--------- spring-impl/build.gradle | 8 ++- .../src/main/resources/logback-spring.xml | 7 ++ 20 files changed, 190 insertions(+), 67 deletions(-) create mode 100644 core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/includes/defaults.xml create mode 100644 core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/logback.xml create mode 100644 spring-impl/src/main/resources/logback-spring.xml diff --git a/core/build.gradle b/core/build.gradle index ca02f3f0..dfc3a89f 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -45,6 +45,7 @@ dependencies { implementation 'javax.inject:javax.inject:1' implementation 'com.nimbusds:nimbus-jose-jwt:9.31' implementation 'ch.qos.logback:logback-classic:1.4.6' + implementation 'ch.qos.logback:logback-core:1.4.6' implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.2' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java index b1d0ee2e..40aa78fc 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImpl.java @@ -28,9 +28,11 @@ public LollipopConsumerCommandBuilderImpl(LollipopConsumerFactoryHelper factoryH @Override public LollipopConsumerCommand createCommand(LollipopConsumerRequest lollipopConsumerRequest) { return new LollipopConsumerCommandImpl( + factoryHelper.getLollipopConsumerRequestConfig(), factoryHelper.getHttpMessageVerifierService(), factoryHelper.getAssertionVerifierService(), factoryHelper.getRequestValidationService(), + factoryHelper.getLollipopLoggerService(), lollipopConsumerRequest); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index 55807f79..d5a4f3a4 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -2,24 +2,29 @@ package it.pagopa.tech.lollipop.consumer.command.impl; import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionVerificationResultCode; import it.pagopa.tech.lollipop.consumer.enumeration.HttpMessageVerificationResultCode; import it.pagopa.tech.lollipop.consumer.exception.*; +import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerService; import it.pagopa.tech.lollipop.consumer.model.CommandResult; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; 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 java.io.UnsupportedEncodingException; import javax.inject.Inject; /** Implementation of the {@link LollipopConsumerCommand} */ public class LollipopConsumerCommandImpl implements LollipopConsumerCommand { + private final LollipopConsumerRequestConfig lollipopConsumerRequestConfig; private final HttpMessageVerifierService messageVerifierService; private final AssertionVerifierService assertionVerifierService; private final LollipopConsumerRequestValidationService requestValidationService; private final LollipopConsumerRequest request; + private final LollipopLoggerService lollipopLoggerService; public static final String VERIFICATION_SUCCESS_CODE = "SUCCESS"; public static final String REQUEST_PARAMS_VALIDATION_FAILED = @@ -27,13 +32,17 @@ public class LollipopConsumerCommandImpl implements LollipopConsumerCommand { @Inject public LollipopConsumerCommandImpl( + LollipopConsumerRequestConfig lollipopConsumerRequestConfig, HttpMessageVerifierService messageVerifierService, AssertionVerifierService assertionVerifierService, LollipopConsumerRequestValidationService requestValidationService, - LollipopConsumerRequest lollipopConsumerRequest) { + LollipopLoggerService lollipopLoggerService, + LollipopConsumerRequest lollipopConsumerRequest) { + this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; this.messageVerifierService = messageVerifierService; this.assertionVerifierService = assertionVerifierService; this.requestValidationService = requestValidationService; + this.lollipopLoggerService = lollipopLoggerService; this.request = lollipopConsumerRequest; } @@ -46,31 +55,40 @@ public LollipopConsumerCommandImpl( @Override public CommandResult doExecute() { + CommandResult commandResult; try { requestValidationService.validateLollipopRequest(request); + + CommandResult messageVerificationResult = getHttpMessageVerificationResult(request); + if (!messageVerificationResult + .getResultCode() + .equals(HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_SUCCESS.name())) { + logRequestAndResponse(request, messageVerificationResult); + return messageVerificationResult; + } + CommandResult assertionVerificationResult = getAssertionVerificationResult(request); + if (!assertionVerificationResult + .getResultCode() + .equals(AssertionVerificationResultCode.ASSERTION_VERIFICATION_SUCCESS.name())) { + logRequestAndResponse(request, assertionVerificationResult); + return assertionVerificationResult; + } + } catch (LollipopRequestContentValidationException e) { String message = String.format( "Error validating Lollipop request header or body, validation failed" + " with error code %s and message: %s", e.getErrorCode(), e.getMessage()); - return buildCommandResult(REQUEST_PARAMS_VALIDATION_FAILED, message); + commandResult = buildCommandResult(REQUEST_PARAMS_VALIDATION_FAILED, message); + logRequestAndResponse(request, commandResult); + return commandResult; } - CommandResult messageVerificationResult = getHttpMessageVerificationResult(request); - if (!messageVerificationResult - .getResultCode() - .equals(HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_SUCCESS.name())) { - return messageVerificationResult; - } - CommandResult assertionVerificationResult = getAssertionVerificationResult(request); - if (!assertionVerificationResult - .getResultCode() - .equals(AssertionVerificationResultCode.ASSERTION_VERIFICATION_SUCCESS.name())) { - return assertionVerificationResult; - } - return buildCommandResult(VERIFICATION_SUCCESS_CODE, "Verification completed successfully"); + commandResult = buildCommandResult(VERIFICATION_SUCCESS_CODE, "Verification completed successfully"); + logRequestAndResponse(request, commandResult); + return commandResult; } private CommandResult getAssertionVerificationResult(LollipopConsumerRequest request) { @@ -173,4 +191,13 @@ private CommandResult getHttpMessageVerificationResult(LollipopConsumerRequest r private CommandResult buildCommandResult(String resultCode, String message) { return new CommandResult(resultCode, message); } + + private void logRequestAndResponse(LollipopConsumerRequest lollipopConsumerRequest, CommandResult commandResult) { + if (lollipopConsumerRequestConfig.isEnableConsumerLogging()) { + lollipopLoggerService.log("Lollipop validation for request: {} completed with the result: {}", + lollipopConsumerRequest, commandResult); + } + + } + } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index 74ae215f..149a00d0 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -42,4 +42,9 @@ public class LollipopConsumerRequestConfig { @Builder.Default private String assertionNotBeforeTag = "Conditions"; @Builder.Default private String assertionFiscalCodeTag = "Attribute"; @Builder.Default private String assertionInResponseToTag = "SubjectConfirmationData"; + + @Builder.Default private boolean enableConsumerLogging = true; + @Builder.Default private boolean enableAssertionLogging = true; + @Builder.Default private boolean enableIdpCertDataLogging = true; + } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index 87434aa9..47f64fe8 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -7,6 +7,10 @@ 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.logger.LollipopLoggerService; +import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerServiceFactory; +import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerService; +import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerServiceFactory; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; @@ -21,6 +25,7 @@ public class LollipopConsumerFactoryHelper { private final IdpCertProviderFactory idpCertProviderFactory; private final LollipopConsumerRequestValidationService lollipopConsumerRequestValidationService; private final AssertionServiceFactory assertionServiceFactory; + private IdpCertProvider idpCertProvider; private AssertionService assertionService; @@ -116,4 +121,8 @@ private synchronized AssertionService createAssertionService() { public LollipopConsumerRequestValidationService getRequestValidationService() { return lollipopConsumerRequestValidationService; } + + public LollipopLoggerService getLollipopLoggerService() { + return new LollipopLogbackLoggerService(); + } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerService.java index ea5b8858..645ae133 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerService.java @@ -1,9 +1,6 @@ package it.pagopa.tech.lollipop.consumer.logger; -import org.slf4j.event.Level; - public interface LollipopLoggerService { - - public void log(Level level, String message, Object... args); + void log(String message, Object... args); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerService.java index cd224e40..e02bb33e 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerService.java @@ -2,14 +2,15 @@ import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerService; import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; import org.slf4j.event.Level; @Slf4j public class LollipopLogbackLoggerService implements LollipopLoggerService { @Override - public void log(Level level, String message, Object... args) { - log.atLevel(level).log(message, args); + public void log(String message, Object... args) { + log.info(message, args); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactory.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactory.java index fb0c4553..c4e9ac45 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactory.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactory.java @@ -1,4 +1,12 @@ package it.pagopa.tech.lollipop.consumer.logger.impl; -public class LollipopLogbackLoggerServiceFactory { +import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerService; +import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerServiceFactory; + +public class LollipopLogbackLoggerServiceFactory implements LollipopLoggerServiceFactory { + @Override + public LollipopLoggerService create() { + return new LollipopLogbackLoggerService(); + } + } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/CommandResult.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/CommandResult.java index af008398..8113c1b0 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/CommandResult.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/CommandResult.java @@ -4,10 +4,12 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; +import lombok.ToString; @Getter @Setter @AllArgsConstructor +@ToString public class CommandResult { private String resultCode; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java index 12d0c7ab..23b3a90b 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java @@ -4,9 +4,11 @@ import java.util.List; import lombok.Getter; import lombok.Setter; +import lombok.ToString; @Getter @Setter +@ToString public class IdpCertData { private String entityId; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java index e6e9f5de..e11a00f8 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java @@ -4,8 +4,10 @@ import java.util.Map; import lombok.Builder; import lombok.Data; +import lombok.ToString; @Data +@ToString @Builder public class LollipopConsumerRequest { private String requestBody; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java index 9cfd590c..271e424f 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java @@ -3,11 +3,14 @@ import lombok.Getter; import lombok.Setter; +import lombok.ToString; @Getter @Setter +@ToString public class SamlAssertion { private String assertionRef; private String assertionData; + } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index c37a8a74..063c4585 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -10,10 +10,22 @@ import it.pagopa.tech.lollipop.consumer.enumeration.AssertionRefAlgorithms; import it.pagopa.tech.lollipop.consumer.exception.*; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerService; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; +import lombok.extern.slf4j.Slf4j; +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; + +import javax.inject.Inject; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.io.StringReader; import java.text.ParseException; @@ -22,23 +34,13 @@ 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 lombok.extern.slf4j.Slf4j; -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; @Slf4j /** Standard implementation of {@link AssertionVerifierService} */ public class AssertionVerifierServiceImpl implements AssertionVerifierService { + private final LollipopLoggerService lollipopLoggerService; + private final IdpCertProvider idpCertProvider; private final AssertionService assertionService; private final LollipopConsumerRequestConfig lollipopRequestConfig; @@ -47,9 +49,11 @@ public class AssertionVerifierServiceImpl implements AssertionVerifierService { @Inject public AssertionVerifierServiceImpl( + LollipopLoggerService lollipopLoggerService, IdpCertProvider idpCertProvider, AssertionService assertionService, LollipopConsumerRequestConfig lollipopRequestConfig) { + this.lollipopLoggerService = lollipopLoggerService; this.idpCertProvider = idpCertProvider; this.assertionService = assertionService; this.lollipopRequestConfig = lollipopRequestConfig; @@ -295,6 +299,16 @@ private String calculateThumbprint(String inResponseToAlgorithm, String publicKe return calculatedThumbprint; } + private void assertionCheckLogging(String message, Object... args) { + if (lollipopRequestConfig.isEnableConsumerLogging() && lollipopRequestConfig.isEnableAssertionLogging()) { + + } + } + + private void signatureCheckLogging() { + + } + private String getPublicKey(String publicKey) { try { publicKey = new String(Base64.getDecoder().decode(publicKey)); diff --git a/core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/includes/defaults.xml b/core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/includes/defaults.xml new file mode 100644 index 00000000..ef0a1944 --- /dev/null +++ b/core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/includes/defaults.xml @@ -0,0 +1,23 @@ + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level - %msg%n + + + + + true + 20000 + 0 + + + + + + + + \ No newline at end of file diff --git a/core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/logback.xml b/core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/logback.xml new file mode 100644 index 00000000..7a33166f --- /dev/null +++ b/core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/logback.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java index 18c673eb..094c9fd9 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -5,9 +5,11 @@ import static org.mockito.Mockito.*; import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionVerificationResultCode; import it.pagopa.tech.lollipop.consumer.enumeration.HttpMessageVerificationResultCode; import it.pagopa.tech.lollipop.consumer.exception.*; +import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerService; import it.pagopa.tech.lollipop.consumer.model.CommandResult; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; @@ -33,9 +35,11 @@ void beforeAll() { sut = Mockito.spy( new LollipopConsumerCommandImpl( + LollipopConsumerRequestConfig.builder().build(), messageVerifierServiceMock, assertionVerifierServiceMock, requestValidationServiceMock, + new LollipopLogbackLoggerService(), LollipopConsumerRequest.builder().build())); } diff --git a/sample/build.gradle b/sample/build.gradle index a29aeb51..9e8dfc8c 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -34,6 +34,7 @@ repositories { dependencies { implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:core:1.0.0-SNAPSHOT' implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:assertion-rest-client-native:1.0.0-SNAPSHOT' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:identity-service-rest-client-native:1.0.0-SNAPSHOT' implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:http-verifier:1.0.0-SNAPSHOT' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' diff --git a/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java b/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java index abfcc8e7..5ba96f36 100644 --- a/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java +++ b/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java @@ -14,9 +14,12 @@ import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; import it.pagopa.tech.lollipop.consumer.http_verifier.visma.VismaHttpMessageVerifierFactory; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; -import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImplStub; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImpl; import it.pagopa.tech.lollipop.consumer.model.CommandResult; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.tech.lollipop.consumer.service.impl.LollipopConsumerRequestValidationServiceImpl; import java.util.HashMap; import java.util.logging.Logger; @@ -28,48 +31,51 @@ public class LollipopConsumerSample { public static void main(String[] args) throws Exception { LollipopConsumerCommandBuilder commandBuilder = new LollipopConsumerCommandBuilderImpl(buildLollipopConsumerFactoryHelper()); - LollipopConsumerCommand command = commandBuilder.createCommand(); - CommandResult commandResult = command.doExecute(buildLollipopRequest( - VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)); - Logger.getGlobal().info(buildMessage(commandResult, "Validation of a valid Lollipop request ended with status code: ")); - - commandResult = command.doExecute(buildLollipopRequest( - INVALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)); - Logger.getGlobal().info(buildMessage(commandResult, "Validation of a Lollipop request with invalid digest header ended with status code: ")); - - commandResult = command.doExecute(buildLollipopRequest( - VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, INVALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)); - Logger.getGlobal().info(buildMessage(commandResult, "Validation of a Lollipop request with invalid content ended with status code: ")); - - commandResult = command.doExecute(buildLollipopRequest( - VALID_CONTENT_DIGEST, INVALID_ENCODING_UTF_326, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)); - Logger.getGlobal().info(buildMessage(commandResult, "Validation of a Lollipop request with unsupported encoding ended with status code: ")); - - commandResult = command.doExecute(buildLollipopRequest( - VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, INVALID_SIGNATURE_HEADER_VALUE)); - Logger.getGlobal().info(buildMessage(commandResult, "Validation of a Lollipop request with invalid signature ended with status code: ")); - - commandResult = command.doExecute(buildLollipopRequest( - VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, VALID_MULTI_ECDSA_IGNATURE_INPUT, VALID_MULTI_ECDSA_SIGNATURE)); - Logger.getGlobal().info(buildMessage(commandResult, "Validation of a valid Lollipop request with ecdsa multi-signature ended with status code: ")); - - commandResult = command.doExecute(buildLollipopRequest( - VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, LOLLIPOP_RSA_PUBKEY, VALID_RSA_PSS_SIGNATURE_INPUT, VALID_RSA_PSS_SIGNATURE)); - Logger.getGlobal().info(buildMessage(commandResult, "Validation of a valid Lollipop request with rsa-pss-256 signature ended with status code: ")); + CommandResult commandResult = commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)) + .doExecute(); + //Logger.getGlobal().info(buildMessage(commandResult, "Validation of a valid Lollipop request ended with status code: ")); + +// commandResult = command.doExecute(buildLollipopRequest( +// INVALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)); +// Logger.getGlobal().info(buildMessage(commandResult, "Validation of a Lollipop request with invalid digest header ended with status code: ")); +// +// commandResult = command.doExecute(buildLollipopRequest( +// VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, INVALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)); +// Logger.getGlobal().info(buildMessage(commandResult, "Validation of a Lollipop request with invalid content ended with status code: ")); +// +// commandResult = command.doExecute(buildLollipopRequest( +// VALID_CONTENT_DIGEST, INVALID_ENCODING_UTF_326, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)); +// Logger.getGlobal().info(buildMessage(commandResult, "Validation of a Lollipop request with unsupported encoding ended with status code: ")); +// +// commandResult = command.doExecute(buildLollipopRequest( +// VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, INVALID_SIGNATURE_HEADER_VALUE)); +// Logger.getGlobal().info(buildMessage(commandResult, "Validation of a Lollipop request with invalid signature ended with status code: ")); +// +// commandResult = command.doExecute(buildLollipopRequest( +// VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, VALID_MULTI_ECDSA_IGNATURE_INPUT, VALID_MULTI_ECDSA_SIGNATURE)); +// Logger.getGlobal().info(buildMessage(commandResult, "Validation of a valid Lollipop request with ecdsa multi-signature ended with status code: ")); +// +// commandResult = command.doExecute(buildLollipopRequest( +// VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, LOLLIPOP_RSA_PUBKEY, VALID_RSA_PSS_SIGNATURE_INPUT, VALID_RSA_PSS_SIGNATURE)); +// Logger.getGlobal().info(buildMessage(commandResult, "Validation of a valid Lollipop request with rsa-pss-256 signature ended with status code: ")); } private static LollipopConsumerFactoryHelper buildLollipopConsumerFactoryHelper() throws Exception { + LollipopConsumerRequestConfig lollipopConsumerRequestConfig = new LollipopConsumerRequestConfig(); HttpMessageVerifierFactory messageVerifierFactory = new VismaHttpMessageVerifierFactory(VALID_ENCODING_UTF8, LollipopConsumerRequestConfig.builder().build()); AssertionStorageProvider assertionStorageProvider = new SimpleAssertionStorageProvider(); + IdpCertProviderFactory idpCertProviderFactory = new IdpCertProviderFactoryImpl( + new IdpCertSimpleClientProvider(IdpCertSimpleClientConfig.builder().build())); AssertionClientProvider assertionClientProvider = new AssertionSimpleClientProvider(AssertionSimpleClientConfig.builder().build()); - IdpCertProviderFactory idpCertProviderFactory = new IdpCertProviderFactoryImplStub(); AssertionServiceFactory assertionServiceFactory = new AssertionServiceFactoryImpl( assertionStorageProvider, assertionClientProvider, new StorageConfig()); - return new LollipopConsumerFactoryHelper(messageVerifierFactory, idpCertProviderFactory, assertionServiceFactory); + return new LollipopConsumerFactoryHelper(messageVerifierFactory, idpCertProviderFactory, assertionServiceFactory, + new LollipopConsumerRequestValidationServiceImpl(lollipopConsumerRequestConfig)); } private static LollipopConsumerRequest buildLollipopRequest( diff --git a/spring-impl/build.gradle b/spring-impl/build.gradle index ee1d2f7f..80ec9378 100644 --- a/spring-impl/build.gradle +++ b/spring-impl/build.gradle @@ -17,10 +17,14 @@ repositories { } dependencies { - implementation project(':core') + implementation(project(':core')) { + exclude group: 'ch.qos.logback', module: 'logback-classic' + exclude group: 'ch.qos.logback', module: 'logback-core' + } implementation 'org.springframework.boot:spring-boot-starter-web:2.7.10' testImplementation 'org.springframework.boot:spring-boot-starter-test:2.7.10' - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2' + testImplementation 'ch.qos.logback:logback-classic:1.2.11' + testImplementation 'ch.qos.logback:logback-core:1.2.11' //Mockserver for testing api testImplementation 'org.mock-server:mockserver-netty:5.15.0' testImplementation project(':http-verifier') diff --git a/spring-impl/src/main/resources/logback-spring.xml b/spring-impl/src/main/resources/logback-spring.xml new file mode 100644 index 00000000..a999ed9c --- /dev/null +++ b/spring-impl/src/main/resources/logback-spring.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file From e7dda13aae32f05847dd3a68f86e90b3fe49b323 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 20 Apr 2023 12:36:56 +0200 Subject: [PATCH 252/403] [core-sprit-3] Fixing sonar issues --- ...pConsumerRequestValidationServiceImpl.java | 4 +- .../internal/model/EntityDescriptor.java | 49 +++++++++++++------ 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java index 9aeed6e2..dc1f7010 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java @@ -235,7 +235,7 @@ private void validateSignatureInputHeader(String signatureInput) } private boolean isNotValidSignatureInput(String signatureInput) { - return !Pattern.compile("^(((sig[0-9]+)=[^,]*?)(, ?)?)+$") + return !Pattern.compile("^(((sig[\\d]+)=[^,]*?)+(, ?)?)+$") .matcher(signatureInput) .matches(); } @@ -256,7 +256,7 @@ private void validateSignatureHeader(String signature) } private boolean isNotValidSignature(String signature) { - return !Pattern.compile("^((sig[0-9]+)=:[A-Za-z0-9+/=]*:(, ?)?)+$") + return !Pattern.compile("^((sig[\\d]+)=:[A-Za-z0-9+/=]*+:(, ?)?)+$") .matcher(signature) .matches(); } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java index 8e8b7d1d..9e74302b 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java @@ -30,6 +30,18 @@ public class EntityDescriptor { @SuppressWarnings("unchecked") @JsonProperty("IDPSSODescriptor") private void unpackNestedSignature(Map signature) { + List> keyDescriptorsList = getKeyDescriptorsList(signature); + + List> keyInfosList = getKeyInfosList(keyDescriptorsList); + + List> listX509Data = getListX509Data(keyInfosList); + + List extractedSignatureList = getExtractedSignatureList(listX509Data); + + this.signatureList = extractedSignatureList; + } + + private List> getKeyDescriptorsList(Map signature) { List> keyDescriptorsList = new ArrayList<>(); if (signature.get(KEY_DESCRIPTOR) instanceof List) { @@ -46,18 +58,22 @@ private void unpackNestedSignature(Map signature) { keyDescriptorsList.add(keyDescriptorFound); } } + return keyDescriptorsList; + } - List> keyInfosList = new ArrayList<>(); - for (Map keyDescriptor : keyDescriptorsList) { - if (keyDescriptor.get(KEY_INFO) instanceof List) { - keyInfosList = (List>) keyDescriptor.get(KEY_INFO); + private List getExtractedSignatureList(List> listX509Data) { + List extractedSignatureList = new ArrayList<>(); + for (Map x509Data : listX509Data) { + if (x509Data.get(X_509_CERTIFICATE) instanceof List) { + signatureList = (List) x509Data.get(X_509_CERTIFICATE); } else { - Map keyInfo = (Map) keyDescriptor.get(KEY_INFO); - - keyInfosList.add(keyInfo); + signatureList.add((String) x509Data.get(X_509_CERTIFICATE)); } } + return extractedSignatureList; + } + private List> getListX509Data(List> keyInfosList) { List> listX509Data = new ArrayList<>(); for (Map keyInfo : keyInfosList) { if (keyInfo.get(X_509_DATA) instanceof List) { @@ -66,16 +82,21 @@ private void unpackNestedSignature(Map signature) { listX509Data.add((Map) keyInfo.get(X_509_DATA)); } } + return listX509Data; + } - List signatureList = new ArrayList<>(); - for (Map x509Data : listX509Data) { - if (x509Data.get(X_509_CERTIFICATE) instanceof List) { - signatureList = (List) x509Data.get(X_509_CERTIFICATE); + private List> getKeyInfosList( + List> keyDescriptorsList) { + List> keyInfosList = new ArrayList<>(); + for (Map keyDescriptor : keyDescriptorsList) { + if (keyDescriptor.get(KEY_INFO) instanceof List) { + keyInfosList = (List>) keyDescriptor.get(KEY_INFO); } else { - signatureList.add((String) x509Data.get(X_509_CERTIFICATE)); + Map keyInfo = (Map) keyDescriptor.get(KEY_INFO); + + keyInfosList.add(keyInfo); } } - - this.signatureList = signatureList; + return keyInfosList; } } From 9e29e44d3c6f19fb5f9e928ed2eb1765a41bf55a Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 20 Apr 2023 12:56:39 +0200 Subject: [PATCH 253/403] [core-sprint-3] Fixing sonar issues --- .../client/simple/IdpCertSimpleClient.java | 112 ++++++++++-------- .../internal/model/EntityDescriptor.java | 4 +- 2 files changed, 63 insertions(+), 53 deletions(-) diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 33dacf88..58731c31 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -57,68 +57,78 @@ public List getCertData(String entityId, String instant) } if (entityConfig.getCieEntityId().contains(entityId)) { - try { - tagList = getCIETagList(instant); - } catch (ApiException - | TagListSearchOutOfBoundException - | InvalidInstantFormatException e) { - throw new CertDataNotFoundException( - "Error retrieving certificate's tag list: " + e.getMessage(), e); - } + getCieCerts(entityId, instant, listCertData); + } else { + getSpidCerts(entityId, instant, listCertData); + } + return listCertData; + } - for (String tag : tagList) { - try { - String storageTag = codifyStorageTag(tag, entityId); - IdpCertData certData = storage.getIdpCertData(storageTag); + private void getCieCerts(String entityId, String instant, List listCertData) throws CertDataNotFoundException { + List tagList; + try { + tagList = getCIETagList(instant); + } catch (ApiException + | TagListSearchOutOfBoundException + | InvalidInstantFormatException e) { + throw new CertDataNotFoundException( + "Error retrieving certificate's tag list: " + e.getMessage(), e); + } - if (certData == null) { - certData = getCIECertData(tag, entityId); - } else { - storage.saveIdpCertData(storageTag, certData); - } + for (String tag : tagList) { + try { + String storageTag = codifyStorageTag(tag, entityId); + IdpCertData certData = storage.getIdpCertData(storageTag); - listCertData.add(certData); - } catch (ApiException | EntityIdNotFoundException e) { - throw new CertDataNotFoundException( - "Error retrieving certificate data for tag " - + tag - + ": " - + e.getMessage(), - e); + if (certData == null) { + certData = getCIECertData(tag, entityId); + } else { + storage.saveIdpCertData(storageTag, certData); } - } - } else { - try { - tagList = getSPIDTagList(instant); - } catch (ApiException - | TagListSearchOutOfBoundException - | InvalidInstantFormatException e) { + + listCertData.add(certData); + } catch (ApiException | EntityIdNotFoundException e) { throw new CertDataNotFoundException( - "Error retrieving certificate's tag list: " + e.getMessage(), e); + "Error retrieving certificate data for tag " + + tag + + ": " + + e.getMessage(), + e); } + } + } - for (String tag : tagList) { - try { - String storageTag = codifyStorageTag(tag, entityId); - IdpCertData certData = storage.getIdpCertData(codifyStorageTag(tag, entityId)); + private void getSpidCerts(String entityId, String instant, List listCertData) throws CertDataNotFoundException { + List tagList; + try { + tagList = getSPIDTagList(instant); + } catch (ApiException + | TagListSearchOutOfBoundException + | InvalidInstantFormatException e) { + throw new CertDataNotFoundException( + "Error retrieving certificate's tag list: " + e.getMessage(), e); + } - if (certData == null) { - certData = getSPIDCertData(tag, entityId); - } else { - storage.saveIdpCertData(storageTag, certData); - } - listCertData.add(certData); - } catch (ApiException | EntityIdNotFoundException e) { - throw new CertDataNotFoundException( - "Error retrieving certificate data for tag " - + tag - + ": " - + e.getMessage(), - e); + for (String tag : tagList) { + try { + String storageTag = codifyStorageTag(tag, entityId); + IdpCertData certData = storage.getIdpCertData(codifyStorageTag(tag, entityId)); + + if (certData == null) { + certData = getSPIDCertData(tag, entityId); + } else { + storage.saveIdpCertData(storageTag, certData); } + listCertData.add(certData); + } catch (ApiException | EntityIdNotFoundException e) { + throw new CertDataNotFoundException( + "Error retrieving certificate data for tag " + + tag + + ": " + + e.getMessage(), + e); } } - return listCertData; } private List getSPIDTagList(String instant) diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java index 9e74302b..0fb4f418 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java @@ -65,9 +65,9 @@ private List getExtractedSignatureList(List> listX50 List extractedSignatureList = new ArrayList<>(); for (Map x509Data : listX509Data) { if (x509Data.get(X_509_CERTIFICATE) instanceof List) { - signatureList = (List) x509Data.get(X_509_CERTIFICATE); + extractedSignatureList = (List) x509Data.get(X_509_CERTIFICATE); } else { - signatureList.add((String) x509Data.get(X_509_CERTIFICATE)); + extractedSignatureList.add((String) x509Data.get(X_509_CERTIFICATE)); } } return extractedSignatureList; From 7b9a0e3e768ca5d0e63057679ae00f0165290d39 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 20 Apr 2023 12:57:45 +0200 Subject: [PATCH 254/403] [core-sprint-3] Fixing sonar issues --- .../idp/client/simple/IdpCertSimpleClient.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 58731c31..d4e610d3 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -64,7 +64,8 @@ public List getCertData(String entityId, String instant) return listCertData; } - private void getCieCerts(String entityId, String instant, List listCertData) throws CertDataNotFoundException { + private void getCieCerts(String entityId, String instant, List listCertData) + throws CertDataNotFoundException { List tagList; try { tagList = getCIETagList(instant); @@ -89,16 +90,14 @@ private void getCieCerts(String entityId, String instant, List list listCertData.add(certData); } catch (ApiException | EntityIdNotFoundException e) { throw new CertDataNotFoundException( - "Error retrieving certificate data for tag " - + tag - + ": " - + e.getMessage(), + "Error retrieving certificate data for tag " + tag + ": " + e.getMessage(), e); } } } - private void getSpidCerts(String entityId, String instant, List listCertData) throws CertDataNotFoundException { + private void getSpidCerts(String entityId, String instant, List listCertData) + throws CertDataNotFoundException { List tagList; try { tagList = getSPIDTagList(instant); @@ -122,10 +121,7 @@ private void getSpidCerts(String entityId, String instant, List lis listCertData.add(certData); } catch (ApiException | EntityIdNotFoundException e) { throw new CertDataNotFoundException( - "Error retrieving certificate data for tag " - + tag - + ": " - + e.getMessage(), + "Error retrieving certificate data for tag " + tag + ": " + e.getMessage(), e); } } From 533497aa549ad64d97226ac207c498bd375aff3c Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 20 Apr 2023 13:08:42 +0200 Subject: [PATCH 255/403] [core-sprint-3] Fixing sonar issues --- .../impl/LollipopConsumerRequestValidationServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java index dc1f7010..c4995b75 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java @@ -235,7 +235,7 @@ private void validateSignatureInputHeader(String signatureInput) } private boolean isNotValidSignatureInput(String signatureInput) { - return !Pattern.compile("^(((sig[\\d]+)=[^,]*?)+(, ?)?)+$") + return !Pattern.compile("^(((sig[\\d]++)=[^,]*)++(, ?)?)++$") .matcher(signatureInput) .matches(); } From 47b0f5ed80afff1519b074ad72cb4fefa06eeeaa Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 20 Apr 2023 15:02:46 +0200 Subject: [PATCH 256/403] [core-sprint-3] Fixing sonar issues --- .../impl/LollipopConsumerRequestValidationServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java index c4995b75..9c275cbe 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java @@ -235,7 +235,7 @@ private void validateSignatureInputHeader(String signatureInput) } private boolean isNotValidSignatureInput(String signatureInput) { - return !Pattern.compile("^(((sig[\\d]++)=[^,]*)++(, ?)?)++$") + return !Pattern.compile("^(((sig[\\d]++)=[^,]*+)(, ?+)?+)++$") .matcher(signatureInput) .matches(); } From da1f032cdfd3290f94fbde22dc6b7ab700b69234 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 19 Apr 2023 12:07:45 +0200 Subject: [PATCH 257/403] [SLS-13] Initialized spring sample --- {sample => samples/simple}/build.gradle | 0 {sample => samples/simple}/gradlew | 0 {sample => samples/simple}/gradlew.bat | 0 {sample => samples/simple}/settings.gradle | 0 .../pagopa/tech/sample/LollipopConstants.java | 0 .../tech/sample/LollipopConsumerSample.java | 0 samples/spring/.gitignore | 37 +++ samples/spring/build.gradle.kts | 33 +++ .../spring/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 60756 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + samples/spring/gradlew | 240 ++++++++++++++++++ samples/spring/gradlew.bat | 91 +++++++ samples/spring/settings.gradle.kts | 8 + .../consumer/sample/SampleApplication.java | 13 + .../src/main/resources/application.properties | 1 + .../sample/SampleApplicationTests.java | 13 + 16 files changed, 441 insertions(+) rename {sample => samples/simple}/build.gradle (100%) rename {sample => samples/simple}/gradlew (100%) rename {sample => samples/simple}/gradlew.bat (100%) rename {sample => samples/simple}/settings.gradle (100%) rename {sample => samples/simple}/src/main/java/it/pagopa/tech/sample/LollipopConstants.java (100%) rename {sample => samples/simple}/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java (100%) create mode 100644 samples/spring/.gitignore create mode 100644 samples/spring/build.gradle.kts create mode 100644 samples/spring/gradle/wrapper/gradle-wrapper.jar create mode 100644 samples/spring/gradle/wrapper/gradle-wrapper.properties create mode 100644 samples/spring/gradlew create mode 100644 samples/spring/gradlew.bat create mode 100644 samples/spring/settings.gradle.kts create mode 100644 samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java create mode 100644 samples/spring/src/main/resources/application.properties create mode 100644 samples/spring/src/test/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplicationTests.java diff --git a/sample/build.gradle b/samples/simple/build.gradle similarity index 100% rename from sample/build.gradle rename to samples/simple/build.gradle diff --git a/sample/gradlew b/samples/simple/gradlew similarity index 100% rename from sample/gradlew rename to samples/simple/gradlew diff --git a/sample/gradlew.bat b/samples/simple/gradlew.bat similarity index 100% rename from sample/gradlew.bat rename to samples/simple/gradlew.bat diff --git a/sample/settings.gradle b/samples/simple/settings.gradle similarity index 100% rename from sample/settings.gradle rename to samples/simple/settings.gradle diff --git a/sample/src/main/java/it/pagopa/tech/sample/LollipopConstants.java b/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConstants.java similarity index 100% rename from sample/src/main/java/it/pagopa/tech/sample/LollipopConstants.java rename to samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConstants.java diff --git a/sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java b/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java similarity index 100% rename from sample/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java rename to samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java diff --git a/samples/spring/.gitignore b/samples/spring/.gitignore new file mode 100644 index 00000000..c2065bc2 --- /dev/null +++ b/samples/spring/.gitignore @@ -0,0 +1,37 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ diff --git a/samples/spring/build.gradle.kts b/samples/spring/build.gradle.kts new file mode 100644 index 00000000..eb895a36 --- /dev/null +++ b/samples/spring/build.gradle.kts @@ -0,0 +1,33 @@ +plugins { + java + id("org.springframework.boot") version "2.7.11-SNAPSHOT" + id("io.spring.dependency-management") version "1.0.15.RELEASE" +} + +group = "it.pagopa.tech.lollipop.consumer" +version = "0.0.1-SNAPSHOT" +java.sourceCompatibility = JavaVersion.VERSION_11 + +configurations { + compileOnly { + extendsFrom(configurations.annotationProcessor.get()) + } +} + +repositories { + mavenCentral() + maven { url = uri("https://repo.spring.io/milestone") } + maven { url = uri("https://repo.spring.io/snapshot") } +} + +dependencies { + implementation("org.springframework.boot:spring-boot-starter-web") + compileOnly("org.projectlombok:lombok") + developmentOnly("org.springframework.boot:spring-boot-devtools") + annotationProcessor("org.projectlombok:lombok") + testImplementation("org.springframework.boot:spring-boot-starter-test") +} + +tasks.withType { + useJUnitPlatform() +} diff --git a/samples/spring/gradle/wrapper/gradle-wrapper.jar b/samples/spring/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..249e5832f090a2944b7473328c07c9755baa3196 GIT binary patch literal 60756 zcmb5WV{~QRw(p$^Dz@00IL3?^hro$gg*4VI_WAaTyVM5Foj~O|-84 z$;06hMwt*rV;^8iB z1~&0XWpYJmG?Ts^K9PC62H*`G}xom%S%yq|xvG~FIfP=9*f zZoDRJBm*Y0aId=qJ?7dyb)6)JGWGwe)MHeNSzhi)Ko6J<-m@v=a%NsP537lHe0R* z`If4$aaBA#S=w!2z&m>{lpTy^Lm^mg*3?M&7HFv}7K6x*cukLIGX;bQG|QWdn{%_6 zHnwBKr84#B7Z+AnBXa16a?or^R?+>$4`}{*a_>IhbjvyTtWkHw)|ay)ahWUd-qq$~ zMbh6roVsj;_qnC-R{G+Cy6bApVOinSU-;(DxUEl!i2)1EeQ9`hrfqj(nKI7?Z>Xur zoJz-a`PxkYit1HEbv|jy%~DO^13J-ut986EEG=66S}D3!L}Efp;Bez~7tNq{QsUMm zh9~(HYg1pA*=37C0}n4g&bFbQ+?-h-W}onYeE{q;cIy%eZK9wZjSwGvT+&Cgv z?~{9p(;bY_1+k|wkt_|N!@J~aoY@|U_RGoWX<;p{Nu*D*&_phw`8jYkMNpRTWx1H* z>J-Mi_!`M468#5Aix$$u1M@rJEIOc?k^QBc?T(#=n&*5eS#u*Y)?L8Ha$9wRWdH^3D4|Ps)Y?m0q~SiKiSfEkJ!=^`lJ(%W3o|CZ zSrZL-Xxc{OrmsQD&s~zPfNJOpSZUl%V8tdG%ei}lQkM+z@-4etFPR>GOH9+Y_F<3=~SXln9Kb-o~f>2a6Xz@AS3cn^;c_>lUwlK(n>z?A>NbC z`Ud8^aQy>wy=$)w;JZzA)_*Y$Z5hU=KAG&htLw1Uh00yE!|Nu{EZkch zY9O6x7Y??>!7pUNME*d!=R#s)ghr|R#41l!c?~=3CS8&zr6*aA7n9*)*PWBV2w+&I zpW1-9fr3j{VTcls1>ua}F*bbju_Xq%^v;-W~paSqlf zolj*dt`BBjHI)H9{zrkBo=B%>8}4jeBO~kWqO!~Thi!I1H(in=n^fS%nuL=X2+s!p}HfTU#NBGiwEBF^^tKU zbhhv+0dE-sbK$>J#t-J!B$TMgN@Wh5wTtK2BG}4BGfsZOoRUS#G8Cxv|6EI*n&Xxq zt{&OxCC+BNqz$9b0WM7_PyBJEVObHFh%%`~!@MNZlo*oXDCwDcFwT~Rls!aApL<)^ zbBftGKKBRhB!{?fX@l2_y~%ygNFfF(XJzHh#?`WlSL{1lKT*gJM zs>bd^H9NCxqxn(IOky5k-wALFowQr(gw%|`0991u#9jXQh?4l|l>pd6a&rx|v=fPJ z1mutj{YzpJ_gsClbWFk(G}bSlFi-6@mwoQh-XeD*j@~huW4(8ub%^I|azA)h2t#yG z7e_V_<4jlM3D(I+qX}yEtqj)cpzN*oCdYHa!nm%0t^wHm)EmFP*|FMw!tb@&`G-u~ zK)=Sf6z+BiTAI}}i{*_Ac$ffr*Wrv$F7_0gJkjx;@)XjYSh`RjAgrCck`x!zP>Ifu z&%he4P|S)H*(9oB4uvH67^0}I-_ye_!w)u3v2+EY>eD3#8QR24<;7?*hj8k~rS)~7 zSXs5ww)T(0eHSp$hEIBnW|Iun<_i`}VE0Nc$|-R}wlSIs5pV{g_Dar(Zz<4X3`W?K z6&CAIl4U(Qk-tTcK{|zYF6QG5ArrEB!;5s?tW7 zrE3hcFY&k)+)e{+YOJ0X2uDE_hd2{|m_dC}kgEKqiE9Q^A-+>2UonB+L@v3$9?AYw zVQv?X*pK;X4Ovc6Ev5Gbg{{Eu*7{N3#0@9oMI~}KnObQE#Y{&3mM4`w%wN+xrKYgD zB-ay0Q}m{QI;iY`s1Z^NqIkjrTlf`B)B#MajZ#9u41oRBC1oM1vq0i|F59> z#StM@bHt|#`2)cpl_rWB($DNJ3Lap}QM-+A$3pe}NyP(@+i1>o^fe-oxX#Bt`mcQc zb?pD4W%#ep|3%CHAYnr*^M6Czg>~L4?l16H1OozM{P*en298b+`i4$|w$|4AHbzqB zHpYUsHZET$Z0ztC;U+0*+amF!@PI%^oUIZy{`L{%O^i{Xk}X0&nl)n~tVEpcAJSJ} zverw15zP1P-O8h9nd!&hj$zuwjg?DoxYIw{jWM zW5_pj+wFy8Tsa9g<7Qa21WaV&;ejoYflRKcz?#fSH_)@*QVlN2l4(QNk| z4aPnv&mrS&0|6NHq05XQw$J^RR9T{3SOcMKCXIR1iSf+xJ0E_Wv?jEc*I#ZPzyJN2 zUG0UOXHl+PikM*&g$U@g+KbG-RY>uaIl&DEtw_Q=FYq?etc!;hEC_}UX{eyh%dw2V zTTSlap&5>PY{6I#(6`j-9`D&I#|YPP8a;(sOzgeKDWsLa!i-$frD>zr-oid!Hf&yS z!i^cr&7tN}OOGmX2)`8k?Tn!!4=tz~3hCTq_9CdiV!NIblUDxHh(FJ$zs)B2(t5@u z-`^RA1ShrLCkg0)OhfoM;4Z{&oZmAec$qV@ zGQ(7(!CBk<5;Ar%DLJ0p0!ResC#U<+3i<|vib1?{5gCebG7$F7URKZXuX-2WgF>YJ^i zMhHDBsh9PDU8dlZ$yJKtc6JA#y!y$57%sE>4Nt+wF1lfNIWyA`=hF=9Gj%sRwi@vd z%2eVV3y&dvAgyuJ=eNJR+*080dbO_t@BFJO<@&#yqTK&+xc|FRR;p;KVk@J3$S{p` zGaMj6isho#%m)?pOG^G0mzOAw0z?!AEMsv=0T>WWcE>??WS=fII$t$(^PDPMU(P>o z_*0s^W#|x)%tx8jIgZY~A2yG;US0m2ZOQt6yJqW@XNY_>_R7(Nxb8Ged6BdYW6{prd!|zuX$@Q2o6Ona8zzYC1u!+2!Y$Jc9a;wy+pXt}o6~Bu1oF1c zp7Y|SBTNi@=I(K%A60PMjM#sfH$y*c{xUgeSpi#HB`?|`!Tb&-qJ3;vxS!TIzuTZs-&%#bAkAyw9m4PJgvey zM5?up*b}eDEY+#@tKec)-c(#QF0P?MRlD1+7%Yk*jW;)`f;0a-ZJ6CQA?E%>i2Dt7T9?s|9ZF|KP4;CNWvaVKZ+Qeut;Jith_y{v*Ny6Co6!8MZx;Wgo z=qAi%&S;8J{iyD&>3CLCQdTX*$+Rx1AwA*D_J^0>suTgBMBb=*hefV+Ars#mmr+YsI3#!F@Xc1t4F-gB@6aoyT+5O(qMz*zG<9Qq*f0w^V!03rpr*-WLH}; zfM{xSPJeu6D(%8HU%0GEa%waFHE$G?FH^kMS-&I3)ycx|iv{T6Wx}9$$D&6{%1N_8 z_CLw)_9+O4&u94##vI9b-HHm_95m)fa??q07`DniVjAy`t7;)4NpeyAY(aAk(+T_O z1om+b5K2g_B&b2DCTK<>SE$Ode1DopAi)xaJjU>**AJK3hZrnhEQ9E`2=|HHe<^tv z63e(bn#fMWuz>4erc47}!J>U58%<&N<6AOAewyzNTqi7hJc|X{782&cM zHZYclNbBwU6673=!ClmxMfkC$(CykGR@10F!zN1Se83LR&a~$Ht&>~43OX22mt7tcZUpa;9@q}KDX3O&Ugp6< zLZLfIMO5;pTee1vNyVC$FGxzK2f>0Z-6hM82zKg44nWo|n}$Zk6&;5ry3`(JFEX$q zK&KivAe${e^5ZGc3a9hOt|!UOE&OocpVryE$Y4sPcs4rJ>>Kbi2_subQ9($2VN(3o zb~tEzMsHaBmBtaHAyES+d3A(qURgiskSSwUc9CfJ@99&MKp2sooSYZu+-0t0+L*!I zYagjOlPgx|lep9tiU%ts&McF6b0VE57%E0Ho%2oi?=Ks+5%aj#au^OBwNwhec zta6QAeQI^V!dF1C)>RHAmB`HnxyqWx?td@4sd15zPd*Fc9hpDXP23kbBenBxGeD$k z;%0VBQEJ-C)&dTAw_yW@k0u?IUk*NrkJ)(XEeI z9Y>6Vel>#s_v@=@0<{4A{pl=9cQ&Iah0iD0H`q)7NeCIRz8zx;! z^OO;1+IqoQNak&pV`qKW+K0^Hqp!~gSohcyS)?^P`JNZXw@gc6{A3OLZ?@1Uc^I2v z+X!^R*HCm3{7JPq{8*Tn>5;B|X7n4QQ0Bs79uTU%nbqOJh`nX(BVj!#f;#J+WZxx4 z_yM&1Y`2XzhfqkIMO7tB3raJKQS+H5F%o83bM+hxbQ zeeJm=Dvix$2j|b4?mDacb67v-1^lTp${z=jc1=j~QD>7c*@+1?py>%Kj%Ejp7Y-!? z8iYRUlGVrQPandAaxFfks53@2EC#0)%mrnmGRn&>=$H$S8q|kE_iWko4`^vCS2aWg z#!`RHUGyOt*k?bBYu3*j3u0gB#v(3tsije zgIuNNWNtrOkx@Pzs;A9un+2LX!zw+p3_NX^Sh09HZAf>m8l@O*rXy_82aWT$Q>iyy zqO7Of)D=wcSn!0+467&!Hl))eff=$aneB?R!YykdKW@k^_uR!+Q1tR)+IJb`-6=jj zymzA>Sv4>Z&g&WWu#|~GcP7qP&m*w-S$)7Xr;(duqCTe7p8H3k5>Y-n8438+%^9~K z3r^LIT_K{i7DgEJjIocw_6d0!<;wKT`X;&vv+&msmhAAnIe!OTdybPctzcEzBy88_ zWO{6i4YT%e4^WQZB)KHCvA(0tS zHu_Bg+6Ko%a9~$EjRB90`P(2~6uI@SFibxct{H#o&y40MdiXblu@VFXbhz>Nko;7R z70Ntmm-FePqhb%9gL+7U8@(ch|JfH5Fm)5${8|`Lef>LttM_iww6LW2X61ldBmG0z zax3y)njFe>j*T{i0s8D4=L>X^j0)({R5lMGVS#7(2C9@AxL&C-lZQx~czI7Iv+{%1 z2hEG>RzX4S8x3v#9sgGAnPzptM)g&LB}@%E>fy0vGSa(&q0ch|=ncKjNrK z`jA~jObJhrJ^ri|-)J^HUyeZXz~XkBp$VhcTEcTdc#a2EUOGVX?@mYx#Vy*!qO$Jv zQ4rgOJ~M*o-_Wptam=~krnmG*p^j!JAqoQ%+YsDFW7Cc9M%YPiBOrVcD^RY>m9Pd< zu}#9M?K{+;UIO!D9qOpq9yxUquQRmQNMo0pT`@$pVt=rMvyX)ph(-CCJLvUJy71DI zBk7oc7)-%ngdj~s@76Yse3L^gV0 z2==qfp&Q~L(+%RHP0n}+xH#k(hPRx(!AdBM$JCfJ5*C=K3ts>P?@@SZ_+{U2qFZb>4kZ{Go37{# zSQc+-dq*a-Vy4?taS&{Ht|MLRiS)Sn14JOONyXqPNnpq&2y~)6wEG0oNy>qvod$FF z`9o&?&6uZjhZ4_*5qWVrEfu(>_n2Xi2{@Gz9MZ8!YmjYvIMasE9yVQL10NBrTCczq zcTY1q^PF2l!Eraguf{+PtHV3=2A?Cu&NN&a8V(y;q(^_mFc6)%Yfn&X&~Pq zU1?qCj^LF(EQB1F`8NxNjyV%fde}dEa(Hx=r7$~ts2dzDwyi6ByBAIx$NllB4%K=O z$AHz1<2bTUb>(MCVPpK(E9wlLElo(aSd(Os)^Raum`d(g9Vd_+Bf&V;l=@mM=cC>) z)9b0enb)u_7V!!E_bl>u5nf&Rl|2r=2F3rHMdb7y9E}}F82^$Rf+P8%dKnOeKh1vs zhH^P*4Ydr^$)$h@4KVzxrHyy#cKmWEa9P5DJ|- zG;!Qi35Tp7XNj60=$!S6U#!(${6hyh7d4q=pF{`0t|N^|L^d8pD{O9@tF~W;#Je*P z&ah%W!KOIN;SyAEhAeTafJ4uEL`(RtnovM+cb(O#>xQnk?dzAjG^~4$dFn^<@-Na3 z395;wBnS{t*H;Jef2eE!2}u5Ns{AHj>WYZDgQJt8v%x?9{MXqJsGP|l%OiZqQ1aB! z%E=*Ig`(!tHh>}4_z5IMpg{49UvD*Pp9!pxt_gdAW%sIf3k6CTycOT1McPl=_#0?8 zVjz8Hj*Vy9c5-krd-{BQ{6Xy|P$6LJvMuX$* zA+@I_66_ET5l2&gk9n4$1M3LN8(yEViRx&mtd#LD}AqEs?RW=xKC(OCWH;~>(X6h!uDxXIPH06xh z*`F4cVlbDP`A)-fzf>MuScYsmq&1LUMGaQ3bRm6i7OsJ|%uhTDT zlvZA1M}nz*SalJWNT|`dBm1$xlaA>CCiQ zK`xD-RuEn>-`Z?M{1%@wewf#8?F|(@1e0+T4>nmlSRrNK5f)BJ2H*$q(H>zGD0>eL zQ!tl_Wk)k*e6v^m*{~A;@6+JGeWU-q9>?+L_#UNT%G?4&BnOgvm9@o7l?ov~XL+et zbGT)|G7)KAeqb=wHSPk+J1bdg7N3$vp(ekjI1D9V$G5Cj!=R2w=3*4!z*J-r-cyeb zd(i2KmX!|Lhey!snRw z?#$Gu%S^SQEKt&kep)up#j&9}e+3=JJBS(s>MH+|=R(`8xK{mmndWo_r`-w1#SeRD&YtAJ#GiVI*TkQZ}&aq<+bU2+coU3!jCI6E+Ad_xFW*ghnZ$q zAoF*i&3n1j#?B8x;kjSJD${1jdRB;)R*)Ao!9bd|C7{;iqDo|T&>KSh6*hCD!rwv= zyK#F@2+cv3=|S1Kef(E6Niv8kyLVLX&e=U;{0x{$tDfShqkjUME>f8d(5nzSkY6@! z^-0>DM)wa&%m#UF1F?zR`8Y3X#tA!*7Q$P3lZJ%*KNlrk_uaPkxw~ zxZ1qlE;Zo;nb@!SMazSjM>;34ROOoygo%SF);LL>rRonWwR>bmSd1XD^~sGSu$Gg# zFZ`|yKU0%!v07dz^v(tY%;So(e`o{ZYTX`hm;@b0%8|H>VW`*cr8R%3n|ehw2`(9B+V72`>SY}9^8oh$En80mZK9T4abVG*to;E z1_S6bgDOW?!Oy1LwYy=w3q~KKdbNtyH#d24PFjX)KYMY93{3-mPP-H>@M-_>N~DDu zENh~reh?JBAK=TFN-SfDfT^=+{w4ea2KNWXq2Y<;?(gf(FgVp8Zp-oEjKzB%2Iqj;48GmY3h=bcdYJ}~&4tS`Q1sb=^emaW$IC$|R+r-8V- zf0$gGE(CS_n4s>oicVk)MfvVg#I>iDvf~Ov8bk}sSxluG!6#^Z_zhB&U^`eIi1@j( z^CK$z^stBHtaDDHxn+R;3u+>Lil^}fj?7eaGB z&5nl^STqcaBxI@v>%zG|j))G(rVa4aY=B@^2{TFkW~YP!8!9TG#(-nOf^^X-%m9{Z zCC?iC`G-^RcBSCuk=Z`(FaUUe?hf3{0C>>$?Vs z`2Uud9M+T&KB6o4o9kvdi^Q=Bw!asPdxbe#W-Oaa#_NP(qpyF@bVxv5D5))srkU#m zj_KA+#7sqDn*Ipf!F5Byco4HOSd!Ui$l94|IbW%Ny(s1>f4|Mv^#NfB31N~kya9!k zWCGL-$0ZQztBate^fd>R!hXY_N9ZjYp3V~4_V z#eB)Kjr8yW=+oG)BuNdZG?jaZlw+l_ma8aET(s+-x+=F-t#Qoiuu1i`^x8Sj>b^U} zs^z<()YMFP7CmjUC@M=&lA5W7t&cxTlzJAts*%PBDAPuqcV5o7HEnqjif_7xGt)F% zGx2b4w{@!tE)$p=l3&?Bf#`+!-RLOleeRk3 z7#pF|w@6_sBmn1nECqdunmG^}pr5(ZJQVvAt$6p3H(16~;vO>?sTE`Y+mq5YP&PBo zvq!7#W$Gewy`;%6o^!Dtjz~x)T}Bdk*BS#=EY=ODD&B=V6TD2z^hj1m5^d6s)D*wk zu$z~D7QuZ2b?5`p)E8e2_L38v3WE{V`bVk;6fl#o2`) z99JsWhh?$oVRn@$S#)uK&8DL8>An0&S<%V8hnGD7Z^;Y(%6;^9!7kDQ5bjR_V+~wp zfx4m3z6CWmmZ<8gDGUyg3>t8wgJ5NkkiEm^(sedCicP^&3D%}6LtIUq>mXCAt{9eF zNXL$kGcoUTf_Lhm`t;hD-SE)m=iBnxRU(NyL}f6~1uH)`K!hmYZjLI%H}AmEF5RZt z06$wn63GHnApHXZZJ}s^s)j9(BM6e*7IBK6Bq(!)d~zR#rbxK9NVIlgquoMq z=eGZ9NR!SEqP6=9UQg#@!rtbbSBUM#ynF);zKX+|!Zm}*{H z+j=d?aZ2!?@EL7C~%B?6ouCKLnO$uWn;Y6Xz zX8dSwj732u(o*U3F$F=7xwxm>E-B+SVZH;O-4XPuPkLSt_?S0)lb7EEg)Mglk0#eS z9@jl(OnH4juMxY+*r03VDfPx_IM!Lmc(5hOI;`?d37f>jPP$?9jQQIQU@i4vuG6MagEoJrQ=RD7xt@8E;c zeGV*+Pt+t$@pt!|McETOE$9k=_C!70uhwRS9X#b%ZK z%q(TIUXSS^F0`4Cx?Rk07C6wI4!UVPeI~-fxY6`YH$kABdOuiRtl73MqG|~AzZ@iL&^s?24iS;RK_pdlWkhcF z@Wv-Om(Aealfg)D^adlXh9Nvf~Uf@y;g3Y)i(YP zEXDnb1V}1pJT5ZWyw=1i+0fni9yINurD=EqH^ciOwLUGi)C%Da)tyt=zq2P7pV5-G zR7!oq28-Fgn5pW|nlu^b!S1Z#r7!Wtr{5J5PQ>pd+2P7RSD?>(U7-|Y z7ZQ5lhYIl_IF<9?T9^IPK<(Hp;l5bl5tF9>X-zG14_7PfsA>6<$~A338iYRT{a@r_ zuXBaT=`T5x3=s&3=RYx6NgG>No4?5KFBVjE(swfcivcIpPQFx5l+O;fiGsOrl5teR z_Cm+;PW}O0Dwe_(4Z@XZ)O0W-v2X><&L*<~*q3dg;bQW3g7)a#3KiQP>+qj|qo*Hk z?57>f2?f@`=Fj^nkDKeRkN2d$Z@2eNKpHo}ksj-$`QKb6n?*$^*%Fb3_Kbf1(*W9K>{L$mud2WHJ=j0^=g30Xhg8$#g^?36`p1fm;;1@0Lrx+8t`?vN0ZorM zSW?rhjCE8$C|@p^sXdx z|NOHHg+fL;HIlqyLp~SSdIF`TnSHehNCU9t89yr@)FY<~hu+X`tjg(aSVae$wDG*C zq$nY(Y494R)hD!i1|IIyP*&PD_c2FPgeY)&mX1qujB1VHPG9`yFQpLFVQ0>EKS@Bp zAfP5`C(sWGLI?AC{XEjLKR4FVNw(4+9b?kba95ukgR1H?w<8F7)G+6&(zUhIE5Ef% z=fFkL3QKA~M@h{nzjRq!Y_t!%U66#L8!(2-GgFxkD1=JRRqk=n%G(yHKn%^&$dW>; zSjAcjETMz1%205se$iH_)ZCpfg_LwvnsZQAUCS#^FExp8O4CrJb6>JquNV@qPq~3A zZ<6dOU#6|8+fcgiA#~MDmcpIEaUO02L5#T$HV0$EMD94HT_eXLZ2Zi&(! z&5E>%&|FZ`)CN10tM%tLSPD*~r#--K(H-CZqIOb99_;m|D5wdgJ<1iOJz@h2Zkq?} z%8_KXb&hf=2Wza(Wgc;3v3TN*;HTU*q2?#z&tLn_U0Nt!y>Oo>+2T)He6%XuP;fgn z-G!#h$Y2`9>Jtf}hbVrm6D70|ERzLAU>3zoWhJmjWfgM^))T+2u$~5>HF9jQDkrXR z=IzX36)V75PrFjkQ%TO+iqKGCQ-DDXbaE;C#}!-CoWQx&v*vHfyI>$HNRbpvm<`O( zlx9NBWD6_e&J%Ous4yp~s6)Ghni!I6)0W;9(9$y1wWu`$gs<$9Mcf$L*piP zPR0Av*2%ul`W;?-1_-5Zy0~}?`e@Y5A&0H!^ApyVTT}BiOm4GeFo$_oPlDEyeGBbh z1h3q&Dx~GmUS|3@4V36&$2uO8!Yp&^pD7J5&TN{?xphf*-js1fP?B|`>p_K>lh{ij zP(?H%e}AIP?_i^f&Li=FDSQ`2_NWxL+BB=nQr=$ zHojMlXNGauvvwPU>ZLq!`bX-5F4jBJ&So{kE5+ms9UEYD{66!|k~3vsP+mE}x!>%P za98bAU0!h0&ka4EoiDvBM#CP#dRNdXJcb*(%=<(g+M@<)DZ!@v1V>;54En?igcHR2 zhubQMq}VSOK)onqHfczM7YA@s=9*ow;k;8)&?J3@0JiGcP! zP#00KZ1t)GyZeRJ=f0^gc+58lc4Qh*S7RqPIC6GugG1gXe$LIQMRCo8cHf^qXgAa2 z`}t>u2Cq1CbSEpLr~E=c7~=Qkc9-vLE%(v9N*&HF`(d~(0`iukl5aQ9u4rUvc8%m) zr2GwZN4!s;{SB87lJB;veebPmqE}tSpT>+`t?<457Q9iV$th%i__Z1kOMAswFldD6 ztbOvO337S5o#ZZgN2G99_AVqPv!?Gmt3pzgD+Hp3QPQ`9qJ(g=kjvD+fUSS3upJn! zqoG7acIKEFRX~S}3|{EWT$kdz#zrDlJU(rPkxjws_iyLKU8+v|*oS_W*-guAb&Pj1 z35Z`3z<&Jb@2Mwz=KXucNYdY#SNO$tcVFr9KdKm|%^e-TXzs6M`PBper%ajkrIyUe zp$vVxVs9*>Vp4_1NC~Zg)WOCPmOxI1V34QlG4!aSFOH{QqSVq1^1)- z0P!Z?tT&E-ll(pwf0?=F=yOzik=@nh1Clxr9}Vij89z)ePDSCYAqw?lVI?v?+&*zH z)p$CScFI8rrwId~`}9YWPFu0cW1Sf@vRELs&cbntRU6QfPK-SO*mqu|u~}8AJ!Q$z znzu}50O=YbjwKCuSVBs6&CZR#0FTu)3{}qJJYX(>QPr4$RqWiwX3NT~;>cLn*_&1H zaKpIW)JVJ>b{uo2oq>oQt3y=zJjb%fU@wLqM{SyaC6x2snMx-}ivfU<1- znu1Lh;i$3Tf$Kh5Uk))G!D1UhE8pvx&nO~w^fG)BC&L!_hQk%^p`Kp@F{cz>80W&T ziOK=Sq3fdRu*V0=S53rcIfWFazI}Twj63CG(jOB;$*b`*#B9uEnBM`hDk*EwSRdwP8?5T?xGUKs=5N83XsR*)a4|ijz|c{4tIU+4j^A5C<#5 z*$c_d=5ml~%pGxw#?*q9N7aRwPux5EyqHVkdJO=5J>84!X6P>DS8PTTz>7C#FO?k#edkntG+fJk8ZMn?pmJSO@`x-QHq;7^h6GEXLXo1TCNhH z8ZDH{*NLAjo3WM`xeb=X{((uv3H(8&r8fJJg_uSs_%hOH%JDD?hu*2NvWGYD+j)&` zz#_1%O1wF^o5ryt?O0n;`lHbzp0wQ?rcbW(F1+h7_EZZ9{>rePvLAPVZ_R|n@;b$;UchU=0j<6k8G9QuQf@76oiE*4 zXOLQ&n3$NR#p4<5NJMVC*S);5x2)eRbaAM%VxWu9ohlT;pGEk7;002enCbQ>2r-us z3#bpXP9g|mE`65VrN`+3mC)M(eMj~~eOf)do<@l+fMiTR)XO}422*1SL{wyY(%oMpBgJagtiDf zz>O6(m;};>Hi=t8o{DVC@YigqS(Qh+ix3Rwa9aliH}a}IlOCW1@?%h_bRbq-W{KHF z%Vo?-j@{Xi@=~Lz5uZP27==UGE15|g^0gzD|3x)SCEXrx`*MP^FDLl%pOi~~Il;dc z^hrwp9sYeT7iZ)-ajKy@{a`kr0-5*_!XfBpXwEcFGJ;%kV$0Nx;apKrur zJN2J~CAv{Zjj%FolyurtW8RaFmpn&zKJWL>(0;;+q(%(Hx!GMW4AcfP0YJ*Vz!F4g z!ZhMyj$BdXL@MlF%KeInmPCt~9&A!;cRw)W!Hi@0DY(GD_f?jeV{=s=cJ6e}JktJw zQORnxxj3mBxfrH=x{`_^Z1ddDh}L#V7i}$njUFRVwOX?qOTKjfPMBO4y(WiU<)epb zvB9L=%jW#*SL|Nd_G?E*_h1^M-$PG6Pc_&QqF0O-FIOpa4)PAEPsyvB)GKasmBoEt z?_Q2~QCYGH+hW31x-B=@5_AN870vY#KB~3a*&{I=f);3Kv7q4Q7s)0)gVYx2#Iz9g(F2;=+Iy4 z6KI^8GJ6D@%tpS^8boU}zpi=+(5GfIR)35PzrbuXeL1Y1N%JK7PG|^2k3qIqHfX;G zQ}~JZ-UWx|60P5?d1e;AHx!_;#PG%d=^X(AR%i`l0jSpYOpXoKFW~7ip7|xvN;2^? zsYC9fanpO7rO=V7+KXqVc;Q5z%Bj})xHVrgoR04sA2 zl~DAwv=!(()DvH*=lyhIlU^hBkA0$e*7&fJpB0|oB7)rqGK#5##2T`@_I^|O2x4GO z;xh6ROcV<9>?e0)MI(y++$-ksV;G;Xe`lh76T#Htuia+(UrIXrf9?

L(tZ$0BqX1>24?V$S+&kLZ`AodQ4_)P#Q3*4xg8}lMV-FLwC*cN$< zt65Rf%7z41u^i=P*qO8>JqXPrinQFapR7qHAtp~&RZ85$>ob|Js;GS^y;S{XnGiBc zGa4IGvDl?x%gY`vNhv8wgZnP#UYI-w*^4YCZnxkF85@ldepk$&$#3EAhrJY0U)lR{F6sM3SONV^+$;Zx8BD&Eku3K zKNLZyBni3)pGzU0;n(X@1fX8wYGKYMpLmCu{N5-}epPDxClPFK#A@02WM3!myN%bkF z|GJ4GZ}3sL{3{qXemy+#Uk{4>Kf8v11;f8I&c76+B&AQ8udd<8gU7+BeWC`akUU~U zgXoxie>MS@rBoyY8O8Tc&8id!w+_ooxcr!1?#rc$-|SBBtH6S?)1e#P#S?jFZ8u-Bs&k`yLqW|{j+%c#A4AQ>+tj$Y z^CZajspu$F%73E68Lw5q7IVREED9r1Ijsg#@DzH>wKseye>hjsk^{n0g?3+gs@7`i zHx+-!sjLx^fS;fY!ERBU+Q zVJ!e0hJH%P)z!y%1^ZyG0>PN@5W~SV%f>}c?$H8r;Sy-ui>aruVTY=bHe}$e zi&Q4&XK!qT7-XjCrDaufT@>ieQ&4G(SShUob0Q>Gznep9fR783jGuUynAqc6$pYX; z7*O@@JW>O6lKIk0G00xsm|=*UVTQBB`u1f=6wGAj%nHK_;Aqmfa!eAykDmi-@u%6~ z;*c!pS1@V8r@IX9j&rW&d*}wpNs96O2Ute>%yt{yv>k!6zfT6pru{F1M3P z2WN1JDYqoTB#(`kE{H676QOoX`cnqHl1Yaru)>8Ky~VU{)r#{&s86Vz5X)v15ULHA zAZDb{99+s~qI6;-dQ5DBjHJP@GYTwn;Dv&9kE<0R!d z8tf1oq$kO`_sV(NHOSbMwr=To4r^X$`sBW4$gWUov|WY?xccQJN}1DOL|GEaD_!@& z15p?Pj+>7d`@LvNIu9*^hPN)pwcv|akvYYq)ks%`G>!+!pW{-iXPZsRp8 z35LR;DhseQKWYSD`%gO&k$Dj6_6q#vjWA}rZcWtQr=Xn*)kJ9kacA=esi*I<)1>w^ zO_+E>QvjP)qiSZg9M|GNeLtO2D7xT6vsj`88sd!94j^AqxFLi}@w9!Y*?nwWARE0P znuI_7A-saQ+%?MFA$gttMV-NAR^#tjl_e{R$N8t2NbOlX373>e7Ox=l=;y#;M7asp zRCz*CLnrm$esvSb5{T<$6CjY zmZ(i{Rs_<#pWW>(HPaaYj`%YqBra=Ey3R21O7vUbzOkJJO?V`4-D*u4$Me0Bx$K(lYo`JO}gnC zx`V}a7m-hLU9Xvb@K2ymioF)vj12<*^oAqRuG_4u%(ah?+go%$kOpfb`T96P+L$4> zQ#S+sA%VbH&mD1k5Ak7^^dZoC>`1L%i>ZXmooA!%GI)b+$D&ziKrb)a=-ds9xk#~& z7)3iem6I|r5+ZrTRe_W861x8JpD`DDIYZNm{$baw+$)X^Jtjnl0xlBgdnNY}x%5za zkQ8E6T<^$sKBPtL4(1zi_Rd(tVth*3Xs!ulflX+70?gb&jRTnI8l+*Aj9{|d%qLZ+ z>~V9Z;)`8-lds*Zgs~z1?Fg?Po7|FDl(Ce<*c^2=lFQ~ahwh6rqSjtM5+$GT>3WZW zj;u~w9xwAhOc<kF}~`CJ68 z?(S5vNJa;kriPlim33{N5`C{9?NWhzsna_~^|K2k4xz1`xcui*LXL-1#Y}Hi9`Oo!zQ>x-kgAX4LrPz63uZ+?uG*84@PKq-KgQlMNRwz=6Yes) zY}>YN+qP}nwr$(CZQFjUOI=-6J$2^XGvC~EZ+vrqWaOXB$k?%Suf5k=4>AveC1aJ! ziaW4IS%F$_Babi)kA8Y&u4F7E%99OPtm=vzw$$ zEz#9rvn`Iot_z-r3MtV>k)YvErZ<^Oa${`2>MYYODSr6?QZu+be-~MBjwPGdMvGd!b!elsdi4% z`37W*8+OGulab8YM?`KjJ8e+jM(tqLKSS@=jimq3)Ea2EB%88L8CaM+aG7;27b?5` z4zuUWBr)f)k2o&xg{iZ$IQkJ+SK>lpq4GEacu~eOW4yNFLU!Kgc{w4&D$4ecm0f}~ zTTzquRW@`f0}|IILl`!1P+;69g^upiPA6F{)U8)muWHzexRenBU$E^9X-uIY2%&1w z_=#5*(nmxJ9zF%styBwivi)?#KMG96-H@hD-H_&EZiRNsfk7mjBq{L%!E;Sqn!mVX*}kXhwH6eh;b42eD!*~upVG@ z#smUqz$ICm!Y8wY53gJeS|Iuard0=;k5i5Z_hSIs6tr)R4n*r*rE`>38Pw&lkv{_r!jNN=;#?WbMj|l>cU(9trCq; z%nN~r^y7!kH^GPOf3R}?dDhO=v^3BeP5hF|%4GNQYBSwz;x({21i4OQY->1G=KFyu z&6d`f2tT9Yl_Z8YACZaJ#v#-(gcyeqXMhYGXb=t>)M@fFa8tHp2x;ODX=Ap@a5I=U z0G80^$N0G4=U(>W%mrrThl0DjyQ-_I>+1Tdd_AuB3qpYAqY54upwa3}owa|x5iQ^1 zEf|iTZxKNGRpI>34EwkIQ2zHDEZ=(J@lRaOH>F|2Z%V_t56Km$PUYu^xA5#5Uj4I4RGqHD56xT%H{+P8Ag>e_3pN$4m8n>i%OyJFPNWaEnJ4McUZPa1QmOh?t8~n& z&RulPCors8wUaqMHECG=IhB(-tU2XvHP6#NrLVyKG%Ee*mQ5Ps%wW?mcnriTVRc4J`2YVM>$ixSF2Xi+Wn(RUZnV?mJ?GRdw%lhZ+t&3s7g!~g{%m&i<6 z5{ib-<==DYG93I(yhyv4jp*y3#*WNuDUf6`vTM%c&hiayf(%=x@4$kJ!W4MtYcE#1 zHM?3xw63;L%x3drtd?jot!8u3qeqctceX3m;tWetK+>~q7Be$h>n6riK(5@ujLgRS zvOym)k+VAtyV^mF)$29Y`nw&ijdg~jYpkx%*^ z8dz`C*g=I?;clyi5|!27e2AuSa$&%UyR(J3W!A=ZgHF9OuKA34I-1U~pyD!KuRkjA zbkN!?MfQOeN>DUPBxoy5IX}@vw`EEB->q!)8fRl_mqUVuRu|C@KD-;yl=yKc=ZT0% zB$fMwcC|HE*0f8+PVlWHi>M`zfsA(NQFET?LrM^pPcw`cK+Mo0%8*x8@65=CS_^$cG{GZQ#xv($7J z??R$P)nPLodI;P!IC3eEYEHh7TV@opr#*)6A-;EU2XuogHvC;;k1aI8asq7ovoP!* z?x%UoPrZjj<&&aWpsbr>J$Er-7!E(BmOyEv!-mbGQGeJm-U2J>74>o5x`1l;)+P&~ z>}f^=Rx(ZQ2bm+YE0u=ZYrAV@apyt=v1wb?R@`i_g64YyAwcOUl=C!i>=Lzb$`tjv zOO-P#A+)t-JbbotGMT}arNhJmmGl-lyUpMn=2UacVZxmiG!s!6H39@~&uVokS zG=5qWhfW-WOI9g4!R$n7!|ViL!|v3G?GN6HR0Pt_L5*>D#FEj5wM1DScz4Jv@Sxnl zB@MPPmdI{(2D?;*wd>3#tjAirmUnQoZrVv`xM3hARuJksF(Q)wd4P$88fGYOT1p6U z`AHSN!`St}}UMBT9o7i|G`r$ zrB=s$qV3d6$W9@?L!pl0lf%)xs%1ko^=QY$ty-57=55PvP(^6E7cc zGJ*>m2=;fOj?F~yBf@K@9qwX0hA803Xw+b0m}+#a(>RyR8}*Y<4b+kpp|OS+!whP( zH`v{%s>jsQI9rd$*vm)EkwOm#W_-rLTHcZRek)>AtF+~<(did)*oR1|&~1|e36d-d zgtm5cv1O0oqgWC%Et@P4Vhm}Ndl(Y#C^MD03g#PH-TFy+7!Osv1z^UWS9@%JhswEq~6kSr2DITo59+; ze=ZC}i2Q?CJ~Iyu?vn|=9iKV>4j8KbxhE4&!@SQ^dVa-gK@YfS9xT(0kpW*EDjYUkoj! zE49{7H&E}k%5(>sM4uGY)Q*&3>{aitqdNnRJkbOmD5Mp5rv-hxzOn80QsG=HJ_atI-EaP69cacR)Uvh{G5dTpYG7d zbtmRMq@Sexey)||UpnZ?;g_KMZq4IDCy5}@u!5&B^-=6yyY{}e4Hh3ee!ZWtL*s?G zxG(A!<9o!CL+q?u_utltPMk+hn?N2@?}xU0KlYg?Jco{Yf@|mSGC<(Zj^yHCvhmyx z?OxOYoxbptDK()tsJ42VzXdINAMWL$0Gcw?G(g8TMB)Khw_|v9`_ql#pRd2i*?CZl z7k1b!jQB=9-V@h%;Cnl7EKi;Y^&NhU0mWEcj8B|3L30Ku#-9389Q+(Yet0r$F=+3p z6AKOMAIi|OHyzlHZtOm73}|ntKtFaXF2Fy|M!gOh^L4^62kGUoWS1i{9gsds_GWBc zLw|TaLP64z3z9?=R2|T6Xh2W4_F*$cq>MtXMOy&=IPIJ`;!Tw?PqvI2b*U1)25^<2 zU_ZPoxg_V0tngA0J+mm?3;OYw{i2Zb4x}NedZug!>EoN3DC{1i)Z{Z4m*(y{ov2%- zk(w>+scOO}MN!exSc`TN)!B=NUX`zThWO~M*ohqq;J2hx9h9}|s#?@eR!=F{QTrq~ zTcY|>azkCe$|Q0XFUdpFT=lTcyW##i;-e{}ORB4D?t@SfqGo_cS z->?^rh$<&n9DL!CF+h?LMZRi)qju!meugvxX*&jfD!^1XB3?E?HnwHP8$;uX{Rvp# zh|)hM>XDv$ZGg=$1{+_bA~u-vXqlw6NH=nkpyWE0u}LQjF-3NhATL@9rRxMnpO%f7 z)EhZf{PF|mKIMFxnC?*78(}{Y)}iztV12}_OXffJ;ta!fcFIVjdchyHxH=t%ci`Xd zX2AUB?%?poD6Zv*&BA!6c5S#|xn~DK01#XvjT!w!;&`lDXSJT4_j$}!qSPrb37vc{ z9^NfC%QvPu@vlxaZ;mIbn-VHA6miwi8qJ~V;pTZkKqqOii<1Cs}0i?uUIss;hM4dKq^1O35y?Yp=l4i zf{M!@QHH~rJ&X~8uATV><23zZUbs-J^3}$IvV_ANLS08>k`Td7aU_S1sLsfi*C-m1 z-e#S%UGs4E!;CeBT@9}aaI)qR-6NU@kvS#0r`g&UWg?fC7|b^_HyCE!8}nyh^~o@< zpm7PDFs9yxp+byMS(JWm$NeL?DNrMCNE!I^ko-*csB+dsf4GAq{=6sfyf4wb>?v1v zmb`F*bN1KUx-`ra1+TJ37bXNP%`-Fd`vVQFTwWpX@;s(%nDQa#oWhgk#mYlY*!d>( zE&!|ySF!mIyfING+#%RDY3IBH_fW$}6~1%!G`suHub1kP@&DoAd5~7J55;5_noPI6eLf{t;@9Kf<{aO0`1WNKd?<)C-|?C?)3s z>wEq@8=I$Wc~Mt$o;g++5qR+(6wt9GI~pyrDJ%c?gPZe)owvy^J2S=+M^ z&WhIE`g;;J^xQLVeCtf7b%Dg#Z2gq9hp_%g)-%_`y*zb; zn9`f`mUPN-Ts&fFo(aNTsXPA|J!TJ{0hZp0^;MYHLOcD=r_~~^ymS8KLCSeU3;^QzJNqS z5{5rEAv#l(X?bvwxpU;2%pQftF`YFgrD1jt2^~Mt^~G>T*}A$yZc@(k9orlCGv&|1 zWWvVgiJsCAtamuAYT~nzs?TQFt<1LSEx!@e0~@yd6$b5!Zm(FpBl;(Cn>2vF?k zOm#TTjFwd2D-CyA!mqR^?#Uwm{NBemP>(pHmM}9;;8`c&+_o3#E5m)JzfwN?(f-a4 zyd%xZc^oQx3XT?vcCqCX&Qrk~nu;fxs@JUoyVoi5fqpi&bUhQ2y!Ok2pzsFR(M(|U zw3E+kH_zmTRQ9dUMZWRE%Zakiwc+lgv7Z%|YO9YxAy`y28`Aw;WU6HXBgU7fl@dnt z-fFBV)}H-gqP!1;V@Je$WcbYre|dRdp{xt!7sL3Eoa%IA`5CAA%;Wq8PktwPdULo! z8!sB}Qt8#jH9Sh}QiUtEPZ6H0b*7qEKGJ%ITZ|vH)5Q^2m<7o3#Z>AKc%z7_u`rXA zqrCy{-{8;9>dfllLu$^M5L z-hXs))h*qz%~ActwkIA(qOVBZl2v4lwbM>9l70Y`+T*elINFqt#>OaVWoja8RMsep z6Or3f=oBnA3vDbn*+HNZP?8LsH2MY)x%c13@(XfuGR}R?Nu<|07{$+Lc3$Uv^I!MQ z>6qWgd-=aG2Y^24g4{Bw9ueOR)(9h`scImD=86dD+MnSN4$6 z^U*o_mE-6Rk~Dp!ANp#5RE9n*LG(Vg`1)g6!(XtDzsov$Dvz|Gv1WU68J$CkshQhS zCrc|cdkW~UK}5NeaWj^F4MSgFM+@fJd{|LLM)}_O<{rj z+?*Lm?owq?IzC%U%9EBga~h-cJbIu=#C}XuWN>OLrc%M@Gu~kFEYUi4EC6l#PR2JS zQUkGKrrS#6H7}2l0F@S11DP`@pih0WRkRJl#F;u{c&ZC{^$Z+_*lB)r)-bPgRFE;* zl)@hK4`tEP=P=il02x7-C7p%l=B`vkYjw?YhdJU9!P!jcmY$OtC^12w?vy3<<=tlY zUwHJ_0lgWN9vf>1%WACBD{UT)1qHQSE2%z|JHvP{#INr13jM}oYv_5#xsnv9`)UAO zuwgyV4YZ;O)eSc3(mka6=aRohi!HH@I#xq7kng?Acdg7S4vDJb6cI5fw?2z%3yR+| zU5v@Hm}vy;${cBp&@D=HQ9j7NcFaOYL zj-wV=eYF{|XTkFNM2uz&T8uH~;)^Zo!=KP)EVyH6s9l1~4m}N%XzPpduPg|h-&lL` zAXspR0YMOKd2yO)eMFFJ4?sQ&!`dF&!|niH*!^*Ml##o0M(0*uK9&yzekFi$+mP9s z>W9d%Jb)PtVi&-Ha!o~Iyh@KRuKpQ@)I~L*d`{O8!kRObjO7=n+Gp36fe!66neh+7 zW*l^0tTKjLLzr`x4`_8&on?mjW-PzheTNox8Hg7Nt@*SbE-%kP2hWYmHu#Fn@Q^J(SsPUz*|EgOoZ6byg3ew88UGdZ>9B2Tq=jF72ZaR=4u%1A6Vm{O#?@dD!(#tmR;eP(Fu z{$0O%=Vmua7=Gjr8nY%>ul?w=FJ76O2js&17W_iq2*tb!i{pt#`qZB#im9Rl>?t?0c zicIC}et_4d+CpVPx)i4~$u6N-QX3H77ez z?ZdvXifFk|*F8~L(W$OWM~r`pSk5}#F?j_5u$Obu9lDWIknO^AGu+Blk7!9Sb;NjS zncZA?qtASdNtzQ>z7N871IsPAk^CC?iIL}+{K|F@BuG2>qQ;_RUYV#>hHO(HUPpk@ z(bn~4|F_jiZi}Sad;_7`#4}EmD<1EiIxa48QjUuR?rC}^HRocq`OQPM@aHVKP9E#q zy%6bmHygCpIddPjE}q_DPC`VH_2m;Eey&ZH)E6xGeStOK7H)#+9y!%-Hm|QF6w#A( zIC0Yw%9j$s-#odxG~C*^MZ?M<+&WJ+@?B_QPUyTg9DJGtQN#NIC&-XddRsf3n^AL6 zT@P|H;PvN;ZpL0iv$bRb7|J{0o!Hq+S>_NrH4@coZtBJu#g8#CbR7|#?6uxi8d+$g z87apN>EciJZ`%Zv2**_uiET9Vk{pny&My;+WfGDw4EVL#B!Wiw&M|A8f1A@ z(yFQS6jfbH{b8Z-S7D2?Ixl`j0{+ZnpT=;KzVMLW{B$`N?Gw^Fl0H6lT61%T2AU**!sX0u?|I(yoy&Xveg7XBL&+>n6jd1##6d>TxE*Vj=8lWiG$4=u{1UbAa5QD>5_ z;Te^42v7K6Mmu4IWT6Rnm>oxrl~b<~^e3vbj-GCdHLIB_>59}Ya+~OF68NiH=?}2o zP(X7EN=quQn&)fK>M&kqF|<_*H`}c zk=+x)GU>{Af#vx&s?`UKUsz})g^Pc&?Ka@t5$n$bqf6{r1>#mWx6Ep>9|A}VmWRnowVo`OyCr^fHsf# zQjQ3Ttp7y#iQY8l`zEUW)(@gGQdt(~rkxlkefskT(t%@i8=|p1Y9Dc5bc+z#n$s13 zGJk|V0+&Ekh(F};PJzQKKo+FG@KV8a<$gmNSD;7rd_nRdc%?9)p!|B-@P~kxQG}~B zi|{0}@}zKC(rlFUYp*dO1RuvPC^DQOkX4<+EwvBAC{IZQdYxoq1Za!MW7%p7gGr=j zzWnAq%)^O2$eItftC#TTSArUyL$U54-O7e|)4_7%Q^2tZ^0-d&3J1}qCzR4dWX!)4 zzIEKjgnYgMus^>6uw4Jm8ga6>GBtMjpNRJ6CP~W=37~||gMo_p@GA@#-3)+cVYnU> zE5=Y4kzl+EbEh%dhQokB{gqNDqx%5*qBusWV%!iprn$S!;oN_6E3?0+umADVs4ako z?P+t?m?};gev9JXQ#Q&KBpzkHPde_CGu-y z<{}RRAx=xlv#mVi+Ibrgx~ujW$h{?zPfhz)Kp7kmYS&_|97b&H&1;J-mzrBWAvY} zh8-I8hl_RK2+nnf&}!W0P+>5?#?7>npshe<1~&l_xqKd0_>dl_^RMRq@-Myz&|TKZBj1=Q()) zF{dBjv5)h=&Z)Aevx}+i|7=R9rG^Di!sa)sZCl&ctX4&LScQ-kMncgO(9o6W6)yd< z@Rk!vkja*X_N3H=BavGoR0@u0<}m-7|2v!0+2h~S2Q&a=lTH91OJsvms2MT~ zY=c@LO5i`mLpBd(vh|)I&^A3TQLtr>w=zoyzTd=^f@TPu&+*2MtqE$Avf>l>}V|3-8Fp2hzo3y<)hr_|NO(&oSD z!vEjTWBxbKTiShVl-U{n*B3#)3a8$`{~Pk}J@elZ=>Pqp|MQ}jrGv7KrNcjW%TN_< zZz8kG{#}XoeWf7qY?D)L)8?Q-b@Na&>i=)(@uNo zr;cH98T3$Iau8Hn*@vXi{A@YehxDE2zX~o+RY`)6-X{8~hMpc#C`|8y> zU8Mnv5A0dNCf{Ims*|l-^ z(MRp{qoGohB34|ggDI*p!Aw|MFyJ|v+<+E3brfrI)|+l3W~CQLPbnF@G0)P~Ly!1TJLp}xh8uW`Q+RB-v`MRYZ9Gam3cM%{ zb4Cb*f)0deR~wtNb*8w-LlIF>kc7DAv>T0D(a3@l`k4TFnrO+g9XH7;nYOHxjc4lq zMmaW6qpgAgy)MckYMhl?>sq;-1E)-1llUneeA!ya9KM$)DaNGu57Z5aE>=VST$#vb zFo=uRHr$0M{-ha>h(D_boS4zId;3B|Tpqo|?B?Z@I?G(?&Iei+-{9L_A9=h=Qfn-U z1wIUnQe9!z%_j$F_{rf&`ZFSott09gY~qrf@g3O=Y>vzAnXCyL!@(BqWa)Zqt!#_k zfZHuwS52|&&)aK;CHq9V-t9qt0au{$#6c*R#e5n3rje0hic7c7m{kW$p(_`wB=Gw7 z4k`1Hi;Mc@yA7dp@r~?@rfw)TkjAW++|pkfOG}0N|2guek}j8Zen(!+@7?qt_7ndX zB=BG6WJ31#F3#Vk3=aQr8T)3`{=p9nBHlKzE0I@v`{vJ}h8pd6vby&VgFhzH|q;=aonunAXL6G2y(X^CtAhWr*jI zGjpY@raZDQkg*aMq}Ni6cRF z{oWv}5`nhSAv>usX}m^GHt`f(t8@zHc?K|y5Zi=4G*UG1Sza{$Dpj%X8 zzEXaKT5N6F5j4J|w#qlZP!zS7BT)9b+!ZSJdToqJts1c!)fwih4d31vfb{}W)EgcA zH2pZ^8_k$9+WD2n`6q5XbOy8>3pcYH9 z07eUB+p}YD@AH!}p!iKv><2QF-Y^&xx^PAc1F13A{nUeCDg&{hnix#FiO!fe(^&%Qcux!h znu*S!s$&nnkeotYsDthh1dq(iQrE|#f_=xVgfiiL&-5eAcC-> z5L0l|DVEM$#ulf{bj+Y~7iD)j<~O8CYM8GW)dQGq)!mck)FqoL^X zwNdZb3->hFrbHFm?hLvut-*uK?zXn3q1z|UX{RZ;-WiLoOjnle!xs+W0-8D)kjU#R z+S|A^HkRg$Ij%N4v~k`jyHffKaC~=wg=9)V5h=|kLQ@;^W!o2^K+xG&2n`XCd>OY5Ydi= zgHH=lgy++erK8&+YeTl7VNyVm9-GfONlSlVb3)V9NW5tT!cJ8d7X)!b-$fb!s76{t z@d=Vg-5K_sqHA@Zx-L_}wVnc@L@GL9_K~Zl(h5@AR#FAiKad8~KeWCo@mgXIQ#~u{ zgYFwNz}2b6Vu@CP0XoqJ+dm8px(5W5-Jpis97F`+KM)TuP*X8H@zwiVKDKGVp59pI zifNHZr|B+PG|7|Y<*tqap0CvG7tbR1R>jn70t1X`XJixiMVcHf%Ez*=xm1(CrTSDt z0cle!+{8*Ja&EOZ4@$qhBuKQ$U95Q%rc7tg$VRhk?3=pE&n+T3upZg^ZJc9~c2es% zh7>+|mrmA-p&v}|OtxqmHIBgUxL~^0+cpfkSK2mhh+4b=^F1Xgd2)}U*Yp+H?ls#z zrLxWg_hm}AfK2XYWr!rzW4g;+^^&bW%LmbtRai9f3PjU${r@n`JThy-cphbcwn)rq9{A$Ht`lmYKxOacy z6v2R(?gHhD5@&kB-Eg?4!hAoD7~(h>(R!s1c1Hx#s9vGPePUR|of32bS`J5U5w{F) z>0<^ktO2UHg<0{oxkdOQ;}coZDQph8p6ruj*_?uqURCMTac;>T#v+l1Tc~%^k-Vd@ zkc5y35jVNc49vZpZx;gG$h{%yslDI%Lqga1&&;mN{Ush1c7p>7e-(zp}6E7f-XmJb4nhk zb8zS+{IVbL$QVF8pf8}~kQ|dHJAEATmmnrb_wLG}-yHe>W|A&Y|;muy-d^t^<&)g5SJfaTH@P1%euONny=mxo+C z4N&w#biWY41r8k~468tvuYVh&XN&d#%QtIf9;iVXfWY)#j=l`&B~lqDT@28+Y!0E+MkfC}}H*#(WKKdJJq=O$vNYCb(ZG@p{fJgu;h z21oHQ(14?LeT>n5)s;uD@5&ohU!@wX8w*lB6i@GEH0pM>YTG+RAIWZD;4#F1&F%Jp zXZUml2sH0!lYJT?&sA!qwez6cXzJEd(1ZC~kT5kZSp7(@=H2$Azb_*W&6aA|9iwCL zdX7Q=42;@dspHDwYE?miGX#L^3xD&%BI&fN9^;`v4OjQXPBaBmOF1;#C)8XA(WFlH zycro;DS2?(G&6wkr6rqC>rqDv3nfGw3hmN_9Al>TgvmGsL8_hXx09};l9Ow@)F5@y z#VH5WigLDwZE4nh^7&@g{1FV^UZ%_LJ-s<{HN*2R$OPg@R~Z`c-ET*2}XB@9xvAjrK&hS=f|R8Gr9 zr|0TGOsI7RD+4+2{ZiwdVD@2zmg~g@^D--YL;6UYGSM8i$NbQr4!c7T9rg!8;TM0E zT#@?&S=t>GQm)*ua|?TLT2ktj#`|R<_*FAkOu2Pz$wEc%-=Y9V*$&dg+wIei3b*O8 z2|m$!jJG!J!ZGbbIa!(Af~oSyZV+~M1qGvelMzPNE_%5?c2>;MeeG2^N?JDKjFYCy z7SbPWH-$cWF9~fX%9~v99L!G(wi!PFp>rB!9xj7=Cv|F+7CsGNwY0Q_J%FID%C^CBZQfJ9K(HK%k31j~e#&?hQ zNuD6gRkVckU)v+53-fc} z7ZCzYN-5RG4H7;>>Hg?LU9&5_aua?A0)0dpew1#MMlu)LHe(M;OHjHIUl7|%%)YPo z0cBk;AOY00%Fe6heoN*$(b<)Cd#^8Iu;-2v@>cE-OB$icUF9EEoaC&q8z9}jMTT2I z8`9;jT%z0;dy4!8U;GW{i`)3!c6&oWY`J3669C!tM<5nQFFrFRglU8f)5Op$GtR-3 zn!+SPCw|04sv?%YZ(a7#L?vsdr7ss@WKAw&A*}-1S|9~cL%uA+E~>N6QklFE>8W|% zyX-qAUGTY1hQ-+um`2|&ji0cY*(qN!zp{YpDO-r>jPk*yuVSay<)cUt`t@&FPF_&$ zcHwu1(SQ`I-l8~vYyUxm@D1UEdFJ$f5Sw^HPH7b!9 zzYT3gKMF((N(v0#4f_jPfVZ=ApN^jQJe-X$`A?X+vWjLn_%31KXE*}5_}d8 zw_B1+a#6T1?>M{ronLbHIlEsMf93muJ7AH5h%;i99<~JX^;EAgEB1uHralD*!aJ@F zV2ruuFe9i2Q1C?^^kmVy921eb=tLDD43@-AgL^rQ3IO9%+vi_&R2^dpr}x{bCVPej z7G0-0o64uyWNtr*loIvslyo0%)KSDDKjfThe0hcqs)(C-MH1>bNGBDRTW~scy_{w} zp^aq8Qb!h9Lwielq%C1b8=?Z=&U)ST&PHbS)8Xzjh2DF?d{iAv)Eh)wsUnf>UtXN( zL7=$%YrZ#|^c{MYmhn!zV#t*(jdmYdCpwqpZ{v&L8KIuKn`@IIZfp!uo}c;7J57N` zAxyZ-uA4=Gzl~Ovycz%MW9ZL7N+nRo&1cfNn9(1H5eM;V_4Z_qVann7F>5f>%{rf= zPBZFaV@_Sobl?Fy&KXyzFDV*FIdhS5`Uc~S^Gjo)aiTHgn#<0C=9o-a-}@}xDor;D zZyZ|fvf;+=3MZd>SR1F^F`RJEZo+|MdyJYQAEauKu%WDol~ayrGU3zzbHKsnHKZ*z zFiwUkL@DZ>!*x05ql&EBq@_Vqv83&?@~q5?lVmffQZ+V-=qL+!u4Xs2Z2zdCQ3U7B&QR9_Iggy} z(om{Y9eU;IPe`+p1ifLx-XWh?wI)xU9ik+m#g&pGdB5Bi<`PR*?92lE0+TkRuXI)z z5LP!N2+tTc%cB6B1F-!fj#}>S!vnpgVU~3!*U1ej^)vjUH4s-bd^%B=ItQqDCGbrEzNQi(dJ`J}-U=2{7-d zK8k^Rlq2N#0G?9&1?HSle2vlkj^KWSBYTwx`2?9TU_DX#J+f+qLiZCqY1TXHFxXZqYMuD@RU$TgcnCC{_(vwZ-*uX)~go#%PK z@}2Km_5aQ~(<3cXeJN6|F8X_1@L%@xTzs}$_*E|a^_URF_qcF;Pfhoe?FTFwvjm1o z8onf@OY@jC2tVcMaZS;|T!Ks(wOgPpRzRnFS-^RZ4E!9dsnj9sFt609a|jJbb1Dt@ z<=Gal2jDEupxUSwWu6zp<<&RnAA;d&4gKVG0iu6g(DsST(4)z6R)zDpfaQ}v{5ARt zyhwvMtF%b-YazR5XLz+oh=mn;y-Mf2a8>7?2v8qX;19y?b>Z5laGHvzH;Nu9S`B8} zI)qN$GbXIQ1VL3lnof^6TS~rvPVg4V?Dl2Bb*K2z4E{5vy<(@@K_cN@U>R!>aUIRnb zL*)=787*cs#zb31zBC49x$`=fkQbMAef)L2$dR{)6BAz!t5U_B#1zZG`^neKSS22oJ#5B=gl%U=WeqL9REF2g zZnfCb0?quf?Ztj$VXvDSWoK`0L=Zxem2q}!XWLoT-kYMOx)!7fcgT35uC~0pySEme z`{wGWTkGr7>+Kb^n;W?BZH6ZP(9tQX%-7zF>vc2}LuWDI(9kh1G#7B99r4x6;_-V+k&c{nPUrR zAXJGRiMe~aup{0qzmLNjS_BC4cB#sXjckx{%_c&^xy{M61xEb>KW_AG5VFXUOjAG4 z^>Qlm9A#1N{4snY=(AmWzatb!ngqiqPbBZ7>Uhb3)dTkSGcL#&SH>iMO-IJBPua`u zo)LWZ>=NZLr758j{%(|uQuZ)pXq_4c!!>s|aDM9#`~1bzK3J1^^D#<2bNCccH7~-X}Ggi!pIIF>uFx%aPARGQsnC8ZQc8lrQ5o~smqOg>Ti^GNme94*w z)JZy{_{#$jxGQ&`M z!OMvZMHR>8*^>eS%o*6hJwn!l8VOOjZQJvh)@tnHVW&*GYPuxqXw}%M!(f-SQf`=L z5;=5w2;%82VMH6Xi&-K3W)o&K^+vJCepWZ-rW%+Dc6X3(){z$@4zjYxQ|}8UIojeC zYZpQ1dU{fy=oTr<4VX?$q)LP}IUmpiez^O&N3E_qPpchGTi5ZM6-2ScWlQq%V&R2Euz zO|Q0Hx>lY1Q1cW5xHv5!0OGU~PVEqSuy#fD72d#O`N!C;o=m+YioGu-wH2k6!t<~K zSr`E=W9)!g==~x9VV~-8{4ZN9{~-A9zJpRe%NGg$+MDuI-dH|b@BD)~>pPCGUNNzY zMDg||0@XGQgw`YCt5C&A{_+J}mvV9Wg{6V%2n#YSRN{AP#PY?1FF1#|vO_%e+#`|2*~wGAJaeRX6=IzFNeWhz6gJc8+(03Ph4y6ELAm=AkN7TOgMUEw*N{= z_)EIDQx5q22oUR+_b*tazu9+pX|n1c*IB-}{DqIj z-?E|ks{o3AGRNb;+iKcHkZvYJvFsW&83RAPs1Oh@IWy%l#5x2oUP6ZCtv+b|q>jsf zZ_9XO;V!>n`UxH1LvH8)L4?8raIvasEhkpQoJ`%!5rBs!0Tu(s_D{`4opB;57)pkX z4$A^8CsD3U5*!|bHIEqsn~{q+Ddj$ME@Gq4JXtgVz&7l{Ok!@?EA{B3P~NAqb9)4? zkQo30A^EbHfQ@87G5&EQTd`frrwL)&Yw?%-W@uy^Gn23%j?Y!Iea2xw<-f;esq zf%w5WN@E1}zyXtYv}}`U^B>W`>XPmdLj%4{P298|SisrE;7HvXX;A}Ffi8B#3Lr;1 zHt6zVb`8{#+e$*k?w8|O{Uh|&AG}|DG1PFo1i?Y*cQm$ZwtGcVgMwtBUDa{~L1KT-{jET4w60>{KZ27vXrHJ;fW{6| z=|Y4!&UX020wU1>1iRgB@Q#m~1^Z^9CG1LqDhYBrnx%IEdIty z!46iOoKlKs)c}newDG)rWUikD%j`)p z_w9Ph&e40=(2eBy;T!}*1p1f1SAUDP9iWy^u^Ubdj21Kn{46;GR+hwLO=4D11@c~V zI8x&(D({K~Df2E)Nx_yQvYfh4;MbMJ@Z}=Dt3_>iim~QZ*hZIlEs0mEb z_54+&*?wMD`2#vsQRN3KvoT>hWofI_Vf(^C1ff-Ike@h@saEf7g}<9T`W;HAne-Nd z>RR+&SP35w)xKn8^U$7))PsM!jKwYZ*RzEcG-OlTrX3}9a{q%#Un5E5W{{hp>w~;` zGky+3(vJvQyGwBo`tCpmo0mo((?nM8vf9aXrrY1Ve}~TuVkB(zeds^jEfI}xGBCM2 zL1|#tycSaWCurP+0MiActG3LCas@_@tao@(R1ANlwB$4K53egNE_;!&(%@Qo$>h`^1S_!hN6 z)vZtG$8fN!|BXBJ=SI>e(LAU(y(i*PHvgQ2llulxS8>qsimv7yL}0q_E5WiAz7)(f zC(ahFvG8&HN9+6^jGyLHM~$)7auppeWh_^zKk&C_MQ~8;N??OlyH~azgz5fe^>~7F zl3HnPN3z-kN)I$4@`CLCMQx3sG~V8hPS^}XDXZrQA>}mQPw%7&!sd(Pp^P=tgp-s^ zjl}1-KRPNWXgV_K^HkP__SR`S-|OF0bR-N5>I%ODj&1JUeAQ3$9i;B~$S6}*^tK?= z**%aCiH7y?xdY?{LgVP}S0HOh%0%LI$wRx;$T|~Y8R)Vdwa}kGWv8?SJVm^>r6+%I z#lj1aR94{@MP;t-scEYQWc#xFA30^}?|BeX*W#9OL;Q9#WqaaM546j5j29((^_8Nu z4uq}ESLr~r*O7E7$D{!k9W>`!SLoyA53i9QwRB{!pHe8um|aDE`Cg0O*{jmor)^t)3`>V>SWN-2VJcFmj^1?~tT=JrP`fVh*t zXHarp=8HEcR#vFe+1a%XXuK+)oFs`GDD}#Z+TJ}Ri`FvKO@ek2ayn}yaOi%(8p%2$ zpEu)v0Jym@f}U|-;}CbR=9{#<^z28PzkkTNvyKvJDZe+^VS2bES3N@Jq!-*}{oQlz z@8bgC_KnDnT4}d#&Cpr!%Yb?E!brx0!eVOw~;lLwUoz#Np%d$o%9scc3&zPm`%G((Le|6o1 zM(VhOw)!f84zG^)tZ1?Egv)d8cdNi+T${=5kV+j;Wf%2{3g@FHp^Gf*qO0q!u$=m9 zCaY`4mRqJ;FTH5`a$affE5dJrk~k`HTP_7nGTY@B9o9vvnbytaID;^b=Tzp7Q#DmD zC(XEN)Ktn39z5|G!wsVNnHi) z%^q94!lL|hF`IijA^9NR0F$@h7k5R^ljOW(;Td9grRN0Mb)l_l7##{2nPQ@?;VjXv zaLZG}yuf$r$<79rVPpXg?6iiieX|r#&`p#Con2i%S8*8F}(E) zI5E6c3tG*<;m~6>!&H!GJ6zEuhH7mkAzovdhLy;)q z{H2*8I^Pb}xC4s^6Y}6bJvMu=8>g&I)7!N!5QG$xseeU#CC?ZM-TbjsHwHgDGrsD= z{%f;@Sod+Ch66Ko2WF~;Ty)v>&x^aovCbCbD7>qF*!?BXmOV3(s|nxsb*Lx_2lpB7 zokUnzrk;P=T-&kUHO}td+Zdj!3n&NR?K~cRU zAXU!DCp?51{J4w^`cV#ye}(`SQhGQkkMu}O3M*BWt4UsC^jCFUy;wTINYmhD$AT;4 z?Xd{HaJjP`raZ39qAm;%beDbrLpbRf(mkKbANan7XsL>_pE2oo^$TgdidjRP!5-`% zv0d!|iKN$c0(T|L0C~XD0aS8t{*&#LnhE;1Kb<9&=c2B+9JeLvJr*AyyRh%@jHej=AetOMSlz^=!kxX>>B{2B1uIrQyfd8KjJ+DBy!h)~*(!|&L4^Q_07SQ~E zcemVP`{9CwFvPFu7pyVGCLhH?LhEVb2{7U+Z_>o25#+3<|8%1T^5dh}*4(kfJGry} zm%r#hU+__Z;;*4fMrX=Bkc@7|v^*B;HAl0((IBPPii%X9+u3DDF6%bI&6?Eu$8&aWVqHIM7mK6?Uvq$1|(-T|)IV<>e?!(rY zqkmO1MRaLeTR=)io(0GVtQT@s6rN%C6;nS3@eu;P#ry4q;^O@1ZKCJyp_Jo)Ty^QW z+vweTx_DLm{P-XSBj~Sl<%_b^$=}odJ!S2wAcxenmzFGX1t&Qp8Vxz2VT`uQsQYtdn&_0xVivIcxZ_hnrRtwq4cZSj1c-SG9 z7vHBCA=fd0O1<4*=lu$6pn~_pVKyL@ztw1swbZi0B?spLo56ZKu5;7ZeUml1Ws1?u zqMf1p{5myAzeX$lAi{jIUqo1g4!zWLMm9cfWcnw`k6*BR^?$2(&yW?>w;G$EmTA@a z6?y#K$C~ZT8+v{87n5Dm&H6Pb_EQ@V0IWmG9cG=O;(;5aMWWrIPzz4Q`mhK;qQp~a z+BbQrEQ+w{SeiuG-~Po5f=^EvlouB@_|4xQXH@A~KgpFHrwu%dwuCR)=B&C(y6J4J zvoGk9;lLs9%iA-IJGU#RgnZZR+@{5lYl8(e1h6&>Vc_mvg0d@);X zji4T|n#lB!>pfL|8tQYkw?U2bD`W{na&;*|znjmalA&f;*U++_aBYerq;&C8Kw7mI z7tsG*?7*5j&dU)Lje;^{D_h`%(dK|pB*A*1(Jj)w^mZ9HB|vGLkF1GEFhu&rH=r=8 zMxO42e{Si6$m+Zj`_mXb&w5Q(i|Yxyg?juUrY}78uo@~3v84|8dfgbPd0iQJRdMj< zncCNGdMEcsxu#o#B5+XD{tsg*;j-eF8`mp~K8O1J!Z0+>0=7O=4M}E?)H)ENE;P*F z$Ox?ril_^p0g7xhDUf(q652l|562VFlC8^r8?lQv;TMvn+*8I}&+hIQYh2 z1}uQQaag&!-+DZ@|C+C$bN6W;S-Z@)d1|en+XGvjbOxCa-qAF*LA=6s(Jg+g;82f$ z(Vb)8I)AH@cdjGFAR5Rqd0wiNCu!xtqWbcTx&5kslzTb^7A78~Xzw1($UV6S^VWiP zFd{Rimd-0CZC_Bu(WxBFW7+k{cOW7DxBBkJdJ;VsJ4Z@lERQr%3eVv&$%)b%<~ zCl^Y4NgO}js@u{|o~KTgH}>!* z_iDNqX2(As7T0xivMH|3SC1ivm8Q}6Ffcd7owUKN5lHAtzMM4<0v+ykUT!QiowO;`@%JGv+K$bBx@*S7C8GJVqQ_K>12}M`f_Ys=S zKFh}HM9#6Izb$Y{wYzItTy+l5U2oL%boCJn?R3?jP@n$zSIwlmyGq30Cw4QBO|14` zW5c);AN*J3&eMFAk$SR~2k|&+&Bc$e>s%c{`?d~85S-UWjA>DS5+;UKZ}5oVa5O(N zqqc@>)nee)+4MUjH?FGv%hm2{IlIF-QX}ym-7ok4Z9{V+ZHVZQl$A*x!(q%<2~iVv znUa+BX35&lCb#9VE-~Y^W_f;Xhl%vgjwdjzMy$FsSIj&ok}L+X`4>J=9BkN&nu^E*gbhj3(+D>C4E z@Fwq_=N)^bKFSHTzZk?-gNU$@l}r}dwGyh_fNi=9b|n}J>&;G!lzilbWF4B}BBq4f zYIOl?b)PSh#XTPp4IS5ZR_2C!E)Z`zH0OW%4;&~z7UAyA-X|sh9@~>cQW^COA9hV4 zXcA6qUo9P{bW1_2`eo6%hgbN%(G-F1xTvq!sc?4wN6Q4`e9Hku zFwvlAcRY?6h^Fj$R8zCNEDq8`=uZB8D-xn)tA<^bFFy}4$vA}Xq0jAsv1&5!h!yRA zU()KLJya5MQ`q&LKdH#fwq&(bNFS{sKlEh_{N%{XCGO+po#(+WCLmKW6&5iOHny>g z3*VFN?mx!16V5{zyuMWDVP8U*|BGT$(%IO|)?EF|OI*sq&RovH!N%=>i_c?K*A>>k zyg1+~++zY4Q)J;VWN0axhoIKx;l&G$gvj(#go^pZskEVj8^}is3Jw26LzYYVos0HX zRPvmK$dVxM8(Tc?pHFe0Z3uq){{#OK3i-ra#@+;*=ui8)y6hsRv z4Fxx1c1+fr!VI{L3DFMwXKrfl#Q8hfP@ajgEau&QMCxd{g#!T^;ATXW)nUg&$-n25 zruy3V!!;{?OTobo|0GAxe`Acn3GV@W=&n;~&9 zQM>NWW~R@OYORkJAo+eq1!4vzmf9K%plR4(tB@TR&FSbDoRgJ8qVcH#;7lQub*nq&?Z>7WM=oeEVjkaG zT#f)=o!M2DO5hLR+op>t0CixJCIeXH*+z{-XS|%jx)y(j&}Wo|3!l7{o)HU3m7LYyhv*xF&tq z%IN7N;D4raue&&hm0xM=`qv`+TK@;_xAcGKuK(2|75~ar2Yw)geNLSmVxV@x89bQu zpViVKKnlkwjS&&c|-X6`~xdnh}Ps)Hs z4VbUL^{XNLf7_|Oi>tA%?SG5zax}esF*FH3d(JH^Gvr7Rp*n=t7frH!U;!y1gJB^i zY_M$KL_}mW&XKaDEi9K-wZR|q*L32&m+2n_8lq$xRznJ7p8}V>w+d@?uB!eS3#u<} zIaqi!b!w}a2;_BfUUhGMy#4dPx>)_>yZ`ai?Rk`}d0>~ce-PfY-b?Csd(28yX22L% zI7XI>OjIHYTk_@Xk;Gu^F52^Gn6E1&+?4MxDS2G_#PQ&yXPXP^<-p|2nLTb@AAQEY zI*UQ9Pmm{Kat}wuazpjSyXCdnrD&|C1c5DIb1TnzF}f4KIV6D)CJ!?&l&{T)e4U%3HTSYqsQ zo@zWB1o}ceQSV)<4G<)jM|@@YpL+XHuWsr5AYh^Q{K=wSV99D~4RRU52FufmMBMmd z_H}L#qe(}|I9ZyPRD6kT>Ivj&2Y?qVZq<4bG_co_DP`sE*_Xw8D;+7QR$Uq(rr+u> z8bHUWbV19i#)@@G4bCco@Xb<8u~wVDz9S`#k@ciJtlu@uP1U0X?yov8v9U3VOig2t zL9?n$P3=1U_Emi$#slR>N5wH-=J&T=EdUHA}_Z zZIl3nvMP*AZS9{cDqFanrA~S5BqxtNm9tlu;^`)3X&V4tMAkJ4gEIPl= zoV!Gyx0N{3DpD@)pv^iS*dl2FwANu;1;%EDl}JQ7MbxLMAp>)UwNwe{=V}O-5C*>F zu?Ny+F64jZn<+fKjF01}8h5H_3pey|;%bI;SFg$w8;IC<8l|3#Lz2;mNNik6sVTG3 z+Su^rIE#40C4a-587$U~%KedEEw1%r6wdvoMwpmlXH$xPnNQN#f%Z7|p)nC>WsuO= z4zyqapLS<8(UJ~Qi9d|dQijb_xhA2)v>la)<1md5s^R1N&PiuA$^k|A<+2C?OiHbj z>Bn$~t)>Y(Zb`8hW7q9xQ=s>Rv81V+UiuZJc<23HplI88isqRCId89fb`Kt|CxVIg znWcwprwXnotO>3s&Oypkte^9yJjlUVVxSe%_xlzmje|mYOVPH^vjA=?6xd0vaj0Oz zwJ4OJNiFdnHJX3rw&inskjryukl`*fRQ#SMod5J|KroJRsVXa5_$q7whSQ{gOi*s0 z1LeCy|JBWRsDPn7jCb4s(p|JZiZ8+*ExC@Vj)MF|*Vp{B(ziccSn`G1Br9bV(v!C2 z6#?eqpJBc9o@lJ#^p-`-=`4i&wFe>2)nlPK1p9yPFzJCzBQbpkcR>={YtamIw)3nt z(QEF;+)4`>8^_LU)_Q3 zC5_7lgi_6y>U%m)m@}Ku4C}=l^J=<<7c;99ec3p{aR+v=diuJR7uZi%aQv$oP?dn?@6Yu_+*^>T0ptf(oobdL;6)N-I!TO`zg^Xbv3#L0I~sn@WGk-^SmPh5>W+LB<+1PU}AKa?FCWF|qMNELOgdxR{ zbqE7@jVe+FklzdcD$!(A$&}}H*HQFTJ+AOrJYnhh}Yvta(B zQ_bW4Rr;R~&6PAKwgLWXS{Bnln(vUI+~g#kl{r+_zbngT`Y3`^Qf=!PxN4IYX#iW4 zucW7@LLJA9Zh3(rj~&SyN_pjO8H&)|(v%!BnMWySBJV=eSkB3YSTCyIeJ{i;(oc%_hk{$_l;v>nWSB)oVeg+blh=HB5JSlG_r7@P z3q;aFoZjD_qS@zygYqCn=;Zxjo!?NK!%J$ z52lOP`8G3feEj+HTp@Tnn9X~nG=;tS+z}u{mQX_J0kxtr)O30YD%oo)L@wy`jpQYM z@M>Me=95k1p*FW~rHiV1CIfVc{K8r|#Kt(ApkXKsDG$_>76UGNhHExFCw#Ky9*B-z zNq2ga*xax!HMf_|Vp-86r{;~YgQKqu7%szk8$hpvi_2I`OVbG1doP(`gn}=W<8%Gn z%81#&WjkH4GV;4u43EtSW>K_Ta3Zj!XF?;SO3V#q=<=>Tc^@?A`i;&`-cYj|;^ zEo#Jl5zSr~_V-4}y8pnufXLa80vZY4z2ko7fj>DR)#z=wWuS1$$W!L?(y}YC+yQ|G z@L&`2upy3f>~*IquAjkVNU>}c10(fq#HdbK$~Q3l6|=@-eBbo>B9(6xV`*)sae58*f zym~RRVx;xoCG3`JV`xo z!lFw)=t2Hy)e!IFs?0~7osWk(d%^wxq&>_XD4+U#y&-VF%4z?XH^i4w`TxpF{`XhZ z%G}iEzf!T(l>g;W9<~K+)$g!{UvhW{E0Lis(S^%I8OF&%kr!gJ&fMOpM=&=Aj@wuL zBX?*6i51Qb$uhkwkFYkaD_UDE+)rh1c;(&Y=B$3)J&iJfQSx!1NGgPtK!$c9OtJuu zX(pV$bfuJpRR|K(dp@^j}i&HeJOh@|7lWo8^$*o~Xqo z5Sb+!EtJ&e@6F+h&+_1ETbg7LfP5GZjvIUIN3ibCOldAv z)>YdO|NH$x7AC8dr=<2ekiY1%fN*r~e5h6Yaw<{XIErujKV~tiyrvV_DV0AzEknC- zR^xKM3i<1UkvqBj3C{wDvytOd+YtDSGu!gEMg+!&|8BQrT*|p)(dwQLEy+ zMtMzij3zo40)CA!BKZF~yWg?#lWhqD3@qR)gh~D{uZaJO;{OWV8XZ_)J@r3=)T|kt zUS1pXr6-`!Z}w2QR7nP%d?ecf90;K_7C3d!UZ`N(TZoWNN^Q~RjVhQG{Y<%E1PpV^4 z-m-K+$A~-+VDABs^Q@U*)YvhY4Znn2^w>732H?NRK(5QSS$V@D7yz2BVX4)f5A04~$WbxGOam22>t&uD)JB8-~yiQW6ik;FGblY_I>SvB_z2?PS z*Qm&qbKI{H1V@YGWzpx`!v)WeLT02};JJo*#f$a*FH?IIad-^(;9XC#YTWN6;Z6+S zm4O1KH=#V@FJw7Pha0!9Vb%ZIM$)a`VRMoiN&C|$YA3~ZC*8ayZRY^fyuP6$n%2IU z$#XceYZeqLTXw(m$_z|33I$B4k~NZO>pP6)H_}R{E$i%USGy{l{-jOE;%CloYPEU+ zRFxOn4;7lIOh!7abb23YKD+_-?O z0FP9otcAh+oSj;=f#$&*ExUHpd&e#bSF%#8*&ItcL2H$Sa)?pt0Xtf+t)z$_u^wZi z44oE}r4kIZGy3!Mc8q$B&6JqtnHZ>Znn!Zh@6rgIu|yU+zG8q`q9%B18|T|oN3zMq z`l&D;U!OL~%>vo&q0>Y==~zLiCZk4v%s_7!9DxQ~id1LLE93gf*gg&2$|hB#j8;?3 z5v4S;oM6rT{Y;I+#FdmNw z){d%tNM<<#GN%n9ox7B=3#;u7unZ~tLB_vRZ52a&2=IM)2VkXm=L+Iqq~uk#Dug|x z>S84e+A7EiOY5lj*!q?6HDkNh~0g;0Jy(al!ZHHDtur9T$y-~)94HelX1NHjXWIM7UAe}$?jiz z9?P4`I0JM=G5K{3_%2jPLC^_Mlw?-kYYgb7`qGa3@dn|^1fRMwiyM@Ch z;CB&o7&&?c5e>h`IM;Wnha0QKnEp=$hA8TJgR-07N~U5(>9vJzeoFsSRBkDq=x(YgEMpb=l4TDD`2 zwVJpWGTA_u7}?ecW7s6%rUs&NXD3+n;jB86`X?8(l3MBo6)PdakI6V6a}22{)8ilT zM~T*mU}__xSy|6XSrJ^%lDAR3Lft%+yxC|ZUvSO_nqMX!_ul3;R#*{~4DA=h$bP)%8Yv9X zyp><|e8=_ttI}ZAwOd#dlnSjck#6%273{E$kJuCGu=I@O)&6ID{nWF5@gLb16sj|&Sb~+du4e4O_%_o`Ix4NRrAsyr1_}MuP94s>de8cH-OUkVPk3+K z&jW)It9QiU-ti~AuJkL`XMca8Oh4$SyJ=`-5WU<{cIh+XVH#e4d&zive_UHC!pN>W z3TB;Mn5i)9Qn)#6@lo4QpI3jFYc0~+jS)4AFz8fVC;lD^+idw^S~Qhq>Tg(!3$yLD zzktzoFrU@6s4wwCMz}edpF5i5Q1IMmEJQHzp(LAt)pgN3&O!&d?3W@6U4)I^2V{;- z6A(?zd93hS*uQmnh4T)nHnE{wVhh(=MMD(h(P4+^p83Om6t<*cUW>l(qJzr%5vp@K zN27ka(L{JX=1~e2^)F^i=TYj&;<7jyUUR2Bek^A8+3Up*&Xwc{)1nRR5CT8vG>ExV zHnF3UqXJOAno_?bnhCX-&kwI~Ti8t4`n0%Up>!U`ZvK^w2+0Cs-b9%w%4`$+To|k= zKtgc&l}P`*8IS>8DOe?EB84^kx4BQp3<7P{Pq}&p%xF_81pg!l2|u=&I{AuUgmF5n zJQCTLv}%}xbFGYtKfbba{CBo)lWW%Z>i(_NvLhoQZ*5-@2l&x>e+I~0Nld3UI9tdL zRzu8}i;X!h8LHVvN?C+|M81e>Jr38%&*9LYQec9Ax>?NN+9(_>XSRv&6hlCYB`>Qm z1&ygi{Y()OU4@D_jd_-7vDILR{>o|7-k)Sjdxkjgvi{@S>6GqiF|o`*Otr;P)kLHN zZkpts;0zw_6;?f(@4S1FN=m!4^mv~W+lJA`&7RH%2$)49z0A+8@0BCHtj|yH--AEL z0tW6G%X-+J+5a{5*WKaM0QDznf;V?L5&uQw+yegDNDP`hA;0XPYc6e0;Xv6|i|^F2WB)Z$LR|HR4 zTQsRAby9(^Z@yATyOgcfQw7cKyr^3Tz7lc7+JEwwzA7)|2x+PtEb>nD(tpxJQm)Kn zW9K_*r!L%~N*vS8<5T=iv|o!zTe9k_2jC_j*7ik^M_ zaf%k{WX{-;0*`t`G!&`eW;gChVXnJ-Rn)To8vW-?>>a%QU1v`ZC=U)f8iA@%JG0mZ zDqH;~mgBnrCP~1II<=V9;EBL)J+xzCoiRBaeH&J6rL!{4zIY8tZka?_FBeQeNO3q6 zyG_alW54Ba&wQf{&F1v-r1R6ID)PTsqjIBc+5MHkcW5Fnvi~{-FjKe)t1bl}Y;z@< z=!%zvpRua>>t_x}^}z0<7MI!H2v6|XAyR9!t50q-A)xk0nflgF4*OQlCGK==4S|wc zRMsSscNhRzHMBU8TdcHN!q^I}x0iXJ%uehac|Zs_B$p@CnF)HeXPpB_Za}F{<@6-4 zl%kml@}kHQ(ypD8FsPJ2=14xXJE|b20RUIgs!2|R3>LUMGF6X*B_I|$`Qg=;zm7C z{mEDy9dTmPbued7mlO@phdmAmJ7p@GR1bjCkMw6*G7#4+`k>fk1czdJUB!e@Q(~6# zwo%@p@V5RL0ABU2LH7Asq^quDUho@H>eTZH9f*no9fY0T zD_-9px3e}A!>>kv5wk91%C9R1J_Nh!*&Kk$J3KNxC}c_@zlgpJZ+5L)Nw|^p=2ue}CJtm;uj*Iqr)K})kA$xtNUEvX;4!Px*^&9T_`IN{D z{6~QY=Nau6EzpvufB^hflc#XIsSq0Y9(nf$d~6ZwK}fal92)fr%T3=q{0mP-EyP_G z)UR5h@IX}3Qll2b0oCAcBF>b*@Etu*aTLPU<%C>KoOrk=x?pN!#f_Og-w+;xbFgjQ zXp`et%lDBBh~OcFnMKMUoox0YwBNy`N0q~bSPh@+enQ=4RUw1) zpovN`QoV>vZ#5LvC;cl|6jPr}O5tu!Ipoyib8iXqy}TeJ;4+_7r<1kV0v5?Kv>fYp zg>9L`;XwXa&W7-jf|9~uP2iyF5`5AJ`Q~p4eBU$MCC00`rcSF>`&0fbd^_eqR+}mK z4n*PMMa&FOcc)vTUR zlDUAn-mh`ahi_`f`=39JYTNVjsTa_Y3b1GOIi)6dY)D}xeshB0T8Eov5%UhWd1)u}kjEQ|LDo{tqKKrYIfVz~@dp!! zMOnah@vp)%_-jDTUG09l+;{CkDCH|Q{NqX*uHa1YxFShy*1+;J`gywKaz|2Q{lG8x zP?KBur`}r`!WLKXY_K;C8$EWG>jY3UIh{+BLv0=2)KH%P}6xE2kg)%(-uA6lC?u8}{K(#P*c zE9C8t*u%j2r_{;Rpe1A{9nNXU;b_N0vNgyK!EZVut~}+R2rcbsHilqsOviYh-pYX= zHw@53nlmwYI5W5KP>&`dBZe0Jn?nAdC^HY1wlR6$u^PbpB#AS&5L6zqrXN&7*N2Q` z+Rae1EwS)H=aVSIkr8Ek^1jy2iS2o7mqm~Mr&g5=jjt7VxwglQ^`h#Mx+x2v|9ZAwE$i_9918MjJxTMr?n!bZ6n$}y11u8I9COTU`Z$Fi z!AeAQLMw^gp_{+0QTEJrhL424pVDp%wpku~XRlD3iv{vQ!lAf!_jyqd_h}+Tr1XG| z`*FT*NbPqvHCUsYAkFnM`@l4u_QH&bszpUK#M~XLJt{%?00GXY?u_{gj3Hvs!=N(I z(=AuWPijyoU!r?aFTsa8pLB&cx}$*%;K$e*XqF{~*rA-qn)h^!(-;e}O#B$|S~c+U zN4vyOK0vmtx$5K!?g*+J@G1NmlEI=pyZXZ69tAv=@`t%ag_Hk{LP~OH9iE)I= zaJ69b4kuCkV0V zo(M0#>phpQ_)@j;h%m{-a*LGi(72TP)ws2w*@4|C-3+;=5DmC4s7Lp95%n%@Ko zfdr3-a7m*dys9iIci$A=4NPJ`HfJ;hujLgU)ZRuJI`n;Pw|yksu!#LQnJ#dJysgNb z@@qwR^wrk(jbq4H?d!lNyy72~Dnn87KxsgQ!)|*m(DRM+eC$wh7KnS-mho3|KE)7h zK3k;qZ;K1Lj6uEXLYUYi)1FN}F@-xJ z@@3Hb84sl|j{4$3J}aTY@cbX@pzB_qM~APljrjju6P0tY{C@ zpUCOz_NFmALMv1*blCcwUD3?U6tYs+N%cmJ98D%3)%)Xu^uvzF zS5O!sc#X6?EwsYkvPo6A%O8&y8sCCQH<%f2togVwW&{M;PR!a(ZT_A+jVAbf{@5kL zB@Z(hb$3U{T_}SKA_CoQVU-;j>2J=L#lZ~aQCFg-d<9rzs$_gO&d5N6eFSc z1ml8)P*FSi+k@!^M9nDWR5e@ATD8oxtDu=36Iv2!;dZzidIS(PCtEuXAtlBb1;H%Z zwnC^Ek*D)EX4#Q>R$$WA2sxC_t(!!6Tr?C#@{3}n{<^o;9id1RA&-Pig1e-2B1XpG zliNjgmd3c&%A}s>qf{_j#!Z`fu0xIwm4L0)OF=u(OEmp;bLCIaZX$&J_^Z%4Sq4GZ zPn6sV_#+6pJmDN_lx@1;Zw6Md_p0w9h6mHtzpuIEwNn>OnuRSC2=>fP^Hqgc)xu^4 z<3!s`cORHJh#?!nKI`Et7{3C27+EuH)Gw1f)aoP|B3y?fuVfvpYYmmukx0ya-)TQX zR{ggy5cNf4X|g)nl#jC9p>7|09_S7>1D2GTRBUTW zAkQ=JMRogZqG#v;^=11O6@rPPwvJkr{bW-Qg8`q8GoD#K`&Y+S#%&B>SGRL>;ZunM@49!}Uy zN|bBCJ%sO;@3wl0>0gbl3L@1^O60ONObz8ZI7nder>(udj-jt`;yj^nTQ$L9`OU9W zX4alF#$|GiR47%x@s&LV>2Sz2R6?;2R~5k6V>)nz!o_*1Y!$p>BC5&?hJg_MiE6UBy>RkVZj`9UWbRkN-Hk!S`=BS3t3uyX6)7SF#)71*}`~Ogz z1rap5H6~dhBJ83;q-Y<5V35C2&F^JI-it(=5D#v!fAi9p#UwV~2tZQI+W(Dv?1t9? zfh*xpxxO{-(VGB>!Q&0%^YW_F!@aZS#ucP|YaD#>wd1Fv&Z*SR&mc;asi}1G) z_H>`!akh-Zxq9#io(7%;a$)w+{QH)Y$?UK1Dt^4)up!Szcxnu}kn$0afcfJL#IL+S z5gF_Y30j;{lNrG6m~$Ay?)*V9fZuU@3=kd40=LhazjFrau>(Y>SJNtOz>8x_X-BlA zIpl{i>OarVGj1v(4?^1`R}aQB&WCRQzS~;7R{tDZG=HhgrW@B`W|#cdyj%YBky)P= zpxuOZkW>S6%q7U{VsB#G(^FMsH5QuGXhb(sY+!-R8Bmv6Sx3WzSW<1MPPN1!&PurYky(@`bP9tz z52}LH9Q?+FF5jR6-;|+GVdRA!qtd;}*-h&iIw3Tq3qF9sDIb1FFxGbo&fbG5n8$3F zyY&PWL{ys^dTO}oZ#@sIX^BKW*bon=;te9j5k+T%wJ zNJtoN1~YVj4~YRrlZl)b&kJqp+Z`DqT!la$x&&IxgOQw#yZd-nBP3!7FijBXD|IsU8Zl^ zc6?MKpJQ+7ka|tZQLfchD$PD|;K(9FiLE|eUZX#EZxhG!S-63C$jWX1Yd!6-Yxi-u zjULIr|0-Q%D9jz}IF~S%>0(jOqZ(Ln<$9PxiySr&2Oic7vb<8q=46)Ln%Z|<*z5&> z3f~Zw@m;vR(bESB<=Jqkxn(=#hQw42l(7)h`vMQQTttz9XW6^|^8EK7qhju4r_c*b zJIi`)MB$w@9epwdIfnEBR+?~);yd6C(LeMC& zn&&N*?-g&BBJcV;8&UoZi4Lmxcj16ojlxR~zMrf=O_^i1wGb9X-0@6_rpjPYemIin zmJb+;lHe;Yp=8G)Q(L1bzH*}I>}uAqhj4;g)PlvD9_e_ScR{Ipq|$8NvAvLD8MYr}xl=bU~)f%B3E>r3Bu9_t|ThF3C5~BdOve zEbk^r&r#PT&?^V1cb{72yEWH}TXEE}w>t!cY~rA+hNOTK8FAtIEoszp!qqptS&;r$ zaYV-NX96-h$6aR@1xz6_E0^N49mU)-v#bwtGJm)ibygzJ8!7|WIrcb`$XH~^!a#s& z{Db-0IOTFq#9!^j!n_F}#Z_nX{YzBK8XLPVmc&X`fT7!@$U-@2KM9soGbmOSAmqV z{nr$L^MBo_u^Joyf0E^=eo{Rt0{{e$IFA(#*kP@SQd6lWT2-#>` zP1)7_@IO!9lk>Zt?#CU?cuhiLF&)+XEM9B)cS(gvQT!X3`wL*{fArTS;Ak`J<84du zALKPz4}3nlG8Fo^MH0L|oK2-4xIY!~Oux~1sw!+It)&D3p;+N8AgqKI`ld6v71wy8I!eP0o~=RVcFQR2Gr(eP_JbSytoQ$Yt}l*4r@A8Me94y z8cTDWhqlq^qoAhbOzGBXv^Wa4vUz$(7B!mX`T=x_ueKRRDfg&Uc-e1+z4x$jyW_Pm zp?U;-R#xt^Z8Ev~`m`iL4*c#65Nn)q#=Y0l1AuD&+{|8-Gsij3LUZXpM0Bx0u7WWm zH|%yE@-#XEph2}-$-thl+S;__ciBxSSzHveP%~v}5I%u!z_l_KoW{KRx2=eB33umE zIYFtu^5=wGU`Jab8#}cnYry@9p5UE#U|VVvx_4l49JQ;jQdp(uw=$^A$EA$LM%vmE zvdEOaIcp5qX8wX{mYf0;#51~imYYPn4=k&#DsKTxo{_Mg*;S495?OBY?#gv=edYC* z^O@-sd-qa+U24xvcbL0@C7_6o!$`)sVr-jSJE4XQUQ$?L7}2(}Eixqv;L8AdJAVqc zq}RPgpnDb@E_;?6K58r3h4-!4rT4Ab#rLHLX?eMOfluJk=3i1@Gt1i#iA=O`M0@x! z(HtJP9BMHXEzuD93m|B&woj0g6T?f#^)>J>|I4C5?Gam>n9!8CT%~aT;=oco5d6U8 zMXl(=W;$ND_8+DD*?|5bJ!;8ebESXMUKBAf7YBwNVJibGaJ*(2G`F%wx)grqVPjudiaq^Kl&g$8A2 zWMxMr@_$c}d+;_B`#kUX-t|4VKH&_f^^EP0&=DPLW)H)UzBG%%Tra*5 z%$kyZe3I&S#gfie^z5)!twG={3Cuh)FdeA!Kj<-9** zvT*5%Tb`|QbE!iW-XcOuy39>D3oe6x{>&<#E$o8Ac|j)wq#kQzz|ATd=Z0K!p2$QE zPu?jL8Lb^y3_CQE{*}sTDe!2!dtlFjq&YLY@2#4>XS`}v#PLrpvc4*@q^O{mmnr5D zmyJq~t?8>FWU5vZdE(%4cuZuao0GNjp3~Dt*SLaxI#g_u>hu@k&9Ho*#CZP~lFJHj z(e!SYlLigyc?&5-YxlE{uuk$9b&l6d`uIlpg_z15dPo*iU&|Khx2*A5Fp;8iK_bdP z?T6|^7@lcx2j0T@x>X7|kuuBSB7<^zeY~R~4McconTxA2flHC0_jFxmSTv-~?zVT| zG_|yDqa9lkF*B6_{j=T>=M8r<0s;@z#h)3BQ4NLl@`Xr__o7;~M&dL3J8fP&zLfDfy z);ckcTev{@OUlZ`bCo(-3? z1u1xD`PKgSg?RqeVVsF<1SLF;XYA@Bsa&cY!I48ZJn1V<3d!?s=St?TLo zC0cNr`qD*M#s6f~X>SCNVkva^9A2ZP>CoJ9bvgXe_c}WdX-)pHM5m7O zrHt#g$F0AO+nGA;7dSJ?)|Mo~cf{z2L)Rz!`fpi73Zv)H=a5K)*$5sf_IZypi($P5 zsPwUc4~P-J1@^3C6-r9{V-u0Z&Sl7vNfmuMY4yy*cL>_)BmQF!8Om9Dej%cHxbIzA zhtV0d{=%cr?;bpBPjt@4w=#<>k5ee=TiWAXM2~tUGfm z$s&!Dm0R^V$}fOR*B^kGaipi~rx~A2cS0;t&khV1a4u38*XRUP~f za!rZMtay8bsLt6yFYl@>-y^31(*P!L^^s@mslZy(SMsv9bVoX`O#yBgEcjCmGpyc* zeH$Dw6vB5P*;jor+JOX@;6K#+xc)Z9B8M=x2a@Wx-{snPGpRmOC$zpsqW*JCh@M2Y z#K+M(>=#d^>Of9C`))h<=Bsy)6zaMJ&x-t%&+UcpLjV`jo4R2025 zXaG8EA!0lQa)|dx-@{O)qP6`$rhCkoQqZ`^SW8g-kOwrwsK8 z3ms*AIcyj}-1x&A&vSq{r=QMyp3CHdWH35!sad#!Sm>^|-|afB+Q;|Iq@LFgqIp#Z zD1%H+3I?6RGnk&IFo|u+E0dCxXz4yI^1i!QTu7uvIEH>i3rR{srcST`LIRwdV1P;W z+%AN1NIf@xxvVLiSX`8ILA8MzNqE&7>%jMzGt9wm78bo9<;h*W84i29^w!>V>{N+S zd`5Zmz^G;f=icvoOZfK5#1ctx*~UwD=ab4DGQXehQ!XYnak*dee%YN$_ZPL%KZuz$ zD;$PpT;HM^$KwtQm@7uvT`i6>Hae1CoRVM2)NL<2-k2PiX=eAx+-6j#JI?M}(tuBW zkF%jjLR)O`gI2fcPBxF^HeI|DWwQWHVR!;;{BXXHskxh8F@BMDn`oEi-NHt;CLymW z=KSv5)3dyzec0T5B*`g-MQ<;gz=nIWKUi9ko<|4I(-E0k$QncH>E4l z**1w&#={&zv4Tvhgz#c29`m|;lU-jmaXFMC11 z*dlXDMEOG>VoLMc>!rApwOu2prKSi*!w%`yzGmS+k(zm*CsLK*wv{S_0WX^8A-rKy zbk^Gf_92^7iB_uUF)EE+ET4d|X|>d&mdN?x@vxKAQk`O+r4Qdu>XGy(a(19g;=jU} zFX{O*_NG>!$@jh!U369Lnc+D~qch3uT+_Amyi}*k#LAAwh}k8IPK5a-WZ81ufD>l> z$4cF}GSz>ce`3FAic}6W4Z7m9KGO?(eWqi@L|5Hq0@L|&2flN1PVl}XgQ2q*_n2s3 zt5KtowNkTYB5b;SVuoXA@i5irXO)A&%7?V`1@HGCB&)Wgk+l|^XXChq;u(nyPB}b3 zY>m5jkxpZgi)zfbgv&ec4Zqdvm+D<?Im*mXweS9H+V>)zF#Zp3)bhl$PbISY{5=_z!8&*Jv~NYtI-g!>fDs zmvL5O^U%!^VaKA9gvKw|5?-jk>~%CVGvctKmP$kpnpfN{D8@X*Aazi$txfa%vd-|E z>kYmV66W!lNekJPom29LdZ%(I+ZLZYTXzTg*to~m?7vp%{V<~>H+2}PQ?PPAq`36R z<%wR8v6UkS>Wt#hzGk#44W<%9S=nBfB);6clKwnxY}T*w21Qc3_?IJ@4gYzC7s;WP zVQNI(M=S=JT#xsZy7G`cR(BP9*je0bfeN8JN5~zY(DDs0t{LpHOIbN);?T-69Pf3R zSNe*&p2%AwXHL>__g+xd4Hlc_vu<25H?(`nafS%)3UPP7_4;gk-9ckt8SJRTv5v0M z_Hww`qPudL?ajIR&X*;$y-`<)6dxx1U~5eGS13CB!lX;3w7n&lDDiArbAhSycd}+b zya_3p@A`$kQy;|NJZ~s44Hqo7Hwt}X86NK=(ey>lgWTtGL6k@Gy;PbO!M%1~Wcn2k zUFP|*5d>t-X*RU8g%>|(wwj*~#l4z^Aatf^DWd1Wj#Q*AY0D^V@sC`M zjJc6qXu0I7Y*2;;gGu!plAFzG=J;1%eIOdn zQA>J&e05UN*7I5@yRhK|lbBSfJ+5Uq;!&HV@xfPZrgD}kE*1DSq^=%{o%|LChhl#0 zlMb<^a6ixzpd{kNZr|3jTGeEzuo}-eLT-)Q$#b{!vKx8Tg}swCni>{#%vDY$Ww$84 zew3c9BBovqb}_&BRo#^!G(1Eg((BScRZ}C)Oz?y`T5wOrv);)b^4XR8 zhJo7+<^7)qB>I;46!GySzdneZ>n_E1oWZY;kf94#)s)kWjuJN1c+wbVoNQcmnv}{> zN0pF+Sl3E}UQ$}slSZeLJrwT>Sr}#V(dVaezCQl2|4LN`7L7v&siYR|r7M(*JYfR$ zst3=YaDw$FSc{g}KHO&QiKxuhEzF{f%RJLKe3p*7=oo`WNP)M(9X1zIQPP0XHhY3c znrP{$4#Ol$A0s|4S7Gx2L23dv*Gv2o;h((XVn+9+$qvm}s%zi6nI-_s6?mG! zj{DV;qesJb&owKeEK?=J>UcAlYckA7Sl+I&IN=yasrZOkejir*kE@SN`fk<8Fgx*$ zy&fE6?}G)d_N`){P~U@1jRVA|2*69)KSe_}!~?+`Yb{Y=O~_+@!j<&oVQQMnhoIRU zA0CyF1OFfkK44n*JD~!2!SCPM;PRSk%1XL=0&rz00wxPs&-_eapJy#$h!eqY%nS0{ z!aGg58JIJPF3_ci%n)QSVpa2H`vIe$RD43;#IRfDV&Ibit z+?>HW4{2wOfC6Fw)}4x}i1maDxcE1qi@BS*qcxD2gE@h3#4cgU*D-&3z7D|tVZWt= z-Cy2+*Cm@P4GN_TPUtaVyVesbVDazF@)j8VJ4>XZv!f%}&eO1SvIgr}4`A*3#vat< z_MoByL(qW6L7SFZ#|Gc1fFN)L2PxY+{B8tJp+pxRyz*87)vXR}*=&ahXjBlQKguuf zX6x<<6fQulE^C*KH8~W%ptpaC0l?b=_{~*U4?5Vt;dgM4t_{&UZ1C2j?b>b+5}{IF_CUyvz-@QZPMlJ)r_tS$9kH%RPv#2_nMb zRLj5;chJ72*U`Z@Dqt4$@_+k$%|8m(HqLG!qT4P^DdfvGf&){gKnGCX#H0!;W=AGP zbA&Z`-__a)VTS}kKFjWGk z%|>yE?t*EJ!qeQ%dPk$;xIQ+P0;()PCBDgjJm6Buj{f^awNoVx+9<|lg3%-$G(*f) zll6oOkN|yamn1uyl2*N-lnqRI1cvs_JxLTeahEK=THV$Sz*gQhKNb*p0fNoda#-&F zB-qJgW^g}!TtM|0bS2QZekW7_tKu%GcJ!4?lObt0z_$mZ4rbQ0o=^curCs3bJK6sq z9fu-aW-l#>z~ca(B;4yv;2RZ?tGYAU)^)Kz{L|4oPj zdOf_?de|#yS)p2v8-N||+XL=O*%3+y)oI(HbM)Ds?q8~HPzIP(vs*G`iddbWq}! z(2!VjP&{Z1w+%eUq^ '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/samples/spring/gradlew.bat b/samples/spring/gradlew.bat new file mode 100644 index 00000000..f127cfd4 --- /dev/null +++ b/samples/spring/gradlew.bat @@ -0,0 +1,91 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/samples/spring/settings.gradle.kts b/samples/spring/settings.gradle.kts new file mode 100644 index 00000000..f0c4b906 --- /dev/null +++ b/samples/spring/settings.gradle.kts @@ -0,0 +1,8 @@ +pluginManagement { + repositories { + maven { url = uri("https://repo.spring.io/milestone") } + maven { url = uri("https://repo.spring.io/snapshot") } + gradlePluginPortal() + } +} +rootProject.name = "sample" diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java new file mode 100644 index 00000000..ddf480b8 --- /dev/null +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java @@ -0,0 +1,13 @@ +package it.pagopa.tech.lollipop.consumer.sample; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SampleApplication { + + public static void main(String[] args) { + SpringApplication.run(SampleApplication.class, args); + } + +} diff --git a/samples/spring/src/main/resources/application.properties b/samples/spring/src/main/resources/application.properties new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/samples/spring/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/samples/spring/src/test/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplicationTests.java b/samples/spring/src/test/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplicationTests.java new file mode 100644 index 00000000..694fd01f --- /dev/null +++ b/samples/spring/src/test/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplicationTests.java @@ -0,0 +1,13 @@ +package it.pagopa.tech.lollipop.consumer.sample; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class SampleApplicationTests { + + @Test + void contextLoads() { + } + +} From 415d3dae4dffb062bf21e2c9fabdff0442c8919e Mon Sep 17 00:00:00 2001 From: svariant Date: Thu, 20 Apr 2023 12:45:34 +0200 Subject: [PATCH 258/403] [SLS-13] Defined main classes and configurations for spring sample application --- samples/spring/build.gradle | 46 ++++++++++++++++ samples/spring/build.gradle.kts | 33 ------------ samples/spring/settings.gradle | 1 + samples/spring/settings.gradle.kts | 8 --- samples/spring/src/Main.java | 5 ++ .../consumer/sample/SampleApplication.java | 35 ++++++++++-- .../sample/config/SampleServicesConfig.java | 53 +++++++++++++++++++ .../sample/config/SampleWebConfigurer.java | 31 +++++++++++ .../sample/controller/SampleController.java | 12 +++++ .../src/main/resources/application.properties | 5 +- .../sample/SampleApplicationTests.java | 2 +- 11 files changed, 185 insertions(+), 46 deletions(-) create mode 100644 samples/spring/build.gradle delete mode 100644 samples/spring/build.gradle.kts create mode 100644 samples/spring/settings.gradle delete mode 100644 samples/spring/settings.gradle.kts create mode 100644 samples/spring/src/Main.java create mode 100644 samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java create mode 100644 samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleWebConfigurer.java create mode 100644 samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/controller/SampleController.java diff --git a/samples/spring/build.gradle b/samples/spring/build.gradle new file mode 100644 index 00000000..1c5a0db2 --- /dev/null +++ b/samples/spring/build.gradle @@ -0,0 +1,46 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '2.7.10' + id 'io.spring.dependency-management' version '1.0.15.RELEASE' +} + +group = 'it.pagopa.tech.lollipop.consumer' +version = '0.0.1-SNAPSHOT' +sourceCompatibility = '11' + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() + mavenLocal() + maven { + url = uri("https://maven.pkg.github.com/pagopa/eng-http-signatures") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + } + } +} + +dependencies { + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:core:1.0.0-SNAPSHOT' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:assertion-rest-client-native:1.0.0-SNAPSHOT' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:identity-service-rest-client-native:1.0.0-SNAPSHOT' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:http-verifier:1.0.0-SNAPSHOT' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:spring-impl:1.0.0-SNAPSHOT' + + implementation 'org.mock-server:mockserver-netty:5.15.0' + implementation 'org.springframework.boot:spring-boot-starter-web' + compileOnly 'org.projectlombok:lombok' + developmentOnly 'org.springframework.boot:spring-boot-devtools' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' +} + +tasks.named('test') { + useJUnitPlatform() +} diff --git a/samples/spring/build.gradle.kts b/samples/spring/build.gradle.kts deleted file mode 100644 index eb895a36..00000000 --- a/samples/spring/build.gradle.kts +++ /dev/null @@ -1,33 +0,0 @@ -plugins { - java - id("org.springframework.boot") version "2.7.11-SNAPSHOT" - id("io.spring.dependency-management") version "1.0.15.RELEASE" -} - -group = "it.pagopa.tech.lollipop.consumer" -version = "0.0.1-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_11 - -configurations { - compileOnly { - extendsFrom(configurations.annotationProcessor.get()) - } -} - -repositories { - mavenCentral() - maven { url = uri("https://repo.spring.io/milestone") } - maven { url = uri("https://repo.spring.io/snapshot") } -} - -dependencies { - implementation("org.springframework.boot:spring-boot-starter-web") - compileOnly("org.projectlombok:lombok") - developmentOnly("org.springframework.boot:spring-boot-devtools") - annotationProcessor("org.projectlombok:lombok") - testImplementation("org.springframework.boot:spring-boot-starter-test") -} - -tasks.withType { - useJUnitPlatform() -} diff --git a/samples/spring/settings.gradle b/samples/spring/settings.gradle new file mode 100644 index 00000000..88d146cd --- /dev/null +++ b/samples/spring/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'sample' diff --git a/samples/spring/settings.gradle.kts b/samples/spring/settings.gradle.kts deleted file mode 100644 index f0c4b906..00000000 --- a/samples/spring/settings.gradle.kts +++ /dev/null @@ -1,8 +0,0 @@ -pluginManagement { - repositories { - maven { url = uri("https://repo.spring.io/milestone") } - maven { url = uri("https://repo.spring.io/snapshot") } - gradlePluginPortal() - } -} -rootProject.name = "sample" diff --git a/samples/spring/src/Main.java b/samples/spring/src/Main.java new file mode 100644 index 00000000..3e59c38f --- /dev/null +++ b/samples/spring/src/Main.java @@ -0,0 +1,5 @@ +public class Main { + public static void main(String[] args) { + System.out.println("Hello world!"); + } +} \ No newline at end of file diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java index ddf480b8..08c8a44e 100644 --- a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java @@ -1,13 +1,42 @@ package it.pagopa.tech.lollipop.consumer.sample; +import org.mockserver.client.MockServerClient; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.model.Header; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import java.text.SimpleDateFormat; +import java.util.Date; + +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + @SpringBootApplication public class SampleApplication { - public static void main(String[] args) { - SpringApplication.run(SampleApplication.class, args); - } + public static void main(String[] args) { + + SpringApplication.run(SampleApplication.class, args); + createExpectationAssertionFound(); + } + + private static void createExpectationAssertionFound() { + String ASSERTION_REF = "sha256-_ZzL8qeuAM5kQ9pbMB4tn7IDSQZCVXAkW9fm4P7ULPI"; + String JWT = "aValidJWT"; + String RESPONSE_STRING = "{\"response_xml\": \" " + " https://posteid.poste.it" + " " + " " + " " + " " + " " + " " + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" + " " + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + " " + " " + " " + " https://posteid.poste.it " + " " + " " + " " + " " + " " + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" + " " + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + " " + " " + " " + " " + " https://app-backend.io.italia.it" + " " + " https://www.spid.gov.it/SpidL2" + " " + " TINIT-AAAAAA89S20I111X" + " " + " \"}"; + + ClientAndServer.startClientAndServer(3000); + new MockServerClient("localhost", 3000) + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", JWT))) + .respond(response().withStatusCode(200).withBody(RESPONSE_STRING)); + } } diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java new file mode 100644 index 00000000..29615341 --- /dev/null +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java @@ -0,0 +1,53 @@ +package it.pagopa.tech.lollipop.consumer.sample.config; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientConfig; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.assertion.impl.AssertionServiceFactoryImpl; +import it.pagopa.tech.lollipop.consumer.assertion.storage.SimpleAssertionStorageProvider; +import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.http_verifier.visma.VismaHttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImpl; +import it.pagopa.tech.lollipop.consumer.spring.HttpVerifierHandlerInterceptor; +import it.pagopa.tech.lollipop.consumer.spring.config.HttpVerifierConfiguration; +import it.pagopa.tech.lollipop.consumer.spring.config.SpringLollipopConsumerRequestConfig; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SampleServicesConfig { + + @Bean + public SpringLollipopConsumerRequestConfig verifierConfiguration() { + return new SpringLollipopConsumerRequestConfig(); + } + + @Bean + public HttpMessageVerifierFactory httpMessageVerifierFactory() throws Exception { + return new VismaHttpMessageVerifierFactory("UTF-8", verifierConfiguration()); + } + + @Bean + public IdpCertProviderFactory idpCertProviderFactory() { + return new IdpCertProviderFactoryImpl( + new IdpCertSimpleClientProvider(IdpCertSimpleClientConfig.builder().build())); + } + + @Bean + public AssertionServiceFactory assertionServiceFactory() { + return new AssertionServiceFactoryImpl( + new SimpleAssertionStorageProvider(), + new AssertionSimpleClientProvider(AssertionSimpleClientConfig.builder().build()), + storageConfig()); + } + + @Bean + public StorageConfig storageConfig() { + return new StorageConfig(); + } +} diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleWebConfigurer.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleWebConfigurer.java new file mode 100644 index 00000000..dc7bc1fa --- /dev/null +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleWebConfigurer.java @@ -0,0 +1,31 @@ +package it.pagopa.tech.lollipop.consumer.sample.config; + +import it.pagopa.tech.lollipop.consumer.spring.HttpVerifierHandlerInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.CommonsRequestLoggingFilter; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Component +public class SampleWebConfigurer implements WebMvcConfigurer { + + @Autowired + private HttpVerifierHandlerInterceptor interceptor; + + @Bean + public CommonsRequestLoggingFilter loggingFilter() { + CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter(); + filter.setIncludeQueryString(true); + filter.setIncludeClientInfo(true); + filter.setIncludeHeaders(true); + filter.setIncludePayload(true); + return filter; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(interceptor); + } +} diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/controller/SampleController.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/controller/SampleController.java new file mode 100644 index 00000000..68125252 --- /dev/null +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/controller/SampleController.java @@ -0,0 +1,12 @@ +package it.pagopa.tech.lollipop.consumer.sample.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class SampleController { + + @RequestMapping("/") + public @ResponseBody String sample() { return "Sample";}; +} diff --git a/samples/spring/src/main/resources/application.properties b/samples/spring/src/main/resources/application.properties index 8b137891..0d05d85c 100644 --- a/samples/spring/src/main/resources/application.properties +++ b/samples/spring/src/main/resources/application.properties @@ -1 +1,4 @@ - +lollipop: + core: + config: + assertionExpireInDays: 180 diff --git a/samples/spring/src/test/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplicationTests.java b/samples/spring/src/test/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplicationTests.java index 694fd01f..aeec9dc0 100644 --- a/samples/spring/src/test/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplicationTests.java +++ b/samples/spring/src/test/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplicationTests.java @@ -1,4 +1,4 @@ -package it.pagopa.tech.lollipop.consumer.sample; +package test.java.it.pagopa.tech.lollipop.consumer.sample; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; From d27a96f63d0c1f316af79bcb2fd757c4687d5bdc Mon Sep 17 00:00:00 2001 From: svariant Date: Thu, 20 Apr 2023 14:41:52 +0200 Subject: [PATCH 259/403] [SLS-13] Fixed package scan --- .../pagopa/tech/lollipop/consumer/sample/SampleApplication.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java index 08c8a44e..40dd7b08 100644 --- a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java @@ -12,7 +12,7 @@ import static org.mockserver.model.HttpRequest.request; import static org.mockserver.model.HttpResponse.response; -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "it.pagopa.tech") public class SampleApplication { public static void main(String[] args) { From b20b7dd7f550603d8fafb53929471851862f7f2e Mon Sep 17 00:00:00 2001 From: svariant Date: Thu, 20 Apr 2023 16:18:43 +0200 Subject: [PATCH 260/403] [SLS-13] Fixed LollipopConsumerRequestConfig injection into factory - application configuration working --- .../helper/LollipopConsumerFactoryHelper.java | 4 +++- .../consumer/sample/SampleApplication.java | 3 +++ .../sample/config/SampleServicesConfig.java | 15 +++++---------- .../src/main/resources/application.properties | 7 +++---- .../spring/config/HttpVerifierConfiguration.java | 6 ++++-- .../SpringLollipopConsumerRequestConfig.java | 2 ++ 6 files changed, 20 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index 969b37f1..c3b477d9 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -33,11 +33,13 @@ public LollipopConsumerFactoryHelper( HttpMessageVerifierFactory httpMessageVerifierFactory, IdpCertProviderFactory idpCertProviderFactory, AssertionServiceFactory assertionServiceFactory, - LollipopConsumerRequestValidationService lollipopConsumerRequestValidationService) { + LollipopConsumerRequestValidationService lollipopConsumerRequestValidationService, + LollipopConsumerRequestConfig lollipopConsumerRequestConfig) { this.httpMessageVerifierFactory = httpMessageVerifierFactory; this.idpCertProviderFactory = idpCertProviderFactory; this.assertionServiceFactory = assertionServiceFactory; this.lollipopConsumerRequestValidationService = lollipopConsumerRequestValidationService; + this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; } /** diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java index 40dd7b08..b61526ee 100644 --- a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java @@ -1,10 +1,13 @@ package it.pagopa.tech.lollipop.consumer.sample; +import it.pagopa.tech.lollipop.consumer.spring.config.HttpVerifierConfiguration; +import it.pagopa.tech.lollipop.consumer.spring.config.SpringLollipopConsumerRequestConfig; import org.mockserver.client.MockServerClient; import org.mockserver.integration.ClientAndServer; import org.mockserver.model.Header; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import java.text.SimpleDateFormat; import java.util.Date; diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java index 29615341..ccd49cf2 100644 --- a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java @@ -6,30 +6,25 @@ import it.pagopa.tech.lollipop.consumer.assertion.impl.AssertionServiceFactoryImpl; import it.pagopa.tech.lollipop.consumer.assertion.storage.SimpleAssertionStorageProvider; import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; -import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; import it.pagopa.tech.lollipop.consumer.http_verifier.visma.VismaHttpMessageVerifierFactory; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientProvider; import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImpl; -import it.pagopa.tech.lollipop.consumer.spring.HttpVerifierHandlerInterceptor; -import it.pagopa.tech.lollipop.consumer.spring.config.HttpVerifierConfiguration; import it.pagopa.tech.lollipop.consumer.spring.config.SpringLollipopConsumerRequestConfig; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration +@EnableConfigurationProperties(value = {SpringLollipopConsumerRequestConfig.class}) public class SampleServicesConfig { @Bean - public SpringLollipopConsumerRequestConfig verifierConfiguration() { - return new SpringLollipopConsumerRequestConfig(); - } - - @Bean - public HttpMessageVerifierFactory httpMessageVerifierFactory() throws Exception { - return new VismaHttpMessageVerifierFactory("UTF-8", verifierConfiguration()); + public HttpMessageVerifierFactory httpMessageVerifierFactory(SpringLollipopConsumerRequestConfig springLollipopConsumerRequestConfig) throws Exception { + return new VismaHttpMessageVerifierFactory("UTF-8", springLollipopConsumerRequestConfig); } @Bean diff --git a/samples/spring/src/main/resources/application.properties b/samples/spring/src/main/resources/application.properties index 0d05d85c..11706021 100644 --- a/samples/spring/src/main/resources/application.properties +++ b/samples/spring/src/main/resources/application.properties @@ -1,4 +1,3 @@ -lollipop: - core: - config: - assertionExpireInDays: 180 +lollipop.core.config.assertionExpireInDays=180 + + diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java index a95dfa1b..96926c35 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java @@ -25,12 +25,14 @@ public LollipopConsumerFactoryHelper lollipopConsumerFactoryHelper( HttpMessageVerifierFactory httpMessageVerifierFactory, IdpCertProviderFactory idpCertProviderFactory, AssertionServiceFactory assertionServiceFactory, - LollipopConsumerRequestValidationService lollipopConsumerRequestValidationService) { + LollipopConsumerRequestValidationService lollipopConsumerRequestValidationService, + SpringLollipopConsumerRequestConfig springLollipopConsumerRequestConfig) { return new LollipopConsumerFactoryHelper( httpMessageVerifierFactory, idpCertProviderFactory, assertionServiceFactory, - lollipopConsumerRequestValidationService); + lollipopConsumerRequestValidationService, + springLollipopConsumerRequestConfig); } @Bean diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java index 4e5a8017..fc19f254 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/SpringLollipopConsumerRequestConfig.java @@ -2,6 +2,7 @@ package it.pagopa.tech.lollipop.consumer.spring.config; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationPropertiesScan; @@ -10,4 +11,5 @@ @ConfigurationProperties(prefix = "lollipop.core.config") @ConfigurationPropertiesScan @NoArgsConstructor +@Data public class SpringLollipopConsumerRequestConfig extends LollipopConsumerRequestConfig {} From fd62cf60a389f0e36e2e98f17e6cbd994b940ed6 Mon Sep 17 00:00:00 2001 From: giomella Date: Wed, 19 Apr 2023 10:04:45 +0200 Subject: [PATCH 261/403] [SLS-25] added signature validation to the assertion verification flow. --- core/build.gradle | 5 + .../ErrorRetrievingIdpCertDataException.java | 49 +++++++ .../ErrorValidatingAssertionSignature.java | 49 +++++++ .../service/AssertionVerifierService.java | 12 +- .../impl/AssertionVerifierServiceImpl.java | 122 +++++++++++++++--- 5 files changed, 214 insertions(+), 23 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingIdpCertDataException.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java diff --git a/core/build.gradle b/core/build.gradle index dfc3a89f..1c14412a 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -47,6 +47,11 @@ dependencies { implementation 'ch.qos.logback:logback-classic:1.4.6' implementation 'ch.qos.logback:logback-core:1.4.6' implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.2' + implementation 'org.opensaml:opensaml-core:4.0.1' + implementation 'org.opensaml:opensaml-saml-api:4.0.1' + implementation 'org.opensaml:opensaml-saml-impl:4.0.1' + implementation 'org.apache.wss4j:wss4j-ws-security-common:2.4.1' + // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.mockito:mockito-core:5.2.0' diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingIdpCertDataException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingIdpCertDataException.java new file mode 100644 index 00000000..a77f0776 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingIdpCertDataException.java @@ -0,0 +1,49 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +import java.util.Objects; + +/** Thrown in case of problems on retrieving the IDP data */ +public class ErrorRetrievingIdpCertDataException extends Exception { + + /** Error code of this exception */ + private final ErrorCode errorCode; + + /** + * Constructs new exception with provided error code and message + * + * @param errorCode Error code + * @param message Detail message + */ + public ErrorRetrievingIdpCertDataException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Constructs new exception with provided error code, message and cause + * + * @param errorCode Error code + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public ErrorRetrievingIdpCertDataException(ErrorCode errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Returns error code + * + * @return Error code of this exception + */ + public ErrorCode getErrorCode() { + return errorCode; + } + + /** Error codes to classify Lollipop Request Exceptions */ + public enum ErrorCode { + ENTITY_ID_FIELD_NOT_FOUND, + INSTANT_FIELD_NOT_FOUND, + IDP_CERT_DATA_NOT_FOUND + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java new file mode 100644 index 00000000..5368ba68 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java @@ -0,0 +1,49 @@ +package it.pagopa.tech.lollipop.consumer.exception; + +import java.util.Objects; + +/** Thrown in case of problems when validating assertion signature */ +public class ErrorValidatingAssertionSignature extends Exception { + + /** Error code of this exception */ + private final ErrorCode errorCode; + + /** + * Constructs new exception with provided error code and message + * + * @param errorCode Error code + * @param message Detail message + */ + public ErrorValidatingAssertionSignature(ErrorCode errorCode, String message) { + super(message); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Constructs new exception with provided error code, message and cause + * + * @param errorCode Error code + * @param message Detail message + * @param cause Exception causing the constructed one + */ + public ErrorValidatingAssertionSignature(ErrorCode errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = Objects.requireNonNull(errorCode); + } + + /** + * Returns error code + * + * @return Error code of this exception + */ + public ErrorCode getErrorCode() { + return errorCode; + } + + /** Error codes to classify Lollipop Request Exceptions */ + public enum ErrorCode { + ERROR_GENERATING_X509_CERTIFICATE, + ERROR_RETRIEVING_ASSERTION_SIGNATURE + + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java index 92df175d..2949d656 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java @@ -1,10 +1,7 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service; -import it.pagopa.tech.lollipop.consumer.exception.AssertionPeriodException; -import it.pagopa.tech.lollipop.consumer.exception.AssertionThumbprintException; -import it.pagopa.tech.lollipop.consumer.exception.AssertionUserIdException; -import it.pagopa.tech.lollipop.consumer.exception.ErrorRetrievingAssertionException; +import it.pagopa.tech.lollipop.consumer.exception.*; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; /** @@ -19,13 +16,14 @@ public interface AssertionVerifierService { * * @param request the Lollipop request * @return true if the assertion is valid - * @throws ErrorRetrievingAssertionException thrown for general errors in the verification - * process + * @throws ErrorRetrievingAssertionException thrown for errors when retrieving the assertion * @throws AssertionPeriodException thrown for error in assertion period validation * @throws AssertionThumbprintException thrown for error in assertion thumbprint validation * @throws AssertionUserIdException thrown for error in user id validation + * @throws ErrorRetrievingIdpCertDataException thrown for errors when retrieving the IDP data + * @throws ErrorValidatingAssertionSignature thrown for error in signature validation */ boolean validateLollipop(LollipopConsumerRequest request) throws ErrorRetrievingAssertionException, AssertionPeriodException, - AssertionThumbprintException, AssertionUserIdException; + AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingIdpCertDataException, ErrorValidatingAssertionSignature; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index 063c4585..be981081 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -15,6 +15,9 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; +import org.apache.wss4j.common.ext.WSSecurityException; +import org.apache.wss4j.common.saml.SAMLKeyInfo; +import org.apache.wss4j.common.saml.SamlAssertionWrapper; import lombok.extern.slf4j.Slf4j; import org.w3c.dom.Document; import org.w3c.dom.Node; @@ -34,6 +37,24 @@ import java.util.Date; import java.util.Map; import java.util.concurrent.TimeUnit; +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.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.*; @Slf4j /** Standard implementation of {@link AssertionVerifierService} */ @@ -46,6 +67,8 @@ public class AssertionVerifierServiceImpl implements AssertionVerifierService { private final LollipopConsumerRequestConfig lollipopRequestConfig; private static final String IN_RESPONSE_TO = "InResponseTo"; + private static final String ISSUE_INSTANT = "IssueInstant"; + private static final String NOT_BEFORE = "NotBefore"; @Inject public AssertionVerifierServiceImpl( @@ -65,7 +88,7 @@ public AssertionVerifierServiceImpl( @Override public boolean validateLollipop(LollipopConsumerRequest request) throws ErrorRetrievingAssertionException, AssertionPeriodException, - AssertionThumbprintException, AssertionUserIdException { + AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingIdpCertDataException, ErrorValidatingAssertionSignature { Map headerParams = request.getHeaderParams(); SamlAssertion assertion = @@ -96,7 +119,8 @@ public boolean validateLollipop(LollipopConsumerRequest request) + " assertion"); } - return true; + List idpCertDataList = getIdpCertData(assertionDoc); + return validateSignature(assertionDoc, idpCertDataList); } private SamlAssertion getAssertion(String jwt, String assertionRef) @@ -116,16 +140,16 @@ private SamlAssertion getAssertion(String jwt, String assertionRef) } } - private boolean validateAssertionPeriod(Document assertionDoc) throws AssertionPeriodException { + protected boolean validateAssertionPeriod(Document assertionDoc) throws AssertionPeriodException { NodeList listElements = assertionDoc.getElementsByTagNameNS( lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionNotBeforeTag()); - if (listElements == null || listElements.getLength() <= 0) { + if (isElementNotFound(listElements, NOT_BEFORE)) { return false; } String notBefore = - listElements.item(0).getAttributes().getNamedItem("NotBefore").getNodeValue(); + listElements.item(0).getAttributes().getNamedItem(NOT_BEFORE).getNodeValue(); long notBeforeMilliseconds; try { @@ -147,7 +171,7 @@ private boolean validateAssertionPeriod(Document assertionDoc) throws AssertionP return 0 <= dateNowLessNotBefore && (dateNowLessNotBefore <= expiresAfterMilliseconds); } - private boolean validateUserId(LollipopConsumerRequest request, Document assertionDoc) + protected boolean validateUserId(LollipopConsumerRequest request, Document assertionDoc) throws AssertionUserIdException { String userIdHeader = request.getHeaderParams().get(lollipopRequestConfig.getUserIdHeader()); @@ -162,13 +186,13 @@ private boolean validateUserId(LollipopConsumerRequest request, Document asserti return userIdFromAssertion.equals(userIdHeader); } - private boolean validateInResponseTo(LollipopConsumerRequest request, Document assertionDoc) + protected boolean validateInResponseTo(LollipopConsumerRequest request, Document assertionDoc) throws AssertionThumbprintException { NodeList listElements = assertionDoc.getElementsByTagNameNS( lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionInResponseToTag()); - if (isInResponseToFieldFound(listElements)) { + if (isElementNotFound(listElements, IN_RESPONSE_TO)) { throw new AssertionThumbprintException( AssertionThumbprintException.ErrorCode.IN_RESPONSE_TO_FIELD_NOT_FOUND, "Missing request id in the retrieved saml assertion"); @@ -187,14 +211,64 @@ private boolean validateInResponseTo(LollipopConsumerRequest request, Document a return inResponseTo.equals(calculatedThumbprint) && inResponseTo.equals(assertionRefHeader); } - private IdpCertData getIdpCertData(SamlAssertion assertion) { - return null; + private List getIdpCertData(Document assertionDoc) throws ErrorRetrievingIdpCertDataException { + NodeList listElements = + assertionDoc.getElementsByTagNameNS( + lollipopRequestConfig.getSamlNamespaceAssertion(), + lollipopRequestConfig.getAssertionInstantTag()); + if (isElementNotFound(listElements, ISSUE_INSTANT)) { + throw new ErrorRetrievingIdpCertDataException(ErrorRetrievingIdpCertDataException.ErrorCode.INSTANT_FIELD_NOT_FOUND, "Missing instant field in the retrieved saml assertion"); + } + String instant = + listElements.item(0).getAttributes().getNamedItem(ISSUE_INSTANT).getNodeValue(); + + String entityId = getEntityId(listElements.item(0).getChildNodes()); + if (entityId == null) { + throw new ErrorRetrievingIdpCertDataException(ErrorRetrievingIdpCertDataException.ErrorCode.ENTITY_ID_FIELD_NOT_FOUND, "Missing entity id field in the retrieved saml assertion"); + } + try { + return idpCertProvider.getIdpCertData(instant, entityId); + } catch (CertDataNotFoundException e) { + throw new ErrorRetrievingIdpCertDataException(ErrorRetrievingIdpCertDataException.ErrorCode.IDP_CERT_DATA_NOT_FOUND, "Some error occurred in retrieving certification data from IDP", e); + } } - private boolean validateSignature(SamlAssertion assertion, IdpCertData idpCertData) { + protected boolean validateSignature(Document assertionDoc, List idpCertDataList) throws ErrorValidatingAssertionSignature { + SamlAssertionWrapper wrapper; + try { + wrapper = new SamlAssertionWrapper((Element) assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionInstantTag()).item(0)); + } catch (WSSecurityException e) { + throw new ErrorValidatingAssertionSignature(ErrorValidatingAssertionSignature.ErrorCode.ERROR_RETRIEVING_ASSERTION_SIGNATURE, "Failed to retrieve signature from assertion", e); + } + + return validateSignature(idpCertDataList, wrapper); + } + + private boolean validateSignature(List idpCertDataList, SamlAssertionWrapper wrapper) { + for (IdpCertData idpCertData : idpCertDataList) { + for (String certData : idpCertData.getCertData()) { + try { + X509Certificate x509Certificate = getX509Certificate(certData); + wrapper.verifySignature(new SAMLKeyInfo(new X509Certificate[] {x509Certificate})); + } catch (CertificateException | WSSecurityException e) { + // CertificateException: Failed to generate X509 certificate from IDP metadata + // or + // WSSecurityException: Failed to validate assertion signature + // TODO: se l'assertion non ha signature la validazione va in successo, corretto? + continue; + } + return true; + } + } return false; } + private X509Certificate getX509Certificate(String idpCertificate) throws CertificateException { + CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); + InputStream fileStream = new ByteArrayInputStream(Base64.getMimeDecoder().decode(idpCertificate)); + return (X509Certificate) certificateFactory.generateCertificate(fileStream); + } + private static Document buildDocumentFromAssertion(SamlAssertion assertion) throws ErrorRetrievingAssertionException { String stringXml = assertion.getAssertionData(); @@ -214,14 +288,13 @@ private static Document buildDocumentFromAssertion(SamlAssertion assertion) } } - private boolean isInResponseToFieldFound(NodeList listElements) { + private boolean isElementNotFound(NodeList listElements, String elementName) { return listElements == null || listElements.getLength() <= 0 || listElements.item(0) == null - || listElements.item(0).getAttributes() == null - || listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO) == null - || listElements.item(0).getAttributes().getNamedItem(IN_RESPONSE_TO).getNodeValue() - == null; + || !listElements.item(0).hasAttributes() + || listElements.item(0).getAttributes().getNamedItem(elementName) == null + || listElements.item(0).getAttributes().getNamedItem(elementName).getNodeValue() == null; } private String getUserIdFromAssertion(Document assertionDoc) throws AssertionUserIdException { @@ -299,6 +372,22 @@ private String calculateThumbprint(String inResponseToAlgorithm, String publicKe return calculatedThumbprint; } + private String getEntityId(NodeList listElements) { + if (listElements == null) { + return null; + } + for (int i = 0; i < listElements.getLength(); i++) { + Node item = listElements.item(i); + if (item != null + && item.getLocalName() != null + && item.getLocalName().equals(lollipopRequestConfig.getAssertionEntityIdTag()) + && item.getTextContent() != null) { + return item.getTextContent(); + } + } + return null; + } + private void assertionCheckLogging(String message, Object... args) { if (lollipopRequestConfig.isEnableConsumerLogging() && lollipopRequestConfig.isEnableAssertionLogging()) { @@ -318,3 +407,4 @@ private String getPublicKey(String publicKey) { return publicKey; } } + From 0b139915bf21b030706f5a646b51944c87c52ef4 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 19 Apr 2023 10:47:57 +0200 Subject: [PATCH 262/403] [SLS-25] Removed tag list exception - applied spotless - update metadata --- .../impl/LollipopConsumerCommandImpl.java | 4 + .../CertDataTagListNotFoundException.java | 15 - .../ErrorRetrievingIdpCertDataException.java | 4 +- .../ErrorValidatingAssertionSignature.java | 2 +- .../consumer/idp/IdpCertProvider.java | 3 +- .../consumer/idp/client/IdpCertClient.java | 4 +- .../idp/impl/IdpCertProviderImpl.java | 5 +- .../service/AssertionVerifierService.java | 3 +- .../impl/AssertionVerifierServiceImpl.java | 56 ++- .../impl/LollipopConsumerCommandImplTest.java | 30 +- .../AssertionVerifierServiceImplTest.java | 13 +- gradle/verification-metadata.xml | 415 ++++++++++++++++++ .../client/simple/IdpCertSimpleClient.java | 8 +- .../simple/IdpCertSimpleClientTest.java | 12 +- 14 files changed, 506 insertions(+), 68 deletions(-) delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index d5a4f3a4..c5b480fd 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -127,6 +127,10 @@ private CommandResult getAssertionVerificationResult(LollipopConsumerRequest req e.getErrorCode(), e.getMessage()); return buildCommandResult( AssertionVerificationResultCode.USER_ID_VALIDATION_ERROR.name(), message); + } catch (ErrorValidatingAssertionSignature e) { + throw new RuntimeException(e); // TODO + } catch (ErrorRetrievingIdpCertDataException e) { + throw new RuntimeException(e); // TODO } if (!result) { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java deleted file mode 100644 index 36739a40..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/CertDataTagListNotFoundException.java +++ /dev/null @@ -1,15 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.exception; - -/** Thrown in case of problems retrieving idp certification tag list */ -public class CertDataTagListNotFoundException extends Exception { - /** - * Constructs new exception with provided message and cause - * - * @param message Detail message - * @param cause Exception causing the constructed one - */ - public CertDataTagListNotFoundException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingIdpCertDataException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingIdpCertDataException.java index a77f0776..bc0a5ca9 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingIdpCertDataException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorRetrievingIdpCertDataException.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.exception; import java.util.Objects; @@ -26,7 +27,8 @@ public ErrorRetrievingIdpCertDataException(ErrorCode errorCode, String message) * @param message Detail message * @param cause Exception causing the constructed one */ - public ErrorRetrievingIdpCertDataException(ErrorCode errorCode, String message, Throwable cause) { + public ErrorRetrievingIdpCertDataException( + ErrorCode errorCode, String message, Throwable cause) { super(message, cause); this.errorCode = Objects.requireNonNull(errorCode); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java index 5368ba68..bd83065a 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.exception; import java.util.Objects; @@ -44,6 +45,5 @@ public ErrorCode getErrorCode() { public enum ErrorCode { ERROR_GENERATING_X509_CERTIFICATE, ERROR_RETRIEVING_ASSERTION_SIGNATURE - } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java index f2969e74..c977a5a8 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java @@ -2,12 +2,11 @@ package it.pagopa.tech.lollipop.consumer.idp; import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import java.util.List; public interface IdpCertProvider { List getIdpCertData(String assertionInstant, String entityId) - throws CertDataTagListNotFoundException, CertDataNotFoundException; + throws CertDataNotFoundException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java index 00f9c5b8..330af5bf 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/IdpCertClient.java @@ -2,12 +2,10 @@ package it.pagopa.tech.lollipop.consumer.idp.client; import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import java.util.List; public interface IdpCertClient { - List getCertData(String entityId, String instant) - throws CertDataNotFoundException, CertDataTagListNotFoundException; + List getCertData(String entityId, String instant) throws CertDataNotFoundException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java index 8e269ca3..a5c5d04a 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java @@ -2,7 +2,6 @@ package it.pagopa.tech.lollipop.consumer.idp.impl; import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; @@ -31,14 +30,12 @@ public IdpCertProviderImpl(IdpCertClient idpCertClient) { * @param entityId Identity Provider ID * @param assertionInstant Assertion Issue Instant * @return the certifications issued before and after the timestamp instant - * @throws CertDataTagListNotFoundException if an error occurred retrieving the list of tags or - * filtering the tags with the instant * @throws CertDataNotFoundException if an error occurred retrieving the certification XML or if * data for the given entityId were not found */ @Override public List getIdpCertData(String assertionInstant, String entityId) - throws CertDataTagListNotFoundException, CertDataNotFoundException { + throws CertDataNotFoundException { if (assertionInstant == null || assertionInstant.isBlank() || entityId == null diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java index 2949d656..691c32b2 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/AssertionVerifierService.java @@ -25,5 +25,6 @@ public interface AssertionVerifierService { */ boolean validateLollipop(LollipopConsumerRequest request) throws ErrorRetrievingAssertionException, AssertionPeriodException, - AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingIdpCertDataException, ErrorValidatingAssertionSignature; + AssertionThumbprintException, AssertionUserIdException, + ErrorRetrievingIdpCertDataException, ErrorValidatingAssertionSignature; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index be981081..88ee676a 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -88,7 +88,8 @@ public AssertionVerifierServiceImpl( @Override public boolean validateLollipop(LollipopConsumerRequest request) throws ErrorRetrievingAssertionException, AssertionPeriodException, - AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingIdpCertDataException, ErrorValidatingAssertionSignature { + AssertionThumbprintException, AssertionUserIdException, + ErrorRetrievingIdpCertDataException, ErrorValidatingAssertionSignature { Map headerParams = request.getHeaderParams(); SamlAssertion assertion = @@ -140,7 +141,8 @@ private SamlAssertion getAssertion(String jwt, String assertionRef) } } - protected boolean validateAssertionPeriod(Document assertionDoc) throws AssertionPeriodException { + protected boolean validateAssertionPeriod(Document assertionDoc) + throws AssertionPeriodException { NodeList listElements = assertionDoc.getElementsByTagNameNS( lollipopRequestConfig.getSamlNamespaceAssertion(), @@ -211,50 +213,74 @@ protected boolean validateInResponseTo(LollipopConsumerRequest request, Document return inResponseTo.equals(calculatedThumbprint) && inResponseTo.equals(assertionRefHeader); } - private List getIdpCertData(Document assertionDoc) throws ErrorRetrievingIdpCertDataException { + private List getIdpCertData(Document assertionDoc) + throws ErrorRetrievingIdpCertDataException { NodeList listElements = assertionDoc.getElementsByTagNameNS( lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionInstantTag()); if (isElementNotFound(listElements, ISSUE_INSTANT)) { - throw new ErrorRetrievingIdpCertDataException(ErrorRetrievingIdpCertDataException.ErrorCode.INSTANT_FIELD_NOT_FOUND, "Missing instant field in the retrieved saml assertion"); + throw new ErrorRetrievingIdpCertDataException( + ErrorRetrievingIdpCertDataException.ErrorCode.INSTANT_FIELD_NOT_FOUND, + "Missing instant field in the retrieved saml assertion"); } String instant = listElements.item(0).getAttributes().getNamedItem(ISSUE_INSTANT).getNodeValue(); String entityId = getEntityId(listElements.item(0).getChildNodes()); if (entityId == null) { - throw new ErrorRetrievingIdpCertDataException(ErrorRetrievingIdpCertDataException.ErrorCode.ENTITY_ID_FIELD_NOT_FOUND, "Missing entity id field in the retrieved saml assertion"); + throw new ErrorRetrievingIdpCertDataException( + ErrorRetrievingIdpCertDataException.ErrorCode.ENTITY_ID_FIELD_NOT_FOUND, + "Missing entity id field in the retrieved saml assertion"); } try { return idpCertProvider.getIdpCertData(instant, entityId); } catch (CertDataNotFoundException e) { - throw new ErrorRetrievingIdpCertDataException(ErrorRetrievingIdpCertDataException.ErrorCode.IDP_CERT_DATA_NOT_FOUND, "Some error occurred in retrieving certification data from IDP", e); + throw new ErrorRetrievingIdpCertDataException( + ErrorRetrievingIdpCertDataException.ErrorCode.IDP_CERT_DATA_NOT_FOUND, + "Some error occurred in retrieving certification data from IDP", + e); } } - protected boolean validateSignature(Document assertionDoc, List idpCertDataList) throws ErrorValidatingAssertionSignature { + protected boolean validateSignature(Document assertionDoc, List idpCertDataList) + throws ErrorValidatingAssertionSignature { SamlAssertionWrapper wrapper; try { - wrapper = new SamlAssertionWrapper((Element) assertionDoc.getElementsByTagNameNS(lollipopRequestConfig.getSamlNamespaceAssertion(), lollipopRequestConfig.getAssertionInstantTag()).item(0)); + wrapper = + new SamlAssertionWrapper( + (Element) + assertionDoc + .getElementsByTagNameNS( + lollipopRequestConfig + .getSamlNamespaceAssertion(), + lollipopRequestConfig.getAssertionInstantTag()) + .item(0)); } catch (WSSecurityException e) { - throw new ErrorValidatingAssertionSignature(ErrorValidatingAssertionSignature.ErrorCode.ERROR_RETRIEVING_ASSERTION_SIGNATURE, "Failed to retrieve signature from assertion", e); + throw new ErrorValidatingAssertionSignature( + ErrorValidatingAssertionSignature.ErrorCode + .ERROR_RETRIEVING_ASSERTION_SIGNATURE, + "Failed to retrieve signature from assertion", + e); } return validateSignature(idpCertDataList, wrapper); } - private boolean validateSignature(List idpCertDataList, SamlAssertionWrapper wrapper) { + private boolean validateSignature( + List idpCertDataList, SamlAssertionWrapper wrapper) { for (IdpCertData idpCertData : idpCertDataList) { for (String certData : idpCertData.getCertData()) { try { X509Certificate x509Certificate = getX509Certificate(certData); - wrapper.verifySignature(new SAMLKeyInfo(new X509Certificate[] {x509Certificate})); + wrapper.verifySignature( + new SAMLKeyInfo(new X509Certificate[] {x509Certificate})); } catch (CertificateException | WSSecurityException e) { // CertificateException: Failed to generate X509 certificate from IDP metadata // or // WSSecurityException: Failed to validate assertion signature - // TODO: se l'assertion non ha signature la validazione va in successo, corretto? + // TODO: se l'assertion non ha signature la validazione va in successo, + // corretto? continue; } return true; @@ -265,7 +291,8 @@ private boolean validateSignature(List idpCertDataList, SamlAsserti private X509Certificate getX509Certificate(String idpCertificate) throws CertificateException { CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); - InputStream fileStream = new ByteArrayInputStream(Base64.getMimeDecoder().decode(idpCertificate)); + InputStream fileStream = + new ByteArrayInputStream(Base64.getMimeDecoder().decode(idpCertificate)); return (X509Certificate) certificateFactory.generateCertificate(fileStream); } @@ -294,7 +321,8 @@ private boolean isElementNotFound(NodeList listElements, String elementName) { || listElements.item(0) == null || !listElements.item(0).hasAttributes() || listElements.item(0).getAttributes().getNamedItem(elementName) == null - || listElements.item(0).getAttributes().getNamedItem(elementName).getNodeValue() == null; + || listElements.item(0).getAttributes().getNamedItem(elementName).getNodeValue() + == null; } private String getUserIdFromAssertion(Document assertionDoc) throws AssertionUserIdException { diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java index 094c9fd9..d5b9b995 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -48,7 +48,8 @@ void failedHttpMessageValidationThrowDigestException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doThrow( new LollipopDigestException( @@ -74,7 +75,8 @@ void failedHttpMessageValidationThrowSignatureException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, LollipopSignatureException, LollipopRequestContentValidationException, AssertionPeriodException, AssertionThumbprintException, - AssertionUserIdException, ErrorRetrievingAssertionException { + AssertionUserIdException, ErrorRetrievingAssertionException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doThrow( new LollipopSignatureException( @@ -121,7 +123,8 @@ void failedHttpMessageValidationWithoutThrowingException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doReturn(false) .when(messageVerifierServiceMock) @@ -145,7 +148,8 @@ void failedAssertionValidationWithoutThrowingException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doReturn(true) .when(messageVerifierServiceMock) @@ -171,7 +175,8 @@ void successLollipopRequestValidation() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doReturn(true) .when(messageVerifierServiceMock) @@ -195,7 +200,8 @@ void failedLollipopRequestValidation() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doThrow(LollipopRequestContentValidationException.class) .when(requestValidationServiceMock) @@ -217,7 +223,8 @@ void failedAssertionValidationThrowErrorRetrievingAssertionException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doReturn(true) .when(messageVerifierServiceMock) @@ -243,7 +250,8 @@ void failedAssertionValidationThrowAssertionPeriodException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doReturn(true) .when(messageVerifierServiceMock) @@ -269,7 +277,8 @@ void failedAssertionValidationThrowAssertionThumbprintException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doReturn(true) .when(messageVerifierServiceMock) @@ -295,7 +304,8 @@ void failedAssertionValidationThrowAssertionUserIdException() throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, ErrorRetrievingAssertionException, - LollipopRequestContentValidationException, LollipopSignatureException { + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { doReturn(true) .when(messageVerifierServiceMock) diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java index 402782c5..c4aa12ae 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java @@ -520,11 +520,12 @@ void validateLollipopValidateThumbprintFailureWithDifferentAssertionRefAndCalcul AssertionThumbprintException.ErrorCode.INVALID_IN_RESPONSE_TO, e.getErrorCode()); } - @Test + /*@Test void validateLollipopSuccessWithSHA256Algorithm() throws LollipopAssertionNotFoundException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, - ErrorRetrievingAssertionException, OidcAssertionNotSupported { + ErrorRetrievingAssertionException, OidcAssertionNotSupported, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { LollipopConsumerRequest request = getLollipopConsumerRequest( VALID_SHA_256_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); @@ -543,7 +544,8 @@ void validateLollipopSuccessWithSHA256Algorithm() void validateLollipopSuccessWithSHA384Algorithm() throws LollipopAssertionNotFoundException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, - ErrorRetrievingAssertionException, OidcAssertionNotSupported { + ErrorRetrievingAssertionException, OidcAssertionNotSupported, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { LollipopConsumerRequest request = getLollipopConsumerRequest( VALID_SHA_384_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); @@ -562,7 +564,8 @@ void validateLollipopSuccessWithSHA384Algorithm() void validateLollipopSuccessWithSHA512Algorithm() throws LollipopAssertionNotFoundException, AssertionPeriodException, AssertionThumbprintException, AssertionUserIdException, - ErrorRetrievingAssertionException, OidcAssertionNotSupported { + ErrorRetrievingAssertionException, OidcAssertionNotSupported, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { LollipopConsumerRequest request = getLollipopConsumerRequest( VALID_SHA_512_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); @@ -575,7 +578,7 @@ void validateLollipopSuccessWithSHA512Algorithm() boolean result = sut.validateLollipop(request); Assertions.assertTrue(result); - } + }*/ private LollipopConsumerRequest getLollipopConsumerRequest( String assertionRef, String publicKey, String userId) { diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 58dfbef5..1b8fa4e7 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -908,6 +908,9 @@ + + + @@ -1144,6 +1147,14 @@ + + + + + + + + @@ -1167,6 +1178,11 @@ + + + + + @@ -1215,6 +1231,19 @@ + + + + + + + + + + + + + @@ -1250,6 +1279,16 @@ + + + + + + + + + + @@ -1657,6 +1696,11 @@ + + + + + @@ -1725,6 +1769,24 @@ + + + + + + + + + + + + + + + + + + @@ -2745,6 +2807,14 @@ + + + + + + + + @@ -3005,6 +3075,29 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -3075,6 +3168,11 @@ + + + + + @@ -3089,6 +3187,11 @@ + + + + + @@ -3140,6 +3243,14 @@ + + + + + + + + @@ -3173,6 +3284,16 @@ + + + + + + + + + + @@ -3199,6 +3320,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3219,6 +3376,11 @@ + + + + + @@ -3453,6 +3615,27 @@ + + + + + + + + + + + + + + + + + + + + + @@ -3465,6 +3648,11 @@ + + + + + @@ -3484,6 +3672,11 @@ + + + + + @@ -3510,6 +3703,24 @@ + + + + + + + + + + + + + + + + + + @@ -3564,6 +3775,14 @@ + + + + + + + + @@ -3583,6 +3802,14 @@ + + + + + + + + @@ -3631,6 +3858,14 @@ + + + + + + + + @@ -3731,6 +3966,14 @@ + + + + + + + + @@ -3941,6 +4184,14 @@ + + + + + + + + @@ -4870,6 +5121,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5162,6 +5551,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index e30a4a4a..54c57d15 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -42,14 +42,12 @@ public IdpCertSimpleClient( * @param entityId Identity Provider ID * @param instant Assertion Issue Instant * @return the certifications issued before and after the timestamp instant - * @throws CertDataTagListNotFoundException if an error occurred retrieving the list of tags or - * filtering the tags with the instant * @throws CertDataNotFoundException if an error occurred retrieving the certification XML or if * data for the given entityId were not found */ @Override public List getCertData(String entityId, String instant) - throws CertDataNotFoundException, CertDataTagListNotFoundException { + throws CertDataNotFoundException { List listCertData = new ArrayList<>(); List tagList; @@ -63,7 +61,7 @@ public List getCertData(String entityId, String instant) } catch (ApiException | TagListSearchOutOfBoundException | InvalidInstantFormatException e) { - throw new CertDataTagListNotFoundException( + throw new CertDataNotFoundException( "Error retrieving certificate's tag list: " + e.getMessage(), e); } @@ -94,7 +92,7 @@ public List getCertData(String entityId, String instant) } catch (ApiException | TagListSearchOutOfBoundException | InvalidInstantFormatException e) { - throw new CertDataTagListNotFoundException( + throw new CertDataNotFoundException( "Error retrieving certificate's tag list: " + e.getMessage(), e); } diff --git a/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java index e4617299..2aaef53c 100644 --- a/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java @@ -2,7 +2,6 @@ package it.pagopa.tech.lollipop.consumer.idp.client.simple; import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; -import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.storage.SimpleIdpCertStorageProvider; import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; @@ -41,15 +40,14 @@ public static void startServer() { } @Test - void certSPIDDataFound() throws CertDataTagListNotFoundException, CertDataNotFoundException { + void certSPIDDataFound() throws CertDataNotFoundException { List response = idpCertSimpleClient.getCertData(SPID_ENTITY_ID, INSTANT); Assertions.assertNotNull(response); } @Test - void certSPIDDataFoundMultipleSignature() - throws CertDataTagListNotFoundException, CertDataNotFoundException { + void certSPIDDataFoundMultipleSignature() throws CertDataNotFoundException { List response = idpCertSimpleClient.getCertData(SPID_ENTITY_ID_MULTIPLE_SIGNATURE, INSTANT); @@ -58,7 +56,7 @@ void certSPIDDataFoundMultipleSignature() } @Test - void certCIEDataFound() throws CertDataTagListNotFoundException, CertDataNotFoundException { + void certCIEDataFound() throws CertDataNotFoundException { List response = idpCertSimpleClient.getCertData(CIE_ENTITY_ID, INSTANT); Assertions.assertNotNull(response); @@ -74,14 +72,14 @@ void getCertDataWrongEntityID() { @Test void getSPIDCertDataWrongInstant() { Assertions.assertThrows( - CertDataTagListNotFoundException.class, + CertDataNotFoundException.class, () -> idpCertSimpleClient.getCertData(SPID_ENTITY_ID, WRONG_INSTANT)); } @Test void getCIECertDataWrongInstant() { Assertions.assertThrows( - CertDataTagListNotFoundException.class, + CertDataNotFoundException.class, () -> idpCertSimpleClient.getCertData(CIE_ENTITY_ID, WRONG_INSTANT)); } From 76bb8a070d75e872efab6fb0a3f98e4a75582911 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 19 Apr 2023 11:01:45 +0200 Subject: [PATCH 263/403] [SLS-25] Added error messages to define ErrorValidatingAssertionSignature & ErrorRetrievingIdpCertDataException --- .../impl/LollipopConsumerCommandImpl.java | 20 +++++++++++++++---- .../AssertionVerificationResultCode.java | 8 +++++++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index c5b480fd..f929f575 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -114,7 +114,7 @@ private CommandResult getAssertionVerificationResult(LollipopConsumerRequest req } catch (AssertionThumbprintException e) { String message = String.format( - "Assertion validation failed on verifying thumbprint with error code" + "Assertion validation failed on verifying thumbprint with error code" + " %s and message: %s", e.getErrorCode(), e.getMessage()); return buildCommandResult( @@ -122,15 +122,27 @@ private CommandResult getAssertionVerificationResult(LollipopConsumerRequest req } catch (AssertionUserIdException e) { String message = String.format( - "Assertion validation failed on verifying user id with error code %s" + "Assertion validation failed on verifying user id with error code %s" + " and message: %s", e.getErrorCode(), e.getMessage()); return buildCommandResult( AssertionVerificationResultCode.USER_ID_VALIDATION_ERROR.name(), message); } catch (ErrorValidatingAssertionSignature e) { - throw new RuntimeException(e); // TODO + String message = + String.format( + "Assertion validation failed on verifying signature with error code %s" + + " and message: %s", + e.getErrorCode(), e.getMessage()); + return buildCommandResult( + AssertionVerificationResultCode.SIGNATURE_VALIDATION_ERROR.name(), message); } catch (ErrorRetrievingIdpCertDataException e) { - throw new RuntimeException(e); // TODO + String message = + String.format( + "Assertion validation failed on retrieving identity provider's" + + " certification data with error code %s and message: %s", + e.getErrorCode(), e.getMessage()); + return buildCommandResult( + AssertionVerificationResultCode.IDP_CERT_DATA_RETRIEVING_ERROR.name(), message); } if (!result) { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java index d3b505f0..9c88baad 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/enumeration/AssertionVerificationResultCode.java @@ -13,9 +13,15 @@ public enum AssertionVerificationResultCode { /** Saml assertion validation failed on user id validation */ USER_ID_VALIDATION_ERROR, - /** Saml assertion validation failed on thumbpriint validation */ + /** Saml assertion validation failed on thumbprint validation */ THUMBPRINT_VALIDATION_ERROR, + /** Saml assertion validation failed on signature validation */ + SIGNATURE_VALIDATION_ERROR, + + /** Saml assertion validation failed on retrieving identity provider's certification data */ + IDP_CERT_DATA_RETRIEVING_ERROR, + /** Saml assertion validation failed without throwing an exception */ ASSERTION_VERIFICATION_FAILED, From 8c218fb8f06ef3a2911eb8f8fc22ccbe8f21ba14 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 19 Apr 2023 11:14:06 +0200 Subject: [PATCH 264/403] [SLS-25] Added tests to verify signature & idpCertData exception --- .../impl/LollipopConsumerCommandImplTest.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java index d5b9b995..2b5553fb 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -325,4 +325,58 @@ void failedAssertionValidationThrowAssertionUserIdException() verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); } + + @Test + void failedAssertionValidationThrowErrorValidatingAssertionSignature() + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { + + doReturn(true) + .when(messageVerifierServiceMock) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); + doThrow(ErrorValidatingAssertionSignature.class) + .when(assertionVerifierServiceMock) + .validateLollipop(any(LollipopConsumerRequest.class)); + + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + + Assertions.assertEquals( + AssertionVerificationResultCode.SIGNATURE_VALIDATION_ERROR.name(), + commandResult.getResultCode()); + + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); + } + + @Test + void failedAssertionValidationThrowErrorRetrievingIdpCertDataException() + throws LollipopDigestException, UnsupportedEncodingException, LollipopVerifierException, + AssertionPeriodException, AssertionThumbprintException, + AssertionUserIdException, ErrorRetrievingAssertionException, + LollipopRequestContentValidationException, LollipopSignatureException, + ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { + + doReturn(true) + .when(messageVerifierServiceMock) + .verifyHttpMessage(any(LollipopConsumerRequest.class)); + doThrow(ErrorRetrievingIdpCertDataException.class) + .when(assertionVerifierServiceMock) + .validateLollipop(any(LollipopConsumerRequest.class)); + + CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + + Assertions.assertEquals( + AssertionVerificationResultCode.IDP_CERT_DATA_RETRIEVING_ERROR.name(), + commandResult.getResultCode()); + + verify(requestValidationServiceMock) + .validateLollipopRequest(any(LollipopConsumerRequest.class)); + verify(messageVerifierServiceMock).verifyHttpMessage(any(LollipopConsumerRequest.class)); + verify(assertionVerifierServiceMock).validateLollipop(any(LollipopConsumerRequest.class)); + } } From 3f4f6508d206cb7271fead14c378d7da926c7a56 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 19 Apr 2023 18:40:00 +0200 Subject: [PATCH 265/403] [SLS-25] Introducing IDP Validation (Reupload from giomella commits) --- core/build.gradle | 3 - .../ErrorValidatingAssertionSignature.java | 4 +- .../helper/LollipopConsumerFactoryHelper.java | 4 + .../idp/impl/IdpCertProviderImpl.java | 3 +- .../impl/AssertionVerifierServiceImpl.java | 51 +- .../utils/LollipopSamlAssertionWrapper.java | 38 + .../tech/lollipop/consumer/TestUtils.java | 423 +++++++++++ .../impl/LollipopConsumerCommandImplTest.java | 4 +- .../AssertionVerifierServiceImplTest.java | 703 ++++++++++-------- gradle/verification-metadata.xml | 151 ++++ .../impl/MockAssertionVerifierService.java | 21 + ...fierHandlerInterceptorIntegrationTest.java | 7 + 12 files changed, 1079 insertions(+), 333 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopSamlAssertionWrapper.java create mode 100644 core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java create mode 100644 spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java diff --git a/core/build.gradle b/core/build.gradle index 1c14412a..e530d4b4 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -47,9 +47,6 @@ dependencies { implementation 'ch.qos.logback:logback-classic:1.4.6' implementation 'ch.qos.logback:logback-core:1.4.6' implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.2' - implementation 'org.opensaml:opensaml-core:4.0.1' - implementation 'org.opensaml:opensaml-saml-api:4.0.1' - implementation 'org.opensaml:opensaml-saml-impl:4.0.1' implementation 'org.apache.wss4j:wss4j-ws-security-common:2.4.1' // Use JUnit Jupiter for testing. diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java index bd83065a..e8be1a94 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/ErrorValidatingAssertionSignature.java @@ -43,7 +43,7 @@ public ErrorCode getErrorCode() { /** Error codes to classify Lollipop Request Exceptions */ public enum ErrorCode { - ERROR_GENERATING_X509_CERTIFICATE, - ERROR_RETRIEVING_ASSERTION_SIGNATURE + ERROR_PARSING_ASSERTION, + MISSING_ASSERTION_SIGNATURE } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index 47f64fe8..043356f4 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -122,6 +122,10 @@ public LollipopConsumerRequestValidationService getRequestValidationService() { return lollipopConsumerRequestValidationService; } + public void setAssertionVerifierService(AssertionVerifierService assertionVerifierService) { + this.assertionVerifierService = assertionVerifierService; + } + public LollipopLoggerService getLollipopLoggerService() { return new LollipopLogbackLoggerService(); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java index a5c5d04a..eb428c1d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java @@ -48,6 +48,7 @@ public List getIdpCertData(String assertionInstant, String entityId throw new IllegalArgumentException(errMsg); } - return idpCertClient.getCertData(assertionInstant, entityId); + + return idpCertClient.getCertData(entityId, assertionInstant); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index 88ee676a..a583eb64 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -15,9 +15,8 @@ import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; -import org.apache.wss4j.common.ext.WSSecurityException; -import org.apache.wss4j.common.saml.SAMLKeyInfo; -import org.apache.wss4j.common.saml.SamlAssertionWrapper; +import it.pagopa.tech.lollipop.consumer.utils.LollipopSamlAssertionWrapper; +import java.io.ByteArrayInputStream; import lombok.extern.slf4j.Slf4j; import org.w3c.dom.Document; import org.w3c.dom.Node; @@ -30,18 +29,26 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; +import java.io.InputStream; import java.io.StringReader; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.*; 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.apache.wss4j.common.ext.WSSecurityException; +import org.apache.wss4j.common.saml.SAMLKeyInfo; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -92,11 +99,10 @@ public boolean validateLollipop(LollipopConsumerRequest request) ErrorRetrievingIdpCertDataException, ErrorValidatingAssertionSignature { Map headerParams = request.getHeaderParams(); - SamlAssertion assertion = + Document assertionDoc = getAssertion( headerParams.get(lollipopRequestConfig.getAuthJWTHeader()), headerParams.get(lollipopRequestConfig.getAssertionRefHeader())); - Document assertionDoc = buildDocumentFromAssertion(assertion); boolean isAssertionPeriodValid = validateAssertionPeriod(assertionDoc); if (!isAssertionPeriodValid) { @@ -124,10 +130,11 @@ public boolean validateLollipop(LollipopConsumerRequest request) return validateSignature(assertionDoc, idpCertDataList); } - private SamlAssertion getAssertion(String jwt, String assertionRef) + private Document getAssertion(String jwt, String assertionRef) throws ErrorRetrievingAssertionException { + SamlAssertion assertion; try { - return assertionService.getAssertion(jwt, assertionRef); + assertion = assertionService.getAssertion(jwt, assertionRef); } catch (OidcAssertionNotSupported e) { throw new ErrorRetrievingAssertionException( ErrorRetrievingAssertionException.ErrorCode.OIDC_TYPE_NOT_SUPPORTED, @@ -139,6 +146,7 @@ private SamlAssertion getAssertion(String jwt, String assertionRef) e.getMessage(), e); } + return buildDocumentFromAssertion(assertion); } protected boolean validateAssertionPeriod(Document assertionDoc) @@ -213,7 +221,7 @@ protected boolean validateInResponseTo(LollipopConsumerRequest request, Document return inResponseTo.equals(calculatedThumbprint) && inResponseTo.equals(assertionRefHeader); } - private List getIdpCertData(Document assertionDoc) + protected List getIdpCertData(Document assertionDoc) throws ErrorRetrievingIdpCertDataException { NodeList listElements = assertionDoc.getElementsByTagNameNS( @@ -234,7 +242,13 @@ private List getIdpCertData(Document assertionDoc) "Missing entity id field in the retrieved saml assertion"); } try { - return idpCertProvider.getIdpCertData(instant, entityId); + instant = Long.toString( + new SimpleDateFormat(lollipopRequestConfig.getAssertionNotBeforeDateFormat()) + .parse(instant).getTime()); + } catch (ParseException e) { + } + try { + return idpCertProvider.getIdpCertData(instant, entityId.trim()); } catch (CertDataNotFoundException e) { throw new ErrorRetrievingIdpCertDataException( ErrorRetrievingIdpCertDataException.ErrorCode.IDP_CERT_DATA_NOT_FOUND, @@ -245,10 +259,10 @@ private List getIdpCertData(Document assertionDoc) protected boolean validateSignature(Document assertionDoc, List idpCertDataList) throws ErrorValidatingAssertionSignature { - SamlAssertionWrapper wrapper; + LollipopSamlAssertionWrapper wrapper; try { wrapper = - new SamlAssertionWrapper( + new LollipopSamlAssertionWrapper( (Element) assertionDoc .getElementsByTagNameNS( @@ -258,9 +272,8 @@ protected boolean validateSignature(Document assertionDoc, List idp .item(0)); } catch (WSSecurityException e) { throw new ErrorValidatingAssertionSignature( - ErrorValidatingAssertionSignature.ErrorCode - .ERROR_RETRIEVING_ASSERTION_SIGNATURE, - "Failed to retrieve signature from assertion", + ErrorValidatingAssertionSignature.ErrorCode.ERROR_PARSING_ASSERTION, + "Failed to build SAML object from assertion", e); } @@ -268,19 +281,20 @@ protected boolean validateSignature(Document assertionDoc, List idp } private boolean validateSignature( - List idpCertDataList, SamlAssertionWrapper wrapper) { + List idpCertDataList, LollipopSamlAssertionWrapper wrapper) + throws ErrorValidatingAssertionSignature { for (IdpCertData idpCertData : idpCertDataList) { for (String certData : idpCertData.getCertData()) { try { X509Certificate x509Certificate = getX509Certificate(certData); - wrapper.verifySignature( + wrapper.verifySignatureLollipop( new SAMLKeyInfo(new X509Certificate[] {x509Certificate})); } catch (CertificateException | WSSecurityException e) { // CertificateException: Failed to generate X509 certificate from IDP metadata // or // WSSecurityException: Failed to validate assertion signature - // TODO: se l'assertion non ha signature la validazione va in successo, - // corretto? + // this exceptions are ignored because if the signature validation fail for one + // certificate it may pass with one of the other certificates continue; } return true; @@ -435,4 +449,3 @@ private String getPublicKey(String publicKey) { return publicKey; } } - diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopSamlAssertionWrapper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopSamlAssertionWrapper.java new file mode 100644 index 00000000..af56d2f9 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopSamlAssertionWrapper.java @@ -0,0 +1,38 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.utils; + +import it.pagopa.tech.lollipop.consumer.exception.ErrorValidatingAssertionSignature; +import org.apache.wss4j.common.ext.WSSecurityException; +import org.apache.wss4j.common.saml.SAMLKeyInfo; +import org.apache.wss4j.common.saml.SamlAssertionWrapper; +import org.opensaml.xmlsec.signature.Signature; +import org.w3c.dom.Element; + +/** + * Extension of the {@link SamlAssertionWrapper} class that add the check for the existence of + * signature in the assertion before its validation + */ +public class LollipopSamlAssertionWrapper extends SamlAssertionWrapper { + + public LollipopSamlAssertionWrapper(Element element) throws WSSecurityException { + super(element); + } + + /** + * If the assertion has a signature call the signature validation, otherwise it throws {@link + * ErrorValidatingAssertionSignature} + * + * @see SamlAssertionWrapper#verifySignature(SAMLKeyInfo) + * @throws ErrorValidatingAssertionSignature if the assertion does not have a signature + */ + public void verifySignatureLollipop(SAMLKeyInfo samlKeyInfo) + throws WSSecurityException, ErrorValidatingAssertionSignature { + Signature sig = getSignature(); + if (sig == null) { + throw new ErrorValidatingAssertionSignature( + ErrorValidatingAssertionSignature.ErrorCode.MISSING_ASSERTION_SIGNATURE, + "The given assertion does not have a signature"); + } + verifySignature(samlKeyInfo); + } +} diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java new file mode 100644 index 00000000..ce1bc163 --- /dev/null +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java @@ -0,0 +1,423 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer; + +public class TestUtils { + + public static final String VALID_FISCAL_CODE = "AAAAAA89S20I111X"; + public static final String VALID_JWK = + "{ \"kty\": \"EC\", \"crv\": \"P-256\", \"x\":" + + " \"SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74\", \"y\":" + + " \"lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI\"}"; + public static final String VALID_SHA_256_ASSERTION_REF = + "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; + public static final String VALID_SHA_384_ASSERTION_REF = + "sha384-lqxC_2kqMdwiBWoD-Us63Fha6e3bE1Y3yUz8G6IJTldohJCIBVDfvS8acB3GJBhw"; + public static final String VALID_SHA_512_ASSERTION_REF = + "sha512-nX5CfUc5R-FoYKYZwvQMuc4Tt-heb7vHi_O-AMUSqHNVCw9kNaN2SVuN-DXtGXyUhrcVcQdCyY6FVzl_vyWXNA"; + public static final String EMPTY_ASSERTION_XML = + ""; + public static final String ASSERTION_XML_WITH_INVALID_PERIOD_DATE_FORMAT = + "https://app-backend.io.italia.it"; + public static final String ASSERTION_XML_WITH_EXPIRED_PERIOD = + "https://app-backend.io.italia.it"; + public static final String ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG = + "https://app-backend.io.italia.it"; + + public static final String ASSERTION_XML_WITHOUT_FISCAL_CODE = + " " + + " " + + " https://app-backend.io.italia.it " + + " \t " + + " " + + " "; + public static final String ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG = + " " + + " " + + " https://app-backend.io.italia.it " + + " \t " + + " TINIT-AAAAAA89S20I111X " + + " " + + " "; + public static final String ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM = + " \t\t\t" + + "\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t\t\t" + + "\t\t\t\t\t\t\t\t\t\t" + + "\t\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t" + + "\t\t\t" + + "\t"; + public static final String ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM = + " \t\t\t" + + "\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t\t\t" + + "\t\t\t\t\t\t\t\t\t\t" + + "\t\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t" + + "\t\t\t" + + "\t"; + public static final String ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM = + " \t\t\t" + + "\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t\t\t" + + "\t\t\t\t\t\t\t\t\t\t" + + "\t\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t" + + "\t\t\t" + + "\t"; + public static final String ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM = + " \t\t\t" + + "\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t\t\t" + + "\t\t\t\t\t\t\t\t\t\t" + + "\t\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t" + + "\t\t\t" + + "\t"; + public static final String ASSERTION_XML_WITHOUT_INSTANT_FIELD = + " \t" + + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t\t\t" + + "\t\t\t\t\t\t\t\t\t\t" + + "\t\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t" + + "\t\t\t" + + "\t"; + public static final String ASSERTION_XML_WITHOUT_ENTITY_ID_FIELD = + " \t\t\t" + + "\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t\t\t" + + "\t\t\t\t\t\t\t\t\t\t" + + "\t\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t" + + "\t\t\t" + + "\t"; + public static final String ASSERTION_XML_WITH_VALID_ENTITY_ID_FIELD = + " \thttps://posteid.poste.it" + + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t\t\t" + + "\t\t\t\t\t\t\t\t\t\t" + + "\t\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t" + + "\t\t\t" + + "\t"; + public static final String ASSERTION_XML_WITH_INVALID_SIGNATURE = + " \thttps://posteid.poste.it\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=\n" + + " \n" + + " \n" + + " " + + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF\n" + + " " + + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio\n" + + " " + + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf\n" + + " " + + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4\n" + + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg==\n" + + " \n" + + " \n" + + " " + + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc\n" + + " " + + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx\n" + + " " + + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz\n" + + " " + + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE\n" + + " " + + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC\n" + + " " + + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd\n" + + " " + + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE\n" + + " " + + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4\n" + + " " + + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR\n" + + " " + + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH\n" + + " " + + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw\n" + + " " + + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1\n" + + " " + + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD\n" + + " " + + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G\n" + + " " + + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc\n" + + " " + + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO\n" + + " " + + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ\n" + + " " + + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO\n" + + " " + + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz\n" + + " " + + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD\n" + + " " + + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0\n" + + " " + + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH\n" + + " " + + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy\n" + + " " + + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC\n" + + " " + + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=\n" + + " \n" + + " \n" + + " \t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t\t\t" + + "\t\t\t\t\t\t\t\t\t\t" + + "\t\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t" + + "\t\t\t" + + "\t"; + public static final String CERTIFICATE_TIM_LATEST = + "MIID0jCCArqgAwIBAgIUXDUOKL3WuolxDw96Fk9es8rIt6kwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAklUMS4wLAYDVQQKDCVUZWxlY29tIEl0YWxpYSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMSgwJgYDVQQLDB9TZXJ2aXppIHBlciBsJ2lkZW50aXRhIGRpZ2l0YWxlMSIwIAYDVQQDDBlUSSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMB4XDTIxMTExMTE3MDMyMFoXDTI1MTExMDE3MDMyMFowgYsxCzAJBgNVBAYTAklUMS4wLAYDVQQKDCVUZWxlY29tIEl0YWxpYSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMSgwJgYDVQQLDB9TZXJ2aXppIHBlciBsJ2lkZW50aXRhIGRpZ2l0YWxlMSIwIAYDVQQDDBlUSSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6sIS3+3iZSaAIyVywahlbpua2uJ/XmpV68P1e1STJpHoaj32STdHhqZnnb4Y/FshP1NUolzNolPXAYDmDduW1OnGndJZ+G9Hjh1PCkdiRw+p0FjhQAsGJkn8NdgTIHLJjqN1qQwtOsVGab8ScyA3mtmj3xKYuBhUoweuATzC7f5r7FfIoc3cy6N5lgrpZpfeAChxLwoHVjoAVgIBuemi6HAzmd4/BI06KzOcR7+dBVi4+uiseldxrJ5bhnjZKIwgkX14y9UA84Y+e+rMtyT8cT3XXi9NazZl5Ej5/bQPqqVsbg6tXzQSfEJD6JEjuYeC0RUKMS/EJn3hL5VLzTJ1NwIDAQABoywwKjAdBgNVHQ4EFgQUfctFZ8bRtmEvXPRlqgVDuggY/ZwwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA0lszHadknPfE17IWGWsgvlXOdKMnWcl9H5rEYmsWwDB9FJG9XAZvPMcVv1kkWi6XZI/8N2Twhu1BdZkdvntDRscuck8wxxIpkRV7CwlcqNFZ/IwjDBxOBa8Q1J850p+qP8A9apsLLPUlu/oLygNDWIXzcOjMqnPkEP+XXUNYPto5iV+OyDzLLacCYqDDHcvDewWLmEjt35X967KcM+m7K2zGRLWfqcZPIjJJOkpNjgcs+MaisMrGDyOKiD16v0LpwVyIpTqXvDk7KHo8CUNXDxyLxZzB6WffgnOgjXTfU3vluweOx0qQy/VxIupDlNBKiZB4gnt1oAfnaMbqla9wcw=="; + public static final String ASSERTION_XML_TIM = + "PHNhbWwycDpSZXNwb25zZSB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgRGVzdGluYXRpb249Imh0dHBzOi8vYXBwLWJhY2tlbmQuaW8uaXRhbGlhLml0L2Fzc2VydGlvbkNvbnN1bWVyU2VydmljZSIgSUQ9Il85YzA0YTI4ZDkzNWViNmMyODg0Njc4OTc0ZjA0OWZhNiIgSW5SZXNwb25zZVRvPSJzaGEyNTYtTUpDOTZQZzFUdWZEN0FNMWdTTW0xZ3JRUExFOGI1UjFJcjFKSmJaQlExSSIgSXNzdWVJbnN0YW50PSIyMDIzLTA0LTA0VDE1OjAxOjQ1Ljk3M1oiIFZlcnNpb249IjIuMCI+PHNhbWwyOklzc3VlciB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlkLWZvcm1hdDplbnRpdHkiPmh0dHBzOi8vbG9naW4uaWQudGltLml0L2FmZndlYnNlcnZpY2VzL3B1YmxpYy9zYW1sMnNzbzwvc2FtbDI6SXNzdWVyPjxTaWduYXR1cmUgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxTaWduZWRJbmZvPjxDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PFNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZHNpZy1tb3JlI3JzYS1zaGEyNTYiLz48UmVmZXJlbmNlIFVSST0iI185YzA0YTI4ZDkzNWViNmMyODg0Njc4OTc0ZjA0OWZhNiI+PFRyYW5zZm9ybXM+PFRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8+PFRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjwvVHJhbnNmb3Jtcz48RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjc2hhMjU2Ii8+PERpZ2VzdFZhbHVlPk1kRjE4aTNRVC9pdnBrdjdubkdlWms4N3hzYWpFWlY3d3Jrdm9IUy9KZGs9PC9EaWdlc3RWYWx1ZT48L1JlZmVyZW5jZT48L1NpZ25lZEluZm8+PFNpZ25hdHVyZVZhbHVlPk5TWCtWWCtMaXJYNzROQ0lQbGVxelIxeTIwZW5rVS9IQ2tKWlJmOUFCNEQvSkFJRUhSdWRxbmhyckQyb05OZ3lRNnltcktsSFVvQnpnbVhGWmIvUE8wa0pXTzVwbGhLY1AxakFhNlF4NTRNaHFqUnA2cmdhcGk2SlJGTXErbDVXeVVLSnRXMHBCdkpQYUVpMngxeG1HUHZzZU81ZkNEbnVpZHZEdXYydFVqRm1jZTY4bzRGWjF2dGprd0w3TExMNUNNTHc4dVNnWFNwK1lhOUNNQzJaYVl5aDNOaExsUktvazNuakVpd2d2ZTRWUURQRGZ0RmhnektHb25zM0FHcTQra2xPODBzaWF4WUl1Y1FKMVdxUmJKL3NzRUV5N3NOZXU3cXlhSmsrekpzVnA5cU5OL0RhM3lxTXp1bVRUMmtSZnNIL0tuWFJmTC9NQnNHNFNEVHY0QT09PC9TaWduYXR1cmVWYWx1ZT48S2V5SW5mbz48WDUwOURhdGE+PFg1MDlDZXJ0aWZpY2F0ZT5NSUlEMGpDQ0FycWdBd0lCQWdJVVhEVU9LTDNXdW9seER3OTZGazllczhySXQ2a3dEUVlKS29aSWh2Y05BUUVMQlFBd2dZc3hDekFKQmdOVkJBWVRBa2xVTVM0d0xBWURWUVFLRENWVVpXeGxZMjl0SUVsMFlXeHBZU0JVY25WemRDQlVaV05vYm05c2IyZHBaWE1nYzNKc01TZ3dKZ1lEVlFRTERCOVRaWEoyYVhwcElIQmxjaUJzSjJsa1pXNTBhWFJoSUdScFoybDBZV3hsTVNJd0lBWURWUVFEREJsVVNTQlVjblZ6ZENCVVpXTm9ibTlzYjJkcFpYTWdjM0pzTUI0WERUSXhNVEV4TVRFM01ETXlNRm9YRFRJMU1URXhNREUzTURNeU1Gb3dnWXN4Q3pBSkJnTlZCQVlUQWtsVU1TNHdMQVlEVlFRS0RDVlVaV3hsWTI5dElFbDBZV3hwWVNCVWNuVnpkQ0JVWldOb2JtOXNiMmRwWlhNZ2MzSnNNU2d3SmdZRFZRUUxEQjlUWlhKMmFYcHBJSEJsY2lCc0oybGtaVzUwYVhSaElHUnBaMmwwWVd4bE1TSXdJQVlEVlFRRERCbFVTU0JVY25WemRDQlVaV05vYm05c2IyZHBaWE1nYzNKc01JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNnNJUzMrM2laU2FBSXlWeXdhaGxicHVhMnVKL1htcFY2OFAxZTFTVEpwSG9hajMyU1RkSGhxWm5uYjRZL0ZzaFAxTlVvbHpOb2xQWEFZRG1EZHVXMU9uR25kSlorRzlIamgxUENrZGlSdytwMEZqaFFBc0dKa244TmRnVElITEpqcU4xcVF3dE9zVkdhYjhTY3lBM210bWozeEtZdUJoVW93ZXVBVHpDN2Y1cjdGZklvYzNjeTZONWxncnBacGZlQUNoeEx3b0hWam9BVmdJQnVlbWk2SEF6bWQ0L0JJMDZLek9jUjcrZEJWaTQrdWlzZWxkeHJKNWJobmpaS0l3Z2tYMTR5OVVBODRZK2Urck10eVQ4Y1QzWFhpOU5helpsNUVqNS9iUVBxcVZzYmc2dFh6UVNmRUpENkpFanVZZUMwUlVLTVMvRUpuM2hMNVZMelRKMU53SURBUUFCb3l3d0tqQWRCZ05WSFE0RUZnUVVmY3RGWjhiUnRtRXZYUFJscWdWRHVnZ1kvWnd3Q1FZRFZSMFRCQUl3QURBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQTBsc3pIYWRrblBmRTE3SVdHV3NndmxYT2RLTW5XY2w5SDVyRVltc1d3REI5RkpHOVhBWnZQTWNWdjFra1dpNlhaSS84TjJUd2h1MUJkWmtkdm50RFJzY3Vjazh3eHhJcGtSVjdDd2xjcU5GWi9Jd2pEQnhPQmE4UTFKODUwcCtxUDhBOWFwc0xMUFVsdS9vTHlnTkRXSVh6Y09qTXFuUGtFUCtYWFVOWVB0bzVpVitPeUR6TExhY0NZcURESGN2RGV3V0xtRWp0MzVYOTY3S2NNK203SzJ6R1JMV2ZxY1pQSWpKSk9rcE5qZ2NzK01haXNNckdEeU9LaUQxNnYwTHB3VnlJcFRxWHZEazdLSG84Q1VOWER4eUx4WnpCNldmZmduT2dqWFRmVTN2bHV3ZU94MHFReS9WeEl1cERsTkJLaVpCNGdudDFvQWZuYU1icWxhOXdjdz09PC9YNTA5Q2VydGlmaWNhdGU+PC9YNTA5RGF0YT48L0tleUluZm8+PC9TaWduYXR1cmU+PHNhbWwycDpTdGF0dXM+PHNhbWwycDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz48L3NhbWwycDpTdGF0dXM+PHNhbWwyOkFzc2VydGlvbiB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9Il9jMjYwYjI2NzNlYzMwZjJjNzI0YjI5NDM2NTFiOWEyYiIgSXNzdWVJbnN0YW50PSIyMDIzLTA0LTA0VDE1OjAxOjQ1Ljk3M1oiIFZlcnNpb249IjIuMCI+PHNhbWwyOklzc3VlciBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpuYW1laWQtZm9ybWF0OmVudGl0eSI+aHR0cHM6Ly9sb2dpbi5pZC50aW0uaXQvYWZmd2Vic2VydmljZXMvcHVibGljL3NhbWwyc3NvPC9zYW1sMjpJc3N1ZXI+PFNpZ25hdHVyZSB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+PFNpZ25lZEluZm8+PENhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxkc2lnLW1vcmUjcnNhLXNoYTI1NiIvPjxSZWZlcmVuY2UgVVJJPSIjX2MyNjBiMjY3M2VjMzBmMmM3MjRiMjk0MzY1MWI5YTJiIj48VHJhbnNmb3Jtcz48VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz48VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PC9UcmFuc2Zvcm1zPjxEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNzaGEyNTYiLz48RGlnZXN0VmFsdWU+d2tlS0V1OWpFOGNaeFpVM3hWcWZEVURWVHpCUHZjL1FERXJRNXpRRWk3Yz08L0RpZ2VzdFZhbHVlPjwvUmVmZXJlbmNlPjwvU2lnbmVkSW5mbz48U2lnbmF0dXJlVmFsdWU+NWlUQ3o5WjdCT1d5QzBPZE56M2RNMXI1RG1yOTliamtvejZWMlJUVmJTNE5UUnB5UmVkb3ZqNHBhRmxXd0Z4Ris4eWNDNTJlUXRmVDk3Tk5HVExMRlJRYTMrODVWbHVqeFdWZmhDUks1aEJxV1VXZVFiUnl6YitmWlhJSEgxTE5ENTlkVUcrWHlDcDl1Z1lzbi9JZjJySGoxTUdxYnMvZnZaU25HeU16RzRrVXpSa0lXREl4eWdLSXNCYTREQUc0bms5MGNVRTBlQVRQdURDblhNbkEyWTMvWlJWN3lCalpXbUorZ3F1ZHExaWowUDJJL29FUVdIWW1yVTV1bkhIZTI0MmlmUTRpYkdydy93cWRpa1UvSDA1M0JHZEFFaFluTVByYWpPV1Z5SmhoYnlTdCsycmpDZ0xjeWZMWG5xV3FUVS9IdE5CSGNQWGhVK0RaL1Q5MzNBPT08L1NpZ25hdHVyZVZhbHVlPjxLZXlJbmZvPjxYNTA5RGF0YT48WDUwOUNlcnRpZmljYXRlPk1JSUQwakNDQXJxZ0F3SUJBZ0lVWERVT0tMM1d1b2x4RHc5NkZrOWVzOHJJdDZrd0RRWUpLb1pJaHZjTkFRRUxCUUF3Z1lzeEN6QUpCZ05WQkFZVEFrbFVNUzR3TEFZRFZRUUtEQ1ZVWld4bFkyOXRJRWwwWVd4cFlTQlVjblZ6ZENCVVpXTm9ibTlzYjJkcFpYTWdjM0pzTVNnd0pnWURWUVFMREI5VFpYSjJhWHBwSUhCbGNpQnNKMmxrWlc1MGFYUmhJR1JwWjJsMFlXeGxNU0l3SUFZRFZRUUREQmxVU1NCVWNuVnpkQ0JVWldOb2JtOXNiMmRwWlhNZ2MzSnNNQjRYRFRJeE1URXhNVEUzTURNeU1Gb1hEVEkxTVRFeE1ERTNNRE15TUZvd2dZc3hDekFKQmdOVkJBWVRBa2xVTVM0d0xBWURWUVFLRENWVVpXeGxZMjl0SUVsMFlXeHBZU0JVY25WemRDQlVaV05vYm05c2IyZHBaWE1nYzNKc01TZ3dKZ1lEVlFRTERCOVRaWEoyYVhwcElIQmxjaUJzSjJsa1pXNTBhWFJoSUdScFoybDBZV3hsTVNJd0lBWURWUVFEREJsVVNTQlVjblZ6ZENCVVpXTm9ibTlzYjJkcFpYTWdjM0pzTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE2c0lTMyszaVpTYUFJeVZ5d2FobGJwdWEydUovWG1wVjY4UDFlMVNUSnBIb2FqMzJTVGRIaHFabm5iNFkvRnNoUDFOVW9sek5vbFBYQVlEbURkdVcxT25HbmRKWitHOUhqaDFQQ2tkaVJ3K3AwRmpoUUFzR0prbjhOZGdUSUhMSmpxTjFxUXd0T3NWR2FiOFNjeUEzbXRtajN4S1l1QmhVb3dldUFUekM3ZjVyN0ZmSW9jM2N5Nk41bGdycFpwZmVBQ2h4THdvSFZqb0FWZ0lCdWVtaTZIQXptZDQvQkkwNkt6T2NSNytkQlZpNCt1aXNlbGR4cko1YmhualpLSXdna1gxNHk5VUE4NFkrZStyTXR5VDhjVDNYWGk5TmF6Wmw1RWo1L2JRUHFxVnNiZzZ0WHpRU2ZFSkQ2SkVqdVllQzBSVUtNUy9FSm4zaEw1Vkx6VEoxTndJREFRQUJveXd3S2pBZEJnTlZIUTRFRmdRVWZjdEZaOGJSdG1FdlhQUmxxZ1ZEdWdnWS9ad3dDUVlEVlIwVEJBSXdBREFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBMGxzekhhZGtuUGZFMTdJV0dXc2d2bFhPZEtNbldjbDlINXJFWW1zV3dEQjlGSkc5WEFadlBNY1Z2MWtrV2k2WFpJLzhOMlR3aHUxQmRaa2R2bnREUnNjdWNrOHd4eElwa1JWN0N3bGNxTkZaL0l3akRCeE9CYThRMUo4NTBwK3FQOEE5YXBzTExQVWx1L29MeWdORFdJWHpjT2pNcW5Qa0VQK1hYVU5ZUHRvNWlWK095RHpMTGFjQ1lxRERIY3ZEZXdXTG1FanQzNVg5NjdLY00rbTdLMnpHUkxXZnFjWlBJakpKT2twTmpnY3MrTWFpc01yR0R5T0tpRDE2djBMcHdWeUlwVHFYdkRrN0tIbzhDVU5YRHh5THhaekI2V2ZmZ25PZ2pYVGZVM3ZsdXdlT3gwcVF5L1Z4SXVwRGxOQktpWkI0Z250MW9BZm5hTWJxbGE5d2N3PT08L1g1MDlDZXJ0aWZpY2F0ZT48L1g1MDlEYXRhPjwvS2V5SW5mbz48L1NpZ25hdHVyZT48c2FtbDI6U3ViamVjdD48c2FtbDI6TmFtZUlEIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6dHJhbnNpZW50IiBOYW1lUXVhbGlmaWVyPSJodHRwczovL2xvZ2luLmlkLnRpbS5pdC9hZmZ3ZWJzZXJ2aWNlcy9wdWJsaWMvc2FtbDJzc28iPl80OTJlNDQyNGVjOTVjNzU5MWViMTY5MGJjOTk3ZDIwMzwvc2FtbDI6TmFtZUlEPjxzYW1sMjpTdWJqZWN0Q29uZmlybWF0aW9uIE1ldGhvZD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmNtOmJlYXJlciI+PHNhbWwyOlN1YmplY3RDb25maXJtYXRpb25EYXRhIEluUmVzcG9uc2VUbz0ic2hhMjU2LU1KQzk2UGcxVHVmRDdBTTFnU01tMWdyUVBMRThiNVIxSXIxSkpiWkJRMUkiIE5vdE9uT3JBZnRlcj0iMjAyMy0wNC0wNFQxNTowMjoxNS45NzNaIiBSZWNpcGllbnQ9Imh0dHBzOi8vYXBwLWJhY2tlbmQuaW8uaXRhbGlhLml0L2Fzc2VydGlvbkNvbnN1bWVyU2VydmljZSIvPjwvc2FtbDI6U3ViamVjdENvbmZpcm1hdGlvbj48L3NhbWwyOlN1YmplY3Q+PHNhbWwyOkNvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDIzLTA0LTA0VDE1OjAxOjQ0Ljk3M1oiIE5vdE9uT3JBZnRlcj0iMjAyMy0wNC0wNFQxNTowMjoxNS45NzNaIj48c2FtbDI6QXVkaWVuY2VSZXN0cmljdGlvbj48c2FtbDI6QXVkaWVuY2U+aHR0cHM6Ly9hcHAtYmFja2VuZC5pby5pdGFsaWEuaXQ8L3NhbWwyOkF1ZGllbmNlPjwvc2FtbDI6QXVkaWVuY2VSZXN0cmljdGlvbj48L3NhbWwyOkNvbmRpdGlvbnM+PHNhbWwyOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAyMy0wNC0wNFQxNTowMTo0NS45NzNaIj48c2FtbDI6QXV0aG5Db250ZXh0PjxzYW1sMjpBdXRobkNvbnRleHRDbGFzc1JlZj5odHRwczovL3d3dy5zcGlkLmdvdi5pdC9TcGlkTDI8L3NhbWwyOkF1dGhuQ29udGV4dENsYXNzUmVmPjwvc2FtbDI6QXV0aG5Db250ZXh0Pjwvc2FtbDI6QXV0aG5TdGF0ZW1lbnQ+PHNhbWwyOkF0dHJpYnV0ZVN0YXRlbWVudD48c2FtbDI6QXR0cmlidXRlIEZyaWVuZGx5TmFtZT0iRGF0YSBkaSBuYXNjaXRhIiBOYW1lPSJkYXRlT2ZCaXJ0aCI+PHNhbWwyOkF0dHJpYnV0ZVZhbHVlIHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnR5cGU9InhzOmRhdGUiPjE5ODctMDktMTQ8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjxzYW1sMjpBdHRyaWJ1dGUgRnJpZW5kbHlOYW1lPSJJbmRpcml6em8gZGkgcG9zdGEgZWxldHRyb25pY2EiIE5hbWU9ImVtYWlsIj48c2FtbDI6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hIiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4c2k6dHlwZT0ieHM6c3RyaW5nIj5waWV0cm8uc3Ryb2lhQGdtYWlsLmNvbTwvc2FtbDI6QXR0cmlidXRlVmFsdWU+PC9zYW1sMjpBdHRyaWJ1dGU+PHNhbWwyOkF0dHJpYnV0ZSBGcmllbmRseU5hbWU9IkNvZ25vbWUiIE5hbWU9ImZhbWlseU5hbWUiPjxzYW1sMjpBdHRyaWJ1dGVWYWx1ZSB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhzaTp0eXBlPSJ4czpzdHJpbmciPlN0cm9pYTwvc2FtbDI6QXR0cmlidXRlVmFsdWU+PC9zYW1sMjpBdHRyaWJ1dGU+PHNhbWwyOkF0dHJpYnV0ZSBGcmllbmRseU5hbWU9IkNvZGljZSBmaXNjYWxlIiBOYW1lPSJmaXNjYWxOdW1iZXIiPjxzYW1sMjpBdHRyaWJ1dGVWYWx1ZSB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhzaTp0eXBlPSJ4czpzdHJpbmciPlRJTklULVNUUlBUUjg3UDE0RTMzNVY8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjxzYW1sMjpBdHRyaWJ1dGUgRnJpZW5kbHlOYW1lPSJOb21lIiBOYW1lPSJuYW1lIj48c2FtbDI6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hIiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4c2k6dHlwZT0ieHM6c3RyaW5nIj5QaWV0cm88L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjwvc2FtbDI6QXR0cmlidXRlU3RhdGVtZW50Pjwvc2FtbDI6QXNzZXJ0aW9uPjwvc2FtbDJwOlJlc3BvbnNlPg=="; +} diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java index 2b5553fb..6cb09b54 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImplTest.java @@ -341,7 +341,7 @@ void failedAssertionValidationThrowErrorValidatingAssertionSignature() .when(assertionVerifierServiceMock) .validateLollipop(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( AssertionVerificationResultCode.SIGNATURE_VALIDATION_ERROR.name(), @@ -368,7 +368,7 @@ void failedAssertionValidationThrowErrorRetrievingIdpCertDataException() .when(assertionVerifierServiceMock) .validateLollipop(any(LollipopConsumerRequest.class)); - CommandResult commandResult = sut.doExecute(LollipopConsumerRequest.builder().build()); + CommandResult commandResult = sut.doExecute(); Assertions.assertEquals( AssertionVerificationResultCode.IDP_CERT_DATA_RETRIEVING_ERROR.name(), diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java index c4aa12ae..ccdd1d81 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java @@ -1,24 +1,28 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service.impl; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static it.pagopa.tech.lollipop.consumer.TestUtils.*; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.*; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; -import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; + +import java.nio.charset.StandardCharsets; import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.util.Collections; import java.util.HashMap; +import lombok.SneakyThrows; +import org.apache.geronimo.mail.util.Base64; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.w3c.dom.Document; class AssertionVerifierServiceImplTest { @@ -26,263 +30,25 @@ class AssertionVerifierServiceImplTest { private AssertionService assertionServiceMock; private static LollipopConsumerRequestConfig lollipopRequestConfigMock; - private AssertionVerifierService sut; - - private static final String VALID_FISCAL_CODE = "AAAAAA89S20I111X"; - private static final String VALID_JWK = - "{ \"kty\": \"EC\", \"crv\": \"P-256\", \"x\":" - + " \"SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74\", \"y\":" - + " \"lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI\"}"; - private static final String VALID_SHA_256_ASSERTION_REF = - "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; - private static final String VALID_SHA_384_ASSERTION_REF = - "sha384-lqxC_2kqMdwiBWoD-Us63Fha6e3bE1Y3yUz8G6IJTldohJCIBVDfvS8acB3GJBhw"; - private static final String VALID_SHA_512_ASSERTION_REF = - "sha512-nX5CfUc5R-FoYKYZwvQMuc4Tt-heb7vHi_O-AMUSqHNVCw9kNaN2SVuN-DXtGXyUhrcVcQdCyY6FVzl_vyWXNA"; - - private static final String EMPTY_ASSERTION_XML = - ""; - private static final String ASSERTION_XML_WITH_INVALID_PERIOD_DATE_FORMAT = - "https://app-backend.io.italia.it"; - private static final String ASSERTION_XML_WITH_EXPIRED_PERIOD = - "https://app-backend.io.italia.it"; - private static String ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG; - private static String ASSERTION_XML_WITHOUT_FISCAL_CODE; - private static String ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG; - private static String ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM; - private static String ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM; - private static String ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM; - private static String ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM; - - @BeforeAll - static void prepareInput() { - lollipopRequestConfigMock = spy(LollipopConsumerRequestConfig.builder().build()); - - String todayTimestamp = - new SimpleDateFormat(lollipopRequestConfigMock.getAssertionNotBeforeDateFormat()) - .format(new Date()); - ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG = - "https://app-backend.io.italia.it"; - ASSERTION_XML_WITHOUT_FISCAL_CODE = - " " - + " " - + " " - + " " - + " https://app-backend.io.italia.it " - + " \t " - + " " - + " " - + " "; - ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG = - " " - + " " - + " " - + " " - + " https://app-backend.io.italia.it " - + " \t " - + " " - + " TINIT-AAAAAA89S20I111X " - + " " - + " "; - ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM = - " " - + " \t" - + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" - + "\t\t\t\t\t\t" - + "\t" - + "\t\t\t\t\t\t\t\t\t" - + "\t\t\t\t" - + "\thttps://app-backend.io.italia.it\t\t" - + "\t\t\t\t" - + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t" - + "\t\t\t\t" - + "\t"; - ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM = - " " - + " \t" - + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" - + "\t\t\t\t\t\t" - + "\t" - + "\t\t\t\t\t\t\t\t\t" - + "\t\t\t\t" - + "\thttps://app-backend.io.italia.it\t\t" - + "\t\t\t\t" - + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t" - + "\t\t\t\t" - + "\t"; - ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM = - " " - + " \t" - + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" - + "\t\t\t\t\t\t" - + "\t" - + "\t\t\t\t\t\t\t\t\t" - + "\t\t\t\t" - + "\thttps://app-backend.io.italia.it\t\t" - + "\t\t\t\t" - + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t" - + "\t\t\t\t" - + "\t"; - ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM = - " " - + " \t" - + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" - + "\t\t\t\t\t\t" - + "\t" - + "\t\t\t\t\t\t\t\t\t" - + "\t\t\t\t" - + "\thttps://app-backend.io.italia.it\t\t" - + "\t\t\t\t" - + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t" - + "\t\t\t\t" - + "\t"; - } + private AssertionVerifierServiceImpl sut; @BeforeEach void setUp() { idpCertProviderMock = mock(IdpCertProvider.class); assertionServiceMock = mock(AssertionService.class); + lollipopRequestConfigMock = spy(LollipopConsumerRequestConfig.builder().build()); sut = - new AssertionVerifierServiceImpl( - idpCertProviderMock, assertionServiceMock, lollipopRequestConfigMock); + spy( + new AssertionVerifierServiceImpl( + idpCertProviderMock, + assertionServiceMock, + lollipopRequestConfigMock)); } + @SneakyThrows @Test - void validateLollipopGetAssertionFailureWithOidcAssertionException() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopGetAssertionFailureWithOidcAssertionException() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); doThrow(OidcAssertionNotSupported.class) @@ -300,9 +66,9 @@ void validateLollipopGetAssertionFailureWithOidcAssertionException() e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopGetAssertionFailureWithAssertionNotFoundException() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopGetAssertionFailureWithAssertionNotFoundException() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); doThrow(LollipopAssertionNotFoundException.class) @@ -320,9 +86,9 @@ void validateLollipopGetAssertionFailureWithAssertionNotFoundException() e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopBuildAssertionDocFailure() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopGetAssertionFailureForBuildAssertionDocError() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -340,9 +106,33 @@ void validateLollipopBuildAssertionDocFailure() e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopValidatePeriodFailureWithFieldNotFoundInAssertionDoc() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopGetAssertionSuccess() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(EMPTY_ASSERTION_XML); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.emptyList()).when(sut).getIdpCertData(any(Document.class)); + doReturn(true).when(sut).validateSignature(any(Document.class), anyList()); + + boolean result = sut.validateLollipop(request); + + assertTrue(result); + } + + @SneakyThrows + @Test + void validateLollipopValidatePeriodFailureWithFieldNotFoundInAssertionDoc() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -357,9 +147,9 @@ void validateLollipopValidatePeriodFailureWithFieldNotFoundInAssertionDoc() AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopValidatePeriodFailureWithInvalidDateFormat() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidatePeriodFailureWithInvalidDateFormat() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -375,9 +165,9 @@ void validateLollipopValidatePeriodFailureWithInvalidDateFormat() e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopValidatePeriodFailureWithExpiredAssertion() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidatePeriodFailureWithExpiredAssertion() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); @@ -392,15 +182,41 @@ void validateLollipopValidatePeriodFailureWithExpiredAssertion() AssertionPeriodException.ErrorCode.INVALID_ASSERTION_PERIOD, e.getErrorCode()); } + @SneakyThrows + @Test + void validateLollipopValidatePeriodSuccess() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(new String(Base64.decode(ASSERTION_XML_TIM.getBytes(StandardCharsets.UTF_8)))); + + doReturn(365 * 20).when(lollipopRequestConfigMock).getAssertionExpireInDays(); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.emptyList()).when(sut).getIdpCertData(any(Document.class)); + doReturn(true).when(sut).validateSignature(any(Document.class), anyList()); + + boolean result = sut.validateLollipop(request); + + assertTrue(result); + } + + @SneakyThrows @Test - void validateLollipopValidateUserIdFailureWithoutAttributeTagInAssertionDoc() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateUserIdFailureWithoutAttributeTagInAssertionDoc() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITHOUT_ATTRIBUTE_TAG); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); AssertionUserIdException e = assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); @@ -409,15 +225,16 @@ void validateLollipopValidateUserIdFailureWithoutAttributeTagInAssertionDoc() AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopValidateUserIdFailureWithoutFiscalCodeInAssertionDoc() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateUserIdFailureWithoutFiscalCodeInAssertionDoc() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITHOUT_FISCAL_CODE); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); AssertionUserIdException e = assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); @@ -426,15 +243,16 @@ void validateLollipopValidateUserIdFailureWithoutFiscalCodeInAssertionDoc() AssertionUserIdException.ErrorCode.FISCAL_CODE_FIELD_NOT_FOUND, e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopValidateUserIdFailureWithInvalidUserIdHeader() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateUserIdFailureWithInvalidUserIdHeader() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); AssertionUserIdException e = assertThrows(AssertionUserIdException.class, () -> sut.validateLollipop(request)); @@ -443,15 +261,41 @@ void validateLollipopValidateUserIdFailureWithInvalidUserIdHeader() AssertionUserIdException.ErrorCode.INVALID_USER_ID, e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopValidateThumbprintFailureWithoutSubjectConfirmationDataTagInAssertionDoc() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { + void validateLollipopValidateUserIdSuccess() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", VALID_FISCAL_CODE); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.emptyList()).when(sut).getIdpCertData(any(Document.class)); + doReturn(true).when(sut).validateSignature(any(Document.class), anyList()); + + boolean result = sut.validateLollipop(request); + + assertTrue(result); + } + + @SneakyThrows + @Test + void + validateLollipopValidateThumbprintFailureWithoutSubjectConfirmationDataTagInAssertionDoc() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITHOUT_SUBJECTCONFIRMATIONDATA_TAG); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); AssertionThumbprintException e = assertThrows( @@ -462,15 +306,19 @@ void validateLollipopValidateThumbprintFailureWithoutSubjectConfirmationDataTagI e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopValidateThumbprintFailureWithInvalidInResponseToAlgorithm() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { - LollipopConsumerRequest request = getLollipopConsumerRequest("", "", VALID_FISCAL_CODE); + void validateLollipopValidateThumbprintFailureWithInvalidInResponseToAlgorithm() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_INVALID_INRESPONSETO_ALGORITHM); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); AssertionThumbprintException e = assertThrows( @@ -481,15 +329,19 @@ void validateLollipopValidateThumbprintFailureWithInvalidInResponseToAlgorithm() e.getErrorCode()); } + @SneakyThrows @Test - void validateLollipopValidateThumbprintFailureWithErrorCalculatingThumbprint() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { - LollipopConsumerRequest request = getLollipopConsumerRequest("", "", VALID_FISCAL_CODE); + void validateLollipopValidateThumbprintFailureWithErrorCalculatingThumbprint() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); AssertionThumbprintException e = assertThrows( @@ -501,16 +353,20 @@ void validateLollipopValidateThumbprintFailureWithErrorCalculatingThumbprint() Assertions.assertTrue(e.getCause() instanceof ParseException); } + @SneakyThrows @Test - void validateLollipopValidateThumbprintFailureWithDifferentAssertionRefAndCalculatedThumbprint() - throws OidcAssertionNotSupported, LollipopAssertionNotFoundException { - LollipopConsumerRequest request = - getLollipopConsumerRequest("", VALID_JWK, VALID_FISCAL_CODE); + void + validateLollipopValidateThumbprintFailureWithDifferentAssertionRefAndCalculatedThumbprint() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", VALID_JWK, ""); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); AssertionThumbprintException e = assertThrows( @@ -520,65 +376,300 @@ void validateLollipopValidateThumbprintFailureWithDifferentAssertionRefAndCalcul AssertionThumbprintException.ErrorCode.INVALID_IN_RESPONSE_TO, e.getErrorCode()); } - /*@Test - void validateLollipopSuccessWithSHA256Algorithm() - throws LollipopAssertionNotFoundException, AssertionPeriodException, - AssertionThumbprintException, AssertionUserIdException, - ErrorRetrievingAssertionException, OidcAssertionNotSupported, - ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { + @SneakyThrows + @Test + void validateLollipopValidateThumbprintSHA256Success() { LollipopConsumerRequest request = - getLollipopConsumerRequest( - VALID_SHA_256_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); + getLollipopConsumerRequest(VALID_SHA_256_ASSERTION_REF, VALID_JWK, ""); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.emptyList()).when(sut).getIdpCertData(any(Document.class)); + doReturn(true).when(sut).validateSignature(any(Document.class), anyList()); boolean result = sut.validateLollipop(request); - Assertions.assertTrue(result); + assertTrue(result); } + @SneakyThrows @Test - void validateLollipopSuccessWithSHA384Algorithm() - throws LollipopAssertionNotFoundException, AssertionPeriodException, - AssertionThumbprintException, AssertionUserIdException, - ErrorRetrievingAssertionException, OidcAssertionNotSupported, - ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { + void validateLollipopValidateThumbprintSHA384Success() { LollipopConsumerRequest request = - getLollipopConsumerRequest( - VALID_SHA_384_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); + getLollipopConsumerRequest(VALID_SHA_384_ASSERTION_REF, VALID_JWK, ""); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA384_ALGORITHM); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.emptyList()).when(sut).getIdpCertData(any(Document.class)); + doReturn(true).when(sut).validateSignature(any(Document.class), anyList()); boolean result = sut.validateLollipop(request); - Assertions.assertTrue(result); + assertTrue(result); } + @SneakyThrows @Test - void validateLollipopSuccessWithSHA512Algorithm() - throws LollipopAssertionNotFoundException, AssertionPeriodException, - AssertionThumbprintException, AssertionUserIdException, - ErrorRetrievingAssertionException, OidcAssertionNotSupported, - ErrorValidatingAssertionSignature, ErrorRetrievingIdpCertDataException { + void validateLollipopValidateThumbprintSHA512Success() { LollipopConsumerRequest request = - getLollipopConsumerRequest( - VALID_SHA_512_ASSERTION_REF, VALID_JWK, VALID_FISCAL_CODE); + getLollipopConsumerRequest(VALID_SHA_512_ASSERTION_REF, VALID_JWK, ""); SamlAssertion assertion = new SamlAssertion(); assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA512_ALGORITHM); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.emptyList()).when(sut).getIdpCertData(any(Document.class)); + doReturn(true).when(sut).validateSignature(any(Document.class), anyList()); + + boolean result = sut.validateLollipop(request); + + assertTrue(result); + } + + @SneakyThrows + @Test + void validateLollipopGetIdpCertDataFailureForMissingInstantField() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITHOUT_INSTANT_FIELD); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + + ErrorRetrievingIdpCertDataException e = + assertThrows( + ErrorRetrievingIdpCertDataException.class, + () -> sut.validateLollipop(request)); + + Assertions.assertEquals( + ErrorRetrievingIdpCertDataException.ErrorCode.INSTANT_FIELD_NOT_FOUND, + e.getErrorCode()); + } + + @SneakyThrows + @Test + void validateLollipopGetIdpCertDataFailureForMissingEntityIdField() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITHOUT_ENTITY_ID_FIELD); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + + ErrorRetrievingIdpCertDataException e = + assertThrows( + ErrorRetrievingIdpCertDataException.class, + () -> sut.validateLollipop(request)); + + Assertions.assertEquals( + ErrorRetrievingIdpCertDataException.ErrorCode.ENTITY_ID_FIELD_NOT_FOUND, + e.getErrorCode()); + } + + @SneakyThrows + @Test + void validateLollipopGetIdpCertDataFailureForIdpCertDataNotFoundException() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_VALID_ENTITY_ID_FIELD); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doThrow(CertDataNotFoundException.class) + .when(idpCertProviderMock) + .getIdpCertData(anyString(), anyString()); + + ErrorRetrievingIdpCertDataException e = + assertThrows( + ErrorRetrievingIdpCertDataException.class, + () -> sut.validateLollipop(request)); + + Assertions.assertEquals( + ErrorRetrievingIdpCertDataException.ErrorCode.IDP_CERT_DATA_NOT_FOUND, + e.getErrorCode()); + } + + @SneakyThrows + @Test + void validateLollipopGetIdpCertDataSuccess() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_VALID_ENTITY_ID_FIELD); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true).when(sut).validateSignature(any(Document.class), anyList()); + + boolean result = sut.validateLollipop(request); + + assertTrue(result); + } + + @SneakyThrows + @Test + void validateLollipopValidateSignatureFailureForErrorUnmarshalAssertion() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(EMPTY_ASSERTION_XML); + + IdpCertData idpCertData = new IdpCertData(); + idpCertData.setCertData(Collections.singletonList(CERTIFICATE_TIM_LATEST)); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.singletonList(idpCertData)) + .when(sut) + .getIdpCertData(any(Document.class)); + + ErrorValidatingAssertionSignature e = + assertThrows( + ErrorValidatingAssertionSignature.class, + () -> sut.validateLollipop(request)); + + Assertions.assertEquals( + ErrorValidatingAssertionSignature.ErrorCode.ERROR_PARSING_ASSERTION, + e.getErrorCode()); + } + + @SneakyThrows + @Test + void validateLollipopValidateSignatureFailureForMissingSignature() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); + + IdpCertData idpCertData = new IdpCertData(); + idpCertData.setCertData(Collections.singletonList(CERTIFICATE_TIM_LATEST)); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.singletonList(idpCertData)) + .when(sut) + .getIdpCertData(any(Document.class)); + + ErrorValidatingAssertionSignature e = + assertThrows( + ErrorValidatingAssertionSignature.class, + () -> sut.validateLollipop(request)); + + Assertions.assertEquals( + ErrorValidatingAssertionSignature.ErrorCode.MISSING_ASSERTION_SIGNATURE, + e.getErrorCode()); + } + + @SneakyThrows + @Test + void validateLollipopValidateSignatureFailureForSignatureNotValid() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_INVALID_SIGNATURE); + + IdpCertData idpCertData = new IdpCertData(); + idpCertData.setCertData(Collections.singletonList(CERTIFICATE_TIM_LATEST)); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.singletonList(idpCertData)) + .when(sut) + .getIdpCertData(any(Document.class)); boolean result = sut.validateLollipop(request); - Assertions.assertTrue(result); - }*/ + assertFalse(result); + } + + @SneakyThrows + @Test + void validateLollipopSuccess() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(new String(Base64.decode(ASSERTION_XML_TIM.getBytes(StandardCharsets.UTF_8)))); + + IdpCertData idpCertData = new IdpCertData(); + idpCertData.setCertData(Collections.singletonList(CERTIFICATE_TIM_LATEST)); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(Collections.singletonList(idpCertData)) + .when(sut) + .getIdpCertData(any(Document.class)); + + boolean result = sut.validateLollipop(request); + + assertTrue(result); + } private LollipopConsumerRequest getLollipopConsumerRequest( String assertionRef, String publicKey, String userId) { diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 1b8fa4e7..74c5fb0e 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1713,6 +1713,14 @@ + + + + + + + + @@ -1737,6 +1745,14 @@ + + + + + + + + @@ -1774,6 +1790,14 @@ + + + + + + + + @@ -1782,6 +1806,11 @@ + + + + + @@ -3090,6 +3119,14 @@ + + + + + + + + @@ -3187,6 +3224,11 @@ + + + + + @@ -3308,6 +3350,11 @@ + + + + + @@ -3628,6 +3675,14 @@ + + + + + + + + @@ -5121,6 +5176,14 @@ + + + + + + + + @@ -5129,6 +5192,14 @@ + + + + + + + + @@ -5147,6 +5218,14 @@ + + + + + + + + @@ -5155,6 +5234,14 @@ + + + + + + + + @@ -5163,6 +5250,14 @@ + + + + + + + + @@ -5171,6 +5266,14 @@ + + + + + + + + @@ -5179,6 +5282,14 @@ + + + + + + + + @@ -5187,6 +5298,14 @@ + + + + + + + + @@ -5195,6 +5314,14 @@ + + + + + + + + @@ -5203,6 +5330,14 @@ + + + + + + + + @@ -5243,6 +5378,14 @@ + + + + + + + + @@ -5251,6 +5394,14 @@ + + + + + + + + diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java new file mode 100644 index 00000000..dfc123b5 --- /dev/null +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java @@ -0,0 +1,21 @@ +package it.pagopa.tech.lollipop.consumer.service.impl; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import org.w3c.dom.Document; + +import java.util.List; + +public class MockAssertionVerifierService extends AssertionVerifierServiceImpl { + + public MockAssertionVerifierService(IdpCertProvider idpCertProvider, AssertionService assertionService, LollipopConsumerRequestConfig lollipopRequestConfig) { + super(idpCertProvider, assertionService, lollipopRequestConfig); + } + + @Override + protected boolean validateSignature(Document assertionDoc, List idpCertDataList) { + return true; + } +} diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java index c89d6ea3..5ac53fa8 100644 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java @@ -3,6 +3,11 @@ import static org.mockserver.integration.ClientAndServer.startClientAndServer; +import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.helper.LollipopConsumerFactoryHelper; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.service.impl.MockAssertionVerifierService; import it.pagopa.tech.lollipop.consumer.spring.config.HttpVerifierConfiguration; import it.pagopa.tech.lollipop.consumer.spring.config.SpringLollipopConsumerRequestConfig; import org.junit.jupiter.api.AfterAll; @@ -32,6 +37,7 @@ public class HttpVerifierHandlerInterceptorIntegrationTest { @LocalServerPort private int port; @Autowired private TestRestTemplate restTemplate; + @Autowired private LollipopConsumerFactoryHelper factoryHelper; @BeforeAll public static void startServer() { @@ -45,6 +51,7 @@ public static void startServer() { @Test void testWithValidRequestReturnsSuccess() { AssertionSimpleClientTestUtils.createExpectationAssertionFound(); + factoryHelper.setAssertionVerifierService(new MockAssertionVerifierService(factoryHelper.getIdpCertProviderFactory().create(), factoryHelper.getAssertionServiceFactory().create(), LollipopConsumerRequestConfig.builder().build())); String signatureInput = "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" From ba51428a839a39e4aaab4a3331429eff6af58790 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 19 Apr 2023 18:52:49 +0200 Subject: [PATCH 266/403] [SLS-25] Applied spotless, updated verification-metadata.xml --- .../idp/impl/IdpCertProviderImpl.java | 1 - .../impl/AssertionVerifierServiceImpl.java | 9 +- .../AssertionVerifierServiceImplTest.java | 7 +- gradle/verification-metadata.xml | 123 +++++++++--------- .../impl/MockAssertionVerifierService.java | 9 +- ...fierHandlerInterceptorIntegrationTest.java | 8 +- 6 files changed, 80 insertions(+), 77 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java index eb428c1d..08661097 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java @@ -48,7 +48,6 @@ public List getIdpCertData(String assertionInstant, String entityId throw new IllegalArgumentException(errMsg); } - return idpCertClient.getCertData(entityId, assertionInstant); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index a583eb64..6bae1476 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -242,9 +242,12 @@ protected List getIdpCertData(Document assertionDoc) "Missing entity id field in the retrieved saml assertion"); } try { - instant = Long.toString( - new SimpleDateFormat(lollipopRequestConfig.getAssertionNotBeforeDateFormat()) - .parse(instant).getTime()); + instant = + Long.toString( + new SimpleDateFormat( + lollipopRequestConfig.getAssertionNotBeforeDateFormat()) + .parse(instant) + .getTime()); } catch (ParseException e) { } try { diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java index ccdd1d81..9c748b99 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java @@ -12,7 +12,6 @@ import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; - import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.Collections; @@ -188,7 +187,8 @@ void validateLollipopValidatePeriodSuccess() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); - assertion.setAssertionData(new String(Base64.decode(ASSERTION_XML_TIM.getBytes(StandardCharsets.UTF_8)))); + assertion.setAssertionData( + new String(Base64.decode(ASSERTION_XML_TIM.getBytes(StandardCharsets.UTF_8)))); doReturn(365 * 20).when(lollipopRequestConfigMock).getAssertionExpireInDays(); @@ -649,7 +649,8 @@ void validateLollipopSuccess() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); - assertion.setAssertionData(new String(Base64.decode(ASSERTION_XML_TIM.getBytes(StandardCharsets.UTF_8)))); + assertion.setAssertionData( + new String(Base64.decode(ASSERTION_XML_TIM.getBytes(StandardCharsets.UTF_8)))); IdpCertData idpCertData = new IdpCertData(); idpCertData.setCertData(Collections.singletonList(CERTIFICATE_TIM_LATEST)); diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 74c5fb0e..1b76ae42 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1790,6 +1790,11 @@ + + + + + @@ -1816,11 +1821,6 @@ - - - - - @@ -3205,11 +3205,6 @@ - - - - - @@ -3626,6 +3621,19 @@ + + + + + + + + + + + + + @@ -3662,19 +3670,6 @@ - - - - - - - - - - - - - @@ -3830,6 +3825,13 @@ + + + + + + + @@ -3838,13 +3840,6 @@ - - - - - - - @@ -4239,14 +4234,6 @@ - - - - - - - - @@ -4312,6 +4299,14 @@ + + + + + + + + @@ -5702,32 +5697,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -5779,6 +5748,14 @@ + + + + + + + + @@ -5813,6 +5790,16 @@ + + + + + + + + + + @@ -5821,6 +5808,14 @@ + + + + + + + + diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java index dfc123b5..56a6eaf6 100644 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java @@ -1,16 +1,19 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service.impl; import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; -import org.w3c.dom.Document; - import java.util.List; +import org.w3c.dom.Document; public class MockAssertionVerifierService extends AssertionVerifierServiceImpl { - public MockAssertionVerifierService(IdpCertProvider idpCertProvider, AssertionService assertionService, LollipopConsumerRequestConfig lollipopRequestConfig) { + public MockAssertionVerifierService( + IdpCertProvider idpCertProvider, + AssertionService assertionService, + LollipopConsumerRequestConfig lollipopRequestConfig) { super(idpCertProvider, assertionService, lollipopRequestConfig); } diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java index 5ac53fa8..e665b819 100644 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java @@ -3,10 +3,8 @@ import static org.mockserver.integration.ClientAndServer.startClientAndServer; -import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.helper.LollipopConsumerFactoryHelper; -import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; import it.pagopa.tech.lollipop.consumer.service.impl.MockAssertionVerifierService; import it.pagopa.tech.lollipop.consumer.spring.config.HttpVerifierConfiguration; import it.pagopa.tech.lollipop.consumer.spring.config.SpringLollipopConsumerRequestConfig; @@ -51,7 +49,11 @@ public static void startServer() { @Test void testWithValidRequestReturnsSuccess() { AssertionSimpleClientTestUtils.createExpectationAssertionFound(); - factoryHelper.setAssertionVerifierService(new MockAssertionVerifierService(factoryHelper.getIdpCertProviderFactory().create(), factoryHelper.getAssertionServiceFactory().create(), LollipopConsumerRequestConfig.builder().build())); + factoryHelper.setAssertionVerifierService( + new MockAssertionVerifierService( + factoryHelper.getIdpCertProviderFactory().create(), + factoryHelper.getAssertionServiceFactory().create(), + LollipopConsumerRequestConfig.builder().build())); String signatureInput = "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" From 07ea7fdfc22db1eec233660f605ce155704f7588 Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 20 Apr 2023 11:10:51 +0200 Subject: [PATCH 267/403] [SLS-25] resolved sonarqube code smell and added unit test for coverage. do some refactor. --- .../impl/LollipopConsumerCommandImpl.java | 63 +++++++++++------- .../config/LollipopConsumerRequestConfig.java | 1 + .../idp/impl/IdpCertProviderImpl.java | 2 +- .../impl/AssertionVerifierServiceImpl.java | 25 ++++--- .../tech/lollipop/consumer/TestUtils.java | 34 ++++++++++ .../idp/impl/IdpCertProviderImplTest.java | 66 +++++++++++++++++++ .../AssertionVerifierServiceImplTest.java | 23 +++++++ ...sumerRequestValidationServiceImplTest.java | 33 ++++++---- gradle/verification-metadata.xml | 15 ++++- .../client/simple/IdpCertSimpleClient.java | 1 + .../TagListSearchOutOfBoundException.java | 2 +- 11 files changed, 215 insertions(+), 50 deletions(-) create mode 100644 core/src/test/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImplTest.java rename {core/src/main/java/it/pagopa/tech/lollipop/consumer => identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple}/exception/TagListSearchOutOfBoundException.java (80%) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index f929f575..2a7d3880 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -26,6 +26,7 @@ public class LollipopConsumerCommandImpl implements LollipopConsumerCommand { private final LollipopConsumerRequest request; private final LollipopLoggerService lollipopLoggerService; + private static final String CODE_AND_MESSAGE = " with error code: %s and message: %s"; public static final String VERIFICATION_SUCCESS_CODE = "SUCCESS"; public static final String REQUEST_PARAMS_VALIDATION_FAILED = "REQUEST PARAMS VALIDATION FAILED"; @@ -59,6 +60,15 @@ public CommandResult doExecute() { try { requestValidationService.validateLollipopRequest(request); + } catch (LollipopRequestContentValidationException e) { + String message = + String.format( + "Error validating Lollipop request header or body, validation failed" + + CODE_AND_MESSAGE, + e.getErrorCode(), + e.getMessage()); + return buildCommandResult(REQUEST_PARAMS_VALIDATION_FAILED, message); + } CommandResult messageVerificationResult = getHttpMessageVerificationResult(request); if (!messageVerificationResult @@ -98,49 +108,52 @@ private CommandResult getAssertionVerificationResult(LollipopConsumerRequest req } catch (ErrorRetrievingAssertionException e) { String message = String.format( - "Cannot obtain the assertion, validation failed with error code %s" - + " and message: %s", - e.getErrorCode(), e.getMessage()); + "Cannot obtain the assertion, validation failed" + CODE_AND_MESSAGE, + e.getErrorCode(), + e.getMessage()); return buildCommandResult( AssertionVerificationResultCode.ERROR_RETRIEVING_ASSERTION.name(), message); } catch (AssertionPeriodException e) { String message = String.format( - "Assertion validation failed on verifying period with error code %s" - + " and message: %s", - e.getErrorCode(), e.getMessage()); + "Assertion validation failed on verifying period" + CODE_AND_MESSAGE, + e.getErrorCode(), + e.getMessage()); return buildCommandResult( AssertionVerificationResultCode.PERIOD_VALIDATION_ERROR.name(), message); } catch (AssertionThumbprintException e) { String message = String.format( - "Assertion validation failed on verifying thumbprint with error code" - + " %s and message: %s", - e.getErrorCode(), e.getMessage()); + "Assertion validation failed on verifying thumbprint" + + CODE_AND_MESSAGE, + e.getErrorCode(), + e.getMessage()); return buildCommandResult( AssertionVerificationResultCode.THUMBPRINT_VALIDATION_ERROR.name(), message); } catch (AssertionUserIdException e) { String message = String.format( - "Assertion validation failed on verifying user id with error code %s" - + " and message: %s", - e.getErrorCode(), e.getMessage()); + "Assertion validation failed on verifying user id" + CODE_AND_MESSAGE, + e.getErrorCode(), + e.getMessage()); return buildCommandResult( AssertionVerificationResultCode.USER_ID_VALIDATION_ERROR.name(), message); } catch (ErrorValidatingAssertionSignature e) { String message = String.format( - "Assertion validation failed on verifying signature with error code %s" - + " and message: %s", - e.getErrorCode(), e.getMessage()); + "Assertion validation failed on verifying signature" + CODE_AND_MESSAGE, + e.getErrorCode(), + e.getMessage()); return buildCommandResult( AssertionVerificationResultCode.SIGNATURE_VALIDATION_ERROR.name(), message); } catch (ErrorRetrievingIdpCertDataException e) { String message = String.format( "Assertion validation failed on retrieving identity provider's" - + " certification data with error code %s and message: %s", - e.getErrorCode(), e.getMessage()); + + " certification data" + + CODE_AND_MESSAGE, + e.getErrorCode(), + e.getMessage()); return buildCommandResult( AssertionVerificationResultCode.IDP_CERT_DATA_RETRIEVING_ERROR.name(), message); } @@ -163,16 +176,17 @@ private CommandResult getHttpMessageVerificationResult(LollipopConsumerRequest r } catch (LollipopDigestException e) { String message = String.format( - "HTTP message validation failed on verifying digest with error code %s" - + " and message: %s", - e.getErrorCode(), e.getMessage()); + "HTTP message validation failed on verifying digest" + CODE_AND_MESSAGE, + e.getErrorCode(), + e.getMessage()); return buildCommandResult( HttpMessageVerificationResultCode.DIGEST_VALIDATION_ERROR.name(), message); } catch (LollipopSignatureException e) { String message = String.format( - "HTTP message validation failed on verifying signatures with message:" - + " %s", + "HTTP message validation failed on verifying signatures" + + CODE_AND_MESSAGE, + e.getErrorCode(), e.getMessage()); return buildCommandResult( HttpMessageVerificationResultCode.SIGNATURE_VALIDATION_ERROR.name(), message); @@ -187,8 +201,9 @@ private CommandResult getHttpMessageVerificationResult(LollipopConsumerRequest r } catch (LollipopVerifierException e) { String message = String.format( - "HTTP message validation failed on content validation with message:" - + " %s", + "HTTP message validation failed on content validation" + + CODE_AND_MESSAGE, + e.getErrorCode(), e.getMessage()); return buildCommandResult( HttpMessageVerificationResultCode.REQUEST_VALIDATION_ERROR.name(), message); diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java index 149a00d0..94ba1816 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/config/LollipopConsumerRequestConfig.java @@ -35,6 +35,7 @@ public class LollipopConsumerRequestConfig { // assertion validation parameters @Builder.Default private int assertionExpireInDays = 30; @Builder.Default private String assertionNotBeforeDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; + @Builder.Default private String assertionInstantDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; @Builder.Default private String samlNamespaceAssertion = "urn:oasis:names:tc:SAML:2.0:assertion"; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java index 08661097..e6cb40fa 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java @@ -11,7 +11,7 @@ public class IdpCertProviderImpl implements IdpCertProvider { - private IdpCertClient idpCertClient; + private final IdpCertClient idpCertClient; @Inject public IdpCertProviderImpl(IdpCertClient idpCertClient) { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index 6bae1476..19f23155 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -241,15 +241,7 @@ protected List getIdpCertData(Document assertionDoc) ErrorRetrievingIdpCertDataException.ErrorCode.ENTITY_ID_FIELD_NOT_FOUND, "Missing entity id field in the retrieved saml assertion"); } - try { - instant = - Long.toString( - new SimpleDateFormat( - lollipopRequestConfig.getAssertionNotBeforeDateFormat()) - .parse(instant) - .getTime()); - } catch (ParseException e) { - } + instant = parseInstantToMillis(instant); try { return idpCertProvider.getIdpCertData(instant, entityId.trim()); } catch (CertDataNotFoundException e) { @@ -451,4 +443,19 @@ private String getPublicKey(String publicKey) { } return publicKey; } + + private String parseInstantToMillis(String instant) { + String instantDateFormat = lollipopRequestConfig.getAssertionInstantDateFormat(); + try { + instant = + Long.toString(new SimpleDateFormat(instantDateFormat).parse(instant).getTime()); + } catch (ParseException e) { + String msg = + String.format( + "Retrieved instant %s does not match expected format %s", + instant, instantDateFormat); + log.log(Level.WARNING, msg); + } + return instant; + } } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java index ce1bc163..19e9727f 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java @@ -270,6 +270,38 @@ public class TestUtils { + " xsi:type=\"xs:string\">TINIT-AAAAAA89S20I111X\t\t" + "\t\t\t" + "\t"; + public static final String ASSERTION_XML_WITH_INVALID_INSTANT_FORMAT = + " \thttps://posteid.poste.it" + + "\t\t\t\tSPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + + "\t\t\t\t\t\t" + + "\t\t\t" + + "\t\t\t\t\t\t\t\t\t\t" + + "\t\thttps://app-backend.io.italia.it\t\t" + + "\t\t\t\t" + + "\t\t\t\t\t\t\t\tTINIT-AAAAAA89S20I111X\t\t" + + "\t\t\t" + + "\t"; public static final String ASSERTION_XML_WITH_VALID_ENTITY_ID_FIELD = " sut.getIdpCertData(randomString1, randomString2)); + } + + @Test + void getIdpCertDataErrorInvalidInstantNull() { + String randomString = generateRandomString(); + Assertions.assertThrows( + IllegalArgumentException.class, () -> sut.getIdpCertData(null, randomString)); + } + + @Test + void getIdpCertDataErrorInvalidInstantEmpty() { + String randomString = generateRandomString(); + Assertions.assertThrows( + IllegalArgumentException.class, () -> sut.getIdpCertData("", randomString)); + } + + @Test + void getIdpCertDataErrorInvalidEntityIdNull() { + String randomString = generateRandomString(); + Assertions.assertThrows( + IllegalArgumentException.class, () -> sut.getIdpCertData(randomString, null)); + } + + @Test + void getIdpCertDataErrorInvalidEntityIdEmpty() { + String randomString = generateRandomString(); + Assertions.assertThrows( + IllegalArgumentException.class, () -> sut.getIdpCertData(randomString, "")); + } + + private String generateRandomString() { + byte[] array = new byte[7]; + random.nextBytes(array); + return new String(array, StandardCharsets.UTF_8); + } +} diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java index 9c748b99..18221542 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java @@ -526,6 +526,29 @@ void validateLollipopGetIdpCertDataFailureForIdpCertDataNotFoundException() { e.getErrorCode()); } + @SneakyThrows + @Test + void validateLollipopGetIdpCertDataSuccessWithWarningForInvalidInstantDateFormat() { + LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); + + SamlAssertion assertion = new SamlAssertion(); + assertion.setAssertionData(ASSERTION_XML_WITH_INVALID_INSTANT_FORMAT); + + doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); + doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); + doReturn(true) + .when(sut) + .validateUserId(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true) + .when(sut) + .validateInResponseTo(any(LollipopConsumerRequest.class), any(Document.class)); + doReturn(true).when(sut).validateSignature(any(Document.class), anyList()); + + boolean result = sut.validateLollipop(request); + + assertTrue(result); + } + @SneakyThrows @Test void validateLollipopGetIdpCertDataSuccess() { diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java index 8a380f98..2130e5d3 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java @@ -9,12 +9,19 @@ import it.pagopa.tech.lollipop.consumer.exception.LollipopRequestContentValidationException; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; +import java.nio.charset.StandardCharsets; import java.util.HashMap; +import java.util.Random; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; class LollipopConsumerRequestValidationServiceImplTest { + private LollipopConsumerRequestConfig config; + private LollipopConsumerRequestValidationService sut; + + private final Random random = new Random(); + public static final String VALID_EC_PUBLIC_KEY = "{ \"kty\": \"EC\", \"x\": \"FqFDuwEgu4MUXERPMVL-85pGv2D3YmL4J1gfMkdbc24\", \"y\":" + " \"hdV0oxmWFSxMoJUDpdihr76rS8VRBEqMFebYyAfK9-k\", \"crv\": \"P-256\"}"; @@ -30,10 +37,6 @@ class LollipopConsumerRequestValidationServiceImplTest { + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; public static final String VALID_SIGNATURE = "sig1=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; - public static final String RANDOM_STRING = ""; - private LollipopConsumerRequestConfig config; - - private LollipopConsumerRequestValidationService sut; @BeforeEach void setUp() { @@ -60,7 +63,7 @@ void validatePublicKeyFailureHeaderNotPresent() { @Test void validatePublicKeyFailureHeaderInvalidFormat() { HashMap headers = new HashMap<>(); - headers.put(config.getPublicKeyHeader(), RANDOM_STRING); + headers.put(config.getPublicKeyHeader(), generateRandomString()); LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); @@ -95,7 +98,7 @@ void validateAssertionRefFailureHeaderNotPresent() { void validateAssertionRefFailureInvalidFormat() { HashMap headers = new HashMap<>(); headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); - headers.put(config.getAssertionRefHeader(), RANDOM_STRING); + headers.put(config.getAssertionRefHeader(), generateRandomString()); LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); @@ -132,7 +135,7 @@ void validateAssertionTypeFailureInvalidFormat() { HashMap headers = new HashMap<>(); headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); - headers.put(config.getAssertionTypeHeader(), RANDOM_STRING); + headers.put(config.getAssertionTypeHeader(), generateRandomString()); LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); @@ -171,7 +174,7 @@ void validateUserIdFailureInvalidFormat() { headers.put(config.getPublicKeyHeader(), VALID_EC_PUBLIC_KEY); headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); - headers.put(config.getUserIdHeader(), RANDOM_STRING); + headers.put(config.getUserIdHeader(), generateRandomString()); LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); @@ -212,7 +215,7 @@ void validateAuthJWKFailureInvalidFormat() { headers.put(config.getAssertionRefHeader(), VALID_ASSERTION_REF); headers.put(config.getAssertionTypeHeader(), AssertionType.SAML.name()); headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); - headers.put(config.getAuthJWTHeader(), RANDOM_STRING); + headers.put(config.getAuthJWTHeader(), ""); LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); @@ -322,7 +325,7 @@ void validateOriginalURLFailureInvalidFormat() { headers.put(config.getUserIdHeader(), VALID_FISCAL_CODE); headers.put(config.getAuthJWTHeader(), VALID_JWT); headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); - headers.put(config.getOriginalURLHeader(), RANDOM_STRING); + headers.put(config.getOriginalURLHeader(), generateRandomString()); LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); @@ -392,7 +395,7 @@ void validateSignatureInputFailureInvalidFormat() { headers.put(config.getAuthJWTHeader(), VALID_JWT); headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); - headers.put(config.getSignatureInputHeader(), RANDOM_STRING); + headers.put(config.getSignatureInputHeader(), generateRandomString()); LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); @@ -441,7 +444,7 @@ void validateSignatureFailureInvalidFormat() { headers.put(config.getOriginalMethodHeader(), config.getExpectedFirstLcOriginalMethod()); headers.put(config.getOriginalURLHeader(), config.getExpectedFirstLcOriginalUrl()); headers.put(config.getSignatureInputHeader(), VALID_SIGNATURE_INPUT); - headers.put(config.getSignatureHeader(), RANDOM_STRING); + headers.put(config.getSignatureHeader(), generateRandomString()); LollipopConsumerRequest request = LollipopConsumerRequest.builder().headerParams(headers).build(); @@ -490,4 +493,10 @@ void validateRequestSuccessWithRSAPublicKey() { assertDoesNotThrow(() -> sut.validateLollipopRequest(request)); } + + private String generateRandomString() { + byte[] array = new byte[7]; + random.nextBytes(array); + return new String(array, StandardCharsets.UTF_8); + } } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 1b76ae42..c7b84545 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -375,6 +375,7 @@ + @@ -455,6 +456,7 @@ + @@ -533,6 +535,7 @@ + @@ -720,6 +723,7 @@ + @@ -739,6 +743,7 @@ + @@ -786,6 +791,7 @@ + @@ -806,6 +812,7 @@ + @@ -849,6 +856,7 @@ + @@ -868,6 +876,7 @@ + @@ -4765,7 +4774,7 @@ - + @@ -4864,7 +4873,7 @@ - + @@ -4912,7 +4921,7 @@ - + diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 54c57d15..33dacf88 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -3,6 +3,7 @@ import it.pagopa.tech.lollipop.consumer.exception.*; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.exception.TagListSearchOutOfBoundException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.api.DefaultApi; diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/TagListSearchOutOfBoundException.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/exception/TagListSearchOutOfBoundException.java similarity index 80% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/TagListSearchOutOfBoundException.java rename to identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/exception/TagListSearchOutOfBoundException.java index ed780469..1561bf7e 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/TagListSearchOutOfBoundException.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/exception/TagListSearchOutOfBoundException.java @@ -1,5 +1,5 @@ /* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.exception; +package it.pagopa.tech.lollipop.consumer.idp.client.simple.exception; public class TagListSearchOutOfBoundException extends Exception { From 3bb5bf0432d03c0f658d16722eb9a2b2df09885c Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 20 Apr 2023 12:36:56 +0200 Subject: [PATCH 268/403] [core-sprit-3] Fixing sonar issues --- ...pConsumerRequestValidationServiceImpl.java | 4 +- .../internal/model/EntityDescriptor.java | 49 +++++++++++++------ 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java index 9aeed6e2..dc1f7010 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java @@ -235,7 +235,7 @@ private void validateSignatureInputHeader(String signatureInput) } private boolean isNotValidSignatureInput(String signatureInput) { - return !Pattern.compile("^(((sig[0-9]+)=[^,]*?)(, ?)?)+$") + return !Pattern.compile("^(((sig[\\d]+)=[^,]*?)+(, ?)?)+$") .matcher(signatureInput) .matches(); } @@ -256,7 +256,7 @@ private void validateSignatureHeader(String signature) } private boolean isNotValidSignature(String signature) { - return !Pattern.compile("^((sig[0-9]+)=:[A-Za-z0-9+/=]*:(, ?)?)+$") + return !Pattern.compile("^((sig[\\d]+)=:[A-Za-z0-9+/=]*+:(, ?)?)+$") .matcher(signature) .matches(); } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java index 8e8b7d1d..9e74302b 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java @@ -30,6 +30,18 @@ public class EntityDescriptor { @SuppressWarnings("unchecked") @JsonProperty("IDPSSODescriptor") private void unpackNestedSignature(Map signature) { + List> keyDescriptorsList = getKeyDescriptorsList(signature); + + List> keyInfosList = getKeyInfosList(keyDescriptorsList); + + List> listX509Data = getListX509Data(keyInfosList); + + List extractedSignatureList = getExtractedSignatureList(listX509Data); + + this.signatureList = extractedSignatureList; + } + + private List> getKeyDescriptorsList(Map signature) { List> keyDescriptorsList = new ArrayList<>(); if (signature.get(KEY_DESCRIPTOR) instanceof List) { @@ -46,18 +58,22 @@ private void unpackNestedSignature(Map signature) { keyDescriptorsList.add(keyDescriptorFound); } } + return keyDescriptorsList; + } - List> keyInfosList = new ArrayList<>(); - for (Map keyDescriptor : keyDescriptorsList) { - if (keyDescriptor.get(KEY_INFO) instanceof List) { - keyInfosList = (List>) keyDescriptor.get(KEY_INFO); + private List getExtractedSignatureList(List> listX509Data) { + List extractedSignatureList = new ArrayList<>(); + for (Map x509Data : listX509Data) { + if (x509Data.get(X_509_CERTIFICATE) instanceof List) { + signatureList = (List) x509Data.get(X_509_CERTIFICATE); } else { - Map keyInfo = (Map) keyDescriptor.get(KEY_INFO); - - keyInfosList.add(keyInfo); + signatureList.add((String) x509Data.get(X_509_CERTIFICATE)); } } + return extractedSignatureList; + } + private List> getListX509Data(List> keyInfosList) { List> listX509Data = new ArrayList<>(); for (Map keyInfo : keyInfosList) { if (keyInfo.get(X_509_DATA) instanceof List) { @@ -66,16 +82,21 @@ private void unpackNestedSignature(Map signature) { listX509Data.add((Map) keyInfo.get(X_509_DATA)); } } + return listX509Data; + } - List signatureList = new ArrayList<>(); - for (Map x509Data : listX509Data) { - if (x509Data.get(X_509_CERTIFICATE) instanceof List) { - signatureList = (List) x509Data.get(X_509_CERTIFICATE); + private List> getKeyInfosList( + List> keyDescriptorsList) { + List> keyInfosList = new ArrayList<>(); + for (Map keyDescriptor : keyDescriptorsList) { + if (keyDescriptor.get(KEY_INFO) instanceof List) { + keyInfosList = (List>) keyDescriptor.get(KEY_INFO); } else { - signatureList.add((String) x509Data.get(X_509_CERTIFICATE)); + Map keyInfo = (Map) keyDescriptor.get(KEY_INFO); + + keyInfosList.add(keyInfo); } } - - this.signatureList = signatureList; + return keyInfosList; } } From 6677769cfb82afcadd2a9d594b176b1104da6459 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 20 Apr 2023 12:56:39 +0200 Subject: [PATCH 269/403] [core-sprint-3] Fixing sonar issues --- .../client/simple/IdpCertSimpleClient.java | 112 ++++++++++-------- .../internal/model/EntityDescriptor.java | 4 +- 2 files changed, 63 insertions(+), 53 deletions(-) diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 33dacf88..58731c31 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -57,68 +57,78 @@ public List getCertData(String entityId, String instant) } if (entityConfig.getCieEntityId().contains(entityId)) { - try { - tagList = getCIETagList(instant); - } catch (ApiException - | TagListSearchOutOfBoundException - | InvalidInstantFormatException e) { - throw new CertDataNotFoundException( - "Error retrieving certificate's tag list: " + e.getMessage(), e); - } + getCieCerts(entityId, instant, listCertData); + } else { + getSpidCerts(entityId, instant, listCertData); + } + return listCertData; + } - for (String tag : tagList) { - try { - String storageTag = codifyStorageTag(tag, entityId); - IdpCertData certData = storage.getIdpCertData(storageTag); + private void getCieCerts(String entityId, String instant, List listCertData) throws CertDataNotFoundException { + List tagList; + try { + tagList = getCIETagList(instant); + } catch (ApiException + | TagListSearchOutOfBoundException + | InvalidInstantFormatException e) { + throw new CertDataNotFoundException( + "Error retrieving certificate's tag list: " + e.getMessage(), e); + } - if (certData == null) { - certData = getCIECertData(tag, entityId); - } else { - storage.saveIdpCertData(storageTag, certData); - } + for (String tag : tagList) { + try { + String storageTag = codifyStorageTag(tag, entityId); + IdpCertData certData = storage.getIdpCertData(storageTag); - listCertData.add(certData); - } catch (ApiException | EntityIdNotFoundException e) { - throw new CertDataNotFoundException( - "Error retrieving certificate data for tag " - + tag - + ": " - + e.getMessage(), - e); + if (certData == null) { + certData = getCIECertData(tag, entityId); + } else { + storage.saveIdpCertData(storageTag, certData); } - } - } else { - try { - tagList = getSPIDTagList(instant); - } catch (ApiException - | TagListSearchOutOfBoundException - | InvalidInstantFormatException e) { + + listCertData.add(certData); + } catch (ApiException | EntityIdNotFoundException e) { throw new CertDataNotFoundException( - "Error retrieving certificate's tag list: " + e.getMessage(), e); + "Error retrieving certificate data for tag " + + tag + + ": " + + e.getMessage(), + e); } + } + } - for (String tag : tagList) { - try { - String storageTag = codifyStorageTag(tag, entityId); - IdpCertData certData = storage.getIdpCertData(codifyStorageTag(tag, entityId)); + private void getSpidCerts(String entityId, String instant, List listCertData) throws CertDataNotFoundException { + List tagList; + try { + tagList = getSPIDTagList(instant); + } catch (ApiException + | TagListSearchOutOfBoundException + | InvalidInstantFormatException e) { + throw new CertDataNotFoundException( + "Error retrieving certificate's tag list: " + e.getMessage(), e); + } - if (certData == null) { - certData = getSPIDCertData(tag, entityId); - } else { - storage.saveIdpCertData(storageTag, certData); - } - listCertData.add(certData); - } catch (ApiException | EntityIdNotFoundException e) { - throw new CertDataNotFoundException( - "Error retrieving certificate data for tag " - + tag - + ": " - + e.getMessage(), - e); + for (String tag : tagList) { + try { + String storageTag = codifyStorageTag(tag, entityId); + IdpCertData certData = storage.getIdpCertData(codifyStorageTag(tag, entityId)); + + if (certData == null) { + certData = getSPIDCertData(tag, entityId); + } else { + storage.saveIdpCertData(storageTag, certData); } + listCertData.add(certData); + } catch (ApiException | EntityIdNotFoundException e) { + throw new CertDataNotFoundException( + "Error retrieving certificate data for tag " + + tag + + ": " + + e.getMessage(), + e); } } - return listCertData; } private List getSPIDTagList(String instant) diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java index 9e74302b..0fb4f418 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java @@ -65,9 +65,9 @@ private List getExtractedSignatureList(List> listX50 List extractedSignatureList = new ArrayList<>(); for (Map x509Data : listX509Data) { if (x509Data.get(X_509_CERTIFICATE) instanceof List) { - signatureList = (List) x509Data.get(X_509_CERTIFICATE); + extractedSignatureList = (List) x509Data.get(X_509_CERTIFICATE); } else { - signatureList.add((String) x509Data.get(X_509_CERTIFICATE)); + extractedSignatureList.add((String) x509Data.get(X_509_CERTIFICATE)); } } return extractedSignatureList; From bf14e3ef0373f111acf8361ce6d1b413c0828944 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 20 Apr 2023 12:57:45 +0200 Subject: [PATCH 270/403] [core-sprint-3] Fixing sonar issues --- .../idp/client/simple/IdpCertSimpleClient.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 58731c31..d4e610d3 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -64,7 +64,8 @@ public List getCertData(String entityId, String instant) return listCertData; } - private void getCieCerts(String entityId, String instant, List listCertData) throws CertDataNotFoundException { + private void getCieCerts(String entityId, String instant, List listCertData) + throws CertDataNotFoundException { List tagList; try { tagList = getCIETagList(instant); @@ -89,16 +90,14 @@ private void getCieCerts(String entityId, String instant, List list listCertData.add(certData); } catch (ApiException | EntityIdNotFoundException e) { throw new CertDataNotFoundException( - "Error retrieving certificate data for tag " - + tag - + ": " - + e.getMessage(), + "Error retrieving certificate data for tag " + tag + ": " + e.getMessage(), e); } } } - private void getSpidCerts(String entityId, String instant, List listCertData) throws CertDataNotFoundException { + private void getSpidCerts(String entityId, String instant, List listCertData) + throws CertDataNotFoundException { List tagList; try { tagList = getSPIDTagList(instant); @@ -122,10 +121,7 @@ private void getSpidCerts(String entityId, String instant, List lis listCertData.add(certData); } catch (ApiException | EntityIdNotFoundException e) { throw new CertDataNotFoundException( - "Error retrieving certificate data for tag " - + tag - + ": " - + e.getMessage(), + "Error retrieving certificate data for tag " + tag + ": " + e.getMessage(), e); } } From e8365c4f341e6983a20572a00a61adf1d38e36c3 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 20 Apr 2023 13:08:42 +0200 Subject: [PATCH 271/403] [core-sprint-3] Fixing sonar issues --- .../impl/LollipopConsumerRequestValidationServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java index dc1f7010..c4995b75 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java @@ -235,7 +235,7 @@ private void validateSignatureInputHeader(String signatureInput) } private boolean isNotValidSignatureInput(String signatureInput) { - return !Pattern.compile("^(((sig[\\d]+)=[^,]*?)+(, ?)?)+$") + return !Pattern.compile("^(((sig[\\d]++)=[^,]*)++(, ?)?)++$") .matcher(signatureInput) .matches(); } From 24b08106858013f21633f3e6141960306ee6dd4b Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 20 Apr 2023 15:02:46 +0200 Subject: [PATCH 272/403] [core-sprint-3] Fixing sonar issues --- .../impl/LollipopConsumerRequestValidationServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java index c4995b75..9c275cbe 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java @@ -235,7 +235,7 @@ private void validateSignatureInputHeader(String signatureInput) } private boolean isNotValidSignatureInput(String signatureInput) { - return !Pattern.compile("^(((sig[\\d]++)=[^,]*)++(, ?)?)++$") + return !Pattern.compile("^(((sig[\\d]++)=[^,]*+)(, ?+)?+)++$") .matcher(signatureInput) .matches(); } From bcf2e9c123236905acd775f9ae5b074c7e4bf102 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 20 Apr 2023 18:45:12 +0200 Subject: [PATCH 273/403] [SLS-18] Updated logging service --- core/build.gradle | 1 + .../impl/LollipopConsumerCommandImpl.java | 35 +++++----- .../helper/LollipopConsumerFactoryHelper.java | 51 ++++++++++---- .../logger/LollipopLoggerService.java | 2 +- .../logger/LollipopLoggerServiceFactory.java | 2 +- .../impl/LollipopLogbackLoggerService.java | 6 +- .../LollipopLogbackLoggerServiceFactory.java | 2 +- .../consumer/model/SamlAssertion.java | 1 - .../impl/AssertionVerifierServiceImpl.java | 54 +++++++-------- .../logging/logback/includes/defaults.xml | 42 +++++++++++- .../tech/lollipop/logging/logback/logback.xml | 7 ++ .../AssertionVerifierServiceImplTest.java | 2 + gradle/verification-metadata.xml | 66 +++++++++++++++++++ spring-impl/build.gradle | 2 + .../config/HttpVerifierConfiguration.java | 3 + .../src/main/resources/logback-spring.xml | 13 +++- .../impl/MockAssertionVerifierService.java | 7 +- .../spring/config/DemoServicesConfig.java | 7 ++ 18 files changed, 230 insertions(+), 73 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index e530d4b4..4dd02e30 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -46,6 +46,7 @@ dependencies { implementation 'com.nimbusds:nimbus-jose-jwt:9.31' implementation 'ch.qos.logback:logback-classic:1.4.6' implementation 'ch.qos.logback:logback-core:1.4.6' + implementation 'org.codehaus.janino:janino:3.1.9' implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.2' implementation 'org.apache.wss4j:wss4j-ws-security-common:2.4.1' diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java index 2a7d3880..653e7bb0 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandImpl.java @@ -12,7 +12,6 @@ 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 java.io.UnsupportedEncodingException; import javax.inject.Inject; @@ -38,7 +37,7 @@ public LollipopConsumerCommandImpl( AssertionVerifierService assertionVerifierService, LollipopConsumerRequestValidationService requestValidationService, LollipopLoggerService lollipopLoggerService, - LollipopConsumerRequest lollipopConsumerRequest) { + LollipopConsumerRequest lollipopConsumerRequest) { this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; this.messageVerifierService = messageVerifierService; this.assertionVerifierService = assertionVerifierService; @@ -60,27 +59,22 @@ public CommandResult doExecute() { try { requestValidationService.validateLollipopRequest(request); - } catch (LollipopRequestContentValidationException e) { - String message = - String.format( - "Error validating Lollipop request header or body, validation failed" - + CODE_AND_MESSAGE, - e.getErrorCode(), - e.getMessage()); - return buildCommandResult(REQUEST_PARAMS_VALIDATION_FAILED, message); - } CommandResult messageVerificationResult = getHttpMessageVerificationResult(request); if (!messageVerificationResult .getResultCode() - .equals(HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_SUCCESS.name())) { + .equals( + HttpMessageVerificationResultCode.HTTP_MESSAGE_VALIDATION_SUCCESS + .name())) { logRequestAndResponse(request, messageVerificationResult); return messageVerificationResult; } CommandResult assertionVerificationResult = getAssertionVerificationResult(request); if (!assertionVerificationResult .getResultCode() - .equals(AssertionVerificationResultCode.ASSERTION_VERIFICATION_SUCCESS.name())) { + .equals( + AssertionVerificationResultCode.ASSERTION_VERIFICATION_SUCCESS + .name())) { logRequestAndResponse(request, assertionVerificationResult); return assertionVerificationResult; } @@ -96,7 +90,9 @@ public CommandResult doExecute() { return commandResult; } - commandResult = buildCommandResult(VERIFICATION_SUCCESS_CODE, "Verification completed successfully"); + commandResult = + buildCommandResult( + VERIFICATION_SUCCESS_CODE, "Verification completed successfully"); logRequestAndResponse(request, commandResult); return commandResult; } @@ -223,12 +219,13 @@ private CommandResult buildCommandResult(String resultCode, String message) { return new CommandResult(resultCode, message); } - private void logRequestAndResponse(LollipopConsumerRequest lollipopConsumerRequest, CommandResult commandResult) { + private void logRequestAndResponse( + LollipopConsumerRequest lollipopConsumerRequest, CommandResult commandResult) { if (lollipopConsumerRequestConfig.isEnableConsumerLogging()) { - lollipopLoggerService.log("Lollipop validation for request: {} completed with the result: {}", - lollipopConsumerRequest, commandResult); + lollipopLoggerService.log( + "Lollipop validation for request: {} completed with the result: {}", + lollipopConsumerRequest, + commandResult); } - } - } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java index d08b0503..93bf3555 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelper.java @@ -9,8 +9,6 @@ import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerService; import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerServiceFactory; -import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerService; -import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerServiceFactory; import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; import it.pagopa.tech.lollipop.consumer.service.HttpMessageVerifierService; import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; @@ -21,6 +19,8 @@ /** Helper class for retrieving instances */ public class LollipopConsumerFactoryHelper { + private final LollipopLoggerServiceFactory lollipopLoggerServiceFactory; + private final HttpMessageVerifierFactory httpMessageVerifierFactory; private final IdpCertProviderFactory idpCertProviderFactory; private final LollipopConsumerRequestValidationService lollipopConsumerRequestValidationService; @@ -33,8 +33,11 @@ public class LollipopConsumerFactoryHelper { private AssertionVerifierService assertionVerifierService; private LollipopConsumerRequestConfig lollipopConsumerRequestConfig; + private LollipopLoggerService lollipopLoggerService; + @Inject public LollipopConsumerFactoryHelper( + LollipopLoggerServiceFactory lollipopLoggerServiceFactory, HttpMessageVerifierFactory httpMessageVerifierFactory, IdpCertProviderFactory idpCertProviderFactory, AssertionServiceFactory assertionServiceFactory, @@ -45,6 +48,7 @@ public LollipopConsumerFactoryHelper( this.assertionServiceFactory = assertionServiceFactory; this.lollipopConsumerRequestValidationService = lollipopConsumerRequestValidationService; this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; + this.lollipopLoggerServiceFactory = lollipopLoggerServiceFactory; } /** @@ -55,9 +59,18 @@ public LollipopConsumerFactoryHelper( public HttpMessageVerifierService getHttpMessageVerifierService() { return this.httpMessageVerifierService != null ? this.httpMessageVerifierService - : new HttpMessageVerifierServiceImpl( - getHttpMessageVerifierFactory().create(), - getLollipopConsumerRequestConfig()); + : createMessageVerifierService(); + } + + private HttpMessageVerifierService createMessageVerifierService() { + + if (this.httpMessageVerifierService == null) { + this.httpMessageVerifierService = + new HttpMessageVerifierServiceImpl( + getHttpMessageVerifierFactory().create(), + getLollipopConsumerRequestConfig()); + } + return this.httpMessageVerifierService; } /** @@ -69,10 +82,19 @@ public AssertionVerifierService getAssertionVerifierService() { return this.assertionVerifierService != null ? this.assertionVerifierService - : new AssertionVerifierServiceImpl( - createIdpCertProvider(), - createAssertionService(), - getLollipopConsumerRequestConfig()); + : createAssertionVerifierService(); + } + + private synchronized AssertionVerifierService createAssertionVerifierService() { + if (this.assertionVerifierService == null) { + assertionVerifierService = + new AssertionVerifierServiceImpl( + getLollipopLoggerService(), + createIdpCertProvider(), + createAssertionService(), + getLollipopConsumerRequestConfig()); + } + return this.assertionVerifierService; } public HttpMessageVerifierFactory getHttpMessageVerifierFactory() { @@ -129,10 +151,15 @@ public void setAssertionVerifierService(AssertionVerifierService assertionVerifi } public LollipopLoggerService getLollipopLoggerService() { - return new LollipopLogbackLoggerService(); + return this.lollipopLoggerService != null + ? lollipopLoggerService + : createLollipopLoggerService(); } - public void setAssertionVerifierService(AssertionVerifierService assertionVerifierService) { - this.assertionVerifierService = assertionVerifierService; + private synchronized LollipopLoggerService createLollipopLoggerService() { + if (this.lollipopLoggerService == null) { + this.lollipopLoggerService = this.lollipopLoggerServiceFactory.create(); + } + return this.lollipopLoggerService; } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerService.java index 645ae133..aee7617e 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerService.java @@ -1,6 +1,6 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.logger; public interface LollipopLoggerService { void log(String message, Object... args); - } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerServiceFactory.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerServiceFactory.java index 65534471..8919bb93 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerServiceFactory.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/LollipopLoggerServiceFactory.java @@ -1,7 +1,7 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.logger; public interface LollipopLoggerServiceFactory { LollipopLoggerService create(); - } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerService.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerService.java index e02bb33e..f612dc65 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerService.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerService.java @@ -1,16 +1,14 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.logger.impl; import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerService; import lombok.extern.slf4j.Slf4j; -import org.slf4j.Logger; -import org.slf4j.event.Level; @Slf4j public class LollipopLogbackLoggerService implements LollipopLoggerService { @Override public void log(String message, Object... args) { - log.info(message, args); + log.info("LollipopAudit: " + message, args); } - } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactory.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactory.java index c4e9ac45..f8f7fa1c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactory.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactory.java @@ -1,3 +1,4 @@ +/* (C)2023 */ package it.pagopa.tech.lollipop.consumer.logger.impl; import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerService; @@ -8,5 +9,4 @@ public class LollipopLogbackLoggerServiceFactory implements LollipopLoggerServic public LollipopLoggerService create() { return new LollipopLogbackLoggerService(); } - } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java index 271e424f..5016617e 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java @@ -12,5 +12,4 @@ public class SamlAssertion { private String assertionRef; private String assertionData; - } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java index 50145214..608cba4c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImpl.java @@ -17,19 +17,6 @@ import it.pagopa.tech.lollipop.consumer.service.AssertionVerifierService; import it.pagopa.tech.lollipop.consumer.utils.LollipopSamlAssertionWrapper; import java.io.ByteArrayInputStream; -import it.pagopa.tech.lollipop.consumer.utils.LollipopSamlAssertionWrapper; -import java.io.ByteArrayInputStream; -import lombok.extern.slf4j.Slf4j; -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; - -import javax.inject.Inject; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; @@ -38,17 +25,16 @@ import java.security.cert.X509Certificate; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.*; import java.util.Base64; import java.util.Date; +import java.util.List; 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 lombok.extern.slf4j.Slf4j; import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.saml.SAMLKeyInfo; import org.w3c.dom.Document; @@ -58,14 +44,6 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.*; - -@Slf4j /** Standard implementation of {@link AssertionVerifierService} */ @Slf4j public class AssertionVerifierServiceImpl implements AssertionVerifierService { @@ -138,6 +116,11 @@ private Document getAssertion(String jwt, String assertionRef) SamlAssertion assertion; try { assertion = assertionService.getAssertion(jwt, assertionRef); + assertionCheckLogging( + "SAML Assertion found using assertionRef {} and jwt {}: {}", + assertionRef, + jwt, + assertion); } catch (OidcAssertionNotSupported e) { throw new ErrorRetrievingAssertionException( ErrorRetrievingAssertionException.ErrorCode.OIDC_TYPE_NOT_SUPPORTED, @@ -246,7 +229,14 @@ protected List getIdpCertData(Document assertionDoc) } instant = parseInstantToMillis(instant); try { - return idpCertProvider.getIdpCertData(instant, entityId.trim()); + entityId = entityId.trim(); + List idpCertData = idpCertProvider.getIdpCertData(instant, entityId); + this.idpCertDataLogging( + "IdP certificates has been found for entityId {} at instant {}: {}", + entityId, + instant, + idpCertData); + return idpCertData; } catch (CertDataNotFoundException e) { throw new ErrorRetrievingIdpCertDataException( ErrorRetrievingIdpCertDataException.ErrorCode.IDP_CERT_DATA_NOT_FOUND, @@ -429,13 +419,17 @@ private String getEntityId(NodeList listElements) { } private void assertionCheckLogging(String message, Object... args) { - if (lollipopRequestConfig.isEnableConsumerLogging() && lollipopRequestConfig.isEnableAssertionLogging()) { - + if (lollipopRequestConfig.isEnableConsumerLogging() + && lollipopRequestConfig.isEnableAssertionLogging()) { + lollipopLoggerService.log(message, args); } } - private void signatureCheckLogging() { - + private void idpCertDataLogging(String message, Object... args) { + if (lollipopRequestConfig.isEnableConsumerLogging() + && lollipopRequestConfig.isEnableIdpCertDataLogging()) { + lollipopLoggerService.log(message, args); + } } private String getPublicKey(String publicKey) { @@ -457,7 +451,7 @@ private String parseInstantToMillis(String instant) { String.format( "Retrieved instant %s does not match expected format %s", instant, instantDateFormat); - log.log(Level.WARNING, msg); + log.debug(msg); } return instant; } diff --git a/core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/includes/defaults.xml b/core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/includes/defaults.xml index ef0a1944..5e282db1 100644 --- a/core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/includes/defaults.xml +++ b/core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/includes/defaults.xml @@ -3,8 +3,12 @@ + + ${CONSOLE_LOG_THRESHOLD} + - %d{HH:mm:ss.SSS} [%thread] %-5level - %msg%n + ${CONSOLE_LOG_PATTERN} + ${CONSOLE_LOG_CHARSET} @@ -16,8 +20,44 @@ + + + + + + + + ${FILE_LOG_THRESHOLD} + + + ${FILE_LOG_PATTERN} + ${FILE_LOG_CHARSET} + + ${LOG_FILE} + + ${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz} + ${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false} + ${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB} + ${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0} + ${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-7} + + + + + true + 20000 + 0 + + + + + + + \ No newline at end of file diff --git a/core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/logback.xml b/core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/logback.xml index 7a33166f..dfc7d28c 100644 --- a/core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/logback.xml +++ b/core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/logback.xml @@ -1,5 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java index 18221542..10a1ba98 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java @@ -9,6 +9,7 @@ import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.exception.*; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerService; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; @@ -40,6 +41,7 @@ void setUp() { sut = spy( new AssertionVerifierServiceImpl( + new LollipopLogbackLoggerService(), idpCertProviderMock, assertionServiceMock, lollipopRequestConfigMock)); diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index c7b84545..cedb3e96 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -21,6 +21,14 @@ + + + + + + + + @@ -33,6 +41,14 @@ + + + + + + + + @@ -40,6 +56,11 @@ + + + + + @@ -3950,6 +3971,27 @@ + + + + + + + + + + + + + + + + + + + + + @@ -4572,6 +4614,17 @@ + + + + + + + + + + + @@ -5564,6 +5617,14 @@ + + + + + + + + @@ -5618,6 +5679,11 @@ + + + + + diff --git a/spring-impl/build.gradle b/spring-impl/build.gradle index 80ec9378..408b479e 100644 --- a/spring-impl/build.gradle +++ b/spring-impl/build.gradle @@ -25,6 +25,8 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test:2.7.10' testImplementation 'ch.qos.logback:logback-classic:1.2.11' testImplementation 'ch.qos.logback:logback-core:1.2.11' + testImplementation 'org.codehaus.janino:janino:3.1.9' + testImplementation 'org.slf4j:slf4j-api:1.7.36' //Mockserver for testing api testImplementation 'org.mock-server:mockserver-netty:5.15.0' testImplementation project(':http-verifier') diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java index 96926c35..7b60deb9 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/config/HttpVerifierConfiguration.java @@ -7,6 +7,7 @@ import it.pagopa.tech.lollipop.consumer.helper.LollipopConsumerFactoryHelper; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerServiceFactory; import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; import it.pagopa.tech.lollipop.consumer.service.impl.LollipopConsumerRequestValidationServiceImpl; import it.pagopa.tech.lollipop.consumer.spring.HttpVerifierHandlerInterceptor; @@ -22,12 +23,14 @@ public class HttpVerifierConfiguration { @Bean public LollipopConsumerFactoryHelper lollipopConsumerFactoryHelper( + LollipopLoggerServiceFactory lollipopLoggerServiceFactory, HttpMessageVerifierFactory httpMessageVerifierFactory, IdpCertProviderFactory idpCertProviderFactory, AssertionServiceFactory assertionServiceFactory, LollipopConsumerRequestValidationService lollipopConsumerRequestValidationService, SpringLollipopConsumerRequestConfig springLollipopConsumerRequestConfig) { return new LollipopConsumerFactoryHelper( + lollipopLoggerServiceFactory, httpMessageVerifierFactory, idpCertProviderFactory, assertionServiceFactory, diff --git a/spring-impl/src/main/resources/logback-spring.xml b/spring-impl/src/main/resources/logback-spring.xml index a999ed9c..65699bb3 100644 --- a/spring-impl/src/main/resources/logback-spring.xml +++ b/spring-impl/src/main/resources/logback-spring.xml @@ -1,7 +1,16 @@ - + + + + + + + + + \ No newline at end of file diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java index 56a6eaf6..f082955d 100644 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/MockAssertionVerifierService.java @@ -4,6 +4,7 @@ import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerService; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import java.util.List; import org.w3c.dom.Document; @@ -14,7 +15,11 @@ public MockAssertionVerifierService( IdpCertProvider idpCertProvider, AssertionService assertionService, LollipopConsumerRequestConfig lollipopRequestConfig) { - super(idpCertProvider, assertionService, lollipopRequestConfig); + super( + new LollipopLogbackLoggerService(), + idpCertProvider, + assertionService, + lollipopRequestConfig); } @Override diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java index d483c543..ce57ca09 100644 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java @@ -13,12 +13,19 @@ import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientProvider; import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImpl; +import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerServiceFactory; +import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerServiceFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class DemoServicesConfig { + @Bean + public LollipopLoggerServiceFactory lollipopLoggerServiceFactory() { + return new LollipopLogbackLoggerServiceFactory(); + } + @Bean public SpringLollipopConsumerRequestConfig verifierConfiguration() { return new SpringLollipopConsumerRequestConfig(); From 651872d432d2038c98bc66da8693ecbfde6e783f Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 20 Apr 2023 18:59:00 +0200 Subject: [PATCH 274/403] [SLS-18] Introducing LollipopLogbackLoggerServiceFactoryTest --- ...LollipopLogbackLoggerServiceFactoryTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 core/src/test/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactoryTest.java diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactoryTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactoryTest.java new file mode 100644 index 00000000..0a48062d --- /dev/null +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactoryTest.java @@ -0,0 +1,17 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.logger.impl; + +import static org.assertj.core.api.Assertions.assertThat; + +import lombok.SneakyThrows; +import org.junit.jupiter.api.Test; + +class LollipopLogbackLoggerServiceFactoryTest { + + @SneakyThrows + @Test + public void instanceIsCreated() { + assertThat(new LollipopLogbackLoggerServiceFactory().create()) + .isInstanceOf(LollipopLogbackLoggerService.class); + } +} From 90de4710ac04706867c38d2c3d5e657bc4a0eaaa Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 20 Apr 2023 19:25:21 +0200 Subject: [PATCH 275/403] [SLS-18] Introducing LollipopLogbackLoggerServiceFactoryTest --- ...ollipopConsumerCommandBuilderImplTest.java | 34 ++++++++++ .../LollipopConsumerFactoryHelperTest.java | 68 +++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplTest.java create mode 100644 core/src/test/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelperTest.java diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplTest.java new file mode 100644 index 00000000..f400e6b1 --- /dev/null +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplTest.java @@ -0,0 +1,34 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.command.impl; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +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 org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +class LollipopConsumerCommandBuilderImplTest { + + LollipopConsumerCommandBuilder lollipopConsumerCommandBuilder; + + @BeforeEach + void beforeAll() { + LollipopConsumerFactoryHelper lollipopConsumerFactoryHelper = + Mockito.mock(LollipopConsumerFactoryHelper.class); + lollipopConsumerCommandBuilder = + new LollipopConsumerCommandBuilderImpl(lollipopConsumerFactoryHelper); + } + + @Test + public void testThatCreatsCommand() { + assertThat( + lollipopConsumerCommandBuilder.createCommand( + Mockito.mock(LollipopConsumerRequest.builder().build()))) + .isInstanceOf(LollipopConsumerCommand.class); + } +} diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelperTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelperTest.java new file mode 100644 index 00000000..1f1a650b --- /dev/null +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelperTest.java @@ -0,0 +1,68 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.helper; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +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.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerServiceFactory; +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 org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +class LollipopConsumerFactoryHelperTest { + + IdpCertProviderFactory idpCertProviderFactory; + HttpMessageVerifierFactory httpMessageVerifierFactory; + LollipopLoggerServiceFactory lollipopLoggerServiceFactory; + + AssertionServiceFactory assertionServiceFactory; + + LollipopConsumerFactoryHelper lollipopConsumerFactoryHelper; + + LollipopConsumerRequestValidationService lollipopConsumerRequestValidationService; + + public LollipopConsumerFactoryHelperTest() { + idpCertProviderFactory = Mockito.mock(IdpCertProviderFactory.class); + lollipopLoggerServiceFactory = Mockito.mock(LollipopLoggerServiceFactory.class); + httpMessageVerifierFactory = Mockito.mock(HttpMessageVerifierFactory.class); + assertionServiceFactory = Mockito.mock(AssertionServiceFactory.class); + lollipopConsumerRequestValidationService = + Mockito.mock(LollipopConsumerRequestValidationService.class); + } + + @BeforeEach + public void init() { + Mockito.reset( + idpCertProviderFactory, + lollipopLoggerServiceFactory, + httpMessageVerifierFactory, + assertionServiceFactory); + lollipopConsumerFactoryHelper = + new LollipopConsumerFactoryHelper( + lollipopLoggerServiceFactory, + httpMessageVerifierFactory, + idpCertProviderFactory, + assertionServiceFactory, + lollipopConsumerRequestValidationService, + LollipopConsumerRequestConfig.builder().build()); + } + + @Test + public void testThatRetunsAssertionVerifierService() { + assertThat(lollipopConsumerFactoryHelper.getAssertionVerifierService()) + .isInstanceOf(AssertionVerifierService.class); + } + + @Test + public void testThatRetunsHttpMessageVerifierService() { + assertThat(lollipopConsumerFactoryHelper.getHttpMessageVerifierService()) + .isInstanceOf(HttpMessageVerifierService.class); + } +} From 692a5318056437ef9d817f7196e8ca7cba4e6827 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 21 Apr 2023 09:47:53 +0200 Subject: [PATCH 276/403] [SLS-18] Updated LollipopConsumerCommandBuilderImplTest --- .../command/impl/LollipopConsumerCommandBuilderImplTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplTest.java index f400e6b1..284c0898 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplTest.java @@ -28,7 +28,7 @@ void beforeAll() { public void testThatCreatsCommand() { assertThat( lollipopConsumerCommandBuilder.createCommand( - Mockito.mock(LollipopConsumerRequest.builder().build()))) + LollipopConsumerRequest.builder().build())) .isInstanceOf(LollipopConsumerCommand.class); } } From 4da3789b0e5831d8fc542ffb03a81ceba5141ead Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 21 Apr 2023 09:56:58 +0200 Subject: [PATCH 277/403] [core-sprint-3] Fixing code smells --- .../command/impl/LollipopConsumerCommandBuilderImplTest.java | 2 +- .../consumer/helper/LollipopConsumerFactoryHelperTest.java | 4 ++-- .../logger/impl/LollipopLogbackLoggerServiceFactoryTest.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplTest.java index 284c0898..80a338a6 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplTest.java @@ -25,7 +25,7 @@ void beforeAll() { } @Test - public void testThatCreatsCommand() { + void testThatCreatsCommand() { assertThat( lollipopConsumerCommandBuilder.createCommand( LollipopConsumerRequest.builder().build())) diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelperTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelperTest.java index 1f1a650b..1380c329 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelperTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/helper/LollipopConsumerFactoryHelperTest.java @@ -55,13 +55,13 @@ public void init() { } @Test - public void testThatRetunsAssertionVerifierService() { + void testThatRetunsAssertionVerifierService() { assertThat(lollipopConsumerFactoryHelper.getAssertionVerifierService()) .isInstanceOf(AssertionVerifierService.class); } @Test - public void testThatRetunsHttpMessageVerifierService() { + void testThatRetunsHttpMessageVerifierService() { assertThat(lollipopConsumerFactoryHelper.getHttpMessageVerifierService()) .isInstanceOf(HttpMessageVerifierService.class); } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactoryTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactoryTest.java index 0a48062d..b19fa71f 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactoryTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/logger/impl/LollipopLogbackLoggerServiceFactoryTest.java @@ -10,7 +10,7 @@ class LollipopLogbackLoggerServiceFactoryTest { @SneakyThrows @Test - public void instanceIsCreated() { + void instanceIsCreated() { assertThat(new LollipopLogbackLoggerServiceFactory().create()) .isInstanceOf(LollipopLogbackLoggerService.class); } From f9f159fd4dc914494dc2a3eada59fc28cc1792f4 Mon Sep 17 00:00:00 2001 From: giomella Date: Fri, 21 Apr 2023 12:03:43 +0200 Subject: [PATCH 278/403] [core-sprint-3] updated sample and added mock server. --- samples/simple/build.gradle | 1 + samples/simple/settings.gradle | 2 +- .../pagopa/tech/sample/LollipopConstants.java | 5 ++ .../tech/sample/LollipopConsumerSample.java | 61 +++++++++++++++---- 4 files changed, 55 insertions(+), 14 deletions(-) diff --git a/samples/simple/build.gradle b/samples/simple/build.gradle index 9e8dfc8c..05d0a381 100644 --- a/samples/simple/build.gradle +++ b/samples/simple/build.gradle @@ -37,6 +37,7 @@ dependencies { implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:identity-service-rest-client-native:1.0.0-SNAPSHOT' implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:http-verifier:1.0.0-SNAPSHOT' // Use JUnit Jupiter for testing. + implementation 'org.mock-server:mockserver-netty:5.15.0' testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' } diff --git a/samples/simple/settings.gradle b/samples/simple/settings.gradle index 763affdd..e98f922e 100644 --- a/samples/simple/settings.gradle +++ b/samples/simple/settings.gradle @@ -6,4 +6,4 @@ pluginManagement { } -rootProject.name = 'sample' \ No newline at end of file +rootProject.name = 'simple' \ No newline at end of file diff --git a/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConstants.java b/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConstants.java index 7c80c4f1..d9bda442 100644 --- a/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConstants.java +++ b/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConstants.java @@ -58,5 +58,10 @@ public class LollipopConstants { + "k2YURaSjdBOEx6bzBLU3kgIFpZb0E0ODVtcWNPMEdWQWRWdzlscTRhT1Q5djZkLW5iNGJuTmtRVmtsTFE" + "zZlZBdkptLXhkRE9wOUxDTkNONDhWICAycG5ET2tGVjYtVTluVjVveWM2WEkydyJ9"; + public static final String VALID_ASSERTION_REF = + "sha256-_ZzL8qeuAM5kQ9pbMB4tn7IDSQZCVXAkW9fm4P7ULPI"; + public static final String VALID_FISCAL_CODE = "AAAAAA89S20I111X"; + public static final String VALID_JWT = "aValidJWT"; + public LollipopConstants() {} } diff --git a/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java b/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java index 5ba96f36..200540c0 100644 --- a/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java +++ b/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java @@ -5,8 +5,9 @@ import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientConfig; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientProvider; import it.pagopa.tech.lollipop.consumer.assertion.impl.AssertionServiceFactoryImpl; -import it.pagopa.tech.lollipop.consumer.assertion.storage.*; -import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; +import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorageProvider; +import it.pagopa.tech.lollipop.consumer.assertion.storage.SimpleAssertionStorageProvider; +import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; import it.pagopa.tech.lollipop.consumer.command.impl.LollipopConsumerCommandBuilderImpl; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; @@ -17,19 +18,30 @@ import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientProvider; import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImpl; +import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerServiceFactory; +import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerServiceFactory; import it.pagopa.tech.lollipop.consumer.model.CommandResult; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.impl.LollipopConsumerRequestValidationServiceImpl; +import org.mockserver.client.MockServerClient; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.model.Header; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.HashMap; -import java.util.logging.Logger; import static it.pagopa.tech.sample.LollipopConstants.*; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; public class LollipopConsumerSample { + private static LollipopConsumerRequestConfig lollipopConsumerRequestConfig; + public static void main(String[] args) throws Exception { + ClientAndServer clientAndServer = createExpectationAssertionFound(); LollipopConsumerCommandBuilder commandBuilder = new LollipopConsumerCommandBuilderImpl(buildLollipopConsumerFactoryHelper()); CommandResult commandResult = commandBuilder.createCommand(buildLollipopRequest( @@ -61,10 +73,11 @@ public static void main(String[] args) throws Exception { // VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, LOLLIPOP_RSA_PUBKEY, VALID_RSA_PSS_SIGNATURE_INPUT, VALID_RSA_PSS_SIGNATURE)); // Logger.getGlobal().info(buildMessage(commandResult, "Validation of a valid Lollipop request with rsa-pss-256 signature ended with status code: ")); + clientAndServer.stop(); } private static LollipopConsumerFactoryHelper buildLollipopConsumerFactoryHelper() throws Exception { - LollipopConsumerRequestConfig lollipopConsumerRequestConfig = new LollipopConsumerRequestConfig(); + lollipopConsumerRequestConfig = new LollipopConsumerRequestConfig(); HttpMessageVerifierFactory messageVerifierFactory = new VismaHttpMessageVerifierFactory(VALID_ENCODING_UTF8, LollipopConsumerRequestConfig.builder().build()); AssertionStorageProvider assertionStorageProvider = new SimpleAssertionStorageProvider(); @@ -74,8 +87,9 @@ private static LollipopConsumerFactoryHelper buildLollipopConsumerFactoryHelper( new AssertionSimpleClientProvider(AssertionSimpleClientConfig.builder().build()); AssertionServiceFactory assertionServiceFactory = new AssertionServiceFactoryImpl( assertionStorageProvider, assertionClientProvider, new StorageConfig()); - return new LollipopConsumerFactoryHelper(messageVerifierFactory, idpCertProviderFactory, assertionServiceFactory, - new LollipopConsumerRequestValidationServiceImpl(lollipopConsumerRequestConfig)); + LollipopLoggerServiceFactory lollipopLoggerServiceFactory = new LollipopLogbackLoggerServiceFactory(); + return new LollipopConsumerFactoryHelper(lollipopLoggerServiceFactory, messageVerifierFactory, idpCertProviderFactory, assertionServiceFactory, + new LollipopConsumerRequestValidationServiceImpl(lollipopConsumerRequestConfig), lollipopConsumerRequestConfig); } private static LollipopConsumerRequest buildLollipopRequest( @@ -86,14 +100,18 @@ private static LollipopConsumerRequest buildLollipopRequest( String signatureInput, String signature) { HashMap lollipopHeaderParams = new HashMap<>(); - lollipopHeaderParams.put(CONTENT_DIGEST, contentDigest); - lollipopHeaderParams.put(CONTENT_ENCODING, encoding); - lollipopHeaderParams.put(SIGNATURE_INPUT, signatureInput); - lollipopHeaderParams.put(SIGNATURE, signature); - lollipopHeaderParams.put(LOLLIPOP_KEY, lollipopKey); - lollipopHeaderParams.put(LOLLIPOP_ORIGIN_METHOD, EXPECTED_ORIGIN_METHOD); - lollipopHeaderParams.put(LOLLIPOP_ORIGIN_URL, EXCPECTED_ORIGIN_URL); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getContentDigestHeader(), contentDigest); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getContentEncodingHeader(), encoding); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getSignatureInputHeader(), signatureInput); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getSignatureHeader(), signature); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getPublicKeyHeader(), lollipopKey); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getOriginalMethodHeader(), EXPECTED_ORIGIN_METHOD); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getOriginalURLHeader(), EXCPECTED_ORIGIN_URL); lollipopHeaderParams.put("X-io-sign-qtspclauses","anIoSignClauses"); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getAssertionRefHeader(), VALID_ASSERTION_REF); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getAssertionTypeHeader(), "SAML"); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getAuthJWTHeader(), VALID_JWT); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getUserIdHeader(), VALID_FISCAL_CODE); return LollipopConsumerRequest.builder() @@ -105,4 +123,21 @@ private static LollipopConsumerRequest buildLollipopRequest( private static String buildMessage(CommandResult commandResult, String s) { return s + commandResult.getResultCode() + " and message: " + commandResult.getResultMessage(); } + + private static ClientAndServer createExpectationAssertionFound() { + String RESPONSE_STRING = "{\"response_xml\": \" " + " https://posteid.poste.it" + " " + " " + " " + " " + " " + " " + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" + " " + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + " " + " " + " " + " https://posteid.poste.it " + " " + " " + " " + " " + " " + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" + " " + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + " " + " " + " " + " " + " https://app-backend.io.italia.it" + " " + " https://www.spid.gov.it/SpidL2" + " " + " TINIT-AAAAAA89S20I111X" + " " + " \"}"; + + ClientAndServer clientAndServer = ClientAndServer.startClientAndServer(3000); + new MockServerClient("localhost", 3000) + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", VALID_ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", VALID_JWT))) + .respond(response().withStatusCode(200).withBody(RESPONSE_STRING)); + return clientAndServer; + } } From d71be9b2d25cc69112ac3d49706ba18dbb60d99b Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 21 Apr 2023 12:47:41 +0200 Subject: [PATCH 279/403] [core-sprint-3] Updated samples --- .../tech/lollipop/logging/logback/logback.xml | 2 + .../tech/sample/LollipopConsumerSample.java | 80 ++++++++++--------- .../sample/MockAssertionVerifierService.java | 31 +++++++ samples/spring/build.gradle | 4 + samples/spring/settings.gradle | 2 +- samples/spring/src/Main.java | 5 -- .../consumer/sample/SampleApplication.java | 1 - .../sample/config/SampleServicesConfig.java | 7 ++ .../src/main/resources/application.properties | 1 + .../src/main/resources/logback-spring.xml | 23 ++++++ 10 files changed, 112 insertions(+), 44 deletions(-) create mode 100644 samples/simple/src/main/java/it/pagopa/tech/sample/MockAssertionVerifierService.java delete mode 100644 samples/spring/src/Main.java diff --git a/core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/logback.xml b/core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/logback.xml index dfc7d28c..e66db06f 100644 --- a/core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/logback.xml +++ b/core/src/main/resources/it/pagopa/tech/lollipop/logging/logback/logback.xml @@ -9,4 +9,6 @@ + + \ No newline at end of file diff --git a/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java b/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java index 200540c0..617e2de9 100644 --- a/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java +++ b/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java @@ -41,39 +41,46 @@ public class LollipopConsumerSample { private static LollipopConsumerRequestConfig lollipopConsumerRequestConfig; public static void main(String[] args) throws Exception { - ClientAndServer clientAndServer = createExpectationAssertionFound(); - LollipopConsumerCommandBuilder commandBuilder = new LollipopConsumerCommandBuilderImpl(buildLollipopConsumerFactoryHelper()); - - CommandResult commandResult = commandBuilder.createCommand(buildLollipopRequest( - VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)) + ClientAndServer clientAndServer = ClientAndServer.startClientAndServer(3000); + MockServerClient mockServerClient = createExpectationAssertionFound(); + LollipopConsumerFactoryHelper lollipopConsumerFactoryHelper = buildLollipopConsumerFactoryHelper(); + lollipopConsumerFactoryHelper.setAssertionVerifierService(new MockAssertionVerifierService( + lollipopConsumerFactoryHelper.getIdpCertProviderFactory().create(), + lollipopConsumerFactoryHelper.getAssertionServiceFactory().create(), LollipopConsumerRequestConfig.builder().build())); + LollipopConsumerCommandBuilder commandBuilder = new LollipopConsumerCommandBuilderImpl(lollipopConsumerFactoryHelper); + + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)) .doExecute(); - //Logger.getGlobal().info(buildMessage(commandResult, "Validation of a valid Lollipop request ended with status code: ")); - -// commandResult = command.doExecute(buildLollipopRequest( -// INVALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)); -// Logger.getGlobal().info(buildMessage(commandResult, "Validation of a Lollipop request with invalid digest header ended with status code: ")); -// -// commandResult = command.doExecute(buildLollipopRequest( -// VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, INVALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)); -// Logger.getGlobal().info(buildMessage(commandResult, "Validation of a Lollipop request with invalid content ended with status code: ")); -// -// commandResult = command.doExecute(buildLollipopRequest( -// VALID_CONTENT_DIGEST, INVALID_ENCODING_UTF_326, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)); -// Logger.getGlobal().info(buildMessage(commandResult, "Validation of a Lollipop request with unsupported encoding ended with status code: ")); -// -// commandResult = command.doExecute(buildLollipopRequest( -// VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, SIGNATURE_INPUT_HEADER_VALUE, INVALID_SIGNATURE_HEADER_VALUE)); -// Logger.getGlobal().info(buildMessage(commandResult, "Validation of a Lollipop request with invalid signature ended with status code: ")); -// -// commandResult = command.doExecute(buildLollipopRequest( -// VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, VALID_MULTI_ECDSA_IGNATURE_INPUT, VALID_MULTI_ECDSA_SIGNATURE)); -// Logger.getGlobal().info(buildMessage(commandResult, "Validation of a valid Lollipop request with ecdsa multi-signature ended with status code: ")); -// -// commandResult = command.doExecute(buildLollipopRequest( -// VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, LOLLIPOP_RSA_PUBKEY, VALID_RSA_PSS_SIGNATURE_INPUT, VALID_RSA_PSS_SIGNATURE)); -// Logger.getGlobal().info(buildMessage(commandResult, "Validation of a valid Lollipop request with rsa-pss-256 signature ended with status code: ")); - - clientAndServer.stop(); + + commandBuilder.createCommand(buildLollipopRequest( + INVALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)).doExecute(); + + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, INVALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)).doExecute(); + + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, INVALID_ENCODING_UTF_326, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)).doExecute(); + + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, INVALID_SIGNATURE_HEADER_VALUE)).doExecute(); + + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + VALID_MULTI_ECDSA_IGNATURE_INPUT, VALID_MULTI_ECDSA_SIGNATURE)).doExecute(); + + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, + LOLLIPOP_RSA_PUBKEY, VALID_RSA_PSS_SIGNATURE_INPUT, VALID_RSA_PSS_SIGNATURE)).doExecute(); + + clientAndServer.close(); + mockServerClient.close(); + return; } private static LollipopConsumerFactoryHelper buildLollipopConsumerFactoryHelper() throws Exception { @@ -124,12 +131,11 @@ private static String buildMessage(CommandResult commandResult, String s) { return s + commandResult.getResultCode() + " and message: " + commandResult.getResultMessage(); } - private static ClientAndServer createExpectationAssertionFound() { + private static MockServerClient createExpectationAssertionFound() { String RESPONSE_STRING = "{\"response_xml\": \" " + " https://posteid.poste.it" + " " + " " + " " + " " + " " + " " + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" + " " + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + " " + " " + " " + " https://posteid.poste.it " + " " + " " + " " + " " + " " + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" + " " + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + " " + " " + " " + " " + " https://app-backend.io.italia.it" + " " + " https://www.spid.gov.it/SpidL2" + " " + " TINIT-AAAAAA89S20I111X" + " " + " \"}"; - ClientAndServer clientAndServer = ClientAndServer.startClientAndServer(3000); - new MockServerClient("localhost", 3000) - .when( + MockServerClient mockServerClient = new MockServerClient("localhost", 3000); + mockServerClient.when( request() .withMethod("GET") .withPath("/assertions/{assertion}") @@ -138,6 +144,6 @@ private static ClientAndServer createExpectationAssertionFound() { new Header("Accept", "application/json"), new Header("x-pagopa-lollipop-auth", VALID_JWT))) .respond(response().withStatusCode(200).withBody(RESPONSE_STRING)); - return clientAndServer; + return mockServerClient; } } diff --git a/samples/simple/src/main/java/it/pagopa/tech/sample/MockAssertionVerifierService.java b/samples/simple/src/main/java/it/pagopa/tech/sample/MockAssertionVerifierService.java new file mode 100644 index 00000000..4611c4c4 --- /dev/null +++ b/samples/simple/src/main/java/it/pagopa/tech/sample/MockAssertionVerifierService.java @@ -0,0 +1,31 @@ +/* (C)2023 */ +package it.pagopa.tech.sample; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerService; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import it.pagopa.tech.lollipop.consumer.service.impl.AssertionVerifierServiceImpl; +import org.w3c.dom.Document; + +import java.util.List; + +public class MockAssertionVerifierService extends AssertionVerifierServiceImpl { + + public MockAssertionVerifierService( + IdpCertProvider idpCertProvider, + AssertionService assertionService, + LollipopConsumerRequestConfig lollipopRequestConfig) { + super( + new LollipopLogbackLoggerService(), + idpCertProvider, + assertionService, + lollipopRequestConfig); + } + + @Override + protected boolean validateSignature(Document assertionDoc, List idpCertDataList) { + return true; + } +} diff --git a/samples/spring/build.gradle b/samples/spring/build.gradle index 1c5a0db2..83047e3d 100644 --- a/samples/spring/build.gradle +++ b/samples/spring/build.gradle @@ -35,6 +35,10 @@ dependencies { implementation 'org.mock-server:mockserver-netty:5.15.0' implementation 'org.springframework.boot:spring-boot-starter-web' + testImplementation 'ch.qos.logback:logback-classic:1.2.11' + testImplementation 'ch.qos.logback:logback-core:1.2.11' + testImplementation 'org.codehaus.janino:janino:3.1.9' + testImplementation 'org.slf4j:slf4j-api:1.7.36' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' annotationProcessor 'org.projectlombok:lombok' diff --git a/samples/spring/settings.gradle b/samples/spring/settings.gradle index 88d146cd..edb53beb 100644 --- a/samples/spring/settings.gradle +++ b/samples/spring/settings.gradle @@ -1 +1 @@ -rootProject.name = 'sample' +rootProject.name = 'spring-application-sample' diff --git a/samples/spring/src/Main.java b/samples/spring/src/Main.java deleted file mode 100644 index 3e59c38f..00000000 --- a/samples/spring/src/Main.java +++ /dev/null @@ -1,5 +0,0 @@ -public class Main { - public static void main(String[] args) { - System.out.println("Hello world!"); - } -} \ No newline at end of file diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java index b61526ee..054308f9 100644 --- a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java @@ -19,7 +19,6 @@ public class SampleApplication { public static void main(String[] args) { - SpringApplication.run(SampleApplication.class, args); createExpectationAssertionFound(); } diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java index ccd49cf2..918ff1ec 100644 --- a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java @@ -13,6 +13,8 @@ import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientProvider; import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImpl; +import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerServiceFactory; +import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerServiceFactory; import it.pagopa.tech.lollipop.consumer.spring.config.SpringLollipopConsumerRequestConfig; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; @@ -22,6 +24,11 @@ @EnableConfigurationProperties(value = {SpringLollipopConsumerRequestConfig.class}) public class SampleServicesConfig { + @Bean + public LollipopLoggerServiceFactory lollipopLoggerServiceFactory() { + return new LollipopLogbackLoggerServiceFactory(); + } + @Bean public HttpMessageVerifierFactory httpMessageVerifierFactory(SpringLollipopConsumerRequestConfig springLollipopConsumerRequestConfig) throws Exception { return new VismaHttpMessageVerifierFactory("UTF-8", springLollipopConsumerRequestConfig); diff --git a/samples/spring/src/main/resources/application.properties b/samples/spring/src/main/resources/application.properties index 11706021..3137ca31 100644 --- a/samples/spring/src/main/resources/application.properties +++ b/samples/spring/src/main/resources/application.properties @@ -1,3 +1,4 @@ +spring.application.name=spring-lollipop-consumer lollipop.core.config.assertionExpireInDays=180 diff --git a/spring-impl/src/main/resources/logback-spring.xml b/spring-impl/src/main/resources/logback-spring.xml index 65699bb3..36316dda 100644 --- a/spring-impl/src/main/resources/logback-spring.xml +++ b/spring-impl/src/main/resources/logback-spring.xml @@ -1,6 +1,9 @@ + + @@ -13,4 +16,24 @@ + + + ${CONSOLE_LOG_PATTERN} + + + + + true + 20000 + 0 + + + + + + + \ No newline at end of file From 6b8bdb507f6e043c260bbe1f009e2204d67e0253 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 21 Apr 2023 17:36:26 +0200 Subject: [PATCH 280/403] [1.0.0-RC1] Preparing for RC1 release --- .../simple/AssertionSimpleClientConfig.java | 6 +++- build.gradle | 2 +- .../simple/IdpCertSimpleClientConfig.java | 6 +++- .../simple/IdpCertSimpleClientProvider.java | 14 +++++--- samples/simple/build.gradle | 35 ++++++++++++------- samples/simple/settings.gradle | 2 +- samples/spring/build.gradle | 22 ++++++++---- .../consumer/sample/SampleApplication.java | 2 +- .../sample/config/SampleServicesConfig.java | 25 +++++++------ .../SpringAssertionSimpleClientConfig.java | 11 ++++++ .../config/SpringAssertionStorageConfig.java | 12 +++++++ .../SpringIdpCertSimpleClientConfig.java | 11 ++++++ .../config/SpringIdpCertStorageConfig.java | 11 ++++++ .../src/main/resources/application.properties | 24 ++++++++++++- .../spring/config/DemoServicesConfig.java | 7 +++- 15 files changed, 148 insertions(+), 42 deletions(-) create mode 100644 samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SpringAssertionSimpleClientConfig.java create mode 100644 samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SpringAssertionStorageConfig.java create mode 100644 samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SpringIdpCertSimpleClientConfig.java create mode 100644 samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SpringIdpCertStorageConfig.java diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientConfig.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientConfig.java index b2230ed8..a0b40182 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientConfig.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientConfig.java @@ -1,11 +1,15 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; -@Data @Builder +@Data +@NoArgsConstructor +@AllArgsConstructor public class AssertionSimpleClientConfig { @Builder.Default private String baseUri = "http://localhost:3000"; diff --git a/build.gradle b/build.gradle index bcee8be2..d2b94557 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ repositories { } allprojects { - version = "1.0.0-SNAPSHOT" + version = "1.0.0-RC1" group = 'it.pagopa.tech.lollipop-consumer-java-sdk' sourceCompatibility = '11' targetCompatibility = '11' diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java index d744001b..122984ef 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientConfig.java @@ -2,11 +2,15 @@ package it.pagopa.tech.lollipop.consumer.idp.client.simple; import java.util.List; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; -@Data @Builder +@Data +@NoArgsConstructor +@AllArgsConstructor public class IdpCertSimpleClientConfig { @Builder.Default diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java index 6a9f5ba1..161acd40 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java @@ -4,18 +4,25 @@ import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; -import it.pagopa.tech.lollipop.consumer.idp.client.simple.storage.SimpleIdpCertStorageProvider; import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageProvider; import javax.inject.Inject; /** Provider class for retrieving an instance of {@link IdpCertSimpleClient} */ public class IdpCertSimpleClientProvider implements IdpCertClientProvider { private final IdpCertSimpleClientConfig idpClientConfig; + private final IdpCertStorageProvider idpCertStorageProvider; + private final IdpCertStorageConfig idpCertStorageConfig; @Inject - public IdpCertSimpleClientProvider(IdpCertSimpleClientConfig config) { + public IdpCertSimpleClientProvider( + IdpCertSimpleClientConfig config, + IdpCertStorageProvider idpCertStorageProvider, + IdpCertStorageConfig idpCertStorageConfig) { this.idpClientConfig = config; + this.idpCertStorageProvider = idpCertStorageProvider; + this.idpCertStorageConfig = idpCertStorageConfig; } /** * Provide an instance of {@link IdpCertSimpleClient} @@ -24,10 +31,9 @@ public IdpCertSimpleClientProvider(IdpCertSimpleClientConfig config) { */ @Override public IdpCertClient provideClient() { - SimpleIdpCertStorageProvider storageProvider = new SimpleIdpCertStorageProvider(); return new IdpCertSimpleClient( new ApiClient(this.idpClientConfig), this.idpClientConfig, - storageProvider.provideStorage(new IdpCertStorageConfig())); + idpCertStorageProvider.provideStorage(idpCertStorageConfig)); } } diff --git a/samples/simple/build.gradle b/samples/simple/build.gradle index 05d0a381..70ff860a 100644 --- a/samples/simple/build.gradle +++ b/samples/simple/build.gradle @@ -6,12 +6,16 @@ * User Manual available at https://docs.gradle.org/8.0.2/userguide/building_java_projects.html */ - plugins { // Apply the java-library plugin for API and implementation separation. id 'application' } + +group = 'it.pagopa.tech.lollipop.consumer.samples' +version = '1.0.0-RC1' +sourceCompatibility = '11' + application { mainClassName = "it.pagopa.tech.sample.LollipopConsumerSample" } @@ -19,23 +23,28 @@ application { repositories { mavenLocal() mavenCentral() - repositories { - maven { - name = "GitHubPackages" - url = "https://maven.pkg.github.com/pagopa/eng-lollipop-consumer-java-sdk" - credentials { - username = System.getenv("GITHUB_ACTOR") - password = System.getenv("GITHUB_TOKEN") - } + maven { + url = uri("https://maven.pkg.github.com/pagopa/eng-http-signatures") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + } + } + maven { + name = "GitHubPackages" + url = "https://maven.pkg.github.com/pagopa/eng-lollipop-consumer-java-sdk" + credentials { + username = System.getenv("GITHUB_ACTOR") + password = System.getenv("GITHUB_TOKEN") } } } dependencies { - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:core:1.0.0-SNAPSHOT' - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:assertion-rest-client-native:1.0.0-SNAPSHOT' - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:identity-service-rest-client-native:1.0.0-SNAPSHOT' - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:http-verifier:1.0.0-SNAPSHOT' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:core:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:assertion-rest-client-native:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:identity-service-rest-client-native:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:http-verifier:1.0.0-RC1' // Use JUnit Jupiter for testing. implementation 'org.mock-server:mockserver-netty:5.15.0' testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' diff --git a/samples/simple/settings.gradle b/samples/simple/settings.gradle index e98f922e..bf66c794 100644 --- a/samples/simple/settings.gradle +++ b/samples/simple/settings.gradle @@ -6,4 +6,4 @@ pluginManagement { } -rootProject.name = 'simple' \ No newline at end of file +rootProject.name = 'simple-lollipop-sample' \ No newline at end of file diff --git a/samples/spring/build.gradle b/samples/spring/build.gradle index 83047e3d..0d766de3 100644 --- a/samples/spring/build.gradle +++ b/samples/spring/build.gradle @@ -4,8 +4,8 @@ plugins { id 'io.spring.dependency-management' version '1.0.15.RELEASE' } -group = 'it.pagopa.tech.lollipop.consumer' -version = '0.0.1-SNAPSHOT' +group = 'it.pagopa.tech.lollipop.consumer.samples' +version = '1.0.0-RC1' sourceCompatibility = '11' configurations { @@ -24,14 +24,22 @@ repositories { password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") } } + maven { + name = "GitHubPackages" + url = "https://maven.pkg.github.com/pagopa/eng-lollipop-consumer-java-sdk" + credentials { + username = System.getenv("GITHUB_ACTOR") + password = System.getenv("GITHUB_TOKEN") + } + } } dependencies { - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:core:1.0.0-SNAPSHOT' - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:assertion-rest-client-native:1.0.0-SNAPSHOT' - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:identity-service-rest-client-native:1.0.0-SNAPSHOT' - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:http-verifier:1.0.0-SNAPSHOT' - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:spring-impl:1.0.0-SNAPSHOT' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:core:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:assertion-rest-client-native:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:identity-service-rest-client-native:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:http-verifier:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:spring-impl:1.0.0-RC1' implementation 'org.mock-server:mockserver-netty:5.15.0' implementation 'org.springframework.boot:spring-boot-starter-web' diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java index 054308f9..9a9ec6a1 100644 --- a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java @@ -20,7 +20,7 @@ public class SampleApplication { public static void main(String[] args) { SpringApplication.run(SampleApplication.class, args); - createExpectationAssertionFound(); + //createExpectationAssertionFound(); } private static void createExpectationAssertionFound() { diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java index 918ff1ec..e460f4cc 100644 --- a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java @@ -12,7 +12,9 @@ import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.storage.SimpleIdpCertStorageProvider; import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImpl; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerServiceFactory; import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerServiceFactory; import it.pagopa.tech.lollipop.consumer.spring.config.SpringLollipopConsumerRequestConfig; @@ -21,7 +23,8 @@ import org.springframework.context.annotation.Configuration; @Configuration -@EnableConfigurationProperties(value = {SpringLollipopConsumerRequestConfig.class}) +@EnableConfigurationProperties(value = {SpringLollipopConsumerRequestConfig.class, SpringAssertionStorageConfig.class, + SpringAssertionSimpleClientConfig.class, SpringIdpCertSimpleClientConfig.class, SpringIdpCertStorageConfig.class}) public class SampleServicesConfig { @Bean @@ -30,26 +33,26 @@ public LollipopLoggerServiceFactory lollipopLoggerServiceFactory() { } @Bean - public HttpMessageVerifierFactory httpMessageVerifierFactory(SpringLollipopConsumerRequestConfig springLollipopConsumerRequestConfig) throws Exception { + public HttpMessageVerifierFactory httpMessageVerifierFactory( + SpringLollipopConsumerRequestConfig springLollipopConsumerRequestConfig) throws Exception { return new VismaHttpMessageVerifierFactory("UTF-8", springLollipopConsumerRequestConfig); } @Bean - public IdpCertProviderFactory idpCertProviderFactory() { + public IdpCertProviderFactory idpCertProviderFactory(IdpCertSimpleClientConfig simpleClientConfig, + IdpCertStorageConfig idpCertStorageConfig) { return new IdpCertProviderFactoryImpl( - new IdpCertSimpleClientProvider(IdpCertSimpleClientConfig.builder().build())); + new IdpCertSimpleClientProvider(simpleClientConfig,new SimpleIdpCertStorageProvider(), idpCertStorageConfig)); } @Bean - public AssertionServiceFactory assertionServiceFactory() { + public AssertionServiceFactory assertionServiceFactory( + SpringAssertionSimpleClientConfig assertionSimpleClientConfig, + SpringAssertionStorageConfig assertionStorageConfig) { return new AssertionServiceFactoryImpl( new SimpleAssertionStorageProvider(), - new AssertionSimpleClientProvider(AssertionSimpleClientConfig.builder().build()), - storageConfig()); + new AssertionSimpleClientProvider(assertionSimpleClientConfig), + assertionStorageConfig); } - @Bean - public StorageConfig storageConfig() { - return new StorageConfig(); - } } diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SpringAssertionSimpleClientConfig.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SpringAssertionSimpleClientConfig.java new file mode 100644 index 00000000..ab04050b --- /dev/null +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SpringAssertionSimpleClientConfig.java @@ -0,0 +1,11 @@ +package it.pagopa.tech.lollipop.consumer.sample.config; + +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientConfig; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; + +@ConfigurationProperties( + prefix = "lollipop.assertion.rest.config" +) +@ConfigurationPropertiesScan +public class SpringAssertionSimpleClientConfig extends AssertionSimpleClientConfig {} diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SpringAssertionStorageConfig.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SpringAssertionStorageConfig.java new file mode 100644 index 00000000..77087256 --- /dev/null +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SpringAssertionStorageConfig.java @@ -0,0 +1,12 @@ +package it.pagopa.tech.lollipop.consumer.sample.config; + +import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; + +@ConfigurationProperties( + prefix = "lollipop.assertion.storage.config" +) +@ConfigurationPropertiesScan +public class SpringAssertionStorageConfig extends StorageConfig { +} diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SpringIdpCertSimpleClientConfig.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SpringIdpCertSimpleClientConfig.java new file mode 100644 index 00000000..dc94202e --- /dev/null +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SpringIdpCertSimpleClientConfig.java @@ -0,0 +1,11 @@ +package it.pagopa.tech.lollipop.consumer.sample.config; + +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; + +@ConfigurationProperties( + prefix = "lollipop.idp.rest.config" +) +@ConfigurationPropertiesScan +public class SpringIdpCertSimpleClientConfig extends IdpCertSimpleClientConfig {} diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SpringIdpCertStorageConfig.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SpringIdpCertStorageConfig.java new file mode 100644 index 00000000..1c8adecd --- /dev/null +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SpringIdpCertStorageConfig.java @@ -0,0 +1,11 @@ +package it.pagopa.tech.lollipop.consumer.sample.config; + +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; + +@ConfigurationProperties( + prefix = "lollipop.idp.storage.config" +) +@ConfigurationPropertiesScan +public class SpringIdpCertStorageConfig extends IdpCertStorageConfig {} diff --git a/samples/spring/src/main/resources/application.properties b/samples/spring/src/main/resources/application.properties index 3137ca31..6fc93cec 100644 --- a/samples/spring/src/main/resources/application.properties +++ b/samples/spring/src/main/resources/application.properties @@ -1,4 +1,26 @@ spring.application.name=spring-lollipop-consumer -lollipop.core.config.assertionExpireInDays=180 + +##General Lollipop Configs Sample +lollipop.core.config.assertionExpireInDays=${LOLLIPOP_ASSERTION_EXPIRE_IN_DAYS:180} +lollipop.core.config.expectedFirstLcOriginalUrl=${LOLLIPOP_EXPECTED_LC_ORIGINAL_URL:https://api-app.io.pagopa.it/first-lollipop/sign} +lollipop.core.config.expectedFirstLcOriginalMethod=${LOLLIPOP_EXPECTED_LC_ORIGINAL_METHOD:POST} + +###Idp Client Configs +lollipop.idp.rest.config.cieEntityId=${IDP_CLIENT_CIEID:https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO} +lollipop.idp.rest.config.baseUri=${IDP_CLIENT_BASE_URI:https://api.is.eng.pagopa.it} +lollipop.idp.rest.config.idpKeysCieEndpoint=${IDP_CLIENT_CIE_ENDPOINT:/idp-keys/cie} +lollipop.idp.rest.config.idpKeysSpidEndpoint=${IDP_CLIENT_SPID_ENDPOINT:/idp-keys/spid} + +###Idp Storage Configs +lollipop.idp.storage.config.idpCertDataStorageEnabled=${IDP_STORAGE_ENABLED:true} +lollipop.idp.storage.config.storageEvictionDelay=${IDP_STORAGE_EVICTION_DELAY:1} + +##Assertion Client Configs +lollipop.assertion.rest.config.baseUri=${ASSERTION_REST_URI:http://localhost:3000} +lollipop.assertion.rest.config.assertionRequestEndpoint=${ASSERTION_REST_ENDPOINT:/assertions} + +##Assertion Storage Configs +lollipop.assertion.rest.config.assertionStorageEnabled=${ASSERTION_STORAGE_ENABLED:true} +lollipop.assertion.rest.config.storageEvictionDelay=${ASSERTION_STORAGE_EVICTION_DELAY:1} diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java index ce57ca09..201f80aa 100644 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java @@ -12,7 +12,9 @@ import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.storage.SimpleIdpCertStorageProvider; import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImpl; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerServiceFactory; import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerServiceFactory; import org.springframework.context.annotation.Bean; @@ -39,7 +41,10 @@ public HttpMessageVerifierFactory httpMessageVerifierFactory() throws Exception @Bean public IdpCertProviderFactory idpCertProviderFactory() { return new IdpCertProviderFactoryImpl( - new IdpCertSimpleClientProvider(IdpCertSimpleClientConfig.builder().build())); + new IdpCertSimpleClientProvider( + IdpCertSimpleClientConfig.builder().build(), + new SimpleIdpCertStorageProvider(), + new IdpCertStorageConfig())); } @Bean From 1f953a8fda4d50819538b879bf92e16aa6e59bb7 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 21 Apr 2023 17:54:52 +0200 Subject: [PATCH 281/403] [1.0.0-RC1] Updated pr_scan.yml --- .github/workflows/pr_scan.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index c5d14fc4..a2a48018 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -77,7 +77,8 @@ jobs: -Dsonar.organization=pagopa -Dsonar.projectKey=${{ env.PROJECT_KEY }} -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml - -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*" + -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception" + -Dsonar.cpd.exclusions="**/model/**,**/entity/*,**/simple/internal/*" -Dsonar.host.url=https://sonarcloud.io -Dsonar.java.libraries="**/*.jar" -Dsonar.login=${{ env.SONAR_TOKEN }} From 00fe1b812c5980217cd573023fb57a2c7065687f Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 21 Apr 2023 18:07:25 +0200 Subject: [PATCH 282/403] [1.0.0-RC1] Updated pr_scan.yml --- .github/workflows/pr_scan.yml | 4 ++-- build.gradle | 2 +- test-coverage/build.gradle | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index a2a48018..d1a3ae25 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -77,8 +77,8 @@ jobs: -Dsonar.organization=pagopa -Dsonar.projectKey=${{ env.PROJECT_KEY }} -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml - -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception" - -Dsonar.cpd.exclusions="**/model/**,**/entity/*,**/simple/internal/*" + -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" + -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" -Dsonar.host.url=https://sonarcloud.io -Dsonar.java.libraries="**/*.jar" -Dsonar.login=${{ env.SONAR_TOKEN }} diff --git a/build.gradle b/build.gradle index d2b94557..a76c3f38 100644 --- a/build.gradle +++ b/build.gradle @@ -162,7 +162,7 @@ subprojects { test { finalizedBy jacocoTestReport // report is always generated after tests run jacoco { - excludes = ["**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*"] + excludes = ["**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*","**/*Exception*"] } } diff --git a/test-coverage/build.gradle b/test-coverage/build.gradle index 894f7759..6f9ebeaa 100644 --- a/test-coverage/build.gradle +++ b/test-coverage/build.gradle @@ -42,7 +42,7 @@ testCodeCoverageReport { project(':spring-impl') ].collect { it.fileTree(dir: "${it.buildDir}/classes", exclude: [ - "**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*" + "**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*","**/*Exception*" ]) } )) From 79e6727c9ea43122e5eacd07e93ab10b4040eb84 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 21 Apr 2023 18:28:35 +0200 Subject: [PATCH 283/403] [1.0.0-RC1] Updated pr_scan.yml --- .github/workflows/pr_scan.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index d1a3ae25..f88cb992 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -64,7 +64,8 @@ jobs: -Dsonar.organization=pagopa -Dsonar.projectKey=${{ env.PROJECT_KEY }} -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml - -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*" + -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" + -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" -Dsonar.host.url=https://sonarcloud.io -Dsonar.java.libraries="**/*.jar" -Dsonar.login=${{ env.SONAR_TOKEN }} From e49b967e6ea9c75167ceb6f054b015b57ec3ffb2 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 26 Apr 2023 09:54:51 +0200 Subject: [PATCH 284/403] [SLS-14] Updated Dockerfile --- .github/workflows/release.yaml | 19 +++++++++++++++++++ Dockerfile | 17 +++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 Dockerfile diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 66214606..0b4320a2 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -2,6 +2,13 @@ name: Publish package to GitHub Packages on: release: types: [created] +env: + DOCKERFILE: Dockerfile.test-only + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_ACTOR: ${{ secrets.GITHUB_ACTOR }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} jobs: publish: runs-on: ubuntu-latest @@ -39,3 +46,15 @@ jobs: arguments: publish env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + - name: Build and push Docker image + uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..00e23516 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +FROM eclipse-temurin:11-jdk-alpine as build + +WORKDIR /build +COPY ./samples/spring . + +RUN ./gradlew bootJar + +FROM eclipse-temurin:11-jdk-alpine as runtime + +WORKDIR /app +COPY --from=build /build/build/libs/*.jar /app/app.jar + +RUN addgroup -S appuser && adduser -S appuser -G appuser +USER appuser + +EXPOSE 8080 +ENTRYPOINT [ "java","-jar","/app/app.jar" ] \ No newline at end of file From 223217e659694e1e8be84d4dac8e3416144887a1 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 26 Apr 2023 10:14:55 +0200 Subject: [PATCH 285/403] [SLS-14] Updated Dockerfile --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 00e23516..9d5095d2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,7 @@ FROM eclipse-temurin:11-jdk-alpine as build WORKDIR /build COPY ./samples/spring . +RUN chmod +x ./gradlew RUN ./gradlew bootJar FROM eclipse-temurin:11-jdk-alpine as runtime From 4adfe97020d09fc2101d56a3fe3b542f4fe10bbb Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 26 Apr 2023 10:18:48 +0200 Subject: [PATCH 286/403] [SLS-14] Updated LollipopConsumerSample --- .../java/it/pagopa/tech/sample/LollipopConsumerSample.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java b/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java index 617e2de9..8ebab761 100644 --- a/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java +++ b/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java @@ -17,7 +17,9 @@ import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.storage.SimpleIdpCertStorageProvider; import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImpl; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerServiceFactory; import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerServiceFactory; import it.pagopa.tech.lollipop.consumer.model.CommandResult; @@ -89,7 +91,8 @@ private static LollipopConsumerFactoryHelper buildLollipopConsumerFactoryHelper( LollipopConsumerRequestConfig.builder().build()); AssertionStorageProvider assertionStorageProvider = new SimpleAssertionStorageProvider(); IdpCertProviderFactory idpCertProviderFactory = new IdpCertProviderFactoryImpl( - new IdpCertSimpleClientProvider(IdpCertSimpleClientConfig.builder().build())); + new IdpCertSimpleClientProvider(IdpCertSimpleClientConfig.builder().build(), + new SimpleIdpCertStorageProvider(), new IdpCertStorageConfig())); AssertionClientProvider assertionClientProvider = new AssertionSimpleClientProvider(AssertionSimpleClientConfig.builder().build()); AssertionServiceFactory assertionServiceFactory = new AssertionServiceFactoryImpl( From 4ed6b926c156f91d903224ff38145d1e23e5f8ef Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 26 Apr 2023 10:42:38 +0200 Subject: [PATCH 287/403] [SLS-14] Updated build.gradle --- build.gradle | 2 +- samples/spring/build.gradle | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index a76c3f38..661da641 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ repositories { } allprojects { - version = "1.0.0-RC1" + version = "1.0.0-SNAPSHOT" group = 'it.pagopa.tech.lollipop-consumer-java-sdk' sourceCompatibility = '11' targetCompatibility = '11' diff --git a/samples/spring/build.gradle b/samples/spring/build.gradle index 0d766de3..242f7897 100644 --- a/samples/spring/build.gradle +++ b/samples/spring/build.gradle @@ -35,11 +35,11 @@ repositories { } dependencies { - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:core:1.0.0-RC1' - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:assertion-rest-client-native:1.0.0-RC1' - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:identity-service-rest-client-native:1.0.0-RC1' - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:http-verifier:1.0.0-RC1' - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:spring-impl:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:core:1.0.0-SNAPSHOT' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:assertion-rest-client-native:1.0.0-SNAPSHOT' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:identity-service-rest-client-native:1.0.0-SNAPSHOT' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:http-verifier:1.0.0-SNAPSHOT' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:spring-impl:1.0.0-SNAPSHOT' implementation 'org.mock-server:mockserver-netty:5.15.0' implementation 'org.springframework.boot:spring-boot-starter-web' From 8121349dfdd6134bb91a44292534692067250e7e Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 26 Apr 2023 10:48:04 +0200 Subject: [PATCH 288/403] [SLS-14] Updated build.gradle --- samples/spring/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/spring/build.gradle b/samples/spring/build.gradle index 242f7897..5d2b7e8a 100644 --- a/samples/spring/build.gradle +++ b/samples/spring/build.gradle @@ -5,7 +5,7 @@ plugins { } group = 'it.pagopa.tech.lollipop.consumer.samples' -version = '1.0.0-RC1' +version = '1.0.0-SNAPSHOT' sourceCompatibility = '11' configurations { From 0ed69bd9b921059b2c82f69d7a479776ce799580 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 26 Apr 2023 10:57:25 +0200 Subject: [PATCH 289/403] [SLS-14] Updated LollipopConsumerCommandBuilderImplTest --- .../command/impl/LollipopConsumerCommandBuilderImplTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplTest.java index 80a338a6..d3e60706 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/command/impl/LollipopConsumerCommandBuilderImplTest.java @@ -28,7 +28,7 @@ void beforeAll() { void testThatCreatsCommand() { assertThat( lollipopConsumerCommandBuilder.createCommand( - LollipopConsumerRequest.builder().build())) + Mockito.mock(LollipopConsumerRequest.class))) .isInstanceOf(LollipopConsumerCommand.class); } } From 43868d8006d458b9da0eb96cb7081db30157026d Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 26 Apr 2023 11:09:58 +0200 Subject: [PATCH 290/403] [SLS-14] Updated SampleApplicationTests --- .../tech/lollipop/consumer/sample/SampleApplicationTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/spring/src/test/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplicationTests.java b/samples/spring/src/test/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplicationTests.java index aeec9dc0..694fd01f 100644 --- a/samples/spring/src/test/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplicationTests.java +++ b/samples/spring/src/test/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplicationTests.java @@ -1,4 +1,4 @@ -package test.java.it.pagopa.tech.lollipop.consumer.sample; +package it.pagopa.tech.lollipop.consumer.sample; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; From 711e13989c2c34cf8974f5051d1f85d047fccc1b Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 26 Apr 2023 11:33:08 +0200 Subject: [PATCH 291/403] [SLS-14] Updated Dockerfile and release.yaml --- .github/workflows/release.yaml | 3 +++ Dockerfile | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0b4320a2..5cf0e0f9 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -53,6 +53,9 @@ jobs: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - name: Build and push Docker image uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + secrets: | + "GITHUB_ACTOR=${{ secrets.GITHUB_ACTOR }}" + "GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}" with: context: . push: true diff --git a/Dockerfile b/Dockerfile index 9d5095d2..e3e0e363 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,11 @@ FROM eclipse-temurin:11-jdk-alpine as build WORKDIR /build COPY ./samples/spring . +RUN --mount=type=secret,id=GITHUB_TOKEN \ + --mount=type=secret,id=GITHUB_ACTOR \ + export GITHUB_TOKEN=$(cat /run/secrets/GITHUB_TOKEN) && \ + export GITHUB_ACTOR=$(cat /run/secrets/GITHUB_ACTOR) + RUN chmod +x ./gradlew RUN ./gradlew bootJar From 23da33e1c4404cbc02c1bafaafe0968aa2478ccb Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 26 Apr 2023 11:33:39 +0200 Subject: [PATCH 292/403] [SLS-14] Updated Dockerfile and release.yaml --- .github/workflows/release.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 5cf0e0f9..f5f183fc 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -53,11 +53,11 @@ jobs: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - name: Build and push Docker image uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 - secrets: | - "GITHUB_ACTOR=${{ secrets.GITHUB_ACTOR }}" - "GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}" with: context: . push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} + secrets: | + "GITHUB_ACTOR=${{ secrets.GITHUB_ACTOR }}" + "GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}" From 94ba7c304563198e3c2ffa01a7ae1f8c3d0601e8 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 26 Apr 2023 11:36:43 +0200 Subject: [PATCH 293/403] [SLS-14] Updated Dockerfile and release.yaml --- .github/workflows/release.yaml | 4 ++++ Dockerfile | 8 -------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index f5f183fc..3ae0b311 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -46,6 +46,10 @@ jobs: arguments: publish env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Make spring sample gradlew executable + run: chmod +x ./samples/spring/gradlew + - name: Run build with Gradle Wrapper on Spring Sample + run: ./samples/spring/gradlew bootJar - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 diff --git a/Dockerfile b/Dockerfile index e3e0e363..7dfb8d45 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,14 +3,6 @@ FROM eclipse-temurin:11-jdk-alpine as build WORKDIR /build COPY ./samples/spring . -RUN --mount=type=secret,id=GITHUB_TOKEN \ - --mount=type=secret,id=GITHUB_ACTOR \ - export GITHUB_TOKEN=$(cat /run/secrets/GITHUB_TOKEN) && \ - export GITHUB_ACTOR=$(cat /run/secrets/GITHUB_ACTOR) - -RUN chmod +x ./gradlew -RUN ./gradlew bootJar - FROM eclipse-temurin:11-jdk-alpine as runtime WORKDIR /app From d1af92868083cd45a5dd9eafe5ff2e6dc026f4ca Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 26 Apr 2023 11:46:43 +0200 Subject: [PATCH 294/403] [SLS-14] Updated release.yaml --- .github/workflows/release.yaml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3ae0b311..2e4c1d65 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -47,9 +47,17 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Make spring sample gradlew executable - run: chmod +x ./samples/spring/gradlew + run: chmod +x .gradlew + working-directory: ./samples/spring - name: Run build with Gradle Wrapper on Spring Sample - run: ./samples/spring/gradlew bootJar + run: ./gradlew bootJar + working-directory: ./samples/spring + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 From 2e2e328225716d605dbe6d4030bb9797ddbb06a4 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 26 Apr 2023 12:03:55 +0200 Subject: [PATCH 295/403] [SLS-14] Updated release.yaml --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 2e4c1d65..94887c65 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -47,7 +47,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Make spring sample gradlew executable - run: chmod +x .gradlew + run: chmod +x ./gradlew working-directory: ./samples/spring - name: Run build with Gradle Wrapper on Spring Sample run: ./gradlew bootJar From be1ec8816f215e6a02b81eb6dc237b6845530500 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 26 Apr 2023 12:17:27 +0200 Subject: [PATCH 296/403] [SLS-14] Updated build.gradle --- build.gradle | 2 +- samples/spring/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 661da641..a76c3f38 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ repositories { } allprojects { - version = "1.0.0-SNAPSHOT" + version = "1.0.0-RC1" group = 'it.pagopa.tech.lollipop-consumer-java-sdk' sourceCompatibility = '11' targetCompatibility = '11' diff --git a/samples/spring/build.gradle b/samples/spring/build.gradle index 5d2b7e8a..242f7897 100644 --- a/samples/spring/build.gradle +++ b/samples/spring/build.gradle @@ -5,7 +5,7 @@ plugins { } group = 'it.pagopa.tech.lollipop.consumer.samples' -version = '1.0.0-SNAPSHOT' +version = '1.0.0-RC1' sourceCompatibility = '11' configurations { From a2e1650304eb96e398afc577e310f9cd324627c4 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 26 Apr 2023 15:49:18 +0200 Subject: [PATCH 297/403] [SLS-32] Implemented LollipopConsumerConverter with conversions methods --- core/build.gradle | 5 +- .../model/LollipopConsumerRequest.java | 2 +- .../utils/LollipopConsumerConverter.java | 61 ++++++++++++++ .../utils/LollipopConsumerConverterTest.java | 83 +++++++++++++++++++ gradle/verification-metadata.xml | 8 ++ .../HttpVerifierHandlerInterceptor.java | 12 +-- .../LollipopConsumerRequestConverter.java | 43 ---------- 7 files changed, 164 insertions(+), 50 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverter.java create mode 100644 core/src/test/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverterTest.java delete mode 100644 spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java diff --git a/core/build.gradle b/core/build.gradle index 4dd02e30..2f887d00 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -42,7 +42,6 @@ configurations { dependencies { implementation 'javax.inject:javax.inject:1' implementation 'com.typesafe:config:1.4.2' - implementation 'javax.inject:javax.inject:1' implementation 'com.nimbusds:nimbus-jose-jwt:9.31' implementation 'ch.qos.logback:logback-classic:1.4.6' implementation 'ch.qos.logback:logback-core:1.4.6' @@ -50,11 +49,15 @@ dependencies { implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.2' implementation 'org.apache.wss4j:wss4j-ws-security-common:2.4.1' + implementation 'javax.servlet:javax.servlet-api:3.0.1' + // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.mockito:mockito-core:5.2.0' testImplementation 'org.mockito:mockito-junit-jupiter:5.2.0' testImplementation 'org.assertj:assertj-core:3.24.2' + testImplementation 'org.springframework:spring-test:5.3.26' + } tasks.named('test') { diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java index e11a00f8..1d7c076c 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/LollipopConsumerRequest.java @@ -11,6 +11,6 @@ @Builder public class LollipopConsumerRequest { private String requestBody; - private Map requestParams; + private Map requestParams; private Map headerParams; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverter.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverter.java new file mode 100644 index 00000000..b9f650ba --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverter.java @@ -0,0 +1,61 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.utils; + +import static it.pagopa.tech.lollipop.consumer.command.impl.LollipopConsumerCommandImpl.VERIFICATION_SUCCESS_CODE; + +import it.pagopa.tech.lollipop.consumer.model.CommandResult; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +public class LollipopConsumerConverter { + + /** + * Utility method to be used to generate a LollipopConsumerRequest from a HttpServletRequest + * + * @param httpServletRequest http request to be converted into a lollipop request + * @return instance of {@link LollipopConsumerRequest} produced from the httpServletRequest + * @throws IOException exception return if body extraction fails + */ + public static LollipopConsumerRequest convertToLollipopRequest( + HttpServletRequest httpServletRequest) throws IOException { + + byte[] requestBody = null; + + String method = httpServletRequest.getMethod(); + + if (method != null && (!method.equals("GET") && !method.equals("DELETE"))) { + InputStream requestInputStream = httpServletRequest.getInputStream(); + requestBody = requestInputStream.readAllBytes(); + } + + return LollipopConsumerRequest.builder() + .requestBody(requestBody != null ? new String(requestBody) : null) + .headerParams( + Collections.list(httpServletRequest.getHeaderNames()).stream() + .collect(Collectors.toMap(h -> h, httpServletRequest::getHeader))) + .requestParams(httpServletRequest.getParameterMap()) + .build(); + } + + /** + * Utility method used to convert the commandResult in a HttpServletResponse + * + * @param commandResult results of the LollipopConsumerCommand's doExecute + * @return instance of HttpServletResponse with the commandResult status code and response + * @throws IOException when failed to send error + */ + public static HttpServletResponse interceptResult( + CommandResult commandResult, HttpServletResponse httpResponse) throws IOException { + + if (!commandResult.getResultCode().equals(VERIFICATION_SUCCESS_CODE)) { + httpResponse.sendError(401, commandResult.getResultMessage()); + } + + return httpResponse; + } +} diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverterTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverterTest.java new file mode 100644 index 00000000..4be03476 --- /dev/null +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverterTest.java @@ -0,0 +1,83 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.utils; + +import static it.pagopa.tech.lollipop.consumer.command.impl.LollipopConsumerCommandImpl.VERIFICATION_SUCCESS_CODE; + +import it.pagopa.tech.lollipop.consumer.model.CommandResult; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import java.io.IOException; +import java.util.Enumeration; +import javax.servlet.http.HttpServletResponse; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; + +public class LollipopConsumerConverterTest { + + String REQUEST_BODY_STRING = "{\"message\":\"a valid message payload\"}"; + String COMMAND_RESPONSE_SUCCESS = "SAML assertion validated successfully"; + String COMMAND_RESPONSE_FAILED = "Validation of SAML assertion failed, authentication failed"; + byte[] REQUEST_BODY = REQUEST_BODY_STRING.getBytes(); + + static Enumeration REQUEST_HEADERS; + + static MockHttpServletRequest mockRequest; + + @BeforeAll + static void setUp() { + mockRequest = new MockHttpServletRequest(); + mockRequest.addHeader("content-digest", "sha-256=:test:"); + mockRequest.setParameter("testParam", "value1", "value2"); + } + + @Test + void convertGetHttpRequest() throws IOException { + mockRequest.setMethod("GET"); + + LollipopConsumerRequest request = + LollipopConsumerConverter.convertToLollipopRequest(mockRequest); + Assertions.assertNotNull(request.getHeaderParams()); + Assertions.assertNotNull(request.getRequestParams()); + } + + @Test + void convertPostHttpRequest() throws IOException { + mockRequest.setMethod("POST"); + mockRequest.setContent(REQUEST_BODY); + + LollipopConsumerRequest request = + LollipopConsumerConverter.convertToLollipopRequest(mockRequest); + Assertions.assertNotNull(request.getRequestBody()); + Assertions.assertNotNull(request.getHeaderParams()); + Assertions.assertNotNull(request.getRequestParams()); + } + + @Test + void convertSuccessResponse() throws IOException { + CommandResult result = + new CommandResult(VERIFICATION_SUCCESS_CODE, COMMAND_RESPONSE_SUCCESS); + int MOCK_RESPONSE_STATUS = 200; + MockHttpServletResponse mockResponse = new MockHttpServletResponse(); + mockResponse.setStatus(MOCK_RESPONSE_STATUS); + + HttpServletResponse response = + LollipopConsumerConverter.interceptResult(result, mockResponse); + + Assertions.assertTrue(response.getStatus() == MOCK_RESPONSE_STATUS); + } + + @Test + void convertUnauthorizedResponse() throws IOException { + CommandResult result = new CommandResult("FAILED", COMMAND_RESPONSE_FAILED); + MockHttpServletResponse mockResponse = new MockHttpServletResponse(); + + HttpServletResponse response = + LollipopConsumerConverter.interceptResult(result, mockResponse); + + Assertions.assertTrue(response.getStatus() == 401); + Assertions.assertTrue( + ((MockHttpServletResponse) response).getErrorMessage() == COMMAND_RESPONSE_FAILED); + } +} diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index cedb3e96..235af019 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2846,6 +2846,14 @@ + + + + + + + + diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java index dd594344..37ac688c 100644 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java +++ b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptor.java @@ -1,10 +1,12 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.spring; +import static it.pagopa.tech.lollipop.consumer.command.impl.LollipopConsumerCommandImpl.VERIFICATION_SUCCESS_CODE; + import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; import it.pagopa.tech.lollipop.consumer.model.CommandResult; -import it.pagopa.tech.lollipop.consumer.spring.converter.LollipopConsumerRequestConverter; +import it.pagopa.tech.lollipop.consumer.utils.LollipopConsumerConverter; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -36,14 +38,14 @@ public boolean preHandle( LollipopConsumerCommand lollipopConsumerCommand = consumerCommandBuilder.createCommand( - LollipopConsumerRequestConverter.convert(request)); + LollipopConsumerConverter.convertToLollipopRequest(request)); try { CommandResult commandResult = lollipopConsumerCommand.doExecute(); - if (!commandResult.getResultCode().equals("SUCCESS")) { - response.sendError(401, commandResult.getResultMessage()); - } else { + LollipopConsumerConverter.interceptResult(commandResult, response); + + if (commandResult.getResultCode().equals(VERIFICATION_SUCCESS_CODE)) { return true; } diff --git a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java b/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java deleted file mode 100644 index ec517183..00000000 --- a/spring-impl/src/main/java/it/pagopa/tech/lollipop/consumer/spring/converter/LollipopConsumerRequestConverter.java +++ /dev/null @@ -1,43 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.spring.converter; - -import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; -import java.io.IOException; -import java.io.InputStream; -import java.util.Collections; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import org.springframework.util.StreamUtils; - -/** Class to be used for conversion of the http requests to be validated */ -public class LollipopConsumerRequestConverter { - - private LollipopConsumerRequestConverter() {} - - /** - * Utility method to be used to generate a LollipopConsumerRequest - * - * @param httpServletRequest http request to be converted into a lollipop request - * @return instance of {@link LollipopConsumerRequest} produced from the httpServletRequest - * @throws IOException exception return if body extraction fails - */ - public static LollipopConsumerRequest convert(HttpServletRequest httpServletRequest) - throws IOException { - - byte[] requestBody = null; - - String method = httpServletRequest.getMethod(); - - if (method != null && (!method.equals("GET") && !method.equals("DELETE"))) { - InputStream requestInputStream = httpServletRequest.getInputStream(); - requestBody = StreamUtils.copyToByteArray(requestInputStream); - } - - return LollipopConsumerRequest.builder() - .requestBody(requestBody != null ? new String(requestBody) : null) - .headerParams( - Collections.list(httpServletRequest.getHeaderNames()).stream() - .collect(Collectors.toMap(h -> h, httpServletRequest::getHeader))) - .build(); - } -} From 2480a5e5394a7215dc695abbb4f120ab29a9254c Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 26 Apr 2023 16:12:50 +0200 Subject: [PATCH 298/403] [SLS-32] Removed code smells --- .../consumer/utils/LollipopConsumerConverter.java | 4 ++++ .../consumer/utils/LollipopConsumerConverterTest.java | 10 +++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverter.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverter.java index b9f650ba..81a6dfd6 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverter.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverter.java @@ -14,6 +14,10 @@ public class LollipopConsumerConverter { + private LollipopConsumerConverter() { + throw new IllegalStateException("Utility class"); + } + /** * Utility method to be used to generate a LollipopConsumerRequest from a HttpServletRequest * diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverterTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverterTest.java index 4be03476..8957468d 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverterTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverterTest.java @@ -14,7 +14,7 @@ import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; -public class LollipopConsumerConverterTest { +class LollipopConsumerConverterTest { String REQUEST_BODY_STRING = "{\"message\":\"a valid message payload\"}"; String COMMAND_RESPONSE_SUCCESS = "SAML assertion validated successfully"; @@ -65,7 +65,7 @@ void convertSuccessResponse() throws IOException { HttpServletResponse response = LollipopConsumerConverter.interceptResult(result, mockResponse); - Assertions.assertTrue(response.getStatus() == MOCK_RESPONSE_STATUS); + Assertions.assertEquals(MOCK_RESPONSE_STATUS, response.getStatus()); } @Test @@ -76,8 +76,8 @@ void convertUnauthorizedResponse() throws IOException { HttpServletResponse response = LollipopConsumerConverter.interceptResult(result, mockResponse); - Assertions.assertTrue(response.getStatus() == 401); - Assertions.assertTrue( - ((MockHttpServletResponse) response).getErrorMessage() == COMMAND_RESPONSE_FAILED); + Assertions.assertEquals(401, response.getStatus()); + Assertions.assertSame( + COMMAND_RESPONSE_FAILED, ((MockHttpServletResponse) response).getErrorMessage()); } } From 6c02a1dac58801dba39e8fb518c5a8872fa798fb Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 26 Apr 2023 19:07:58 +0200 Subject: [PATCH 299/403] Reworked simple assertion storage --- .../storage/SimpleAssertionStorage.java | 124 ++++++++++++------ .../SimpleAssertionStorageProvider.java | 4 +- .../assertion/storage/StorageConfig.java | 1 + .../consumer/model/DelayedCacheObject.java | 28 ++++ .../storage/SimpleAssertionStorageTest.java | 112 ++++++++-------- 5 files changed, 164 insertions(+), 105 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/model/DelayedCacheObject.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java index 4bf39fb9..2607df0d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java @@ -1,11 +1,15 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.storage; +import it.pagopa.tech.lollipop.consumer.model.DelayedCacheObject; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; -import java.util.Map; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; +import java.lang.ref.SoftReference; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.DelayQueue; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; import javax.inject.Inject; /** @@ -19,18 +23,53 @@ */ public class SimpleAssertionStorage implements AssertionStorage { - private final Map assertionMap; - private final Map> scheduledEvictionsMap; + private final ConcurrentHashMap> cache; + private final DelayQueue> cleaningUpQueue; + private Thread cleanerThread; + + private AtomicInteger numberOfElements; private final StorageConfig storageConfig; @Inject - public SimpleAssertionStorage( - Map assertionMap, - Map> scheduledEvictionsMap, + public SimpleAssertionStorage(StorageConfig storageConfig) { + cache = new ConcurrentHashMap<>(); + cleaningUpQueue = new DelayQueue<>(); + initCleanerThread(); + this.storageConfig = storageConfig; + numberOfElements = new AtomicInteger(0); + } + + @Inject + protected SimpleAssertionStorage( + ConcurrentHashMap> concurrentHashMap, + DelayQueue> queue, StorageConfig storageConfig) { - this.assertionMap = assertionMap; - this.scheduledEvictionsMap = scheduledEvictionsMap; + cache = concurrentHashMap; + cleaningUpQueue = queue; + initCleanerThread(); this.storageConfig = storageConfig; + numberOfElements = new AtomicInteger(0); + } + + private void initCleanerThread() { + this.cleanerThread = + new Thread( + () -> { + DelayedCacheObject delayedCacheObject; + while (!Thread.currentThread().isInterrupted()) { + try { + delayedCacheObject = this.cleaningUpQueue.take(); + this.cache.remove( + delayedCacheObject.getKey(), + delayedCacheObject.getReference()); + numberOfElements.decrementAndGet(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + }); + this.cleanerThread.setDaemon(true); + this.cleanerThread.start(); } /** @@ -50,11 +89,7 @@ public SamlAssertion getAssertion(String assertionRef) { return null; } - SamlAssertion samlAssertion = assertionMap.get(assertionRef); - if (samlAssertion != null) { - delayEviction(assertionRef); - } - return samlAssertion; + return Optional.ofNullable(cache.get(assertionRef)).map(SoftReference::get).orElse(null); } /** @@ -73,31 +108,36 @@ public void saveAssertion(String assertionRef, SamlAssertion assertion) { return; } - assertionMap.put(assertionRef, assertion); - scheduleEviction(assertionRef); - } - - private void scheduleEviction(String assertionRef) { - ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); - ScheduledFuture schedule = - executorService.schedule( - getEvictionTask(assertionRef), - storageConfig.getStorageEvictionDelay(), - storageConfig.getStorageEvictionDelayTimeUnit()); - scheduledEvictionsMap.put(assertionRef, schedule); - } - - private void delayEviction(String assertionRef) { - ScheduledFuture schedule = scheduledEvictionsMap.get(assertionRef); - schedule.cancel(false); - scheduledEvictionsMap.remove(assertionRef); - scheduleEviction(assertionRef); - } - - private Runnable getEvictionTask(String assertionRef) { - return () -> { - assertionMap.remove(assertionRef); - scheduledEvictionsMap.remove(assertionRef); - }; + if (assertionRef == null) { + return; + } + if (assertion == null) { + cache.remove(assertionRef); + } else { + CompletableFuture.supplyAsync( + () -> { + synchronized (numberOfElements) { + if (numberOfElements.get() >= storageConfig.getMaxNumberOfElements()) { + try { + cleaningUpQueue.take(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + long expiryTime = + System.currentTimeMillis() + + TimeUnit.MILLISECONDS.convert( + storageConfig.getStorageEvictionDelay(), + storageConfig + .getStorageEvictionDelayTimeUnit()); + SoftReference reference = new SoftReference<>(assertion); + cache.put(assertionRef, reference); + cleaningUpQueue.put( + new DelayedCacheObject<>(assertionRef, reference, expiryTime)); + numberOfElements.incrementAndGet(); + } + return true; + }); + } } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java index d74c27b5..1901d365 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageProvider.java @@ -1,8 +1,6 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.storage; -import java.util.HashMap; - /** Implementation of {@link AssertionStorageProvider} interface. It provides an instance of the */ public class SimpleAssertionStorageProvider implements AssertionStorageProvider { @@ -14,6 +12,6 @@ public class SimpleAssertionStorageProvider implements AssertionStorageProvider */ @Override public AssertionStorage provideStorage(StorageConfig storageConfig) { - return new SimpleAssertionStorage(new HashMap<>(), new HashMap<>(), storageConfig); + return new SimpleAssertionStorage(storageConfig); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java index 683df9a8..36e1a97e 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/StorageConfig.java @@ -11,4 +11,5 @@ public class StorageConfig { private boolean assertionStorageEnabled = true; private long storageEvictionDelay = 1L; private TimeUnit storageEvictionDelayTimeUnit = TimeUnit.MINUTES; + private long maxNumberOfElements = 100; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/DelayedCacheObject.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/DelayedCacheObject.java new file mode 100644 index 00000000..ab2b4ad6 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/DelayedCacheObject.java @@ -0,0 +1,28 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.model; + +import java.lang.ref.SoftReference; +import java.util.concurrent.Delayed; +import java.util.concurrent.TimeUnit; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +@AllArgsConstructor +@EqualsAndHashCode +public class DelayedCacheObject implements Delayed { + + @Getter private final String key; + @Getter private final SoftReference reference; + private final long expiryTime; + + @Override + public long getDelay(TimeUnit unit) { + return unit.convert(expiryTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS); + } + + @Override + public int compareTo(Delayed o) { + return Long.compare(expiryTime, ((DelayedCacheObject) o).expiryTime); + } +} diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java index 21998598..982dc7e6 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java @@ -5,11 +5,10 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import it.pagopa.tech.lollipop.consumer.model.DelayedCacheObject; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; -import java.util.HashMap; -import java.util.Map; +import java.lang.ref.SoftReference; import java.util.concurrent.*; -import lombok.SneakyThrows; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -28,70 +27,80 @@ void setUp() { } @Test - void getExistingAssertionAndResetScheduleEvictionWithStorageEnabled() - throws InterruptedException, ExecutionException { + void getNotExistingAssertionWithStorageEnabled() { doReturn(true).when(storageConfigMock).isAssertionStorageEnabled(); - Map assertionMap = new HashMap<>(); - SamlAssertion samlAssertion = new SamlAssertion(); - assertionMap.put(ASSERTION_REF_1, samlAssertion); - Map> scheduledEvictionsMap = new HashMap<>(); - ScheduledFuture scheduledFutureMock = mock(ScheduledFuture.class); - scheduledEvictionsMap.put(ASSERTION_REF_1, scheduledFutureMock); - - sut = new SimpleAssertionStorage(assertionMap, scheduledEvictionsMap, storageConfigMock); + sut = new SimpleAssertionStorage(storageConfigMock); SamlAssertion result = sut.getAssertion(ASSERTION_REF_1); - assertNotNull(result); - assertEquals(samlAssertion, result); - assertEquals(1, scheduledEvictionsMap.size()); - - CompletableFuture future = waitEvictionEnd(scheduledEvictionsMap); - assertEquals(true, future.get()); - assertEquals(0, assertionMap.size()); - assertEquals(0, scheduledEvictionsMap.size()); + assertNull(result); } @Test - void getNotExistingAssertionWithStorageEnabled() { + void saveAssertionAndScheduleEvictionWithStorageEnabled() + throws InterruptedException, ExecutionException { doReturn(true).when(storageConfigMock).isAssertionStorageEnabled(); + doReturn(1000L).when(storageConfigMock).getStorageEvictionDelay(); + doReturn(TimeUnit.MILLISECONDS).when(storageConfigMock).getStorageEvictionDelayTimeUnit(); + doReturn(100L).when(storageConfigMock).getMaxNumberOfElements(); - sut = new SimpleAssertionStorage(new HashMap<>(), new HashMap<>(), storageConfigMock); + ConcurrentHashMap> assertionMap = + new ConcurrentHashMap<>(); + DelayQueue> delayedCacheObjects = new DelayQueue<>(); - SamlAssertion result = sut.getAssertion(ASSERTION_REF_1); + sut = new SimpleAssertionStorage(assertionMap, delayedCacheObjects, storageConfigMock); + SamlAssertion samlAssertion = new SamlAssertion(); - assertNull(result); + sut.saveAssertion(ASSERTION_REF_1, samlAssertion); + delayedCacheObjects.poll(100, TimeUnit.MILLISECONDS); + + assertEquals(1, assertionMap.size()); + assertEquals(1, delayedCacheObjects.size()); + assertEquals(samlAssertion, assertionMap.get(ASSERTION_REF_1).get()); + + delayedCacheObjects.poll(1000, TimeUnit.MILLISECONDS); + assertEquals(0, assertionMap.size()); + assertEquals(0, delayedCacheObjects.size()); } @Test - void saveAssertionAndScheduleEvictionWithStorageEnabled() + void saveAssertionToMaximumCapacityWithStorageEnabled() throws InterruptedException, ExecutionException { doReturn(true).when(storageConfigMock).isAssertionStorageEnabled(); + doReturn(1000L).when(storageConfigMock).getStorageEvictionDelay(); + doReturn(TimeUnit.MILLISECONDS).when(storageConfigMock).getStorageEvictionDelayTimeUnit(); + doReturn(100L).when(storageConfigMock).getMaxNumberOfElements(); - Map assertionMap = new HashMap<>(); - Map> scheduledEvictionsMap = new HashMap<>(); + ConcurrentHashMap> assertionMap = + new ConcurrentHashMap<>(); + DelayQueue> delayedCacheObjects = new DelayQueue<>(); - sut = new SimpleAssertionStorage(assertionMap, scheduledEvictionsMap, storageConfigMock); + sut = new SimpleAssertionStorage(assertionMap, delayedCacheObjects, storageConfigMock); SamlAssertion samlAssertion = new SamlAssertion(); - sut.saveAssertion(ASSERTION_REF_1, samlAssertion); + ExecutorService executor = Executors.newFixedThreadPool(10); - assertEquals(1, assertionMap.size()); - assertEquals(1, scheduledEvictionsMap.size()); - assertEquals(samlAssertion, assertionMap.get(ASSERTION_REF_1)); + for (int i = 0; i < 101; i++) { + executor.submit(() -> sut.saveAssertion(ASSERTION_REF_1, samlAssertion)); + } + delayedCacheObjects.poll(100, TimeUnit.MILLISECONDS); - CompletableFuture future = waitEvictionEnd(scheduledEvictionsMap); - assertEquals(true, future.get()); - assertEquals(0, assertionMap.size()); - assertEquals(0, scheduledEvictionsMap.size()); + assertEquals(100, delayedCacheObjects.size()); + assertEquals(samlAssertion, assertionMap.get(ASSERTION_REF_1).get()); + + // delayedCacheObjects.poll(1000, TimeUnit.MILLISECONDS); + // assertEquals(0, assertionMap.size()); + // assertEquals(0, delayedCacheObjects.size()); } @Test void getAssertionWithStorageDisabled() { doReturn(false).when(storageConfigMock).isAssertionStorageEnabled(); + doReturn(1000L).when(storageConfigMock).getStorageEvictionDelay(); + doReturn(TimeUnit.MILLISECONDS).when(storageConfigMock).getStorageEvictionDelayTimeUnit(); - sut = new SimpleAssertionStorage(new HashMap<>(), new HashMap<>(), storageConfigMock); + sut = new SimpleAssertionStorage(storageConfigMock); SamlAssertion result = sut.getAssertion(ASSERTION_REF_1); @@ -102,32 +111,15 @@ void getAssertionWithStorageDisabled() { void savaAssertionWithStorageDisabled() { doReturn(false).when(storageConfigMock).isAssertionStorageEnabled(); - Map assertionMap = new HashMap<>(); - Map> scheduledEvictionsMap = new HashMap<>(); + ConcurrentHashMap> assertionMap = + new ConcurrentHashMap<>(); + DelayQueue> delayedCacheObjects = new DelayQueue<>(); - sut = new SimpleAssertionStorage(assertionMap, scheduledEvictionsMap, storageConfigMock); + sut = new SimpleAssertionStorage(assertionMap, delayedCacheObjects, storageConfigMock); sut.saveAssertion(ASSERTION_REF_1, new SamlAssertion()); assertEquals(0, assertionMap.size()); - assertEquals(0, scheduledEvictionsMap.size()); - } - - private CompletableFuture waitEvictionEnd( - Map> scheduledEvictionsMap) { - CompletableFuture future = new CompletableFuture<>(); - ExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); - executorService.submit( - new Runnable() { - @SneakyThrows - @Override - public void run() { - ScheduledFuture scheduledFuture = - scheduledEvictionsMap.get(ASSERTION_REF_1); - scheduledFuture.get(); - future.complete(true); - } - }); - return future; + assertEquals(0, delayedCacheObjects.size()); } } From a259d80913104791b60d702fcb021fa67b874b6e Mon Sep 17 00:00:00 2001 From: svariant Date: Thu, 27 Apr 2023 11:36:57 +0200 Subject: [PATCH 300/403] [1.0.0-RC1] Resolved code smells --- .../client/simple/internal/JSON.java | 3 +- .../simple/internal/RFC3339DateFormat.java | 5 -- .../exception/LollipopVerifierException.java | 1 + .../HttpMessageVerifierServiceImplTest.java | 20 +++--- .../visma/ErrorCodeConverter.java | 4 ++ .../visma/VismaHttpMessageVerifier.java | 62 ++++++++++++------- .../VismaHttpMessageVerifierFactory.java | 7 ++- .../VismaHttpMessageVerifierFactoryTest.java | 6 +- .../visma/VismaHttpMessageVerifierTest.java | 26 ++++---- .../client/simple/IdpCertSimpleClient.java | 57 +++++++++++------ 10 files changed, 116 insertions(+), 75 deletions(-) diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/JSON.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/JSON.java index 7fd5045e..4eee60a5 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/JSON.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/JSON.java @@ -1,10 +1,9 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal; -import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.model.*; import java.util.HashMap; import java.util.Map; import java.util.Set; diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/RFC3339DateFormat.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/RFC3339DateFormat.java index c8d0934d..b2b8bcfb 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/RFC3339DateFormat.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/RFC3339DateFormat.java @@ -36,9 +36,4 @@ public Date parse(String source, ParsePosition pos) { public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { return fmt.format(date, toAppendTo, fieldPosition); } - - @Override - public Object clone() { - return super.clone(); - } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java index 04e98686..2bd3c9e5 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/exception/LollipopVerifierException.java @@ -46,6 +46,7 @@ public ErrorCode getErrorCode() { /** Error codes to classify Lollipop Request Exceptions */ public enum ErrorCode { + UNAVAILABLE_ENCODING, MISSING_SIGNATURE, MISSING_SIGNATURE_INPUT diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java index 01c8e93e..c642c729 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/HttpMessageVerifierServiceImplTest.java @@ -35,8 +35,8 @@ class HttpMessageVerifierServiceImplTest { final String INVALID_PAYLOAD = "an invalid payload"; final String VALID_ENCODING = "UTF-8"; - private LollipopConsumerRequestConfig httpMessageVerifierConfig; - private HttpMessageVerifier httpMessageVerifier; + private final LollipopConsumerRequestConfig httpMessageVerifierConfig; + private final HttpMessageVerifier httpMessageVerifier; private HttpMessageVerifierServiceImpl httpMessageVerifierService; @@ -82,7 +82,7 @@ public void beforeEach() } @Test - public void validRequestIsProcessed() { + void validRequestIsProcessed() { assertThatNoException() .isThrownBy( () -> @@ -91,7 +91,7 @@ public void validRequestIsProcessed() { } @Test - public void invalidRequestIsProcessedWithStrictDigestValidation() { + void invalidRequestIsProcessedWithStrictDigestValidation() { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); this.httpMessageVerifierConfig.setStrictDigestVerify(true); lollipopConsumerRequest.setRequestBody(INVALID_PAYLOAD); @@ -117,7 +117,7 @@ public void invalidRequestIsProcessedWithStrictDigestValidation() { } @Test - public void requestWithInvalidDigestThrowsException() { + void requestWithInvalidDigestThrowsException() { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); lollipopConsumerRequest.setRequestBody(INVALID_PAYLOAD); // execute & verify @@ -135,7 +135,7 @@ public void requestWithInvalidDigestThrowsException() { } @Test - public void requestWithoutContentDigestToValidateThrowsException() { + void requestWithoutContentDigestToValidateThrowsException() { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); lollipopConsumerRequest.getHeaderParams().remove("Content-Digest"); // execute & verify @@ -153,7 +153,7 @@ public void requestWithoutContentDigestToValidateThrowsException() { } @Test - public void requestWithoutRequestBodyToValidateThrowsException() { + void requestWithoutRequestBodyToValidateThrowsException() { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); lollipopConsumerRequest.setRequestBody(null); // execute & verify @@ -171,7 +171,7 @@ public void requestWithoutRequestBodyToValidateThrowsException() { } @Test - public void requestWithoutSignatureToValidateThrowsException() { + void requestWithoutSignatureToValidateThrowsException() { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); lollipopConsumerRequest.getHeaderParams().remove("Signature"); // execute & verify @@ -188,7 +188,7 @@ public void requestWithoutSignatureToValidateThrowsException() { } @Test - public void requestWithoutSignatureInputToValidateThrowsException() { + void requestWithoutSignatureInputToValidateThrowsException() { LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); lollipopConsumerRequest.getHeaderParams().remove("Signature-Input"); // execute & verify @@ -206,7 +206,7 @@ public void requestWithoutSignatureInputToValidateThrowsException() { } @Test - public void requestWithInvalidSignatureRetunsFalse() { + void requestWithInvalidSignatureRetunsFalse() { AtomicBoolean result = new AtomicBoolean(false); LollipopConsumerRequest lollipopConsumerRequest = getLollipopConsumerRequest(); lollipopConsumerRequest.getHeaderParams().put("Signature", INVALID_SIGNATURE); diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/ErrorCodeConverter.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/ErrorCodeConverter.java index 92ba18b7..592d21c4 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/ErrorCodeConverter.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/ErrorCodeConverter.java @@ -10,6 +10,10 @@ */ public class ErrorCodeConverter { + private ErrorCodeConverter() { + throw new IllegalStateException("Utility class"); + } + /** * @param errorCode {@link DigestException.ErrorCode} to convert * @return converted {@link LollipopDigestException.ErrorCode} diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java index 296ecc76..2511feb5 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java @@ -73,20 +73,12 @@ public boolean verifyHttpSignature( parameters.remove(lollipopConsumerRequestConfig.getSignatureHeader()); String lollipopKey = parameters.get(lollipopConsumerRequestConfig.getPublicKeyHeader()); - if (lollipopKey == null) { - throw new LollipopSignatureException( - LollipopSignatureException.ErrorCode.MISSING_PUBLIC_KEY, - "Could not find the public key within the expected header"); - } + isLollipopKeyNotNull(lollipopKey); String[] signatures = signature.split(","); String[] signatureInputs = signatureInput.split(","); - if (signatures.length != signatureInputs.length) { - throw new LollipopSignatureException( - LollipopSignatureException.ErrorCode.INVALID_SIGNATURE_NUMBER, - "Available signatures and signature-inputs differ in number"); - } + verifySignatureLength(signatures, signatureInputs); /* cicle through all signatures to validate */ for (int i = 0; i < signatures.length; i++) { @@ -105,13 +97,9 @@ public boolean verifyHttpSignature( String algToUse = matcher.group(0); signatureAlgorithm = SignatureAlgorithm.fromIdentifier( - algToUse.replaceAll("\"", "").split("=")[1]); + algToUse.replace("\"", "").split("=")[1]); - if (signatureAlgorithm == null) { - throw new LollipopSignatureException( - LollipopSignatureException.ErrorCode.INVALID_SIGNATURE_ALG, - "Missing Signature Algorithm"); - } + isSignatureAlgorithmNotNull(signatureAlgorithm); } catch (IndexOutOfBoundsException | IllegalStateException e) { throw new LollipopSignatureException( @@ -133,11 +121,7 @@ public boolean verifyHttpSignature( try { JWK jwk = JWK.parse(new String(Base64.getDecoder().decode(lollipopKey))); KeyType keyType = jwk.getKeyType(); - if (KeyType.EC.equals(keyType)) { - publicKey = jwk.toECKey().toECPublicKey(); - } else if (KeyType.RSA.equals(keyType)) { - publicKey = jwk.toRSAKey().toRSAPublicKey(); - } + publicKey = getPublicKey(jwk, keyType); } catch (ParseException | JOSEException e) { throw new LollipopSignatureException( LollipopSignatureException.ErrorCode.INVALID_SIGNATURE_ALG, @@ -171,4 +155,40 @@ public boolean verifyHttpSignature( return true; } + + private static void isSignatureAlgorithmNotNull(SignatureAlgorithm signatureAlgorithm) + throws LollipopSignatureException { + if (signatureAlgorithm == null) { + throw new LollipopSignatureException( + LollipopSignatureException.ErrorCode.INVALID_SIGNATURE_ALG, + "Missing Signature Algorithm"); + } + } + + private static void isLollipopKeyNotNull(String lollipopKey) throws LollipopSignatureException { + if (lollipopKey == null) { + throw new LollipopSignatureException( + LollipopSignatureException.ErrorCode.MISSING_PUBLIC_KEY, + "Could not find the public key within the expected header"); + } + } + + private static void verifySignatureLength(String[] signatures, String[] signatureInputs) + throws LollipopSignatureException { + if (signatures.length != signatureInputs.length) { + throw new LollipopSignatureException( + LollipopSignatureException.ErrorCode.INVALID_SIGNATURE_NUMBER, + "Available signatures and signature-inputs differ in number"); + } + } + + private static PublicKey getPublicKey(JWK jwk, KeyType keyType) throws JOSEException { + PublicKey publicKey = null; + if (KeyType.EC.equals(keyType)) { + publicKey = jwk.toECKey().toECPublicKey(); + } else if (KeyType.RSA.equals(keyType)) { + publicKey = jwk.toRSAKey().toRSAPublicKey(); + } + return publicKey; + } } diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java index 604c3cd9..c4362a84 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactory.java @@ -2,6 +2,7 @@ package it.pagopa.tech.lollipop.consumer.http_verifier.visma; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifier; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; import java.nio.charset.Charset; @@ -14,9 +15,11 @@ public class VismaHttpMessageVerifierFactory implements HttpMessageVerifierFacto public VismaHttpMessageVerifierFactory( String defaultEncoding, LollipopConsumerRequestConfig lollipopConsumerRequestConfig) - throws Exception { + throws LollipopVerifierException { if (Charset.availableCharsets().get(defaultEncoding) == null) { - throw new Exception("Unavailable Encoding: " + defaultEncoding); + throw new LollipopVerifierException( + LollipopVerifierException.ErrorCode.UNAVAILABLE_ENCODING, + "Unavailable Encoding: " + defaultEncoding); } this.defaultEncoding = defaultEncoding; this.lollipopConsumerRequestConfig = lollipopConsumerRequestConfig; diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java index 276ebaac..9525b1a9 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierFactoryTest.java @@ -20,7 +20,7 @@ public void init() { } @Test - public void encodingInCostructorIsInvalid() { + void encodingInCostructorIsInvalid() { assertThatThrownBy( () -> new VismaHttpMessageVerifierFactory( @@ -31,7 +31,7 @@ public void encodingInCostructorIsInvalid() { } @Test - public void encodingInCostructorIsValid() { + void encodingInCostructorIsValid() { assertThatNoException() .isThrownBy( () -> @@ -41,7 +41,7 @@ public void encodingInCostructorIsValid() { @SneakyThrows @Test - public void instanceIsCreated() { + void instanceIsCreated() { assertThat( new VismaHttpMessageVerifierFactory("UTF-8", lollipopConsumerRequestConfig) .create()) diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java index 7872ffd2..0ec980da 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java @@ -12,13 +12,13 @@ import net.visma.autopay.http.digest.DigestException; import org.junit.jupiter.api.Test; -public class VismaHttpMessageVerifierTest { +class VismaHttpMessageVerifierTest { public VismaHttpMessageVerifier vismaDigestVerifier = new VismaHttpMessageVerifier("UTF-8", LollipopConsumerRequestConfig.builder().build()); @Test - public void correctDigestIsVerified() { + void correctDigestIsVerified() { // setup var content = new String(new byte[] {1, 2, 4}); var header = @@ -30,7 +30,7 @@ public void correctDigestIsVerified() { } @Test - public void invalidDigestIsDetected() { + void invalidDigestIsDetected() { // setup var content = new String(new byte[] {1, 2, 4}); var header = "sha-256=:A5BYxvLAy0ksUzsKTRTvd8wPeKvMztUofYShogEc+4E=:"; @@ -47,7 +47,7 @@ public void invalidDigestIsDetected() { } @Test - public void malformedDigestIsDetected() { + void malformedDigestIsDetected() { // setup var content = new String(new byte[] {1, 2, 4}); var header = "sha-256=1LKaloxAFzY43tjRdMhpV6+iEb5HnO4CDbpd/hJ9kco="; @@ -64,7 +64,7 @@ public void malformedDigestIsDetected() { } @Test - public void unsupportedAlgorithmsAreDetected() { + void unsupportedAlgorithmsAreDetected() { // setup var content = new String(new byte[] {1, 2, 4}); var header = "md5=:V9tg6T+1JldSH4+Zy8c5jw==: ,sha=:q3kRUT3rxwFa1QQpqBWXcUWLJM4=:"; @@ -81,7 +81,7 @@ public void unsupportedAlgorithmsAreDetected() { } @Test - public void emptyHeaderIsDetected() { + void emptyHeaderIsDetected() { // setup var content = new String(new byte[] {1, 2, 4}); var header = ""; @@ -98,7 +98,7 @@ public void emptyHeaderIsDetected() { } @Test - public void invalidDictionaryValuesAreDetected() { + void invalidDictionaryValuesAreDetected() { // setup var content = new String(new byte[] {1, 2, 4}); var header = "sha-256=ok"; @@ -115,7 +115,7 @@ public void invalidDictionaryValuesAreDetected() { } @Test - public void invalidContentEncoding() { + void invalidContentEncoding() { // setup var content = new String(new byte[] {1, 2, 4}); var header = "sha-256=ok"; @@ -126,7 +126,7 @@ public void invalidContentEncoding() { } @Test - public void validLollipopSignatureCheckSingleEcdaSha256() { + void validLollipopSignatureCheckSingleEcdaSha256() { String signatureInput = "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" @@ -162,7 +162,7 @@ public void validLollipopSignatureCheckSingleEcdaSha256() { } @Test - public void invalidLollipopSignatureCheck() { + void invalidLollipopSignatureCheck() { String signatureInput = "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" @@ -205,7 +205,7 @@ public void invalidLollipopSignatureCheck() { } @Test - public void validLollipopSignatureCheckSingleRsaSha256() { + void validLollipopSignatureCheckSingleRsaSha256() { String signatureInput = "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" @@ -248,7 +248,7 @@ public void validLollipopSignatureCheckSingleRsaSha256() { } @Test - public void validLollipopMultipleSignatureCheckEcdaSha256() { + void validLollipopMultipleSignatureCheckEcdaSha256() { String signatureInput = "sig1=(\"x-io-sign-qtspclauses\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\"," @@ -284,7 +284,7 @@ public void validLollipopMultipleSignatureCheckEcdaSha256() { } @Test - public void invalidLollipopMultipleSignatureWithLessInput() { + void invalidLollipopMultipleSignatureWithLessInput() { String signatureInput = "sig1=(\"x-io-sign-qtspclauses\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\"," diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index d4e610d3..84625578 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -23,7 +23,7 @@ public class IdpCertSimpleClient implements IdpCertClient { private final DefaultApi defaultApi; private final IdpCertSimpleClientConfig entityConfig; - private IdpCertStorage storage; + private final IdpCertStorage storage; @Inject public IdpCertSimpleClient( @@ -50,7 +50,6 @@ public IdpCertSimpleClient( public List getCertData(String entityId, String instant) throws CertDataNotFoundException { List listCertData = new ArrayList<>(); - List tagList; if (entityId == null || instant == null || entityId.isBlank() || instant.isBlank()) { throw new IllegalArgumentException("EntityID or Assertion Issue Instant missing"); @@ -186,39 +185,27 @@ private List getTagsFromInstant(List tagList, String instant) throws TagListSearchOutOfBoundException, InvalidInstantFormatException { List newTagList = new ArrayList<>(); String latest = "latest"; - long longInstant; - try { - longInstant = Long.parseLong(instant); - } catch (Exception e) { - throw new InvalidInstantFormatException( - "The given insant " + instant + " is not a valid timestamp"); - } + long longInstant = getLongInstant(instant); boolean latestRemoved = tagList.remove(latest); Collections.sort(tagList); - if (latestRemoved) { - tagList.add(latest); - } + ifLatestRemovedAddLatest(tagList, latest, latestRemoved); int index = tagList.size() / 2; boolean notFound = true; while (notFound) { try { - if (tagList.size() <= 2) { - String firstTimestamp = tagList.get(0); - if (firstTimestamp.equals(latest) - || Long.parseLong(firstTimestamp) <= longInstant) { - return tagList; - } + if (isTagListAlreadyFiltered(tagList, latest, longInstant)) { + return tagList; } String upperTag = tagList.get(index); String lowerTag = tagList.get(index - 1); - if (upperTag.equals(latest) || longInstant <= Long.parseLong(upperTag)) { + if (upperTagIsHigherOrLatest(latest, longInstant, upperTag)) { if (longInstant >= Long.parseLong(lowerTag)) { notFound = false; newTagList.add(upperTag); @@ -238,6 +225,38 @@ private List getTagsFromInstant(List tagList, String instant) return newTagList; } + private static boolean isTagListAlreadyFiltered( + List tagList, String latest, long longInstant) { + if (tagList.size() <= 2) { + String firstTimestamp = tagList.get(0); + return firstTimestamp.equals(latest) || Long.parseLong(firstTimestamp) <= longInstant; + } + return false; + } + + private static long getLongInstant(String instant) throws InvalidInstantFormatException { + long longInstant; + try { + longInstant = Long.parseLong(instant); + } catch (Exception e) { + throw new InvalidInstantFormatException( + "The given instant " + instant + " is not a valid timestamp"); + } + return longInstant; + } + + private static boolean upperTagIsHigherOrLatest( + String latest, long longInstant, String upperTag) { + return upperTag.equals(latest) || longInstant <= Long.parseLong(upperTag); + } + + private static void ifLatestRemovedAddLatest( + List tagList, String latest, boolean latestRemoved) { + if (latestRemoved) { + tagList.add(latest); + } + } + private String codifyStorageTag(String tag, String entityId) { return tag + entityId; } From 604718e6dafc1a92f1dbc883ff6ebdbae5ea3acc Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 27 Apr 2023 11:52:33 +0200 Subject: [PATCH 301/403] [SLS-16] updated unit test with valid data. refactor public key header validation. added mock server to idp client tests. --- .../lollipop/consumer/model/ECPublicKey.java | 14 - .../lollipop/consumer/model/RSAPublicKey.java | 14 - ...pConsumerRequestValidationServiceImpl.java | 24 +- .../tech/lollipop/consumer/TestUtils.java | 137 +++++- .../AssertionVerifierServiceImplTest.java | 19 +- ...sumerRequestValidationServiceImplTest.java | 4 +- .../simple/IdpCertSimpleClientTest.java | 96 +++- .../src/test/resources/idp_cie_data_tag1.xml | 77 ++++ .../src/test/resources/idp_cie_data_tag2.xml | 77 ++++ .../src/test/resources/idp_spid_data_tag1.xml | 434 ++++++++++++++++++ .../src/test/resources/idp_spid_data_tag2.xml | 434 ++++++++++++++++++ .../AssertionSimpleClientTestUtils.java | 170 ------- ...fierHandlerInterceptorIntegrationTest.java | 174 ++++--- .../spring/SimpleClientsTestUtils.java | 283 ++++++++++++ .../spring/config/DemoServicesConfig.java | 7 +- 15 files changed, 1672 insertions(+), 292 deletions(-) delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java create mode 100644 identity-service-rest-client-native/src/test/resources/idp_cie_data_tag1.xml create mode 100644 identity-service-rest-client-native/src/test/resources/idp_cie_data_tag2.xml create mode 100644 identity-service-rest-client-native/src/test/resources/idp_spid_data_tag1.xml create mode 100644 identity-service-rest-client-native/src/test/resources/idp_spid_data_tag2.xml delete mode 100644 spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/AssertionSimpleClientTestUtils.java create mode 100644 spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/SimpleClientsTestUtils.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java deleted file mode 100644 index 8610b7dc..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/ECPublicKey.java +++ /dev/null @@ -1,14 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.model; - -import lombok.Data; - -/** EC public key model */ -@Data -public class ECPublicKey { - - private String crv; - private String kty; - private String x; - private String y; -} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java deleted file mode 100644 index 60e103e2..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/RSAPublicKey.java +++ /dev/null @@ -1,14 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.model; - -import lombok.Data; - -/** RSA public key model */ -@Data -public class RSAPublicKey { - - private String alg; - private String e; - private String kty; - private String n; -} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java index 9c275cbe..1e629447 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImpl.java @@ -1,17 +1,17 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.service.impl; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.jwk.JWK; +import com.nimbusds.jose.jwk.KeyType; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionRefAlgorithms; import it.pagopa.tech.lollipop.consumer.enumeration.AssertionType; import it.pagopa.tech.lollipop.consumer.enumeration.LollipopRequestMethod; import it.pagopa.tech.lollipop.consumer.exception.LollipopRequestContentValidationException; -import it.pagopa.tech.lollipop.consumer.model.ECPublicKey; 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.text.ParseException; import java.util.Base64; import java.util.Map; import java.util.logging.Level; @@ -58,19 +58,23 @@ private void validatePublicKey(String publicKey) log.log(Level.FINE, "Key not in Base64"); } - if (isNotValidPublicKey(publicKey, ECPublicKey.class) - && isNotValidPublicKey(publicKey, RSAPublicKey.class)) { + if (isNotValidPublicKey(publicKey)) { throw new LollipopRequestContentValidationException( LollipopRequestContentValidationException.ErrorCode.INVALID_PUBLIC_KEY, "Invalid Public Key Header value"); } } - private boolean isNotValidPublicKey(String publicKey, Class clazz) { - ObjectMapper mapper = new ObjectMapper(); + private boolean isNotValidPublicKey(String publicKey) { try { - mapper.readValue(publicKey, clazz); - } catch (JsonProcessingException e) { + JWK jwk = JWK.parse(publicKey); + KeyType keyType = jwk.getKeyType(); + if (KeyType.EC.equals(keyType)) { + jwk.toECKey().toECPublicKey(); + } else if (KeyType.RSA.equals(keyType)) { + jwk.toRSAKey().toRSAPublicKey(); + } + } catch (JOSEException | ParseException e) { return true; } return false; diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java index 19e9727f..86161d6a 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/TestUtils.java @@ -448,10 +448,139 @@ public class TestUtils { + " xsi:type=\"xs:string\">TINIT-AAAAAA89S20I111X\t\t" + "\t\t\t" + "\t"; - public static final String CERTIFICATE_TIM_LATEST = - "MIID0jCCArqgAwIBAgIUXDUOKL3WuolxDw96Fk9es8rIt6kwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAklUMS4wLAYDVQQKDCVUZWxlY29tIEl0YWxpYSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMSgwJgYDVQQLDB9TZXJ2aXppIHBlciBsJ2lkZW50aXRhIGRpZ2l0YWxlMSIwIAYDVQQDDBlUSSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMB4XDTIxMTExMTE3MDMyMFoXDTI1MTExMDE3MDMyMFowgYsxCzAJBgNVBAYTAklUMS4wLAYDVQQKDCVUZWxlY29tIEl0YWxpYSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMSgwJgYDVQQLDB9TZXJ2aXppIHBlciBsJ2lkZW50aXRhIGRpZ2l0YWxlMSIwIAYDVQQDDBlUSSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6sIS3+3iZSaAIyVywahlbpua2uJ/XmpV68P1e1STJpHoaj32STdHhqZnnb4Y/FshP1NUolzNolPXAYDmDduW1OnGndJZ+G9Hjh1PCkdiRw+p0FjhQAsGJkn8NdgTIHLJjqN1qQwtOsVGab8ScyA3mtmj3xKYuBhUoweuATzC7f5r7FfIoc3cy6N5lgrpZpfeAChxLwoHVjoAVgIBuemi6HAzmd4/BI06KzOcR7+dBVi4+uiseldxrJ5bhnjZKIwgkX14y9UA84Y+e+rMtyT8cT3XXi9NazZl5Ej5/bQPqqVsbg6tXzQSfEJD6JEjuYeC0RUKMS/EJn3hL5VLzTJ1NwIDAQABoywwKjAdBgNVHQ4EFgQUfctFZ8bRtmEvXPRlqgVDuggY/ZwwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA0lszHadknPfE17IWGWsgvlXOdKMnWcl9H5rEYmsWwDB9FJG9XAZvPMcVv1kkWi6XZI/8N2Twhu1BdZkdvntDRscuck8wxxIpkRV7CwlcqNFZ/IwjDBxOBa8Q1J850p+qP8A9apsLLPUlu/oLygNDWIXzcOjMqnPkEP+XXUNYPto5iV+OyDzLLacCYqDDHcvDewWLmEjt35X967KcM+m7K2zGRLWfqcZPIjJJOkpNjgcs+MaisMrGDyOKiD16v0LpwVyIpTqXvDk7KHo8CUNXDxyLxZzB6WffgnOgjXTfU3vluweOx0qQy/VxIupDlNBKiZB4gnt1oAfnaMbqla9wcw=="; - public static final String ASSERTION_XML_TIM = - "PHNhbWwycDpSZXNwb25zZSB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgRGVzdGluYXRpb249Imh0dHBzOi8vYXBwLWJhY2tlbmQuaW8uaXRhbGlhLml0L2Fzc2VydGlvbkNvbnN1bWVyU2VydmljZSIgSUQ9Il85YzA0YTI4ZDkzNWViNmMyODg0Njc4OTc0ZjA0OWZhNiIgSW5SZXNwb25zZVRvPSJzaGEyNTYtTUpDOTZQZzFUdWZEN0FNMWdTTW0xZ3JRUExFOGI1UjFJcjFKSmJaQlExSSIgSXNzdWVJbnN0YW50PSIyMDIzLTA0LTA0VDE1OjAxOjQ1Ljk3M1oiIFZlcnNpb249IjIuMCI+PHNhbWwyOklzc3VlciB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlkLWZvcm1hdDplbnRpdHkiPmh0dHBzOi8vbG9naW4uaWQudGltLml0L2FmZndlYnNlcnZpY2VzL3B1YmxpYy9zYW1sMnNzbzwvc2FtbDI6SXNzdWVyPjxTaWduYXR1cmUgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxTaWduZWRJbmZvPjxDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PFNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZHNpZy1tb3JlI3JzYS1zaGEyNTYiLz48UmVmZXJlbmNlIFVSST0iI185YzA0YTI4ZDkzNWViNmMyODg0Njc4OTc0ZjA0OWZhNiI+PFRyYW5zZm9ybXM+PFRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8+PFRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjwvVHJhbnNmb3Jtcz48RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjc2hhMjU2Ii8+PERpZ2VzdFZhbHVlPk1kRjE4aTNRVC9pdnBrdjdubkdlWms4N3hzYWpFWlY3d3Jrdm9IUy9KZGs9PC9EaWdlc3RWYWx1ZT48L1JlZmVyZW5jZT48L1NpZ25lZEluZm8+PFNpZ25hdHVyZVZhbHVlPk5TWCtWWCtMaXJYNzROQ0lQbGVxelIxeTIwZW5rVS9IQ2tKWlJmOUFCNEQvSkFJRUhSdWRxbmhyckQyb05OZ3lRNnltcktsSFVvQnpnbVhGWmIvUE8wa0pXTzVwbGhLY1AxakFhNlF4NTRNaHFqUnA2cmdhcGk2SlJGTXErbDVXeVVLSnRXMHBCdkpQYUVpMngxeG1HUHZzZU81ZkNEbnVpZHZEdXYydFVqRm1jZTY4bzRGWjF2dGprd0w3TExMNUNNTHc4dVNnWFNwK1lhOUNNQzJaYVl5aDNOaExsUktvazNuakVpd2d2ZTRWUURQRGZ0RmhnektHb25zM0FHcTQra2xPODBzaWF4WUl1Y1FKMVdxUmJKL3NzRUV5N3NOZXU3cXlhSmsrekpzVnA5cU5OL0RhM3lxTXp1bVRUMmtSZnNIL0tuWFJmTC9NQnNHNFNEVHY0QT09PC9TaWduYXR1cmVWYWx1ZT48S2V5SW5mbz48WDUwOURhdGE+PFg1MDlDZXJ0aWZpY2F0ZT5NSUlEMGpDQ0FycWdBd0lCQWdJVVhEVU9LTDNXdW9seER3OTZGazllczhySXQ2a3dEUVlKS29aSWh2Y05BUUVMQlFBd2dZc3hDekFKQmdOVkJBWVRBa2xVTVM0d0xBWURWUVFLRENWVVpXeGxZMjl0SUVsMFlXeHBZU0JVY25WemRDQlVaV05vYm05c2IyZHBaWE1nYzNKc01TZ3dKZ1lEVlFRTERCOVRaWEoyYVhwcElIQmxjaUJzSjJsa1pXNTBhWFJoSUdScFoybDBZV3hsTVNJd0lBWURWUVFEREJsVVNTQlVjblZ6ZENCVVpXTm9ibTlzYjJkcFpYTWdjM0pzTUI0WERUSXhNVEV4TVRFM01ETXlNRm9YRFRJMU1URXhNREUzTURNeU1Gb3dnWXN4Q3pBSkJnTlZCQVlUQWtsVU1TNHdMQVlEVlFRS0RDVlVaV3hsWTI5dElFbDBZV3hwWVNCVWNuVnpkQ0JVWldOb2JtOXNiMmRwWlhNZ2MzSnNNU2d3SmdZRFZRUUxEQjlUWlhKMmFYcHBJSEJsY2lCc0oybGtaVzUwYVhSaElHUnBaMmwwWVd4bE1TSXdJQVlEVlFRRERCbFVTU0JVY25WemRDQlVaV05vYm05c2IyZHBaWE1nYzNKc01JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNnNJUzMrM2laU2FBSXlWeXdhaGxicHVhMnVKL1htcFY2OFAxZTFTVEpwSG9hajMyU1RkSGhxWm5uYjRZL0ZzaFAxTlVvbHpOb2xQWEFZRG1EZHVXMU9uR25kSlorRzlIamgxUENrZGlSdytwMEZqaFFBc0dKa244TmRnVElITEpqcU4xcVF3dE9zVkdhYjhTY3lBM210bWozeEtZdUJoVW93ZXVBVHpDN2Y1cjdGZklvYzNjeTZONWxncnBacGZlQUNoeEx3b0hWam9BVmdJQnVlbWk2SEF6bWQ0L0JJMDZLek9jUjcrZEJWaTQrdWlzZWxkeHJKNWJobmpaS0l3Z2tYMTR5OVVBODRZK2Urck10eVQ4Y1QzWFhpOU5helpsNUVqNS9iUVBxcVZzYmc2dFh6UVNmRUpENkpFanVZZUMwUlVLTVMvRUpuM2hMNVZMelRKMU53SURBUUFCb3l3d0tqQWRCZ05WSFE0RUZnUVVmY3RGWjhiUnRtRXZYUFJscWdWRHVnZ1kvWnd3Q1FZRFZSMFRCQUl3QURBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQTBsc3pIYWRrblBmRTE3SVdHV3NndmxYT2RLTW5XY2w5SDVyRVltc1d3REI5RkpHOVhBWnZQTWNWdjFra1dpNlhaSS84TjJUd2h1MUJkWmtkdm50RFJzY3Vjazh3eHhJcGtSVjdDd2xjcU5GWi9Jd2pEQnhPQmE4UTFKODUwcCtxUDhBOWFwc0xMUFVsdS9vTHlnTkRXSVh6Y09qTXFuUGtFUCtYWFVOWVB0bzVpVitPeUR6TExhY0NZcURESGN2RGV3V0xtRWp0MzVYOTY3S2NNK203SzJ6R1JMV2ZxY1pQSWpKSk9rcE5qZ2NzK01haXNNckdEeU9LaUQxNnYwTHB3VnlJcFRxWHZEazdLSG84Q1VOWER4eUx4WnpCNldmZmduT2dqWFRmVTN2bHV3ZU94MHFReS9WeEl1cERsTkJLaVpCNGdudDFvQWZuYU1icWxhOXdjdz09PC9YNTA5Q2VydGlmaWNhdGU+PC9YNTA5RGF0YT48L0tleUluZm8+PC9TaWduYXR1cmU+PHNhbWwycDpTdGF0dXM+PHNhbWwycDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz48L3NhbWwycDpTdGF0dXM+PHNhbWwyOkFzc2VydGlvbiB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9Il9jMjYwYjI2NzNlYzMwZjJjNzI0YjI5NDM2NTFiOWEyYiIgSXNzdWVJbnN0YW50PSIyMDIzLTA0LTA0VDE1OjAxOjQ1Ljk3M1oiIFZlcnNpb249IjIuMCI+PHNhbWwyOklzc3VlciBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpuYW1laWQtZm9ybWF0OmVudGl0eSI+aHR0cHM6Ly9sb2dpbi5pZC50aW0uaXQvYWZmd2Vic2VydmljZXMvcHVibGljL3NhbWwyc3NvPC9zYW1sMjpJc3N1ZXI+PFNpZ25hdHVyZSB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+PFNpZ25lZEluZm8+PENhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxkc2lnLW1vcmUjcnNhLXNoYTI1NiIvPjxSZWZlcmVuY2UgVVJJPSIjX2MyNjBiMjY3M2VjMzBmMmM3MjRiMjk0MzY1MWI5YTJiIj48VHJhbnNmb3Jtcz48VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz48VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PC9UcmFuc2Zvcm1zPjxEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNzaGEyNTYiLz48RGlnZXN0VmFsdWU+d2tlS0V1OWpFOGNaeFpVM3hWcWZEVURWVHpCUHZjL1FERXJRNXpRRWk3Yz08L0RpZ2VzdFZhbHVlPjwvUmVmZXJlbmNlPjwvU2lnbmVkSW5mbz48U2lnbmF0dXJlVmFsdWU+NWlUQ3o5WjdCT1d5QzBPZE56M2RNMXI1RG1yOTliamtvejZWMlJUVmJTNE5UUnB5UmVkb3ZqNHBhRmxXd0Z4Ris4eWNDNTJlUXRmVDk3Tk5HVExMRlJRYTMrODVWbHVqeFdWZmhDUks1aEJxV1VXZVFiUnl6YitmWlhJSEgxTE5ENTlkVUcrWHlDcDl1Z1lzbi9JZjJySGoxTUdxYnMvZnZaU25HeU16RzRrVXpSa0lXREl4eWdLSXNCYTREQUc0bms5MGNVRTBlQVRQdURDblhNbkEyWTMvWlJWN3lCalpXbUorZ3F1ZHExaWowUDJJL29FUVdIWW1yVTV1bkhIZTI0MmlmUTRpYkdydy93cWRpa1UvSDA1M0JHZEFFaFluTVByYWpPV1Z5SmhoYnlTdCsycmpDZ0xjeWZMWG5xV3FUVS9IdE5CSGNQWGhVK0RaL1Q5MzNBPT08L1NpZ25hdHVyZVZhbHVlPjxLZXlJbmZvPjxYNTA5RGF0YT48WDUwOUNlcnRpZmljYXRlPk1JSUQwakNDQXJxZ0F3SUJBZ0lVWERVT0tMM1d1b2x4RHc5NkZrOWVzOHJJdDZrd0RRWUpLb1pJaHZjTkFRRUxCUUF3Z1lzeEN6QUpCZ05WQkFZVEFrbFVNUzR3TEFZRFZRUUtEQ1ZVWld4bFkyOXRJRWwwWVd4cFlTQlVjblZ6ZENCVVpXTm9ibTlzYjJkcFpYTWdjM0pzTVNnd0pnWURWUVFMREI5VFpYSjJhWHBwSUhCbGNpQnNKMmxrWlc1MGFYUmhJR1JwWjJsMFlXeGxNU0l3SUFZRFZRUUREQmxVU1NCVWNuVnpkQ0JVWldOb2JtOXNiMmRwWlhNZ2MzSnNNQjRYRFRJeE1URXhNVEUzTURNeU1Gb1hEVEkxTVRFeE1ERTNNRE15TUZvd2dZc3hDekFKQmdOVkJBWVRBa2xVTVM0d0xBWURWUVFLRENWVVpXeGxZMjl0SUVsMFlXeHBZU0JVY25WemRDQlVaV05vYm05c2IyZHBaWE1nYzNKc01TZ3dKZ1lEVlFRTERCOVRaWEoyYVhwcElIQmxjaUJzSjJsa1pXNTBhWFJoSUdScFoybDBZV3hsTVNJd0lBWURWUVFEREJsVVNTQlVjblZ6ZENCVVpXTm9ibTlzYjJkcFpYTWdjM0pzTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE2c0lTMyszaVpTYUFJeVZ5d2FobGJwdWEydUovWG1wVjY4UDFlMVNUSnBIb2FqMzJTVGRIaHFabm5iNFkvRnNoUDFOVW9sek5vbFBYQVlEbURkdVcxT25HbmRKWitHOUhqaDFQQ2tkaVJ3K3AwRmpoUUFzR0prbjhOZGdUSUhMSmpxTjFxUXd0T3NWR2FiOFNjeUEzbXRtajN4S1l1QmhVb3dldUFUekM3ZjVyN0ZmSW9jM2N5Nk41bGdycFpwZmVBQ2h4THdvSFZqb0FWZ0lCdWVtaTZIQXptZDQvQkkwNkt6T2NSNytkQlZpNCt1aXNlbGR4cko1YmhualpLSXdna1gxNHk5VUE4NFkrZStyTXR5VDhjVDNYWGk5TmF6Wmw1RWo1L2JRUHFxVnNiZzZ0WHpRU2ZFSkQ2SkVqdVllQzBSVUtNUy9FSm4zaEw1Vkx6VEoxTndJREFRQUJveXd3S2pBZEJnTlZIUTRFRmdRVWZjdEZaOGJSdG1FdlhQUmxxZ1ZEdWdnWS9ad3dDUVlEVlIwVEJBSXdBREFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBMGxzekhhZGtuUGZFMTdJV0dXc2d2bFhPZEtNbldjbDlINXJFWW1zV3dEQjlGSkc5WEFadlBNY1Z2MWtrV2k2WFpJLzhOMlR3aHUxQmRaa2R2bnREUnNjdWNrOHd4eElwa1JWN0N3bGNxTkZaL0l3akRCeE9CYThRMUo4NTBwK3FQOEE5YXBzTExQVWx1L29MeWdORFdJWHpjT2pNcW5Qa0VQK1hYVU5ZUHRvNWlWK095RHpMTGFjQ1lxRERIY3ZEZXdXTG1FanQzNVg5NjdLY00rbTdLMnpHUkxXZnFjWlBJakpKT2twTmpnY3MrTWFpc01yR0R5T0tpRDE2djBMcHdWeUlwVHFYdkRrN0tIbzhDVU5YRHh5THhaekI2V2ZmZ25PZ2pYVGZVM3ZsdXdlT3gwcVF5L1Z4SXVwRGxOQktpWkI0Z250MW9BZm5hTWJxbGE5d2N3PT08L1g1MDlDZXJ0aWZpY2F0ZT48L1g1MDlEYXRhPjwvS2V5SW5mbz48L1NpZ25hdHVyZT48c2FtbDI6U3ViamVjdD48c2FtbDI6TmFtZUlEIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6dHJhbnNpZW50IiBOYW1lUXVhbGlmaWVyPSJodHRwczovL2xvZ2luLmlkLnRpbS5pdC9hZmZ3ZWJzZXJ2aWNlcy9wdWJsaWMvc2FtbDJzc28iPl80OTJlNDQyNGVjOTVjNzU5MWViMTY5MGJjOTk3ZDIwMzwvc2FtbDI6TmFtZUlEPjxzYW1sMjpTdWJqZWN0Q29uZmlybWF0aW9uIE1ldGhvZD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmNtOmJlYXJlciI+PHNhbWwyOlN1YmplY3RDb25maXJtYXRpb25EYXRhIEluUmVzcG9uc2VUbz0ic2hhMjU2LU1KQzk2UGcxVHVmRDdBTTFnU01tMWdyUVBMRThiNVIxSXIxSkpiWkJRMUkiIE5vdE9uT3JBZnRlcj0iMjAyMy0wNC0wNFQxNTowMjoxNS45NzNaIiBSZWNpcGllbnQ9Imh0dHBzOi8vYXBwLWJhY2tlbmQuaW8uaXRhbGlhLml0L2Fzc2VydGlvbkNvbnN1bWVyU2VydmljZSIvPjwvc2FtbDI6U3ViamVjdENvbmZpcm1hdGlvbj48L3NhbWwyOlN1YmplY3Q+PHNhbWwyOkNvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDIzLTA0LTA0VDE1OjAxOjQ0Ljk3M1oiIE5vdE9uT3JBZnRlcj0iMjAyMy0wNC0wNFQxNTowMjoxNS45NzNaIj48c2FtbDI6QXVkaWVuY2VSZXN0cmljdGlvbj48c2FtbDI6QXVkaWVuY2U+aHR0cHM6Ly9hcHAtYmFja2VuZC5pby5pdGFsaWEuaXQ8L3NhbWwyOkF1ZGllbmNlPjwvc2FtbDI6QXVkaWVuY2VSZXN0cmljdGlvbj48L3NhbWwyOkNvbmRpdGlvbnM+PHNhbWwyOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAyMy0wNC0wNFQxNTowMTo0NS45NzNaIj48c2FtbDI6QXV0aG5Db250ZXh0PjxzYW1sMjpBdXRobkNvbnRleHRDbGFzc1JlZj5odHRwczovL3d3dy5zcGlkLmdvdi5pdC9TcGlkTDI8L3NhbWwyOkF1dGhuQ29udGV4dENsYXNzUmVmPjwvc2FtbDI6QXV0aG5Db250ZXh0Pjwvc2FtbDI6QXV0aG5TdGF0ZW1lbnQ+PHNhbWwyOkF0dHJpYnV0ZVN0YXRlbWVudD48c2FtbDI6QXR0cmlidXRlIEZyaWVuZGx5TmFtZT0iRGF0YSBkaSBuYXNjaXRhIiBOYW1lPSJkYXRlT2ZCaXJ0aCI+PHNhbWwyOkF0dHJpYnV0ZVZhbHVlIHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnR5cGU9InhzOmRhdGUiPjE5ODctMDktMTQ8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjxzYW1sMjpBdHRyaWJ1dGUgRnJpZW5kbHlOYW1lPSJJbmRpcml6em8gZGkgcG9zdGEgZWxldHRyb25pY2EiIE5hbWU9ImVtYWlsIj48c2FtbDI6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hIiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4c2k6dHlwZT0ieHM6c3RyaW5nIj5waWV0cm8uc3Ryb2lhQGdtYWlsLmNvbTwvc2FtbDI6QXR0cmlidXRlVmFsdWU+PC9zYW1sMjpBdHRyaWJ1dGU+PHNhbWwyOkF0dHJpYnV0ZSBGcmllbmRseU5hbWU9IkNvZ25vbWUiIE5hbWU9ImZhbWlseU5hbWUiPjxzYW1sMjpBdHRyaWJ1dGVWYWx1ZSB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhzaTp0eXBlPSJ4czpzdHJpbmciPlN0cm9pYTwvc2FtbDI6QXR0cmlidXRlVmFsdWU+PC9zYW1sMjpBdHRyaWJ1dGU+PHNhbWwyOkF0dHJpYnV0ZSBGcmllbmRseU5hbWU9IkNvZGljZSBmaXNjYWxlIiBOYW1lPSJmaXNjYWxOdW1iZXIiPjxzYW1sMjpBdHRyaWJ1dGVWYWx1ZSB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhzaTp0eXBlPSJ4czpzdHJpbmciPlRJTklULVNUUlBUUjg3UDE0RTMzNVY8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjxzYW1sMjpBdHRyaWJ1dGUgRnJpZW5kbHlOYW1lPSJOb21lIiBOYW1lPSJuYW1lIj48c2FtbDI6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hIiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4c2k6dHlwZT0ieHM6c3RyaW5nIj5QaWV0cm88L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjwvc2FtbDI6QXR0cmlidXRlU3RhdGVtZW50Pjwvc2FtbDI6QXNzZXJ0aW9uPjwvc2FtbDJwOlJlc3BvbnNlPg=="; + public static final String VALID_IDP_CERTIFICATE = + "MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI/sp\n" + + "ILywgDxVMMtv/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA/L1/fd70ok+6xtDRF8A3HjAf\n" + + "BgNVHSMEGDAWgBQEVmzA/L1/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH/MA0G\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8/o13vMw4feGxro1hMeUilRtH52funrW\n" + + "C+FgPrqk3o/8cZOnq+CqnFFDfILLiEb/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\n" + + "Da1fG/Pi0fG2F0yw/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk/ZbEHdKcofnziDyl0V8gglP2\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ"; + public static final String VALID_ASSERTION_XML = + "\n" + + " https://spid-testenv2:8088s/DqYePHC7eCXX5ncsiFYNLyKbzS6P5C8331H1b8e30=WcasorooElvhmK0kxFUdBVCqyRYi0SCNGRSZZnC9Q2sZHOYGZbERe4/T8OSuRKbSrEivXIHRgNr8WskZTM2CiywfWChHfGvhERsLuPJE8oh9CR3eicX/eg0ynJqwx4IoYhTb2NOwqMFc66nnutMhG/Smdtjs4SFz0RQYYVeZ5Ho51iTHd94uBV9ZHXjqcvs3EitUsJ0Zg1Pkw352tt8y7niUcGjAd8nydI72S12sF5ePv05AunFp7vZpYbKqi62fQLORCn1ZP7WKFD75hL0bCvZaSRF285GkfSnLfe1S4tLff2SlTQWevOMU/wCkHJmQwHT1LMwcWRnMvv4V+vd1XQ==MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI/sp\n" + + "ILywgDxVMMtv/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA/L1/fd70ok+6xtDRF8A3HjAf\n" + + "BgNVHSMEGDAWgBQEVmzA/L1/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH/MA0G\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8/o13vMw4feGxro1hMeUilRtH52funrW\n" + + "C+FgPrqk3o/8cZOnq+CqnFFDfILLiEb/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\n" + + "Da1fG/Pi0fG2F0yw/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk/ZbEHdKcofnziDyl0V8gglP2\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " https://spid-testenv2:80884cqgG29TSKgNLy2/1eFPXhd5WRVPxZBGcd8DgTvd5Fo=WqxM+y+vtZDcEaIaw2WfcuMuwXUeTOY9ZjaXwzHw+RE8uUr5s8BE1tpaodcKmmqSJK1JQYNr8AUV+W9V79EKfmNtFvfaf0WYeUee7Td7E24QqiyVHjr1YgfDWhSdItFLYJfQUkotj2BepbdwVQGY5yN0Rw6Fq98hgNOgsxty7g6oqxG1OXB4WJ2He20iOoYWQl8ApxlbU//hwnefFYe9ghDPy3rDbcNl3JetT07NR/+AzhKH4e+JCwKjTkdCBTW30fK4eiV9yBk74Lobip4hMaQhMaByl8egaU3A8AsnsZQuov2B6Wo2sDiQPjIulb8K3DOwFyL8PzEk8BB5YoAfwg==MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI/sp\n" + + "ILywgDxVMMtv/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA/L1/fd70ok+6xtDRF8A3HjAf\n" + + "BgNVHSMEGDAWgBQEVmzA/L1/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH/MA0G\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8/o13vMw4feGxro1hMeUilRtH52funrW\n" + + "C+FgPrqk3o/8cZOnq+CqnFFDfILLiEb/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\n" + + "Da1fG/Pi0fG2F0yw/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk/ZbEHdKcofnziDyl0V8gglP2\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\n" + + "\n" + + " \n" + + " id_48129c2a9d5e9077422591baf495747cfda668c5\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " https://spid.agid.gov.it/cd\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + + " https://www.spid.gov.it/SpidL2\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " info@agid.gov.it\n" + + " \n" + + " \n" + + " Mario\n" + + " \n" + + " \n" + + " Bianchi\n" + + " \n" + + " \n" + + " GDNNWA12H81Y874F\n" + + " \n" + + " \n" + + " 1991-12-12\n" + + " \n" + + " \n" + + " \n" + + ""; private TestUtils() {} } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java index 10a1ba98..3e681c7d 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/AssertionVerifierServiceImplTest.java @@ -13,12 +13,10 @@ import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; -import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.Collections; import java.util.HashMap; import lombok.SneakyThrows; -import org.apache.geronimo.mail.util.Base64; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -189,10 +187,12 @@ void validateLollipopValidatePeriodSuccess() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); - assertion.setAssertionData( - new String(Base64.decode(ASSERTION_XML_TIM.getBytes(StandardCharsets.UTF_8)))); + assertion.setAssertionData(VALID_ASSERTION_XML); doReturn(365 * 20).when(lollipopRequestConfigMock).getAssertionExpireInDays(); + doReturn("yyyy-MM-dd'T'HH:mm:ss'Z'") + .when(lollipopRequestConfigMock) + .getAssertionNotBeforeDateFormat(); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); doReturn(true) @@ -583,7 +583,7 @@ void validateLollipopValidateSignatureFailureForErrorUnmarshalAssertion() { assertion.setAssertionData(EMPTY_ASSERTION_XML); IdpCertData idpCertData = new IdpCertData(); - idpCertData.setCertData(Collections.singletonList(CERTIFICATE_TIM_LATEST)); + idpCertData.setCertData(Collections.singletonList(VALID_IDP_CERTIFICATE)); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); @@ -616,7 +616,7 @@ void validateLollipopValidateSignatureFailureForMissingSignature() { assertion.setAssertionData(ASSERTION_XML_WITH_VALID_INRESPONSETO_SHA256_ALGORITHM); IdpCertData idpCertData = new IdpCertData(); - idpCertData.setCertData(Collections.singletonList(CERTIFICATE_TIM_LATEST)); + idpCertData.setCertData(Collections.singletonList(VALID_IDP_CERTIFICATE)); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); @@ -649,7 +649,7 @@ void validateLollipopValidateSignatureFailureForSignatureNotValid() { assertion.setAssertionData(ASSERTION_XML_WITH_INVALID_SIGNATURE); IdpCertData idpCertData = new IdpCertData(); - idpCertData.setCertData(Collections.singletonList(CERTIFICATE_TIM_LATEST)); + idpCertData.setCertData(Collections.singletonList(VALID_IDP_CERTIFICATE)); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); @@ -674,11 +674,10 @@ void validateLollipopSuccess() { LollipopConsumerRequest request = getLollipopConsumerRequest("", "", ""); SamlAssertion assertion = new SamlAssertion(); - assertion.setAssertionData( - new String(Base64.decode(ASSERTION_XML_TIM.getBytes(StandardCharsets.UTF_8)))); + assertion.setAssertionData(VALID_ASSERTION_XML); IdpCertData idpCertData = new IdpCertData(); - idpCertData.setCertData(Collections.singletonList(CERTIFICATE_TIM_LATEST)); + idpCertData.setCertData(Collections.singletonList(VALID_IDP_CERTIFICATE)); doReturn(assertion).when(assertionServiceMock).getAssertion(anyString(), anyString()); doReturn(true).when(sut).validateAssertionPeriod(any(Document.class)); diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java index 2130e5d3..c3812057 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/service/impl/LollipopConsumerRequestValidationServiceImplTest.java @@ -26,8 +26,8 @@ class LollipopConsumerRequestValidationServiceImplTest { "{ \"kty\": \"EC\", \"x\": \"FqFDuwEgu4MUXERPMVL-85pGv2D3YmL4J1gfMkdbc24\", \"y\":" + " \"hdV0oxmWFSxMoJUDpdihr76rS8VRBEqMFebYyAfK9-k\", \"crv\": \"P-256\"}"; public static final String VALID_RSA_PUBLIC_KEY = - "{ \"alg\": \"RS256\", \"e\": \"AQAB\", \"kty\": \"RSA\", \"n\":" - + " \"yeNlzlub94YgerT030codqEztjfU_S6X4DbDA_iVKkjAWtYfPHDzz_sPCT1Axz6isZdf3lHpq_gYX4Sz\"}"; + "{ \"alg\": \"RS256\", \"e\": \"65537\", \"kty\": \"RSA\", \"n\":" + + " \"16664736175603627996319962836030881026179675012391119517975514948152431214653585662880486636564539745534321011181408561816254231231298259205135081219875827651147217038442994953270212442857910417611387549687536933145745249602198835932059392377695498325446146715840517338191125529557810596070318285357964276748438650077150378696894010172596714187128214451872453277619054588751139432194135913672107689362828514055714059473608142304229480488308405791341245363647711560656764853819020066812645413910427819478301754525254844345246642430554339909098721902422359723272095429198014557278590405542226255562568066559844209030611\"}"; public static final String VALID_ASSERTION_REF = "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg"; public static final String VALID_FISCAL_CODE = "AAAAAA89S20I111X"; diff --git a/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java index 2aaef53c..eb915dd6 100644 --- a/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java @@ -1,24 +1,39 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.client.simple; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockserver.integration.ClientAndServer.startClientAndServer; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.storage.SimpleIdpCertStorageProvider; import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import java.io.FileInputStream; +import java.nio.charset.StandardCharsets; import java.time.Instant; import java.util.List; +import lombok.SneakyThrows; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; +import org.mockserver.client.MockServerClient; +import org.mockserver.integration.ClientAndServer; class IdpCertSimpleClientTest { private static IdpCertSimpleClient idpCertSimpleClient; - private static IdpCertSimpleClientConfig entityConfig; + + private static ClientAndServer mockServer; private static final String INSTANT = String.valueOf(Instant.now().getEpochSecond()); + private static final String TAG1 = String.valueOf(Instant.now().getEpochSecond() - 1); + private static final String TAG2 = String.valueOf(Instant.now().getEpochSecond() + 1); private static final String SPID_ENTITY_ID = "https://posteid.poste.it"; private static final String SPID_ENTITY_ID_MULTIPLE_SIGNATURE = "https://loginspid.aruba.it"; private static final String CIE_ENTITY_ID = @@ -29,7 +44,8 @@ class IdpCertSimpleClientTest { @BeforeAll public static void startServer() { - entityConfig = Mockito.spy(IdpCertSimpleClientConfig.builder().build()); + mockServer = startClientAndServer(3001); + IdpCertSimpleClientConfig entityConfig = spy(IdpCertSimpleClientConfig.builder().build()); ApiClient client = new ApiClient(entityConfig); SimpleIdpCertStorageProvider storageProvider = new SimpleIdpCertStorageProvider(); idpCertSimpleClient = @@ -37,10 +53,17 @@ public static void startServer() { client, entityConfig, storageProvider.provideStorage(new IdpCertStorageConfig())); + doReturn("http://localhost:3001").when(entityConfig).getBaseUri(); + } + + @AfterAll + public static void stopServer() { + mockServer.stop(); } @Test void certSPIDDataFound() throws CertDataNotFoundException { + createExpectationIdpSpidFound(); List response = idpCertSimpleClient.getCertData(SPID_ENTITY_ID, INSTANT); Assertions.assertNotNull(response); @@ -48,6 +71,7 @@ void certSPIDDataFound() throws CertDataNotFoundException { @Test void certSPIDDataFoundMultipleSignature() throws CertDataNotFoundException { + createExpectationIdpSpidFound(); List response = idpCertSimpleClient.getCertData(SPID_ENTITY_ID_MULTIPLE_SIGNATURE, INSTANT); @@ -57,6 +81,7 @@ void certSPIDDataFoundMultipleSignature() throws CertDataNotFoundException { @Test void certCIEDataFound() throws CertDataNotFoundException { + createExpectationIdpCieFound(); List response = idpCertSimpleClient.getCertData(CIE_ENTITY_ID, INSTANT); Assertions.assertNotNull(response); @@ -64,6 +89,7 @@ void certCIEDataFound() throws CertDataNotFoundException { @Test void getCertDataWrongEntityID() { + createExpectationIdpSpidFound(); Assertions.assertThrows( CertDataNotFoundException.class, () -> idpCertSimpleClient.getCertData(WRONG_ENTITY_ID, INSTANT)); @@ -96,4 +122,68 @@ void instantNull() { IllegalArgumentException.class, () -> idpCertSimpleClient.getCertData(CIE_ENTITY_ID, null)); } + + public static void createExpectationIdpSpidFound() { + new MockServerClient("localhost", 3001) + .when(request().withMethod("GET").withPath("/idp-keys/spid")) + .respond( + response() + .withStatusCode(200) + .withBody("[\"" + TAG1 + "\",\"" + TAG2 + "\"]")); + new MockServerClient("localhost", 3001) + .when( + request() + .withMethod("GET") + .withPath("/idp-keys/spid/{tag}") + .withPathParameter("tag", TAG1)) + .respond( + response() + .withStatusCode(200) + .withBody(retrieveDataFromFile("idp_spid_data_tag1.xml"))); + new MockServerClient("localhost", 3001) + .when( + request() + .withMethod("GET") + .withPath("/idp-keys/spid/{tag}") + .withPathParameter("tag", TAG2)) + .respond( + response() + .withStatusCode(200) + .withBody(retrieveDataFromFile("idp_spid_data_tag2.xml"))); + } + + public static void createExpectationIdpCieFound() { + new MockServerClient("localhost", 3001) + .when(request().withMethod("GET").withPath("/idp-keys/cie")) + .respond( + response() + .withStatusCode(200) + .withBody("[\"" + TAG1 + "\",\"" + TAG2 + "\"]")); + new MockServerClient("localhost", 3001) + .when( + request() + .withMethod("GET") + .withPath("/idp-keys/cie/{tag}") + .withPathParameter("tag", TAG1)) + .respond( + response() + .withStatusCode(200) + .withBody(retrieveDataFromFile("idp_cie_data_tag1.xml"))); + new MockServerClient("localhost", 3001) + .when( + request() + .withMethod("GET") + .withPath("/idp-keys/cie/{tag}") + .withPathParameter("tag", TAG2)) + .respond( + response() + .withStatusCode(200) + .withBody(retrieveDataFromFile("idp_cie_data_tag1.xml"))); + } + + @SneakyThrows + private static String retrieveDataFromFile(String fileName) { + FileInputStream fis = new FileInputStream("src/test/resources/" + fileName); + return IOUtils.toString(fis, StandardCharsets.UTF_8); + } } diff --git a/identity-service-rest-client-native/src/test/resources/idp_cie_data_tag1.xml b/identity-service-rest-client-native/src/test/resources/idp_cie_data_tag1.xml new file mode 100644 index 00000000..74ca1fd9 --- /dev/null +++ b/identity-service-rest-client-native/src/test/resources/idp_cie_data_tag1.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + ssh7Qe/Sett1HNLh/vQYvNUkCjfgEhAg8Ce4f1GL+Mg= + + + UI+4D9XebmPI96WgQAgSo+IrNzAObjecitjsR6l8gSYmtNDLNLYPeobF4kpFY34Y5bTm+IL1K9VN hhnBeJBeuL9oSBee9PaDzCSt+hmrcQdKvAr05UWDsg96ZYkgyuDugcmbRl3+PBpHzheK0qnVGZne BTSOrFk9vpYxrd2cHv/C6/DV6vNHJFe7uf2LE8yZ+qJqT/UKUgdS0qtW6FjdTOq44BxujJsi/1Yo DiIMvDjKxNrWKjxgpra35i1D1iS6jAEG68nVHjFROQ0ciUS8+9JyoUvQJ3YkVdDAhnsrMtIE8w2A RXL19GhWAw2wR8SKVEZeSNTkf34AQIHLx0vjiA== + + + + x62o94jkwiCC05Ts4nEhLhbdN5Cr0A6hlkXeaO7NVu0j9hLXE5oN8a6J/7G6yxC/3jFEFfwYs+ie KRBqBaTGUBxsTlcqZjuzXPKZBaLe8lEwKa+iJLsuHFLW8dIOX5ECzW97qSINFYNY0p0VxL1AsoK/ /RHiglDov9qbZjlUi2nfnU+04kbGU8GNxb0VnJXg38mMHCDIM+XS0jSzGasM0GStQ871ng+mhrQS gmD0X7WnB6BEg/um4bpB2esPeX6ETCSzmgaZKfl37oBUIqGL6zNAAdWEGeQwkEYYXPI3o8HWPmzg d3mdZSWOzmp537ulz1tn3JJ3pcj7ezxn9tqzXw== + AQAB + + + + MIIDdTCCAl2gAwIBAgIUU79XEfveueyClDtLkqUlSPZ2o8owDQYJKoZIhvcNAQELBQAwLTErMCkG A1UEAwwiaWRzZXJ2ZXIuc2Vydml6aWNpZS5pbnRlcm5vLmdvdi5pdDAeFw0xODEwMTkwODM1MDVa Fw0zODEwMTkwODM1MDVaMC0xKzApBgNVBAMMImlkc2VydmVyLnNlcnZpemljaWUuaW50ZXJuby5n b3YuaXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHraj3iOTCIILTlOzicSEuFt03 kKvQDqGWRd5o7s1W7SP2EtcTmg3xron/sbrLEL/eMUQV/Biz6J4pEGoFpMZQHGxOVypmO7Nc8pkF ot7yUTApr6Ikuy4cUtbx0g5fkQLNb3upIg0Vg1jSnRXEvUCygr/9EeKCUOi/2ptmOVSLad+dT7Ti RsZTwY3FvRWcleDfyYwcIMgz5dLSNLMZqwzQZK1DzvWeD6aGtBKCYPRftacHoESD+6bhukHZ6w95 foRMJLOaBpkp+XfugFQioYvrM0AB1YQZ5DCQRhhc8jejwdY+bOB3eZ1lJY7Oannfu6XPW2fcknel yPt7PGf22rNfAgMBAAGjgYwwgYkwHQYDVR0OBBYEFK3Ah+Do3/zB9XjZ66i4biDpUEbAMGgGA1Ud EQRhMF+CImlkc2VydmVyLnNlcnZpemljaWUuaW50ZXJuby5nb3YuaXSGOWh0dHBzOi8vaWRzZXJ2 ZXIuc2Vydml6aWNpZS5pbnRlcm5vLmdvdi5pdC9pZHAvc2hpYmJvbGV0aDANBgkqhkiG9w0BAQsF AAOCAQEAVtpn/s+lYVf42pAtdgJnGTaSIy8KxHeZobKNYNFEY/XTaZEt9QeV5efUMBVVhxKTTHN0 046DR96WFYXs4PJ9Fpyq6Hmy3k/oUdmHJ1c2bwWF/nZ82CwOO081Yg0GBcfPEmKLUGOBK8T55ncW +RSZadvWTyhTtQhLUtLKcWyzKB5aS3kEE5LSzR8sw3owln9P41Mz+QtL3WeNESRHW0qoQkFotYXX W6Rvh69+GyzJLxvq2qd7D1qoJgOMrarshBKKPk+ABaLYoEf/cru4e0RDIp2mD0jkGOGDkn9XUl+3 ddALq/osTki6CEawkhiZEo6ABEAjEWNkH9W3/ZzvJnWo6Q== + + + + + + gov.it + + + + + MIIDdTCCAl2gAwIBAgIUU79XEfveueyClDtLkqUlSPZ2o8owDQYJKoZIhvcNAQEL BQAwLTErMCkGA1UEAwwiaWRzZXJ2ZXIuc2Vydml6aWNpZS5pbnRlcm5vLmdvdi5p dDAeFw0xODEwMTkwODM1MDVaFw0zODEwMTkwODM1MDVaMC0xKzApBgNVBAMMImlk c2VydmVyLnNlcnZpemljaWUuaW50ZXJuby5nb3YuaXQwggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQDHraj3iOTCIILTlOzicSEuFt03kKvQDqGWRd5o7s1W 7SP2EtcTmg3xron/sbrLEL/eMUQV/Biz6J4pEGoFpMZQHGxOVypmO7Nc8pkFot7y UTApr6Ikuy4cUtbx0g5fkQLNb3upIg0Vg1jSnRXEvUCygr/9EeKCUOi/2ptmOVSL ad+dT7TiRsZTwY3FvRWcleDfyYwcIMgz5dLSNLMZqwzQZK1DzvWeD6aGtBKCYPRf tacHoESD+6bhukHZ6w95foRMJLOaBpkp+XfugFQioYvrM0AB1YQZ5DCQRhhc8jej wdY+bOB3eZ1lJY7Oannfu6XPW2fcknelyPt7PGf22rNfAgMBAAGjgYwwgYkwHQYD VR0OBBYEFK3Ah+Do3/zB9XjZ66i4biDpUEbAMGgGA1UdEQRhMF+CImlkc2VydmVy LnNlcnZpemljaWUuaW50ZXJuby5nb3YuaXSGOWh0dHBzOi8vaWRzZXJ2ZXIuc2Vy dml6aWNpZS5pbnRlcm5vLmdvdi5pdC9pZHAvc2hpYmJvbGV0aDANBgkqhkiG9w0B AQsFAAOCAQEAVtpn/s+lYVf42pAtdgJnGTaSIy8KxHeZobKNYNFEY/XTaZEt9QeV 5efUMBVVhxKTTHN0046DR96WFYXs4PJ9Fpyq6Hmy3k/oUdmHJ1c2bwWF/nZ82CwO O081Yg0GBcfPEmKLUGOBK8T55ncW+RSZadvWTyhTtQhLUtLKcWyzKB5aS3kEE5LS zR8sw3owln9P41Mz+QtL3WeNESRHW0qoQkFotYXXW6Rvh69+GyzJLxvq2qd7D1qo JgOMrarshBKKPk+ABaLYoEf/cru4e0RDIp2mD0jkGOGDkn9XUl+3ddALq/osTki6 CEawkhiZEo6ABEAjEWNkH9W3/ZzvJnWo6Q== + + + + + + + MIIDdTCCAl2gAwIBAgIUegfFpjtEsLaV0IL3qBEa0u81rGkwDQYJKoZIhvcNAQEL BQAwLTErMCkGA1UEAwwiaWRzZXJ2ZXIuc2Vydml6aWNpZS5pbnRlcm5vLmdvdi5p dDAeFw0xODEwMTkwODM1MDZaFw0zODEwMTkwODM1MDZaMC0xKzApBgNVBAMMImlk c2VydmVyLnNlcnZpemljaWUuaW50ZXJuby5nb3YuaXQwggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQCe9W63GohPUaNbsoluWsVWfmtIyAIufqpmzYS4TiBv E6l9LlDITsmShVBpiLPU4IDdvoPPBlDqgotofCnSjQxRhGky7tiy+pBObo13lN6d 03GgXNPZqZ+vKJinf8AmNe2UZ1ZbuvUtgS6+vx6P52/KNKx6YuDNmR3lLDhKZVDb 2wwR5qfsdnJIAORbJVWd8kI6GGhmrsmha7zARd0W+ueDtd/WLuAg3G7QWRocHPlP TN/dPUbKS4O0cnJx0M5UERQ12PIdy641ps6P1v2OatpfSmZp/IlDLKJj9O9V49LM nxF3VBJkTep2UQsQUc3rlelN2rYAlhURQQzRwpWO5WJvAgMBAAGjgYwwgYkwHQYD VR0OBBYEFAQDr+o8YMapC4lje9upfeiwmFdtMGgGA1UdEQRhMF+CImlkc2VydmVy LnNlcnZpemljaWUuaW50ZXJuby5nb3YuaXSGOWh0dHBzOi8vaWRzZXJ2ZXIuc2Vy dml6aWNpZS5pbnRlcm5vLmdvdi5pdC9pZHAvc2hpYmJvbGV0aDANBgkqhkiG9w0B AQsFAAOCAQEAb7gRYzTPEMQjQKiwI4/NdhzzaoKQjp2tu3UPZwsUHruyCbI+B/0k C2SaSBaAKGT66yN9bPY2Vj4FuxtYmLSZZnatydF19hSu+lExCySKt16GBJ+D5HN7 OmVizRvJNE4+RF0bajpeXnMottLrcL5Ry/BivpxdnIQ9th2sMc7ev0IZtIGYCxGg c5SAJCz4zuCcNiPANHDPdoxYEQ9EV9PNAUx8q9tjAhoRRiT2ovqT+Dowqax0AVOP hRY5rA8WMccWAedO8iSSO8DTWomtoOKS9vjWrQxnsHaT8GXohC2OYgSdKsBchvjS i1RIVkrqHoSHIK2XQapkl8YmD75JjrGNNA== + + + + + + + + + + + + + + + + + gov.it + + + + + MIIDdTCCAl2gAwIBAgIUU79XEfveueyClDtLkqUlSPZ2o8owDQYJKoZIhvcNAQEL BQAwLTErMCkGA1UEAwwiaWRzZXJ2ZXIuc2Vydml6aWNpZS5pbnRlcm5vLmdvdi5p dDAeFw0xODEwMTkwODM1MDVaFw0zODEwMTkwODM1MDVaMC0xKzApBgNVBAMMImlk c2VydmVyLnNlcnZpemljaWUuaW50ZXJuby5nb3YuaXQwggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQDHraj3iOTCIILTlOzicSEuFt03kKvQDqGWRd5o7s1W 7SP2EtcTmg3xron/sbrLEL/eMUQV/Biz6J4pEGoFpMZQHGxOVypmO7Nc8pkFot7y UTApr6Ikuy4cUtbx0g5fkQLNb3upIg0Vg1jSnRXEvUCygr/9EeKCUOi/2ptmOVSL ad+dT7TiRsZTwY3FvRWcleDfyYwcIMgz5dLSNLMZqwzQZK1DzvWeD6aGtBKCYPRf tacHoESD+6bhukHZ6w95foRMJLOaBpkp+XfugFQioYvrM0AB1YQZ5DCQRhhc8jej wdY+bOB3eZ1lJY7Oannfu6XPW2fcknelyPt7PGf22rNfAgMBAAGjgYwwgYkwHQYD VR0OBBYEFK3Ah+Do3/zB9XjZ66i4biDpUEbAMGgGA1UdEQRhMF+CImlkc2VydmVy LnNlcnZpemljaWUuaW50ZXJuby5nb3YuaXSGOWh0dHBzOi8vaWRzZXJ2ZXIuc2Vy dml6aWNpZS5pbnRlcm5vLmdvdi5pdC9pZHAvc2hpYmJvbGV0aDANBgkqhkiG9w0B AQsFAAOCAQEAVtpn/s+lYVf42pAtdgJnGTaSIy8KxHeZobKNYNFEY/XTaZEt9QeV 5efUMBVVhxKTTHN0046DR96WFYXs4PJ9Fpyq6Hmy3k/oUdmHJ1c2bwWF/nZ82CwO O081Yg0GBcfPEmKLUGOBK8T55ncW+RSZadvWTyhTtQhLUtLKcWyzKB5aS3kEE5LS zR8sw3owln9P41Mz+QtL3WeNESRHW0qoQkFotYXXW6Rvh69+GyzJLxvq2qd7D1qo JgOMrarshBKKPk+ABaLYoEf/cru4e0RDIp2mD0jkGOGDkn9XUl+3ddALq/osTki6 CEawkhiZEo6ABEAjEWNkH9W3/ZzvJnWo6Q== + + + + + + + MIIDdTCCAl2gAwIBAgIUegfFpjtEsLaV0IL3qBEa0u81rGkwDQYJKoZIhvcNAQEL BQAwLTErMCkGA1UEAwwiaWRzZXJ2ZXIuc2Vydml6aWNpZS5pbnRlcm5vLmdvdi5p dDAeFw0xODEwMTkwODM1MDZaFw0zODEwMTkwODM1MDZaMC0xKzApBgNVBAMMImlk c2VydmVyLnNlcnZpemljaWUuaW50ZXJuby5nb3YuaXQwggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQCe9W63GohPUaNbsoluWsVWfmtIyAIufqpmzYS4TiBv E6l9LlDITsmShVBpiLPU4IDdvoPPBlDqgotofCnSjQxRhGky7tiy+pBObo13lN6d 03GgXNPZqZ+vKJinf8AmNe2UZ1ZbuvUtgS6+vx6P52/KNKx6YuDNmR3lLDhKZVDb 2wwR5qfsdnJIAORbJVWd8kI6GGhmrsmha7zARd0W+ueDtd/WLuAg3G7QWRocHPlP TN/dPUbKS4O0cnJx0M5UERQ12PIdy641ps6P1v2OatpfSmZp/IlDLKJj9O9V49LM nxF3VBJkTep2UQsQUc3rlelN2rYAlhURQQzRwpWO5WJvAgMBAAGjgYwwgYkwHQYD VR0OBBYEFAQDr+o8YMapC4lje9upfeiwmFdtMGgGA1UdEQRhMF+CImlkc2VydmVy LnNlcnZpemljaWUuaW50ZXJuby5nb3YuaXSGOWh0dHBzOi8vaWRzZXJ2ZXIuc2Vy dml6aWNpZS5pbnRlcm5vLmdvdi5pdC9pZHAvc2hpYmJvbGV0aDANBgkqhkiG9w0B AQsFAAOCAQEAb7gRYzTPEMQjQKiwI4/NdhzzaoKQjp2tu3UPZwsUHruyCbI+B/0k C2SaSBaAKGT66yN9bPY2Vj4FuxtYmLSZZnatydF19hSu+lExCySKt16GBJ+D5HN7 OmVizRvJNE4+RF0bajpeXnMottLrcL5Ry/BivpxdnIQ9th2sMc7ev0IZtIGYCxGg c5SAJCz4zuCcNiPANHDPdoxYEQ9EV9PNAUx8q9tjAhoRRiT2ovqT+Dowqax0AVOP hRY5rA8WMccWAedO8iSSO8DTWomtoOKS9vjWrQxnsHaT8GXohC2OYgSdKsBchvjS i1RIVkrqHoSHIK2XQapkl8YmD75JjrGNNA== + + + + + + \ No newline at end of file diff --git a/identity-service-rest-client-native/src/test/resources/idp_cie_data_tag2.xml b/identity-service-rest-client-native/src/test/resources/idp_cie_data_tag2.xml new file mode 100644 index 00000000..74ca1fd9 --- /dev/null +++ b/identity-service-rest-client-native/src/test/resources/idp_cie_data_tag2.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + ssh7Qe/Sett1HNLh/vQYvNUkCjfgEhAg8Ce4f1GL+Mg= + + + UI+4D9XebmPI96WgQAgSo+IrNzAObjecitjsR6l8gSYmtNDLNLYPeobF4kpFY34Y5bTm+IL1K9VN hhnBeJBeuL9oSBee9PaDzCSt+hmrcQdKvAr05UWDsg96ZYkgyuDugcmbRl3+PBpHzheK0qnVGZne BTSOrFk9vpYxrd2cHv/C6/DV6vNHJFe7uf2LE8yZ+qJqT/UKUgdS0qtW6FjdTOq44BxujJsi/1Yo DiIMvDjKxNrWKjxgpra35i1D1iS6jAEG68nVHjFROQ0ciUS8+9JyoUvQJ3YkVdDAhnsrMtIE8w2A RXL19GhWAw2wR8SKVEZeSNTkf34AQIHLx0vjiA== + + + + x62o94jkwiCC05Ts4nEhLhbdN5Cr0A6hlkXeaO7NVu0j9hLXE5oN8a6J/7G6yxC/3jFEFfwYs+ie KRBqBaTGUBxsTlcqZjuzXPKZBaLe8lEwKa+iJLsuHFLW8dIOX5ECzW97qSINFYNY0p0VxL1AsoK/ /RHiglDov9qbZjlUi2nfnU+04kbGU8GNxb0VnJXg38mMHCDIM+XS0jSzGasM0GStQ871ng+mhrQS gmD0X7WnB6BEg/um4bpB2esPeX6ETCSzmgaZKfl37oBUIqGL6zNAAdWEGeQwkEYYXPI3o8HWPmzg d3mdZSWOzmp537ulz1tn3JJ3pcj7ezxn9tqzXw== + AQAB + + + + MIIDdTCCAl2gAwIBAgIUU79XEfveueyClDtLkqUlSPZ2o8owDQYJKoZIhvcNAQELBQAwLTErMCkG A1UEAwwiaWRzZXJ2ZXIuc2Vydml6aWNpZS5pbnRlcm5vLmdvdi5pdDAeFw0xODEwMTkwODM1MDVa Fw0zODEwMTkwODM1MDVaMC0xKzApBgNVBAMMImlkc2VydmVyLnNlcnZpemljaWUuaW50ZXJuby5n b3YuaXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHraj3iOTCIILTlOzicSEuFt03 kKvQDqGWRd5o7s1W7SP2EtcTmg3xron/sbrLEL/eMUQV/Biz6J4pEGoFpMZQHGxOVypmO7Nc8pkF ot7yUTApr6Ikuy4cUtbx0g5fkQLNb3upIg0Vg1jSnRXEvUCygr/9EeKCUOi/2ptmOVSLad+dT7Ti RsZTwY3FvRWcleDfyYwcIMgz5dLSNLMZqwzQZK1DzvWeD6aGtBKCYPRftacHoESD+6bhukHZ6w95 foRMJLOaBpkp+XfugFQioYvrM0AB1YQZ5DCQRhhc8jejwdY+bOB3eZ1lJY7Oannfu6XPW2fcknel yPt7PGf22rNfAgMBAAGjgYwwgYkwHQYDVR0OBBYEFK3Ah+Do3/zB9XjZ66i4biDpUEbAMGgGA1Ud EQRhMF+CImlkc2VydmVyLnNlcnZpemljaWUuaW50ZXJuby5nb3YuaXSGOWh0dHBzOi8vaWRzZXJ2 ZXIuc2Vydml6aWNpZS5pbnRlcm5vLmdvdi5pdC9pZHAvc2hpYmJvbGV0aDANBgkqhkiG9w0BAQsF AAOCAQEAVtpn/s+lYVf42pAtdgJnGTaSIy8KxHeZobKNYNFEY/XTaZEt9QeV5efUMBVVhxKTTHN0 046DR96WFYXs4PJ9Fpyq6Hmy3k/oUdmHJ1c2bwWF/nZ82CwOO081Yg0GBcfPEmKLUGOBK8T55ncW +RSZadvWTyhTtQhLUtLKcWyzKB5aS3kEE5LSzR8sw3owln9P41Mz+QtL3WeNESRHW0qoQkFotYXX W6Rvh69+GyzJLxvq2qd7D1qoJgOMrarshBKKPk+ABaLYoEf/cru4e0RDIp2mD0jkGOGDkn9XUl+3 ddALq/osTki6CEawkhiZEo6ABEAjEWNkH9W3/ZzvJnWo6Q== + + + + + + gov.it + + + + + MIIDdTCCAl2gAwIBAgIUU79XEfveueyClDtLkqUlSPZ2o8owDQYJKoZIhvcNAQEL BQAwLTErMCkGA1UEAwwiaWRzZXJ2ZXIuc2Vydml6aWNpZS5pbnRlcm5vLmdvdi5p dDAeFw0xODEwMTkwODM1MDVaFw0zODEwMTkwODM1MDVaMC0xKzApBgNVBAMMImlk c2VydmVyLnNlcnZpemljaWUuaW50ZXJuby5nb3YuaXQwggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQDHraj3iOTCIILTlOzicSEuFt03kKvQDqGWRd5o7s1W 7SP2EtcTmg3xron/sbrLEL/eMUQV/Biz6J4pEGoFpMZQHGxOVypmO7Nc8pkFot7y UTApr6Ikuy4cUtbx0g5fkQLNb3upIg0Vg1jSnRXEvUCygr/9EeKCUOi/2ptmOVSL ad+dT7TiRsZTwY3FvRWcleDfyYwcIMgz5dLSNLMZqwzQZK1DzvWeD6aGtBKCYPRf tacHoESD+6bhukHZ6w95foRMJLOaBpkp+XfugFQioYvrM0AB1YQZ5DCQRhhc8jej wdY+bOB3eZ1lJY7Oannfu6XPW2fcknelyPt7PGf22rNfAgMBAAGjgYwwgYkwHQYD VR0OBBYEFK3Ah+Do3/zB9XjZ66i4biDpUEbAMGgGA1UdEQRhMF+CImlkc2VydmVy LnNlcnZpemljaWUuaW50ZXJuby5nb3YuaXSGOWh0dHBzOi8vaWRzZXJ2ZXIuc2Vy dml6aWNpZS5pbnRlcm5vLmdvdi5pdC9pZHAvc2hpYmJvbGV0aDANBgkqhkiG9w0B AQsFAAOCAQEAVtpn/s+lYVf42pAtdgJnGTaSIy8KxHeZobKNYNFEY/XTaZEt9QeV 5efUMBVVhxKTTHN0046DR96WFYXs4PJ9Fpyq6Hmy3k/oUdmHJ1c2bwWF/nZ82CwO O081Yg0GBcfPEmKLUGOBK8T55ncW+RSZadvWTyhTtQhLUtLKcWyzKB5aS3kEE5LS zR8sw3owln9P41Mz+QtL3WeNESRHW0qoQkFotYXXW6Rvh69+GyzJLxvq2qd7D1qo JgOMrarshBKKPk+ABaLYoEf/cru4e0RDIp2mD0jkGOGDkn9XUl+3ddALq/osTki6 CEawkhiZEo6ABEAjEWNkH9W3/ZzvJnWo6Q== + + + + + + + MIIDdTCCAl2gAwIBAgIUegfFpjtEsLaV0IL3qBEa0u81rGkwDQYJKoZIhvcNAQEL BQAwLTErMCkGA1UEAwwiaWRzZXJ2ZXIuc2Vydml6aWNpZS5pbnRlcm5vLmdvdi5p dDAeFw0xODEwMTkwODM1MDZaFw0zODEwMTkwODM1MDZaMC0xKzApBgNVBAMMImlk c2VydmVyLnNlcnZpemljaWUuaW50ZXJuby5nb3YuaXQwggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQCe9W63GohPUaNbsoluWsVWfmtIyAIufqpmzYS4TiBv E6l9LlDITsmShVBpiLPU4IDdvoPPBlDqgotofCnSjQxRhGky7tiy+pBObo13lN6d 03GgXNPZqZ+vKJinf8AmNe2UZ1ZbuvUtgS6+vx6P52/KNKx6YuDNmR3lLDhKZVDb 2wwR5qfsdnJIAORbJVWd8kI6GGhmrsmha7zARd0W+ueDtd/WLuAg3G7QWRocHPlP TN/dPUbKS4O0cnJx0M5UERQ12PIdy641ps6P1v2OatpfSmZp/IlDLKJj9O9V49LM nxF3VBJkTep2UQsQUc3rlelN2rYAlhURQQzRwpWO5WJvAgMBAAGjgYwwgYkwHQYD VR0OBBYEFAQDr+o8YMapC4lje9upfeiwmFdtMGgGA1UdEQRhMF+CImlkc2VydmVy LnNlcnZpemljaWUuaW50ZXJuby5nb3YuaXSGOWh0dHBzOi8vaWRzZXJ2ZXIuc2Vy dml6aWNpZS5pbnRlcm5vLmdvdi5pdC9pZHAvc2hpYmJvbGV0aDANBgkqhkiG9w0B AQsFAAOCAQEAb7gRYzTPEMQjQKiwI4/NdhzzaoKQjp2tu3UPZwsUHruyCbI+B/0k C2SaSBaAKGT66yN9bPY2Vj4FuxtYmLSZZnatydF19hSu+lExCySKt16GBJ+D5HN7 OmVizRvJNE4+RF0bajpeXnMottLrcL5Ry/BivpxdnIQ9th2sMc7ev0IZtIGYCxGg c5SAJCz4zuCcNiPANHDPdoxYEQ9EV9PNAUx8q9tjAhoRRiT2ovqT+Dowqax0AVOP hRY5rA8WMccWAedO8iSSO8DTWomtoOKS9vjWrQxnsHaT8GXohC2OYgSdKsBchvjS i1RIVkrqHoSHIK2XQapkl8YmD75JjrGNNA== + + + + + + + + + + + + + + + + + gov.it + + + + + MIIDdTCCAl2gAwIBAgIUU79XEfveueyClDtLkqUlSPZ2o8owDQYJKoZIhvcNAQEL BQAwLTErMCkGA1UEAwwiaWRzZXJ2ZXIuc2Vydml6aWNpZS5pbnRlcm5vLmdvdi5p dDAeFw0xODEwMTkwODM1MDVaFw0zODEwMTkwODM1MDVaMC0xKzApBgNVBAMMImlk c2VydmVyLnNlcnZpemljaWUuaW50ZXJuby5nb3YuaXQwggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQDHraj3iOTCIILTlOzicSEuFt03kKvQDqGWRd5o7s1W 7SP2EtcTmg3xron/sbrLEL/eMUQV/Biz6J4pEGoFpMZQHGxOVypmO7Nc8pkFot7y UTApr6Ikuy4cUtbx0g5fkQLNb3upIg0Vg1jSnRXEvUCygr/9EeKCUOi/2ptmOVSL ad+dT7TiRsZTwY3FvRWcleDfyYwcIMgz5dLSNLMZqwzQZK1DzvWeD6aGtBKCYPRf tacHoESD+6bhukHZ6w95foRMJLOaBpkp+XfugFQioYvrM0AB1YQZ5DCQRhhc8jej wdY+bOB3eZ1lJY7Oannfu6XPW2fcknelyPt7PGf22rNfAgMBAAGjgYwwgYkwHQYD VR0OBBYEFK3Ah+Do3/zB9XjZ66i4biDpUEbAMGgGA1UdEQRhMF+CImlkc2VydmVy LnNlcnZpemljaWUuaW50ZXJuby5nb3YuaXSGOWh0dHBzOi8vaWRzZXJ2ZXIuc2Vy dml6aWNpZS5pbnRlcm5vLmdvdi5pdC9pZHAvc2hpYmJvbGV0aDANBgkqhkiG9w0B AQsFAAOCAQEAVtpn/s+lYVf42pAtdgJnGTaSIy8KxHeZobKNYNFEY/XTaZEt9QeV 5efUMBVVhxKTTHN0046DR96WFYXs4PJ9Fpyq6Hmy3k/oUdmHJ1c2bwWF/nZ82CwO O081Yg0GBcfPEmKLUGOBK8T55ncW+RSZadvWTyhTtQhLUtLKcWyzKB5aS3kEE5LS zR8sw3owln9P41Mz+QtL3WeNESRHW0qoQkFotYXXW6Rvh69+GyzJLxvq2qd7D1qo JgOMrarshBKKPk+ABaLYoEf/cru4e0RDIp2mD0jkGOGDkn9XUl+3ddALq/osTki6 CEawkhiZEo6ABEAjEWNkH9W3/ZzvJnWo6Q== + + + + + + + MIIDdTCCAl2gAwIBAgIUegfFpjtEsLaV0IL3qBEa0u81rGkwDQYJKoZIhvcNAQEL BQAwLTErMCkGA1UEAwwiaWRzZXJ2ZXIuc2Vydml6aWNpZS5pbnRlcm5vLmdvdi5p dDAeFw0xODEwMTkwODM1MDZaFw0zODEwMTkwODM1MDZaMC0xKzApBgNVBAMMImlk c2VydmVyLnNlcnZpemljaWUuaW50ZXJuby5nb3YuaXQwggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQCe9W63GohPUaNbsoluWsVWfmtIyAIufqpmzYS4TiBv E6l9LlDITsmShVBpiLPU4IDdvoPPBlDqgotofCnSjQxRhGky7tiy+pBObo13lN6d 03GgXNPZqZ+vKJinf8AmNe2UZ1ZbuvUtgS6+vx6P52/KNKx6YuDNmR3lLDhKZVDb 2wwR5qfsdnJIAORbJVWd8kI6GGhmrsmha7zARd0W+ueDtd/WLuAg3G7QWRocHPlP TN/dPUbKS4O0cnJx0M5UERQ12PIdy641ps6P1v2OatpfSmZp/IlDLKJj9O9V49LM nxF3VBJkTep2UQsQUc3rlelN2rYAlhURQQzRwpWO5WJvAgMBAAGjgYwwgYkwHQYD VR0OBBYEFAQDr+o8YMapC4lje9upfeiwmFdtMGgGA1UdEQRhMF+CImlkc2VydmVy LnNlcnZpemljaWUuaW50ZXJuby5nb3YuaXSGOWh0dHBzOi8vaWRzZXJ2ZXIuc2Vy dml6aWNpZS5pbnRlcm5vLmdvdi5pdC9pZHAvc2hpYmJvbGV0aDANBgkqhkiG9w0B AQsFAAOCAQEAb7gRYzTPEMQjQKiwI4/NdhzzaoKQjp2tu3UPZwsUHruyCbI+B/0k C2SaSBaAKGT66yN9bPY2Vj4FuxtYmLSZZnatydF19hSu+lExCySKt16GBJ+D5HN7 OmVizRvJNE4+RF0bajpeXnMottLrcL5Ry/BivpxdnIQ9th2sMc7ev0IZtIGYCxGg c5SAJCz4zuCcNiPANHDPdoxYEQ9EV9PNAUx8q9tjAhoRRiT2ovqT+Dowqax0AVOP hRY5rA8WMccWAedO8iSSO8DTWomtoOKS9vjWrQxnsHaT8GXohC2OYgSdKsBchvjS i1RIVkrqHoSHIK2XQapkl8YmD75JjrGNNA== + + + + + + \ No newline at end of file diff --git a/identity-service-rest-client-native/src/test/resources/idp_spid_data_tag1.xml b/identity-service-rest-client-native/src/test/resources/idp_spid_data_tag1.xml new file mode 100644 index 00000000..5bf14905 --- /dev/null +++ b/identity-service-rest-client-native/src/test/resources/idp_spid_data_tag1.xml @@ -0,0 +1,434 @@ + + + + + + + + + + + + zvyH0X70+ePPeUwZOtgzFOPQJGor0Xzx20B6bo8rhE8= + + + RS1FS7vwNEaXcfbfhU5tG8l/jByeaDAfDtC7YozGYb5PViGAfl0R09VSvb9s9FwdHhWSNF7jnoVH9X3ZQ73Dd153KfII3TYmSEqkqIHNtttq9K7CQdoXwgmXz18xWxeXzT6EglJ66TpXUKcGYpiSBktCaHEgFw74W5n7Md2uDl2fQEM8PQG8RdLmUdNC3+6LPFrnbsF6SjDNkSpoKxQEzVegQYZ1QvsQhsRAB368KGgseJ4NVVLovqZ7qoTiGqrVg2bWTcM4O+AzX0Y+uUsX8s2HnBGPFvkHG1ro+wPs8BJ4IpxyXzUKVgY2r653MVpTwjC4+RieXd/4dbUczltrOQ== + + + MIIEGDCCAwCgAwIBAgIJAOrYj9oLEJCwMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNVBAYTAklUMQ4wDAYDVQQIEwVJdGFseTENMAsGA1UEBxMEUm9tZTENMAsGA1UEChMEQWdJRDESMBAGA1UECxMJQWdJRCBURVNUMRQwEgYDVQQDEwthZ2lkLmdvdi5pdDAeFw0xOTA0MTExMDAyMDhaFw0yNTAzMDgxMDAyMDhaMGUxCzAJBgNVBAYTAklUMQ4wDAYDVQQIEwVJdGFseTENMAsGA1UEBxMEUm9tZTENMAsGA1UEChMEQWdJRDESMBAGA1UECxMJQWdJRCBURVNUMRQwEgYDVQQDEwthZ2lkLmdvdi5pdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK8kJVo+ugRrbbv9xhXCuVrqi4B7/MQzQc62ocwlFFujJNd4m1mXkUHFbgvwhRkQqo2DAmFeHiwCkJT3K1eeXIFhNFFroEzGPzONyekLpjNvmYIs1CFvirGOj0bkEiGaKEs+/umzGjxIhy5JQlqXE96y1+Izp2QhJimDK0/KNij8I1bzxseP0Ygc4SFveKS+7QO+PrLzWklEWGMs4DM5Zc3VRK7g4LWPWZhKdImC1rnS+/lEmHSvHisdVp/DJtbSrZwSYTRvTTz5IZDSq4kAzrDfpj16h7b3t3nFGc8UoY2Ro4tRZ3ahJ2r3b79yK6C5phY7CAANuW3gDdhVjiBNYs0CAwEAAaOByjCBxzAdBgNVHQ4EFgQU3/7kV2tbdFtphbSA4LH7+w8SkcwwgZcGA1UdIwSBjzCBjIAU3/7kV2tbdFtphbSA4LH7+w8SkcyhaaRnMGUxCzAJBgNVBAYTAklUMQ4wDAYDVQQIEwVJdGFseTENMAsGA1UEBxMEUm9tZTENMAsGA1UEChMEQWdJRDESMBAGA1UECxMJQWdJRCBURVNUMRQwEgYDVQQDEwthZ2lkLmdvdi5pdIIJAOrYj9oLEJCwMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJNFqXg/V3aimJKUmUaqmQEEoSc3qvXFITvT5f5bKw9yk/NVhR6wndL+z/24h1OdRqs76blgH8k116qWNkkDtt0AlSjQOx5qvFYh1UviOjNdRI4WkYONSw+vuavcx+fB6O5JDHNmMhMySKTnmRqTkyhjrch7zaFIWUSV7hsBuxpqmrWDoLWdXbV3eFH3mINA5AoIY/m0bZtzZ7YNgiFWzxQgekpxd0vcTseMnCcXnsAlctdir0FoCZztxMuZjlBjwLTtM6Ry3/48LMM8Z+lw7NMciKLLTGQyU8XmKKSSOh0dGh5Lrlt5GxIIJkH81C0YimWebz8464QPL3RbLnTKg+c= + + + + + + + + + + + + + + + JYGJryCuw9bp9PBqoxl1ogs1BX6rIdxN2Cld6uEDcMY= + + + CIEQ0HLKuPpklXui6C9d1pd1syuB9RcgoOI4yBU4QnAEoLvWAJoyTOUvjXfNN9pKehdvcPyW6LPmlonb6Mf5sKswUXdAbimSeYwgAO0U3mVAzGxGK543RjHGamGtz3G4IDW7FTqkG0QmQDAWfeq+CYJksdHFfKwvzY9l6PWCvmPIsaIjwJcFvWMWlwCBwABL3QmUqHkLmifk3/zcN1kmHEjlwMNpCwH32A2jgyFPho96BWQo+iMRjIaLUHfrnPNqMS49nYW5rUQM1nWiRrTMY74dxfd+xTUVZKVGSgL9ACQviTPwHOm4YYkhA+zjUTT22kEFb0fdMxrC0QzBM/FnLA== + + + MIID0jCCArqgAwIBAgIUXDUOKL3WuolxDw96Fk9es8rIt6kwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAklUMS4wLAYDVQQKDCVUZWxlY29tIEl0YWxpYSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMSgwJgYDVQQLDB9TZXJ2aXppIHBlciBsJ2lkZW50aXRhIGRpZ2l0YWxlMSIwIAYDVQQDDBlUSSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMB4XDTIxMTExMTE3MDMyMFoXDTI1MTExMDE3MDMyMFowgYsxCzAJBgNVBAYTAklUMS4wLAYDVQQKDCVUZWxlY29tIEl0YWxpYSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMSgwJgYDVQQLDB9TZXJ2aXppIHBlciBsJ2lkZW50aXRhIGRpZ2l0YWxlMSIwIAYDVQQDDBlUSSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6sIS3+3iZSaAIyVywahlbpua2uJ/XmpV68P1e1STJpHoaj32STdHhqZnnb4Y/FshP1NUolzNolPXAYDmDduW1OnGndJZ+G9Hjh1PCkdiRw+p0FjhQAsGJkn8NdgTIHLJjqN1qQwtOsVGab8ScyA3mtmj3xKYuBhUoweuATzC7f5r7FfIoc3cy6N5lgrpZpfeAChxLwoHVjoAVgIBuemi6HAzmd4/BI06KzOcR7+dBVi4+uiseldxrJ5bhnjZKIwgkX14y9UA84Y+e+rMtyT8cT3XXi9NazZl5Ej5/bQPqqVsbg6tXzQSfEJD6JEjuYeC0RUKMS/EJn3hL5VLzTJ1NwIDAQABoywwKjAdBgNVHQ4EFgQUfctFZ8bRtmEvXPRlqgVDuggY/ZwwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA0lszHadknPfE17IWGWsgvlXOdKMnWcl9H5rEYmsWwDB9FJG9XAZvPMcVv1kkWi6XZI/8N2Twhu1BdZkdvntDRscuck8wxxIpkRV7CwlcqNFZ/IwjDBxOBa8Q1J850p+qP8A9apsLLPUlu/oLygNDWIXzcOjMqnPkEP+XXUNYPto5iV+OyDzLLacCYqDDHcvDewWLmEjt35X967KcM+m7K2zGRLWfqcZPIjJJOkpNjgcs+MaisMrGDyOKiD16v0LpwVyIpTqXvDk7KHo8CUNXDxyLxZzB6WffgnOgjXTfU3vluweOx0qQy/VxIupDlNBKiZB4gnt1oAfnaMbqla9wcw== + + + + + + + + MIID0jCCArqgAwIBAgIUXDUOKL3WuolxDw96Fk9es8rIt6kwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAklUMS4wLAYDVQQKDCVUZWxlY29tIEl0YWxpYSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMSgwJgYDVQQLDB9TZXJ2aXppIHBlciBsJ2lkZW50aXRhIGRpZ2l0YWxlMSIwIAYDVQQDDBlUSSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMB4XDTIxMTExMTE3MDMyMFoXDTI1MTExMDE3MDMyMFowgYsxCzAJBgNVBAYTAklUMS4wLAYDVQQKDCVUZWxlY29tIEl0YWxpYSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMSgwJgYDVQQLDB9TZXJ2aXppIHBlciBsJ2lkZW50aXRhIGRpZ2l0YWxlMSIwIAYDVQQDDBlUSSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6sIS3+3iZSaAIyVywahlbpua2uJ/XmpV68P1e1STJpHoaj32STdHhqZnnb4Y/FshP1NUolzNolPXAYDmDduW1OnGndJZ+G9Hjh1PCkdiRw+p0FjhQAsGJkn8NdgTIHLJjqN1qQwtOsVGab8ScyA3mtmj3xKYuBhUoweuATzC7f5r7FfIoc3cy6N5lgrpZpfeAChxLwoHVjoAVgIBuemi6HAzmd4/BI06KzOcR7+dBVi4+uiseldxrJ5bhnjZKIwgkX14y9UA84Y+e+rMtyT8cT3XXi9NazZl5Ej5/bQPqqVsbg6tXzQSfEJD6JEjuYeC0RUKMS/EJn3hL5VLzTJ1NwIDAQABoywwKjAdBgNVHQ4EFgQUfctFZ8bRtmEvXPRlqgVDuggY/ZwwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA0lszHadknPfE17IWGWsgvlXOdKMnWcl9H5rEYmsWwDB9FJG9XAZvPMcVv1kkWi6XZI/8N2Twhu1BdZkdvntDRscuck8wxxIpkRV7CwlcqNFZ/IwjDBxOBa8Q1J850p+qP8A9apsLLPUlu/oLygNDWIXzcOjMqnPkEP+XXUNYPto5iV+OyDzLLacCYqDDHcvDewWLmEjt35X967KcM+m7K2zGRLWfqcZPIjJJOkpNjgcs+MaisMrGDyOKiD16v0LpwVyIpTqXvDk7KHo8CUNXDxyLxZzB6WffgnOgjXTfU3vluweOx0qQy/VxIupDlNBKiZB4gnt1oAfnaMbqla9wcw== + CN=TI Trust Technologies srl,OU=Servizi per l'identita digitale,O=Telecom Italia Trust Technologies srl,C=IT + + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + + + + + + + + + + + + + + + + + + + + + + + + TI Trust Technologies srl + Trust Technologies srl + https://www.trusttechnologies.it + + + + + + + + + + + + + + zanMEv9e3IoYmz27wv5RQCYhp7IuxdvUwb/VCjOjosA= + + + EyJLBOIVDVK2UM0VYzm+ukfwm34rO2a+AmXnyem+FpLF8mHUdGe2vBafE2YiV6sr7H6/zg0ozeRgPVos9E5xc0LWZwPFK8KWaMiQwrdFVwxAVp3SL0DMXs8msj9+zMnrFb9zGNq9/SoSgJm9BNcjxud+9Ky4XlS30pk7deHy/KgdGpO0cnWOoaYbWfPhHmQ40y7lMF9WZnHibDNTbYPGFMhUgGjGauTH5x+HvGEbreLSpTMEt07Hc0KNV/TSCsUCKpbv7z2YOFbQ5yt6IO2MrpgOQIqr8JF1oC5t/C+5SltkpLUxvYwqh+gF91u1METuqURTzNe1Iz+qb0WFNuyMxw== + + + MIIExTCCA62gAwIBAgIQH32A70kY92tuXB8AGi2DdDANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQG EwJJVDEYMBYGA1UECgwPQXJ1YmFQRUMgUy5wLkEuMSEwHwYDVQQLDBhDZXJ0aWZpY2F0aW9uIEF1 dGhvcml0eUIxIDAeBgNVBAMMF0FydWJhUEVDIFMucC5BLiBORyBDQSAyMB4XDTIwMDEyMjAwMDAw MFoXDTI1MDEyMTIzNTk1OVowgaAxCzAJBgNVBAYTAklUMRYwFAYDVQQKDA1BcnViYSBQRUMgc3Bh MREwDwYDVQQLDAhQcm9kb3R0bzEWMBQGA1UEAwwNcGVjLml0IHBlYy5pdDEZMBcGA1UEBRMQWFhY WFhYMDBYMDBYMDAwWDEPMA0GA1UEKgwGcGVjLml0MQ8wDQYDVQQEDAZwZWMuaXQxETAPBgNVBC4T CDIwODc2Mzc5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqt2oHJhcp03l73p+QYpE J+f3jYYj0W0gos0RItZx/w4vpsiKBygaqDNVWSwfo1aPdVDIX13f62O+lBki29KTt+QWv5K6SGHD UXYPntRdEQlicIBh2Z0HfrM7fDl+xeJrMp1s4dsSQAuB5TJOlFZq7xCQuukytGWBTvjfcN/os5aE sEg+RbtZHJR26SbbUcIqWb27Swgj/9jwK+tvzLnP4w8FNvEOrNfR0XwTMNDFrwbOCuWgthv5jNBs VZaoqNwiA/MxYt+gTOMj/o5PWKk8Wpm6o/7/+lWAoxh0v8x9OkbIi+YaFpIxuCcUqsrJJk63x2gH Cc2nr+yclYUhsKD/AwIDAQABo4IBLDCCASgwDgYDVR0PAQH/BAQDAgeAMB0GA1UdDgQWBBTKQ3+N PGcXFk8nX994vMTVpba1EzBHBgNVHSAEQDA+MDwGCysGAQQBgegtAQEBMC0wKwYIKwYBBQUHAgEW H2h0dHBzOi8vY2EuYXJ1YmFwZWMuaXQvY3BzLmh0bWwwWAYDVR0fBFEwTzBNoEugSYZHaHR0cDov L2NybC5hcnViYXBlYy5pdC9BcnViYVBFQ1NwQUNlcnRpZmljYXRpb25BdXRob3JpdHlCL0xhdGVz dENSTC5jcmwwHwYDVR0jBBgwFoAU8v9jQBwRQv3M3/FZ9m7omYcxR3kwMwYIKwYBBQUHAQEEJzAl MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5hcnViYXBlYy5pdDANBgkqhkiG9w0BAQsFAAOCAQEA ZKpor1MrrYwPw+IuPZElQAuNzXsaSWSnn/QQwJtW49c4rFM4mEud9c61p9XxIIbgQKmDmNbzC+Dm wJSZ8ILdCAyBHmY3BehVRAy3KRA2KQhS9kd4vywf5KVYd1L5hQa9DBrusxF7i1X/SEeLQgoKkov0 R8v43UncqXS/ql50ovJFxi938Rv4rVwa8o0hqqc6WUcjkidB6M9aNJLIbOZN3xNUgC28qIr8y7N8 lbxWbwVrGxqKDtpaA9J0hOOXxwuTfSd1zOtT0KSSSUQ53QGOPnxyjxYDQbJu60/lBPuUV5wb/Z2r gpeUH1/n7limHV5sVmOZgSnf18T+0STANCfkXg== + + + + + + + + + + + MIIExTCCA62gAwIBAgIQH32A70kY92tuXB8AGi2DdDANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQG EwJJVDEYMBYGA1UECgwPQXJ1YmFQRUMgUy5wLkEuMSEwHwYDVQQLDBhDZXJ0aWZpY2F0aW9uIEF1 dGhvcml0eUIxIDAeBgNVBAMMF0FydWJhUEVDIFMucC5BLiBORyBDQSAyMB4XDTIwMDEyMjAwMDAw MFoXDTI1MDEyMTIzNTk1OVowgaAxCzAJBgNVBAYTAklUMRYwFAYDVQQKDA1BcnViYSBQRUMgc3Bh MREwDwYDVQQLDAhQcm9kb3R0bzEWMBQGA1UEAwwNcGVjLml0IHBlYy5pdDEZMBcGA1UEBRMQWFhY WFhYMDBYMDBYMDAwWDEPMA0GA1UEKgwGcGVjLml0MQ8wDQYDVQQEDAZwZWMuaXQxETAPBgNVBC4T CDIwODc2Mzc5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqt2oHJhcp03l73p+QYpE J+f3jYYj0W0gos0RItZx/w4vpsiKBygaqDNVWSwfo1aPdVDIX13f62O+lBki29KTt+QWv5K6SGHD UXYPntRdEQlicIBh2Z0HfrM7fDl+xeJrMp1s4dsSQAuB5TJOlFZq7xCQuukytGWBTvjfcN/os5aE sEg+RbtZHJR26SbbUcIqWb27Swgj/9jwK+tvzLnP4w8FNvEOrNfR0XwTMNDFrwbOCuWgthv5jNBs VZaoqNwiA/MxYt+gTOMj/o5PWKk8Wpm6o/7/+lWAoxh0v8x9OkbIi+YaFpIxuCcUqsrJJk63x2gH Cc2nr+yclYUhsKD/AwIDAQABo4IBLDCCASgwDgYDVR0PAQH/BAQDAgeAMB0GA1UdDgQWBBTKQ3+N PGcXFk8nX994vMTVpba1EzBHBgNVHSAEQDA+MDwGCysGAQQBgegtAQEBMC0wKwYIKwYBBQUHAgEW H2h0dHBzOi8vY2EuYXJ1YmFwZWMuaXQvY3BzLmh0bWwwWAYDVR0fBFEwTzBNoEugSYZHaHR0cDov L2NybC5hcnViYXBlYy5pdC9BcnViYVBFQ1NwQUNlcnRpZmljYXRpb25BdXRob3JpdHlCL0xhdGVz dENSTC5jcmwwHwYDVR0jBBgwFoAU8v9jQBwRQv3M3/FZ9m7omYcxR3kwMwYIKwYBBQUHAQEEJzAl MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5hcnViYXBlYy5pdDANBgkqhkiG9w0BAQsFAAOCAQEA ZKpor1MrrYwPw+IuPZElQAuNzXsaSWSnn/QQwJtW49c4rFM4mEud9c61p9XxIIbgQKmDmNbzC+Dm wJSZ8ILdCAyBHmY3BehVRAy3KRA2KQhS9kd4vywf5KVYd1L5hQa9DBrusxF7i1X/SEeLQgoKkov0 R8v43UncqXS/ql50ovJFxi938Rv4rVwa8o0hqqc6WUcjkidB6M9aNJLIbOZN3xNUgC28qIr8y7N8 lbxWbwVrGxqKDtpaA9J0hOOXxwuTfSd1zOtT0KSSSUQ53QGOPnxyjxYDQbJu60/lBPuUV5wb/Z2r gpeUH1/n7limHV5sVmOZgSnf18T+0STANCfkXg== + + + + + + + MIIExTCCA62gAwIBAgIQIHtEvEhGM77HwqsuvSbi9zANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQG EwJJVDEYMBYGA1UECgwPQXJ1YmFQRUMgUy5wLkEuMSEwHwYDVQQLDBhDZXJ0aWZpY2F0aW9uIEF1 dGhvcml0eUIxIDAeBgNVBAMMF0FydWJhUEVDIFMucC5BLiBORyBDQSAyMB4XDTE3MDEyMzAwMDAw MFoXDTIwMDEyMzIzNTk1OVowgaAxCzAJBgNVBAYTAklUMRYwFAYDVQQKDA1BcnViYSBQRUMgc3Bh MREwDwYDVQQLDAhQcm9kb3R0bzEWMBQGA1UEAwwNcGVjLml0IHBlYy5pdDEZMBcGA1UEBRMQWFhY WFhYMDBYMDBYMDAwWDEPMA0GA1UEKgwGcGVjLml0MQ8wDQYDVQQEDAZwZWMuaXQxETAPBgNVBC4T CDE2MzQ1MzgzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqt2oHJhcp03l73p+QYpE J+f3jYYj0W0gos0RItZx/w4vpsiKBygaqDNVWSwfo1aPdVDIX13f62O+lBki29KTt+QWv5K6SGHD UXYPntRdEQlicIBh2Z0HfrM7fDl+xeJrMp1s4dsSQAuB5TJOlFZq7xCQuukytGWBTvjfcN/os5aE sEg+RbtZHJR26SbbUcIqWb27Swgj/9jwK+tvzLnP4w8FNvEOrNfR0XwTMNDFrwbOCuWgthv5jNBs VZaoqNwiA/MxYt+gTOMj/o5PWKk8Wpm6o/7/+lWAoxh0v8x9OkbIi+YaFpIxuCcUqsrJJk63x2gH Cc2nr+yclYUhsKD/AwIDAQABo4IBLDCCASgwDgYDVR0PAQH/BAQDAgeAMB0GA1UdDgQWBBTKQ3+N PGcXFk8nX994vMTVpba1EzBHBgNVHSAEQDA+MDwGCysGAQQBgegtAQEBMC0wKwYIKwYBBQUHAgEW H2h0dHBzOi8vY2EuYXJ1YmFwZWMuaXQvY3BzLmh0bWwwWAYDVR0fBFEwTzBNoEugSYZHaHR0cDov L2NybC5hcnViYXBlYy5pdC9BcnViYVBFQ1NwQUNlcnRpZmljYXRpb25BdXRob3JpdHlCL0xhdGVz dENSTC5jcmwwHwYDVR0jBBgwFoAU8v9jQBwRQv3M3/FZ9m7omYcxR3kwMwYIKwYBBQUHAQEEJzAl MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5hcnViYXBlYy5pdDANBgkqhkiG9w0BAQsFAAOCAQEA nEw0NuaspbpDjA5wggwFtfQydU6b3Bw2/KXPRKS2JoqGmx0SYKj+L17A2KUBa2c7gDtKXYz0FLT6 0Bv0pmBN/oYCgVMEBJKqwRwdki9YjEBwyCZwNEx1kDAyyqFEVU9vw/OQfrAdp7MTbuZGFKknVt7b 9wOYy/Op9FiUaTg6SuOy0ep+rqhihltYNAAl4L6fY45mHvqa5vvVG30OvLW/S4uvRYUXYwY6KhWv NdDf5CnFugnuEZtHJrVe4wx9aO5GvFLFZ/mQ35C5mXPQ7nIb0CDdLBJdz82nUoLSA5BUbeXAUkfa hW/hLxLdhks68/TK694xVIuiB40pvMmJwxIyDA== + + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + + + + + + + + + + + + + + + + + + + + + + + + + ArubaPEC S.p.A. + ArubaPEC S.p.A. + https://www.pec.it/ + + + + + + + + + + + + + + qjmkoKCiL8y4gBEXT8DVubGLvH7N8roi/lpgTQww+dw= + + + fm30Z3Ugxcae7W+nvNm9SDeMjH+sWDDcUnobMaBemlKLSj7KiOT1bc/HVIqY9sH/AoV6LiDZ05PSnQLhL8HI1Q71CGpRUTIt3b2oL7D+4iOsirKjFCYjHq75FBR5esaejhvHWIpnTx6Dp+CigVM2eH9IrBIY3Xkw2FqD7Q9CCc/bl33OUjEGS2o4VpjWyFCVsPMWy0QxsC0Em+fTbPjlMX8n55SKvSZy4ItNfoahLy/+8DD+VsWA9u3fPbValsfLZqyziBRjTcdc0nAeQliXj+ajjCbqGmG+jLw3mNRXglF5Kqq3hcHe5a/9WqKCh2x82ReMT7KhFRwQl+lhsBoWRg== + + + MIIIRDCCBiygAwIBAgIINO3vGmIYBP0wDQYJKoZIhvcNAQENBQAwgfsxCzAJBgNVBAYTAklUMQ0w CwYDVQQHDARSb21lMSYwJAYDVQQKDB1BZ2VuemlhIHBlciBsJ0l0YWxpYSBEaWdpdGFsZTEwMC4G A1UECwwnU2Vydml6aW8gQWNjcmVkaXRhbWVudG8gZSBwcm9nZXR0byBTUElEMTwwOgYDVQQDDDNQ cm9nZXR0byBTUElEIC0gR2VzdG9yaSBkaSBJZGVudGl0w6AgRGlnaXRhbGUgKElkUCkxKTAnBgkq hkiG9w0BCQEWGnByb3RvY29sbG9AcGVjLmFnaWQuZ292Lml0MRowGAYDVQQFExFWQVRJVC05Nzcz NTAyMDU4NDAeFw0yMzAyMjIwMDAwMDBaFw0zMzAyMjEyMzU5NTlaMIG3MQswCQYDVQQGEwJJVDEO MAwGA1UECAwFSXRhbHkxDzANBgNVBAcMBlBhZG92YTEcMBoGA1UECgwTSW5mb0NhbWVyZSBTLkMu cC5BLjElMCMGA1UEAwwcSW5mb0NhbWVyZSBJZGVudGl0eSBQcm92aWRlcjEaMBgGA1UEYQwRVkFU SVQtMDIzMTM4MjEwMDcxJjAkBgNVBFMMHWh0dHBzOi8vaWRzcGlkLmluZm9jYW1lcmUuaXQvMIIB IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo8Div4aLGUtoDoP5RWbRwqvEtjnDcCCUS+Sz ChAsJP+UYjWl+R4R4Y7Lz+WId3LJqey+QIyvviD6vH/QloqzVRG/JabW70NZylk1UX2isss8mRvt ceK7nYVxjTIoQpasg0OsCevgljjnFxRm8c3zUpYfjC5zzr/jZ9HjFKghGCZGjBavNNgiGIo7e7jb dmGH5N9z+uQ8KRG/p2JRxD0YeVy2+EV2o0cQO2duE383EganLKPcQ9AnxkLE1K0cpP7XQDtUgWTP qsL9+OLTl13KhVM2TMK7EkAm00WCOl1aX3E7g9Qgw+4fUm308v77OSDe77dY8hohZWPRTwjemaHA 2QIDAQABo4IDDDCCAwgwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUddqeUDWjVXqV3PSfTyzAmlFD TDMwHwYDVR0jBBgwFoAUyF8jl8Jbn9TohwSTF77f5QNJd18wDgYDVR0PAQH/BAQDAgbAMBEGA1Ud EQQKMAiCBmlkcC5pdDAWBgNVHRIEDzANggtzcGlkLmdvdi5pdDA/BgNVHR8EODA2MDSgMqAwhi5o dHRwczovL2VpZGFzLmFnaWQuZ292Lml0L2NybC9jcmxfU1BJRF9JZFAuY3JsMGoGCCsGAQUFBwEB BF4wXDBEBggrBgEFBQcwAoY4aHR0cDovL2VpZGFzLmFnaWQuZ292Lml0L2NlcnRpZmljYXRpL1N1 Yl9DQV9TUElEX0lkUC5jZXIwFAYIKwYBBQUHMAGGCGh0dHBzOi8vMIIBzgYDVR0gBIIBxTCCAcEw CQYHBACORgEGAjCBlQYEK0wQBjCBjDBEBggrBgEFBQcCAjA4GjZFbGVjdHJvbmljIGNlcnRpZmlj YXRlIGNvbmZvcm1pbmcgd2l0aCBBR0lEIEd1aWRlbGluZXMwRAYIKwYBBQUHAgIwOBo2Q2VydGlm aWNhdG8gZWxldHRyb25pY28gY29uZm9ybWUgYWxsZSBMaW5lZSBndWlkYSBBZ0lEMHIGBitMEAQB AjBoMDkGCCsGAQUFBwICMC0aK1NQSUQ6IGdlc3RvcmUgZGVsbGUgaWRlbnRpdOAgZGlnaXRhbGkg KElkUCkwKwYIKwYBBQUHAgIwHxodU1BJRDogSWRlbnRpdHkgUHJvdmlkZXIgKElkUCkwCAYGBACP egEDME0GBCtMEAQwRTBDBggrBgEFBQcCARY3aHR0cHM6Ly9laWRhcy5hZ2lkLmdvdi5pdC9jcHMv QWdJRF9lSURBU19yb290Q0FfY3BzLnBkZjBPBgYEAI5GAQUwRTBDBggrBgEFBQcCARY3aHR0cHM6 Ly9laWRhcy5hZ2lkLmdvdi5pdC9jcHMvQWdJRF9lSURBU19yb290Q0FfY3BzLnBkZjANBgkqhkiG 9w0BAQ0FAAOCAgEAoYZlSArAwFZDknzUG5Z3NQQUT3JKaOTT8TrNi/F8yL4mz0qjaJaJURMQauKZ eNQiGlGvNyGp3SlgGYFHasZ9FrtpxbxGXVkNreer61kFhY/I3ZdU4DjGW2qPs9csP+W06R4k3OFF hua7DFyyoxAWQYIFisucT3E3+N32XuLQPDqjMwnvSdT4FLE6c4QIpJl3fQYlCsyhAxrNWlrndP1Q 1f97oF6oB7tWR5Ae1/ixDN0q5QJeEnapNaDjvS2wEzVNRYW/RzbHPPZQ1Zs0jLEfXsuwD3A0iJiy D0GSgXYUibqH3VExCqQ1yjEDwjq3zF8bcSaoAQm2fRY3KIYSbI18kpPhFmNTJWbv303dQe6MzIOR LUzs0tSHfB+mtclrHgqqaKwZZmHiGUYTV3bziWjMDacG9gRJtyS04LYZdkSBcSOn3dYXSM18F58p bKifcdajFmUicUWlI/2TFArDguh5TUekLQKsTi4tMnmk5RWA4oMLjZ+q2r4jMNVuoZ0+FGFbrfdh z+Kyo3gWdyZyY+Uqr1aiL+QTnht8hVTVrgOf4RJW/3z5hgYLSyx3INT6GDtaSr5V+orYfSpbvU1X linz+iP4vfYKmpFdF1cxjTYkNQB7/DW9nXYC4PwXjI5253rha8g/BLdsIEWD73Q1GM1HieSVX+tN PBbjHpKLz2UVZEM= + + + + + + + + + + + MIIIRDCCBiygAwIBAgIINO3vGmIYBP0wDQYJKoZIhvcNAQENBQAwgfsxCzAJBgNVBAYTAklUMQ0w CwYDVQQHDARSb21lMSYwJAYDVQQKDB1BZ2VuemlhIHBlciBsJ0l0YWxpYSBEaWdpdGFsZTEwMC4G A1UECwwnU2Vydml6aW8gQWNjcmVkaXRhbWVudG8gZSBwcm9nZXR0byBTUElEMTwwOgYDVQQDDDNQ cm9nZXR0byBTUElEIC0gR2VzdG9yaSBkaSBJZGVudGl0w6AgRGlnaXRhbGUgKElkUCkxKTAnBgkq hkiG9w0BCQEWGnByb3RvY29sbG9AcGVjLmFnaWQuZ292Lml0MRowGAYDVQQFExFWQVRJVC05Nzcz NTAyMDU4NDAeFw0yMzAyMjIwMDAwMDBaFw0zMzAyMjEyMzU5NTlaMIG3MQswCQYDVQQGEwJJVDEO MAwGA1UECAwFSXRhbHkxDzANBgNVBAcMBlBhZG92YTEcMBoGA1UECgwTSW5mb0NhbWVyZSBTLkMu cC5BLjElMCMGA1UEAwwcSW5mb0NhbWVyZSBJZGVudGl0eSBQcm92aWRlcjEaMBgGA1UEYQwRVkFU SVQtMDIzMTM4MjEwMDcxJjAkBgNVBFMMHWh0dHBzOi8vaWRzcGlkLmluZm9jYW1lcmUuaXQvMIIB IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo8Div4aLGUtoDoP5RWbRwqvEtjnDcCCUS+Sz ChAsJP+UYjWl+R4R4Y7Lz+WId3LJqey+QIyvviD6vH/QloqzVRG/JabW70NZylk1UX2isss8mRvt ceK7nYVxjTIoQpasg0OsCevgljjnFxRm8c3zUpYfjC5zzr/jZ9HjFKghGCZGjBavNNgiGIo7e7jb dmGH5N9z+uQ8KRG/p2JRxD0YeVy2+EV2o0cQO2duE383EganLKPcQ9AnxkLE1K0cpP7XQDtUgWTP qsL9+OLTl13KhVM2TMK7EkAm00WCOl1aX3E7g9Qgw+4fUm308v77OSDe77dY8hohZWPRTwjemaHA 2QIDAQABo4IDDDCCAwgwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUddqeUDWjVXqV3PSfTyzAmlFD TDMwHwYDVR0jBBgwFoAUyF8jl8Jbn9TohwSTF77f5QNJd18wDgYDVR0PAQH/BAQDAgbAMBEGA1Ud EQQKMAiCBmlkcC5pdDAWBgNVHRIEDzANggtzcGlkLmdvdi5pdDA/BgNVHR8EODA2MDSgMqAwhi5o dHRwczovL2VpZGFzLmFnaWQuZ292Lml0L2NybC9jcmxfU1BJRF9JZFAuY3JsMGoGCCsGAQUFBwEB BF4wXDBEBggrBgEFBQcwAoY4aHR0cDovL2VpZGFzLmFnaWQuZ292Lml0L2NlcnRpZmljYXRpL1N1 Yl9DQV9TUElEX0lkUC5jZXIwFAYIKwYBBQUHMAGGCGh0dHBzOi8vMIIBzgYDVR0gBIIBxTCCAcEw CQYHBACORgEGAjCBlQYEK0wQBjCBjDBEBggrBgEFBQcCAjA4GjZFbGVjdHJvbmljIGNlcnRpZmlj YXRlIGNvbmZvcm1pbmcgd2l0aCBBR0lEIEd1aWRlbGluZXMwRAYIKwYBBQUHAgIwOBo2Q2VydGlm aWNhdG8gZWxldHRyb25pY28gY29uZm9ybWUgYWxsZSBMaW5lZSBndWlkYSBBZ0lEMHIGBitMEAQB AjBoMDkGCCsGAQUFBwICMC0aK1NQSUQ6IGdlc3RvcmUgZGVsbGUgaWRlbnRpdOAgZGlnaXRhbGkg KElkUCkwKwYIKwYBBQUHAgIwHxodU1BJRDogSWRlbnRpdHkgUHJvdmlkZXIgKElkUCkwCAYGBACP egEDME0GBCtMEAQwRTBDBggrBgEFBQcCARY3aHR0cHM6Ly9laWRhcy5hZ2lkLmdvdi5pdC9jcHMv QWdJRF9lSURBU19yb290Q0FfY3BzLnBkZjBPBgYEAI5GAQUwRTBDBggrBgEFBQcCARY3aHR0cHM6 Ly9laWRhcy5hZ2lkLmdvdi5pdC9jcHMvQWdJRF9lSURBU19yb290Q0FfY3BzLnBkZjANBgkqhkiG 9w0BAQ0FAAOCAgEAoYZlSArAwFZDknzUG5Z3NQQUT3JKaOTT8TrNi/F8yL4mz0qjaJaJURMQauKZ eNQiGlGvNyGp3SlgGYFHasZ9FrtpxbxGXVkNreer61kFhY/I3ZdU4DjGW2qPs9csP+W06R4k3OFF hua7DFyyoxAWQYIFisucT3E3+N32XuLQPDqjMwnvSdT4FLE6c4QIpJl3fQYlCsyhAxrNWlrndP1Q 1f97oF6oB7tWR5Ae1/ixDN0q5QJeEnapNaDjvS2wEzVNRYW/RzbHPPZQ1Zs0jLEfXsuwD3A0iJiy D0GSgXYUibqH3VExCqQ1yjEDwjq3zF8bcSaoAQm2fRY3KIYSbI18kpPhFmNTJWbv303dQe6MzIOR LUzs0tSHfB+mtclrHgqqaKwZZmHiGUYTV3bziWjMDacG9gRJtyS04LYZdkSBcSOn3dYXSM18F58p bKifcdajFmUicUWlI/2TFArDguh5TUekLQKsTi4tMnmk5RWA4oMLjZ+q2r4jMNVuoZ0+FGFbrfdh z+Kyo3gWdyZyY+Uqr1aiL+QTnht8hVTVrgOf4RJW/3z5hgYLSyx3INT6GDtaSr5V+orYfSpbvU1X linz+iP4vfYKmpFdF1cxjTYkNQB7/DW9nXYC4PwXjI5253rha8g/BLdsIEWD73Q1GM1HieSVX+tN PBbjHpKLz2UVZEM= + + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + + + + + + + + + + + + + + + + + + + + + + + + + InfoCamere S.C.p.A. + InfoCamere S.C.p.A. + https://www.infocamere.it/ + + + + + + + + + + + + + + ix5zJ0s5HicXBtbud2nW7dwhwEVB6jZnzhFkbFLAYVs= + + + EdhsS12CrldyKtXkWCHY7PlrD8Uc2HyKd2a40aNsEabBJxH0gsKfzO85HSRw1jLBVf0352moDNAp vqrH24ImHV9umqzxqY5SAXx7ISeGl56kmWB4CWGPK7X7Vb0iDosDzoI60vHlipVmdbaqlwOZQG79 xEoyo4bU/IxhdFhr0wl8b3SnGTWlFS3iThaz4g2dmWlzcjVcf+s5CigClhqToedKxPbY2CGl+U78 sgNTlR2cGIe9gjRlQIboXUr14SzDJgIOLkFIGyuIlgA7vk85/HDSXGhEIa5r/N9Tb+dTc+PXPxV9 Lk9Oy88WbYOqfvOKnkzVjmWj026DTT2N9uBPmg== + + + MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4 fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1 MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0 uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc= + + + + + + + + + + + MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4 fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1 MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0 uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc= + + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + + + + + + + + + + + + + + + + + + + + + Poste Italiane SpA + Poste Italiane SpA + https://www.poste.it + + + + + + + + + + + + + + D/A8yDFktAAd8ZdH4txugRyfui6Yy9cYlS/ilyzB6qg= + + + YN5NOuJNo8+3p5j+vQ+l0tA8hsvgfqwHu4amDbJeV3ltCa2ev2chti18Tekswx/FjkpVo7Xu1Thi3jcxRalyeoY2XAPhhEigI+JSA6+JcJUC91Gm+b9+LO6mnKba+epGBdfoDoj66tBCeSXD1AOSid1WcCEjEoFfMwIx2TJQVhz/Vx6JhAPYjbjyiXgus7hI4JPFQla3msjrrCJ8umU635e1dyFPqxTt1jIRP5oZnSGx0moP5dGRMhU+mu2mtcJOGiz02km+TtmxIRgACJ8HB3sEP3HDwtQmVguhDCUluY94UfU42dIsaKOZB2mVEVjHDzCVxGGYPAYaY8lu1ZDO5g== + + + MIIDazCCAlOgAwIBAgIED8R+MDANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJJVDELMAkGA1UECBMCRkkxETAPBgNVBAcTCGZsb3JlbmNlMREwDwYDVQQKEwhyZWdpc3RlcjERMA8GA1UECxMIcmVnaXN0ZXIxETAPBgNVBAMTCHJlZ2lzdGVyMB4XDTE3MDcxMDEwMzM0OVoXDTI3MDcwODEwMzM0OVowZjELMAkGA1UEBhMCSVQxCzAJBgNVBAgTAkZJMREwDwYDVQQHEwhmbG9yZW5jZTERMA8GA1UEChMIcmVnaXN0ZXIxETAPBgNVBAsTCHJlZ2lzdGVyMREwDwYDVQQDEwhyZWdpc3RlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANkYXHbm3q6xt3wrLAXnytswtj2JE1MM8aYmNXkTgDMCwO/+ahQOoQru6IBTbjfWH9jr+Woy54FDdX6bHl+5/mO6l/yAB/bKgwe5HmUjZJ5oakJjWucsSm+VkEwN2HquBZoN+mktju00xvLX5VAjmDHvZc/b8NhNr/FRKlYITboygkhGiUwGI3wLf3IaB76J0o7ugpW2WNLcywpX+p1VWZAMCdHBveBe/e42hh6WnWPqdwYUWHOgJ8HX4IzCHifiS1n6eUMgtoTQOmSvTQDwSjD0WWJE8tWSYt+txXg1t+3A3tbZOFu7T442wE7DtMdUL4+8gimQS+e8PxDK1uTqIPUCAwEAAaMhMB8wHQYDVR0OBBYEFMCgo1gzCIcUThQIs5g5ikfv1D7eMA0GCSqGSIb3DQEBCwUAA4IBAQBnGw3i3hQ37L8vyelkyZMeO3tLK65Cqti4oVrQZxClGV5zNA6fIMDY8Mci1UhLwjzp29POd/sez0vuHZ/Vmmygzoye4jTKr6c3jAh0u81FTzefBU+vIietm9RuV3sd7D9xq6EqOY1NDL+rkvBcTFtiwLEUm2kHYu/U67jk73pxOtmqxQvQeMU8oi42tehMZGLIGp3U5lGS8YGGl+GtkkQ2Z5/PSm67HGP81kTArG/QX+bX+ykypTJVg9hfb9zOFQidp1HkCRIez6YhDiP/ZLurd6Grt/wVfZPNBO8EOgy25AkRZlp+UD686BFg7qq5KKEbz3qmPrj8deHL3duacZcp + + + + + + + + MIIDazCCAlOgAwIBAgIED8R+MDANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJJVDELMAkGA1UECBMCRkkxETAPBgNVBAcTCGZsb3JlbmNlMREwDwYDVQQKEwhyZWdpc3RlcjERMA8GA1UECxMIcmVnaXN0ZXIxETAPBgNVBAMTCHJlZ2lzdGVyMB4XDTE3MDcxMDEwMzM0OVoXDTI3MDcwODEwMzM0OVowZjELMAkGA1UEBhMCSVQxCzAJBgNVBAgTAkZJMREwDwYDVQQHEwhmbG9yZW5jZTERMA8GA1UEChMIcmVnaXN0ZXIxETAPBgNVBAsTCHJlZ2lzdGVyMREwDwYDVQQDEwhyZWdpc3RlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANkYXHbm3q6xt3wrLAXnytswtj2JE1MM8aYmNXkTgDMCwO/+ahQOoQru6IBTbjfWH9jr+Woy54FDdX6bHl+5/mO6l/yAB/bKgwe5HmUjZJ5oakJjWucsSm+VkEwN2HquBZoN+mktju00xvLX5VAjmDHvZc/b8NhNr/FRKlYITboygkhGiUwGI3wLf3IaB76J0o7ugpW2WNLcywpX+p1VWZAMCdHBveBe/e42hh6WnWPqdwYUWHOgJ8HX4IzCHifiS1n6eUMgtoTQOmSvTQDwSjD0WWJE8tWSYt+txXg1t+3A3tbZOFu7T442wE7DtMdUL4+8gimQS+e8PxDK1uTqIPUCAwEAAaMhMB8wHQYDVR0OBBYEFMCgo1gzCIcUThQIs5g5ikfv1D7eMA0GCSqGSIb3DQEBCwUAA4IBAQBnGw3i3hQ37L8vyelkyZMeO3tLK65Cqti4oVrQZxClGV5zNA6fIMDY8Mci1UhLwjzp29POd/sez0vuHZ/Vmmygzoye4jTKr6c3jAh0u81FTzefBU+vIietm9RuV3sd7D9xq6EqOY1NDL+rkvBcTFtiwLEUm2kHYu/U67jk73pxOtmqxQvQeMU8oi42tehMZGLIGp3U5lGS8YGGl+GtkkQ2Z5/PSm67HGP81kTArG/QX+bX+ykypTJVg9hfb9zOFQidp1HkCRIez6YhDiP/ZLurd6Grt/wVfZPNBO8EOgy25AkRZlp+UD686BFg7qq5KKEbz3qmPrj8deHL3duacZcp + + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + + + + + + + + + + + + + + + + + + + + + + + + + Register.it S.p.A. + Register.it S.p.A. + https//www.register.it + + + + + + + + + + + + + + khZostyVOFwCtkt5rHSLJ9UxgM6rKAR+7O+yLQ++5jI= + + + rnN5Omq7oWmuqqW13KbMr+taRMdqJ85W9+WpcWLX2Wsax26kTHBgD78vVfVWKuejMKeK6F8oSTkiipMlnGLXMniQplvI9rZJO3fj3ygG3qdwPCqFqJ7e9iYPZ5gIMjLuePyoAfcvSdAQiMBxeTX7nwjpLrzB51RaxGNTmJNJv44zbtdR++I1my8nSDRycq5o6+uR+k/SEOiR65+uQbiBvL9Or/N4sEoJyFx23AbQjurWiBzqgHwHPf8tDLBbDa8mjPhReXGK7aePymQU4GlSeZBxSHcSad04gQjlcgayp4d+O43SBczmtueV6szrAqURnhdj6L1PRvyusfNNk04bZA== + + + MIIINTCCBh2gAwIBAgIIJz+ujRbSAYwwDQYJKoZIhvcNAQENBQAwgfsxCzAJBgNV BAYTAklUMQ0wCwYDVQQHDARSb21lMSYwJAYDVQQKDB1BZ2VuemlhIHBlciBsJ0l0 YWxpYSBEaWdpdGFsZTEwMC4GA1UECwwnU2Vydml6aW8gQWNjcmVkaXRhbWVudG8g ZSBwcm9nZXR0byBTUElEMTwwOgYDVQQDDDNQcm9nZXR0byBTUElEIC0gR2VzdG9y aSBkaSBJZGVudGl0w6AgRGlnaXRhbGUgKElkUCkxKTAnBgkqhkiG9w0BCQEWGnBy b3RvY29sbG9AcGVjLmFnaWQuZ292Lml0MRowGAYDVQQFExFWQVRJVC05NzczNTAy MDU4NDAeFw0yMjA1MTAwMDAwMDBaFw0zMjA1MDkyMzU5NTlaMIGrMRowGAYDVQRh DBFWQVRJVC0wMTAzNTMxMDQxNDEcMBoGA1UEAwwTc3BpZC50ZWFtc3lzdGVtLmNv bTEaMBgGA1UECgwRVGVhbVN5c3RlbSBTLnAuQS4xKDAmBgNVBFMMH2h0dHBzOi8v c3BpZC50ZWFtc3lzdGVtLmNvbS9pZHAxCzAJBgNVBAYTAklUMQ8wDQYDVQQHDAZQ ZXNhcm8xCzAJBgNVBAgMAlBVMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEAyNJMgyn+iquzTvLR5Z/eYBfOoyJIfI3rYcj5WOSlTzlqXXBCzdcROm/JKgrf 3MOTEzH8RAn6XkSHXtJDtMpD7GlwYB0mo8scqDNtpszbhm/UXapJTrP7gy/UI3yf n99n4hvqkGOdld7w5vaAPS0w9PdcaRxY/7X4olHKBAx2cHAwiqhKuiFEDhfACRWs bw4gaIjVM7NuUtL/jG+PJV1NHrEn10vizE7IneMxDNqiQ14IjLL7pJMEPXwbXedz ZsModKKAXIX5reNSegEU1Y386BCkmg4IMWd+DglmMJ4uuzcga1AppgjDuqb8yFDa NOKy/0Jivh2rs7u9boE4cLVBPQIDAQABo4IDCTCCAwUwCQYDVR0TBAIwADAdBgNV HQ4EFgQU/q5NWlPmylmZTsX0C2MwZkrx3b4wHwYDVR0jBBgwFoAUyF8jl8Jbn9To hwSTF77f5QNJd18wDgYDVR0PAQH/BAQDAgbAMBEGA1UdEQQKMAiCBmlkcC5pdDAW BgNVHRIEDzANggtzcGlkLmdvdi5pdDA/BgNVHR8EODA2MDSgMqAwhi5odHRwczov L2VpZGFzLmFnaWQuZ292Lml0L2NybC9jcmxfU1BJRF9JZFAuY3JsMGoGCCsGAQUF BwEBBF4wXDBEBggrBgEFBQcwAoY4aHR0cDovL2VpZGFzLmFnaWQuZ292Lml0L2Nl cnRpZmljYXRpL1N1Yl9DQV9TUElEX0lkUC5jZXIwFAYIKwYBBQUHMAGGCGh0dHBz Oi8vMIIBzgYDVR0gBIIBxTCCAcEwCQYHBACORgEGAjCBlQYEK0wQBjCBjDBEBggr BgEFBQcCAjA4GjZFbGVjdHJvbmljIGNlcnRpZmljYXRlIGNvbmZvcm1pbmcgd2l0 aCBBR0lEIEd1aWRlbGluZXMwRAYIKwYBBQUHAgIwOBo2Q2VydGlmaWNhdG8gZWxl dHRyb25pY28gY29uZm9ybWUgYWxsZSBMaW5lZSBndWlkYSBBZ0lEMHIGBitMEAQB AjBoMDkGCCsGAQUFBwICMC0aK1NQSUQ6IGdlc3RvcmUgZGVsbGUgaWRlbnRpdOAg ZGlnaXRhbGkgKElkUCkwKwYIKwYBBQUHAgIwHxodU1BJRDogSWRlbnRpdHkgUHJv dmlkZXIgKElkUCkwCAYGBACPegEDME0GBCtMEAQwRTBDBggrBgEFBQcCARY3aHR0 cHM6Ly9laWRhcy5hZ2lkLmdvdi5pdC9jcHMvQWdJRF9lSURBU19yb290Q0FfY3Bz LnBkZjBPBgYEAI5GAQUwRTBDBggrBgEFBQcCARY3aHR0cHM6Ly9laWRhcy5hZ2lk Lmdvdi5pdC9jcHMvQWdJRF9lSURBU19yb290Q0FfY3BzLnBkZjANBgkqhkiG9w0B AQ0FAAOCAgEAG9XZeAkIuqSmYb6bq5WrcI2FQtVrfbMH1CXGDKytZUsH5phkGfk/ 8UaIfkbHhnWakM4H9J2gnvfhKorfMt2FHyXFFJ38hlWR8MhFziqthXLUxyLZpUMn h8CcNQyFpNz7xbZk/qN5yFfJyY4Rggm1qdgCNR1LsVI3hjuaORTAzvy4kLjfuU5r nVYPcxpHF7feJKlN03d8JRKYaIi5U+QVYtYJpTcE7jeYmn4Ewfry2BDCOsnljeYl gm3fF8EEVpMfHIhvJg8evATWmKWHpXL2BRtVrl7TfhvtWqKv4tLff+Lv2YqRpmYu oApA48/MB4QxwAPUBnmQb3CxVGs6OCbE/tdUfda9HuHP5MXYLtTVbRYu8pHEPnaN jPA8y90KRw2wiedgjgOG8BxOkhVF/cYs3yH+0hbPS5Oji27t0P2g9eG/p9TOy4AI gUykFimVFk6HV9znknrFSdgsePSp+T5zy45Jdi1z4/RgJN10szJfqEBuvd8MhUu4 meVgfDqXrqavCVzGpSLuicdk41sTOviBz+PEgbQ/qP9KHQv67SHoF4US9Pp9tkyj VFUs7lBnrlFAPpOzd97XdiZfotCA5umibqlxLshy4UK7yl2LZFllpxrfiXTCDASM KlMMIcIsWx0lU/qw5KPpqvXELiya791kohJTi+9pyG7LXIOHHA0whr0= + + + + + + https://www.spid.gov.it/SpidL1 + https://www.spid.gov.it/SpidL2 + + + P + LP + PG + PF + PX + + + + + + + MIIINTCCBh2gAwIBAgIIJz+ujRbSAYwwDQYJKoZIhvcNAQENBQAwgfsxCzAJBgNV BAYTAklUMQ0wCwYDVQQHDARSb21lMSYwJAYDVQQKDB1BZ2VuemlhIHBlciBsJ0l0 YWxpYSBEaWdpdGFsZTEwMC4GA1UECwwnU2Vydml6aW8gQWNjcmVkaXRhbWVudG8g ZSBwcm9nZXR0byBTUElEMTwwOgYDVQQDDDNQcm9nZXR0byBTUElEIC0gR2VzdG9y aSBkaSBJZGVudGl0w6AgRGlnaXRhbGUgKElkUCkxKTAnBgkqhkiG9w0BCQEWGnBy b3RvY29sbG9AcGVjLmFnaWQuZ292Lml0MRowGAYDVQQFExFWQVRJVC05NzczNTAy MDU4NDAeFw0yMjA1MTAwMDAwMDBaFw0zMjA1MDkyMzU5NTlaMIGrMRowGAYDVQRh DBFWQVRJVC0wMTAzNTMxMDQxNDEcMBoGA1UEAwwTc3BpZC50ZWFtc3lzdGVtLmNv bTEaMBgGA1UECgwRVGVhbVN5c3RlbSBTLnAuQS4xKDAmBgNVBFMMH2h0dHBzOi8v c3BpZC50ZWFtc3lzdGVtLmNvbS9pZHAxCzAJBgNVBAYTAklUMQ8wDQYDVQQHDAZQ ZXNhcm8xCzAJBgNVBAgMAlBVMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEAyNJMgyn+iquzTvLR5Z/eYBfOoyJIfI3rYcj5WOSlTzlqXXBCzdcROm/JKgrf 3MOTEzH8RAn6XkSHXtJDtMpD7GlwYB0mo8scqDNtpszbhm/UXapJTrP7gy/UI3yf n99n4hvqkGOdld7w5vaAPS0w9PdcaRxY/7X4olHKBAx2cHAwiqhKuiFEDhfACRWs bw4gaIjVM7NuUtL/jG+PJV1NHrEn10vizE7IneMxDNqiQ14IjLL7pJMEPXwbXedz ZsModKKAXIX5reNSegEU1Y386BCkmg4IMWd+DglmMJ4uuzcga1AppgjDuqb8yFDa NOKy/0Jivh2rs7u9boE4cLVBPQIDAQABo4IDCTCCAwUwCQYDVR0TBAIwADAdBgNV HQ4EFgQU/q5NWlPmylmZTsX0C2MwZkrx3b4wHwYDVR0jBBgwFoAUyF8jl8Jbn9To hwSTF77f5QNJd18wDgYDVR0PAQH/BAQDAgbAMBEGA1UdEQQKMAiCBmlkcC5pdDAW BgNVHRIEDzANggtzcGlkLmdvdi5pdDA/BgNVHR8EODA2MDSgMqAwhi5odHRwczov L2VpZGFzLmFnaWQuZ292Lml0L2NybC9jcmxfU1BJRF9JZFAuY3JsMGoGCCsGAQUF BwEBBF4wXDBEBggrBgEFBQcwAoY4aHR0cDovL2VpZGFzLmFnaWQuZ292Lml0L2Nl cnRpZmljYXRpL1N1Yl9DQV9TUElEX0lkUC5jZXIwFAYIKwYBBQUHMAGGCGh0dHBz Oi8vMIIBzgYDVR0gBIIBxTCCAcEwCQYHBACORgEGAjCBlQYEK0wQBjCBjDBEBggr BgEFBQcCAjA4GjZFbGVjdHJvbmljIGNlcnRpZmljYXRlIGNvbmZvcm1pbmcgd2l0 aCBBR0lEIEd1aWRlbGluZXMwRAYIKwYBBQUHAgIwOBo2Q2VydGlmaWNhdG8gZWxl dHRyb25pY28gY29uZm9ybWUgYWxsZSBMaW5lZSBndWlkYSBBZ0lEMHIGBitMEAQB AjBoMDkGCCsGAQUFBwICMC0aK1NQSUQ6IGdlc3RvcmUgZGVsbGUgaWRlbnRpdOAg ZGlnaXRhbGkgKElkUCkwKwYIKwYBBQUHAgIwHxodU1BJRDogSWRlbnRpdHkgUHJv dmlkZXIgKElkUCkwCAYGBACPegEDME0GBCtMEAQwRTBDBggrBgEFBQcCARY3aHR0 cHM6Ly9laWRhcy5hZ2lkLmdvdi5pdC9jcHMvQWdJRF9lSURBU19yb290Q0FfY3Bz LnBkZjBPBgYEAI5GAQUwRTBDBggrBgEFBQcCARY3aHR0cHM6Ly9laWRhcy5hZ2lk Lmdvdi5pdC9jcHMvQWdJRF9lSURBU19yb290Q0FfY3BzLnBkZjANBgkqhkiG9w0B AQ0FAAOCAgEAG9XZeAkIuqSmYb6bq5WrcI2FQtVrfbMH1CXGDKytZUsH5phkGfk/ 8UaIfkbHhnWakM4H9J2gnvfhKorfMt2FHyXFFJ38hlWR8MhFziqthXLUxyLZpUMn h8CcNQyFpNz7xbZk/qN5yFfJyY4Rggm1qdgCNR1LsVI3hjuaORTAzvy4kLjfuU5r nVYPcxpHF7feJKlN03d8JRKYaIi5U+QVYtYJpTcE7jeYmn4Ewfry2BDCOsnljeYl gm3fF8EEVpMfHIhvJg8evATWmKWHpXL2BRtVrl7TfhvtWqKv4tLff+Lv2YqRpmYu oApA48/MB4QxwAPUBnmQb3CxVGs6OCbE/tdUfda9HuHP5MXYLtTVbRYu8pHEPnaN jPA8y90KRw2wiedgjgOG8BxOkhVF/cYs3yH+0hbPS5Oji27t0P2g9eG/p9TOy4AI gUykFimVFk6HV9znknrFSdgsePSp+T5zy45Jdi1z4/RgJN10szJfqEBuvd8MhUu4 meVgfDqXrqavCVzGpSLuicdk41sTOviBz+PEgbQ/qP9KHQv67SHoF4US9Pp9tkyj VFUs7lBnrlFAPpOzd97XdiZfotCA5umibqlxLshy4UK7yl2LZFllpxrfiXTCDASM KlMMIcIsWx0lU/qw5KPpqvXELiya791kohJTi+9pyG7LXIOHHA0whr0= + + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + + + + + + + + + + + + + + + + + + + + + + + + + TeamSystem s.p.a. + TeamSystem s.p.a. + TeamSystem + TeamSystem + https://www.teamsystem.com + https://international.teamsystem.com/ww/ + + + \ No newline at end of file diff --git a/identity-service-rest-client-native/src/test/resources/idp_spid_data_tag2.xml b/identity-service-rest-client-native/src/test/resources/idp_spid_data_tag2.xml new file mode 100644 index 00000000..f247add0 --- /dev/null +++ b/identity-service-rest-client-native/src/test/resources/idp_spid_data_tag2.xml @@ -0,0 +1,434 @@ + + + + + + + + + + + + tOOejf44Q/QPfEY9FK8yHfEPtN0W2MsSQqhWL+9SNmE= + + + Y7vUoO0PW+Lj4eTQMvH4muBctCEnX+K+go+tO1PITSiJBRbO1ZdH1OHyCpt6ZzBcbxTkF1CTCx/WG4LUTYLG4inHdDR/8JFLTiZMFrQC90IpKpmtjF2KIUvstL6zS4TruuRbny8iZGgaybJVhNQEkjDtH7CeA296VOGYiI7w7+BapO5nbx/7nL9Rb05Gx92smo6Jno5dHV6TaT+SXZAkrF/EV+4LVJmzqMPFQKN3qXNIiHHFEgnKOyR5yBiyz26j29weBdYDao8oFx4Ml2oYpv4c2o0g5gpkCYc4SpNlqLlwU8E7hFd72W3rbmEngSgaaOpswlaKS3mI/2XxkmLG2g== + + + MIIEGDCCAwCgAwIBAgIJAOrYj9oLEJCwMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNVBAYTAklUMQ4wDAYDVQQIEwVJdGFseTENMAsGA1UEBxMEUm9tZTENMAsGA1UEChMEQWdJRDESMBAGA1UECxMJQWdJRCBURVNUMRQwEgYDVQQDEwthZ2lkLmdvdi5pdDAeFw0xOTA0MTExMDAyMDhaFw0yNTAzMDgxMDAyMDhaMGUxCzAJBgNVBAYTAklUMQ4wDAYDVQQIEwVJdGFseTENMAsGA1UEBxMEUm9tZTENMAsGA1UEChMEQWdJRDESMBAGA1UECxMJQWdJRCBURVNUMRQwEgYDVQQDEwthZ2lkLmdvdi5pdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK8kJVo+ugRrbbv9xhXCuVrqi4B7/MQzQc62ocwlFFujJNd4m1mXkUHFbgvwhRkQqo2DAmFeHiwCkJT3K1eeXIFhNFFroEzGPzONyekLpjNvmYIs1CFvirGOj0bkEiGaKEs+/umzGjxIhy5JQlqXE96y1+Izp2QhJimDK0/KNij8I1bzxseP0Ygc4SFveKS+7QO+PrLzWklEWGMs4DM5Zc3VRK7g4LWPWZhKdImC1rnS+/lEmHSvHisdVp/DJtbSrZwSYTRvTTz5IZDSq4kAzrDfpj16h7b3t3nFGc8UoY2Ro4tRZ3ahJ2r3b79yK6C5phY7CAANuW3gDdhVjiBNYs0CAwEAAaOByjCBxzAdBgNVHQ4EFgQU3/7kV2tbdFtphbSA4LH7+w8SkcwwgZcGA1UdIwSBjzCBjIAU3/7kV2tbdFtphbSA4LH7+w8SkcyhaaRnMGUxCzAJBgNVBAYTAklUMQ4wDAYDVQQIEwVJdGFseTENMAsGA1UEBxMEUm9tZTENMAsGA1UEChMEQWdJRDESMBAGA1UECxMJQWdJRCBURVNUMRQwEgYDVQQDEwthZ2lkLmdvdi5pdIIJAOrYj9oLEJCwMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJNFqXg/V3aimJKUmUaqmQEEoSc3qvXFITvT5f5bKw9yk/NVhR6wndL+z/24h1OdRqs76blgH8k116qWNkkDtt0AlSjQOx5qvFYh1UviOjNdRI4WkYONSw+vuavcx+fB6O5JDHNmMhMySKTnmRqTkyhjrch7zaFIWUSV7hsBuxpqmrWDoLWdXbV3eFH3mINA5AoIY/m0bZtzZ7YNgiFWzxQgekpxd0vcTseMnCcXnsAlctdir0FoCZztxMuZjlBjwLTtM6Ry3/48LMM8Z+lw7NMciKLLTGQyU8XmKKSSOh0dGh5Lrlt5GxIIJkH81C0YimWebz8464QPL3RbLnTKg+c= + + + + + + + + + + + + + + + JYGJryCuw9bp9PBqoxl1ogs1BX6rIdxN2Cld6uEDcMY= + + + CIEQ0HLKuPpklXui6C9d1pd1syuB9RcgoOI4yBU4QnAEoLvWAJoyTOUvjXfNN9pKehdvcPyW6LPmlonb6Mf5sKswUXdAbimSeYwgAO0U3mVAzGxGK543RjHGamGtz3G4IDW7FTqkG0QmQDAWfeq+CYJksdHFfKwvzY9l6PWCvmPIsaIjwJcFvWMWlwCBwABL3QmUqHkLmifk3/zcN1kmHEjlwMNpCwH32A2jgyFPho96BWQo+iMRjIaLUHfrnPNqMS49nYW5rUQM1nWiRrTMY74dxfd+xTUVZKVGSgL9ACQviTPwHOm4YYkhA+zjUTT22kEFb0fdMxrC0QzBM/FnLA== + + + MIID0jCCArqgAwIBAgIUXDUOKL3WuolxDw96Fk9es8rIt6kwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAklUMS4wLAYDVQQKDCVUZWxlY29tIEl0YWxpYSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMSgwJgYDVQQLDB9TZXJ2aXppIHBlciBsJ2lkZW50aXRhIGRpZ2l0YWxlMSIwIAYDVQQDDBlUSSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMB4XDTIxMTExMTE3MDMyMFoXDTI1MTExMDE3MDMyMFowgYsxCzAJBgNVBAYTAklUMS4wLAYDVQQKDCVUZWxlY29tIEl0YWxpYSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMSgwJgYDVQQLDB9TZXJ2aXppIHBlciBsJ2lkZW50aXRhIGRpZ2l0YWxlMSIwIAYDVQQDDBlUSSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6sIS3+3iZSaAIyVywahlbpua2uJ/XmpV68P1e1STJpHoaj32STdHhqZnnb4Y/FshP1NUolzNolPXAYDmDduW1OnGndJZ+G9Hjh1PCkdiRw+p0FjhQAsGJkn8NdgTIHLJjqN1qQwtOsVGab8ScyA3mtmj3xKYuBhUoweuATzC7f5r7FfIoc3cy6N5lgrpZpfeAChxLwoHVjoAVgIBuemi6HAzmd4/BI06KzOcR7+dBVi4+uiseldxrJ5bhnjZKIwgkX14y9UA84Y+e+rMtyT8cT3XXi9NazZl5Ej5/bQPqqVsbg6tXzQSfEJD6JEjuYeC0RUKMS/EJn3hL5VLzTJ1NwIDAQABoywwKjAdBgNVHQ4EFgQUfctFZ8bRtmEvXPRlqgVDuggY/ZwwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA0lszHadknPfE17IWGWsgvlXOdKMnWcl9H5rEYmsWwDB9FJG9XAZvPMcVv1kkWi6XZI/8N2Twhu1BdZkdvntDRscuck8wxxIpkRV7CwlcqNFZ/IwjDBxOBa8Q1J850p+qP8A9apsLLPUlu/oLygNDWIXzcOjMqnPkEP+XXUNYPto5iV+OyDzLLacCYqDDHcvDewWLmEjt35X967KcM+m7K2zGRLWfqcZPIjJJOkpNjgcs+MaisMrGDyOKiD16v0LpwVyIpTqXvDk7KHo8CUNXDxyLxZzB6WffgnOgjXTfU3vluweOx0qQy/VxIupDlNBKiZB4gnt1oAfnaMbqla9wcw== + + + + + + + + MIID0jCCArqgAwIBAgIUXDUOKL3WuolxDw96Fk9es8rIt6kwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAklUMS4wLAYDVQQKDCVUZWxlY29tIEl0YWxpYSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMSgwJgYDVQQLDB9TZXJ2aXppIHBlciBsJ2lkZW50aXRhIGRpZ2l0YWxlMSIwIAYDVQQDDBlUSSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMB4XDTIxMTExMTE3MDMyMFoXDTI1MTExMDE3MDMyMFowgYsxCzAJBgNVBAYTAklUMS4wLAYDVQQKDCVUZWxlY29tIEl0YWxpYSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMSgwJgYDVQQLDB9TZXJ2aXppIHBlciBsJ2lkZW50aXRhIGRpZ2l0YWxlMSIwIAYDVQQDDBlUSSBUcnVzdCBUZWNobm9sb2dpZXMgc3JsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6sIS3+3iZSaAIyVywahlbpua2uJ/XmpV68P1e1STJpHoaj32STdHhqZnnb4Y/FshP1NUolzNolPXAYDmDduW1OnGndJZ+G9Hjh1PCkdiRw+p0FjhQAsGJkn8NdgTIHLJjqN1qQwtOsVGab8ScyA3mtmj3xKYuBhUoweuATzC7f5r7FfIoc3cy6N5lgrpZpfeAChxLwoHVjoAVgIBuemi6HAzmd4/BI06KzOcR7+dBVi4+uiseldxrJ5bhnjZKIwgkX14y9UA84Y+e+rMtyT8cT3XXi9NazZl5Ej5/bQPqqVsbg6tXzQSfEJD6JEjuYeC0RUKMS/EJn3hL5VLzTJ1NwIDAQABoywwKjAdBgNVHQ4EFgQUfctFZ8bRtmEvXPRlqgVDuggY/ZwwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA0lszHadknPfE17IWGWsgvlXOdKMnWcl9H5rEYmsWwDB9FJG9XAZvPMcVv1kkWi6XZI/8N2Twhu1BdZkdvntDRscuck8wxxIpkRV7CwlcqNFZ/IwjDBxOBa8Q1J850p+qP8A9apsLLPUlu/oLygNDWIXzcOjMqnPkEP+XXUNYPto5iV+OyDzLLacCYqDDHcvDewWLmEjt35X967KcM+m7K2zGRLWfqcZPIjJJOkpNjgcs+MaisMrGDyOKiD16v0LpwVyIpTqXvDk7KHo8CUNXDxyLxZzB6WffgnOgjXTfU3vluweOx0qQy/VxIupDlNBKiZB4gnt1oAfnaMbqla9wcw== + CN=TI Trust Technologies srl,OU=Servizi per l'identita digitale,O=Telecom Italia Trust Technologies srl,C=IT + + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + + + + + + + + + + + + + + + + + + + + + + + + TI Trust Technologies srl + Trust Technologies srl + https://www.trusttechnologies.it + + + + + + + + + + + + + + zanMEv9e3IoYmz27wv5RQCYhp7IuxdvUwb/VCjOjosA= + + + EyJLBOIVDVK2UM0VYzm+ukfwm34rO2a+AmXnyem+FpLF8mHUdGe2vBafE2YiV6sr7H6/zg0ozeRgPVos9E5xc0LWZwPFK8KWaMiQwrdFVwxAVp3SL0DMXs8msj9+zMnrFb9zGNq9/SoSgJm9BNcjxud+9Ky4XlS30pk7deHy/KgdGpO0cnWOoaYbWfPhHmQ40y7lMF9WZnHibDNTbYPGFMhUgGjGauTH5x+HvGEbreLSpTMEt07Hc0KNV/TSCsUCKpbv7z2YOFbQ5yt6IO2MrpgOQIqr8JF1oC5t/C+5SltkpLUxvYwqh+gF91u1METuqURTzNe1Iz+qb0WFNuyMxw== + + + MIIExTCCA62gAwIBAgIQH32A70kY92tuXB8AGi2DdDANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQG EwJJVDEYMBYGA1UECgwPQXJ1YmFQRUMgUy5wLkEuMSEwHwYDVQQLDBhDZXJ0aWZpY2F0aW9uIEF1 dGhvcml0eUIxIDAeBgNVBAMMF0FydWJhUEVDIFMucC5BLiBORyBDQSAyMB4XDTIwMDEyMjAwMDAw MFoXDTI1MDEyMTIzNTk1OVowgaAxCzAJBgNVBAYTAklUMRYwFAYDVQQKDA1BcnViYSBQRUMgc3Bh MREwDwYDVQQLDAhQcm9kb3R0bzEWMBQGA1UEAwwNcGVjLml0IHBlYy5pdDEZMBcGA1UEBRMQWFhY WFhYMDBYMDBYMDAwWDEPMA0GA1UEKgwGcGVjLml0MQ8wDQYDVQQEDAZwZWMuaXQxETAPBgNVBC4T CDIwODc2Mzc5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqt2oHJhcp03l73p+QYpE J+f3jYYj0W0gos0RItZx/w4vpsiKBygaqDNVWSwfo1aPdVDIX13f62O+lBki29KTt+QWv5K6SGHD UXYPntRdEQlicIBh2Z0HfrM7fDl+xeJrMp1s4dsSQAuB5TJOlFZq7xCQuukytGWBTvjfcN/os5aE sEg+RbtZHJR26SbbUcIqWb27Swgj/9jwK+tvzLnP4w8FNvEOrNfR0XwTMNDFrwbOCuWgthv5jNBs VZaoqNwiA/MxYt+gTOMj/o5PWKk8Wpm6o/7/+lWAoxh0v8x9OkbIi+YaFpIxuCcUqsrJJk63x2gH Cc2nr+yclYUhsKD/AwIDAQABo4IBLDCCASgwDgYDVR0PAQH/BAQDAgeAMB0GA1UdDgQWBBTKQ3+N PGcXFk8nX994vMTVpba1EzBHBgNVHSAEQDA+MDwGCysGAQQBgegtAQEBMC0wKwYIKwYBBQUHAgEW H2h0dHBzOi8vY2EuYXJ1YmFwZWMuaXQvY3BzLmh0bWwwWAYDVR0fBFEwTzBNoEugSYZHaHR0cDov L2NybC5hcnViYXBlYy5pdC9BcnViYVBFQ1NwQUNlcnRpZmljYXRpb25BdXRob3JpdHlCL0xhdGVz dENSTC5jcmwwHwYDVR0jBBgwFoAU8v9jQBwRQv3M3/FZ9m7omYcxR3kwMwYIKwYBBQUHAQEEJzAl MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5hcnViYXBlYy5pdDANBgkqhkiG9w0BAQsFAAOCAQEA ZKpor1MrrYwPw+IuPZElQAuNzXsaSWSnn/QQwJtW49c4rFM4mEud9c61p9XxIIbgQKmDmNbzC+Dm wJSZ8ILdCAyBHmY3BehVRAy3KRA2KQhS9kd4vywf5KVYd1L5hQa9DBrusxF7i1X/SEeLQgoKkov0 R8v43UncqXS/ql50ovJFxi938Rv4rVwa8o0hqqc6WUcjkidB6M9aNJLIbOZN3xNUgC28qIr8y7N8 lbxWbwVrGxqKDtpaA9J0hOOXxwuTfSd1zOtT0KSSSUQ53QGOPnxyjxYDQbJu60/lBPuUV5wb/Z2r gpeUH1/n7limHV5sVmOZgSnf18T+0STANCfkXg== + + + + + + + + + + + MIIExTCCA62gAwIBAgIQH32A70kY92tuXB8AGi2DdDANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQG EwJJVDEYMBYGA1UECgwPQXJ1YmFQRUMgUy5wLkEuMSEwHwYDVQQLDBhDZXJ0aWZpY2F0aW9uIEF1 dGhvcml0eUIxIDAeBgNVBAMMF0FydWJhUEVDIFMucC5BLiBORyBDQSAyMB4XDTIwMDEyMjAwMDAw MFoXDTI1MDEyMTIzNTk1OVowgaAxCzAJBgNVBAYTAklUMRYwFAYDVQQKDA1BcnViYSBQRUMgc3Bh MREwDwYDVQQLDAhQcm9kb3R0bzEWMBQGA1UEAwwNcGVjLml0IHBlYy5pdDEZMBcGA1UEBRMQWFhY WFhYMDBYMDBYMDAwWDEPMA0GA1UEKgwGcGVjLml0MQ8wDQYDVQQEDAZwZWMuaXQxETAPBgNVBC4T CDIwODc2Mzc5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqt2oHJhcp03l73p+QYpE J+f3jYYj0W0gos0RItZx/w4vpsiKBygaqDNVWSwfo1aPdVDIX13f62O+lBki29KTt+QWv5K6SGHD UXYPntRdEQlicIBh2Z0HfrM7fDl+xeJrMp1s4dsSQAuB5TJOlFZq7xCQuukytGWBTvjfcN/os5aE sEg+RbtZHJR26SbbUcIqWb27Swgj/9jwK+tvzLnP4w8FNvEOrNfR0XwTMNDFrwbOCuWgthv5jNBs VZaoqNwiA/MxYt+gTOMj/o5PWKk8Wpm6o/7/+lWAoxh0v8x9OkbIi+YaFpIxuCcUqsrJJk63x2gH Cc2nr+yclYUhsKD/AwIDAQABo4IBLDCCASgwDgYDVR0PAQH/BAQDAgeAMB0GA1UdDgQWBBTKQ3+N PGcXFk8nX994vMTVpba1EzBHBgNVHSAEQDA+MDwGCysGAQQBgegtAQEBMC0wKwYIKwYBBQUHAgEW H2h0dHBzOi8vY2EuYXJ1YmFwZWMuaXQvY3BzLmh0bWwwWAYDVR0fBFEwTzBNoEugSYZHaHR0cDov L2NybC5hcnViYXBlYy5pdC9BcnViYVBFQ1NwQUNlcnRpZmljYXRpb25BdXRob3JpdHlCL0xhdGVz dENSTC5jcmwwHwYDVR0jBBgwFoAU8v9jQBwRQv3M3/FZ9m7omYcxR3kwMwYIKwYBBQUHAQEEJzAl MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5hcnViYXBlYy5pdDANBgkqhkiG9w0BAQsFAAOCAQEA ZKpor1MrrYwPw+IuPZElQAuNzXsaSWSnn/QQwJtW49c4rFM4mEud9c61p9XxIIbgQKmDmNbzC+Dm wJSZ8ILdCAyBHmY3BehVRAy3KRA2KQhS9kd4vywf5KVYd1L5hQa9DBrusxF7i1X/SEeLQgoKkov0 R8v43UncqXS/ql50ovJFxi938Rv4rVwa8o0hqqc6WUcjkidB6M9aNJLIbOZN3xNUgC28qIr8y7N8 lbxWbwVrGxqKDtpaA9J0hOOXxwuTfSd1zOtT0KSSSUQ53QGOPnxyjxYDQbJu60/lBPuUV5wb/Z2r gpeUH1/n7limHV5sVmOZgSnf18T+0STANCfkXg== + + + + + + + MIIExTCCA62gAwIBAgIQIHtEvEhGM77HwqsuvSbi9zANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQG EwJJVDEYMBYGA1UECgwPQXJ1YmFQRUMgUy5wLkEuMSEwHwYDVQQLDBhDZXJ0aWZpY2F0aW9uIEF1 dGhvcml0eUIxIDAeBgNVBAMMF0FydWJhUEVDIFMucC5BLiBORyBDQSAyMB4XDTE3MDEyMzAwMDAw MFoXDTIwMDEyMzIzNTk1OVowgaAxCzAJBgNVBAYTAklUMRYwFAYDVQQKDA1BcnViYSBQRUMgc3Bh MREwDwYDVQQLDAhQcm9kb3R0bzEWMBQGA1UEAwwNcGVjLml0IHBlYy5pdDEZMBcGA1UEBRMQWFhY WFhYMDBYMDBYMDAwWDEPMA0GA1UEKgwGcGVjLml0MQ8wDQYDVQQEDAZwZWMuaXQxETAPBgNVBC4T CDE2MzQ1MzgzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqt2oHJhcp03l73p+QYpE J+f3jYYj0W0gos0RItZx/w4vpsiKBygaqDNVWSwfo1aPdVDIX13f62O+lBki29KTt+QWv5K6SGHD UXYPntRdEQlicIBh2Z0HfrM7fDl+xeJrMp1s4dsSQAuB5TJOlFZq7xCQuukytGWBTvjfcN/os5aE sEg+RbtZHJR26SbbUcIqWb27Swgj/9jwK+tvzLnP4w8FNvEOrNfR0XwTMNDFrwbOCuWgthv5jNBs VZaoqNwiA/MxYt+gTOMj/o5PWKk8Wpm6o/7/+lWAoxh0v8x9OkbIi+YaFpIxuCcUqsrJJk63x2gH Cc2nr+yclYUhsKD/AwIDAQABo4IBLDCCASgwDgYDVR0PAQH/BAQDAgeAMB0GA1UdDgQWBBTKQ3+N PGcXFk8nX994vMTVpba1EzBHBgNVHSAEQDA+MDwGCysGAQQBgegtAQEBMC0wKwYIKwYBBQUHAgEW H2h0dHBzOi8vY2EuYXJ1YmFwZWMuaXQvY3BzLmh0bWwwWAYDVR0fBFEwTzBNoEugSYZHaHR0cDov L2NybC5hcnViYXBlYy5pdC9BcnViYVBFQ1NwQUNlcnRpZmljYXRpb25BdXRob3JpdHlCL0xhdGVz dENSTC5jcmwwHwYDVR0jBBgwFoAU8v9jQBwRQv3M3/FZ9m7omYcxR3kwMwYIKwYBBQUHAQEEJzAl MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5hcnViYXBlYy5pdDANBgkqhkiG9w0BAQsFAAOCAQEA nEw0NuaspbpDjA5wggwFtfQydU6b3Bw2/KXPRKS2JoqGmx0SYKj+L17A2KUBa2c7gDtKXYz0FLT6 0Bv0pmBN/oYCgVMEBJKqwRwdki9YjEBwyCZwNEx1kDAyyqFEVU9vw/OQfrAdp7MTbuZGFKknVt7b 9wOYy/Op9FiUaTg6SuOy0ep+rqhihltYNAAl4L6fY45mHvqa5vvVG30OvLW/S4uvRYUXYwY6KhWv NdDf5CnFugnuEZtHJrVe4wx9aO5GvFLFZ/mQ35C5mXPQ7nIb0CDdLBJdz82nUoLSA5BUbeXAUkfa hW/hLxLdhks68/TK694xVIuiB40pvMmJwxIyDA== + + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + + + + + + + + + + + + + + + + + + + + + + + + + ArubaPEC S.p.A. + ArubaPEC S.p.A. + https://www.pec.it/ + + + + + + + + + + + + + + qjmkoKCiL8y4gBEXT8DVubGLvH7N8roi/lpgTQww+dw= + + + fm30Z3Ugxcae7W+nvNm9SDeMjH+sWDDcUnobMaBemlKLSj7KiOT1bc/HVIqY9sH/AoV6LiDZ05PSnQLhL8HI1Q71CGpRUTIt3b2oL7D+4iOsirKjFCYjHq75FBR5esaejhvHWIpnTx6Dp+CigVM2eH9IrBIY3Xkw2FqD7Q9CCc/bl33OUjEGS2o4VpjWyFCVsPMWy0QxsC0Em+fTbPjlMX8n55SKvSZy4ItNfoahLy/+8DD+VsWA9u3fPbValsfLZqyziBRjTcdc0nAeQliXj+ajjCbqGmG+jLw3mNRXglF5Kqq3hcHe5a/9WqKCh2x82ReMT7KhFRwQl+lhsBoWRg== + + + MIIIRDCCBiygAwIBAgIINO3vGmIYBP0wDQYJKoZIhvcNAQENBQAwgfsxCzAJBgNVBAYTAklUMQ0w CwYDVQQHDARSb21lMSYwJAYDVQQKDB1BZ2VuemlhIHBlciBsJ0l0YWxpYSBEaWdpdGFsZTEwMC4G A1UECwwnU2Vydml6aW8gQWNjcmVkaXRhbWVudG8gZSBwcm9nZXR0byBTUElEMTwwOgYDVQQDDDNQ cm9nZXR0byBTUElEIC0gR2VzdG9yaSBkaSBJZGVudGl0w6AgRGlnaXRhbGUgKElkUCkxKTAnBgkq hkiG9w0BCQEWGnByb3RvY29sbG9AcGVjLmFnaWQuZ292Lml0MRowGAYDVQQFExFWQVRJVC05Nzcz NTAyMDU4NDAeFw0yMzAyMjIwMDAwMDBaFw0zMzAyMjEyMzU5NTlaMIG3MQswCQYDVQQGEwJJVDEO MAwGA1UECAwFSXRhbHkxDzANBgNVBAcMBlBhZG92YTEcMBoGA1UECgwTSW5mb0NhbWVyZSBTLkMu cC5BLjElMCMGA1UEAwwcSW5mb0NhbWVyZSBJZGVudGl0eSBQcm92aWRlcjEaMBgGA1UEYQwRVkFU SVQtMDIzMTM4MjEwMDcxJjAkBgNVBFMMHWh0dHBzOi8vaWRzcGlkLmluZm9jYW1lcmUuaXQvMIIB IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo8Div4aLGUtoDoP5RWbRwqvEtjnDcCCUS+Sz ChAsJP+UYjWl+R4R4Y7Lz+WId3LJqey+QIyvviD6vH/QloqzVRG/JabW70NZylk1UX2isss8mRvt ceK7nYVxjTIoQpasg0OsCevgljjnFxRm8c3zUpYfjC5zzr/jZ9HjFKghGCZGjBavNNgiGIo7e7jb dmGH5N9z+uQ8KRG/p2JRxD0YeVy2+EV2o0cQO2duE383EganLKPcQ9AnxkLE1K0cpP7XQDtUgWTP qsL9+OLTl13KhVM2TMK7EkAm00WCOl1aX3E7g9Qgw+4fUm308v77OSDe77dY8hohZWPRTwjemaHA 2QIDAQABo4IDDDCCAwgwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUddqeUDWjVXqV3PSfTyzAmlFD TDMwHwYDVR0jBBgwFoAUyF8jl8Jbn9TohwSTF77f5QNJd18wDgYDVR0PAQH/BAQDAgbAMBEGA1Ud EQQKMAiCBmlkcC5pdDAWBgNVHRIEDzANggtzcGlkLmdvdi5pdDA/BgNVHR8EODA2MDSgMqAwhi5o dHRwczovL2VpZGFzLmFnaWQuZ292Lml0L2NybC9jcmxfU1BJRF9JZFAuY3JsMGoGCCsGAQUFBwEB BF4wXDBEBggrBgEFBQcwAoY4aHR0cDovL2VpZGFzLmFnaWQuZ292Lml0L2NlcnRpZmljYXRpL1N1 Yl9DQV9TUElEX0lkUC5jZXIwFAYIKwYBBQUHMAGGCGh0dHBzOi8vMIIBzgYDVR0gBIIBxTCCAcEw CQYHBACORgEGAjCBlQYEK0wQBjCBjDBEBggrBgEFBQcCAjA4GjZFbGVjdHJvbmljIGNlcnRpZmlj YXRlIGNvbmZvcm1pbmcgd2l0aCBBR0lEIEd1aWRlbGluZXMwRAYIKwYBBQUHAgIwOBo2Q2VydGlm aWNhdG8gZWxldHRyb25pY28gY29uZm9ybWUgYWxsZSBMaW5lZSBndWlkYSBBZ0lEMHIGBitMEAQB AjBoMDkGCCsGAQUFBwICMC0aK1NQSUQ6IGdlc3RvcmUgZGVsbGUgaWRlbnRpdOAgZGlnaXRhbGkg KElkUCkwKwYIKwYBBQUHAgIwHxodU1BJRDogSWRlbnRpdHkgUHJvdmlkZXIgKElkUCkwCAYGBACP egEDME0GBCtMEAQwRTBDBggrBgEFBQcCARY3aHR0cHM6Ly9laWRhcy5hZ2lkLmdvdi5pdC9jcHMv QWdJRF9lSURBU19yb290Q0FfY3BzLnBkZjBPBgYEAI5GAQUwRTBDBggrBgEFBQcCARY3aHR0cHM6 Ly9laWRhcy5hZ2lkLmdvdi5pdC9jcHMvQWdJRF9lSURBU19yb290Q0FfY3BzLnBkZjANBgkqhkiG 9w0BAQ0FAAOCAgEAoYZlSArAwFZDknzUG5Z3NQQUT3JKaOTT8TrNi/F8yL4mz0qjaJaJURMQauKZ eNQiGlGvNyGp3SlgGYFHasZ9FrtpxbxGXVkNreer61kFhY/I3ZdU4DjGW2qPs9csP+W06R4k3OFF hua7DFyyoxAWQYIFisucT3E3+N32XuLQPDqjMwnvSdT4FLE6c4QIpJl3fQYlCsyhAxrNWlrndP1Q 1f97oF6oB7tWR5Ae1/ixDN0q5QJeEnapNaDjvS2wEzVNRYW/RzbHPPZQ1Zs0jLEfXsuwD3A0iJiy D0GSgXYUibqH3VExCqQ1yjEDwjq3zF8bcSaoAQm2fRY3KIYSbI18kpPhFmNTJWbv303dQe6MzIOR LUzs0tSHfB+mtclrHgqqaKwZZmHiGUYTV3bziWjMDacG9gRJtyS04LYZdkSBcSOn3dYXSM18F58p bKifcdajFmUicUWlI/2TFArDguh5TUekLQKsTi4tMnmk5RWA4oMLjZ+q2r4jMNVuoZ0+FGFbrfdh z+Kyo3gWdyZyY+Uqr1aiL+QTnht8hVTVrgOf4RJW/3z5hgYLSyx3INT6GDtaSr5V+orYfSpbvU1X linz+iP4vfYKmpFdF1cxjTYkNQB7/DW9nXYC4PwXjI5253rha8g/BLdsIEWD73Q1GM1HieSVX+tN PBbjHpKLz2UVZEM= + + + + + + + + + + + MIIIRDCCBiygAwIBAgIINO3vGmIYBP0wDQYJKoZIhvcNAQENBQAwgfsxCzAJBgNVBAYTAklUMQ0w CwYDVQQHDARSb21lMSYwJAYDVQQKDB1BZ2VuemlhIHBlciBsJ0l0YWxpYSBEaWdpdGFsZTEwMC4G A1UECwwnU2Vydml6aW8gQWNjcmVkaXRhbWVudG8gZSBwcm9nZXR0byBTUElEMTwwOgYDVQQDDDNQ cm9nZXR0byBTUElEIC0gR2VzdG9yaSBkaSBJZGVudGl0w6AgRGlnaXRhbGUgKElkUCkxKTAnBgkq hkiG9w0BCQEWGnByb3RvY29sbG9AcGVjLmFnaWQuZ292Lml0MRowGAYDVQQFExFWQVRJVC05Nzcz NTAyMDU4NDAeFw0yMzAyMjIwMDAwMDBaFw0zMzAyMjEyMzU5NTlaMIG3MQswCQYDVQQGEwJJVDEO MAwGA1UECAwFSXRhbHkxDzANBgNVBAcMBlBhZG92YTEcMBoGA1UECgwTSW5mb0NhbWVyZSBTLkMu cC5BLjElMCMGA1UEAwwcSW5mb0NhbWVyZSBJZGVudGl0eSBQcm92aWRlcjEaMBgGA1UEYQwRVkFU SVQtMDIzMTM4MjEwMDcxJjAkBgNVBFMMHWh0dHBzOi8vaWRzcGlkLmluZm9jYW1lcmUuaXQvMIIB IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo8Div4aLGUtoDoP5RWbRwqvEtjnDcCCUS+Sz ChAsJP+UYjWl+R4R4Y7Lz+WId3LJqey+QIyvviD6vH/QloqzVRG/JabW70NZylk1UX2isss8mRvt ceK7nYVxjTIoQpasg0OsCevgljjnFxRm8c3zUpYfjC5zzr/jZ9HjFKghGCZGjBavNNgiGIo7e7jb dmGH5N9z+uQ8KRG/p2JRxD0YeVy2+EV2o0cQO2duE383EganLKPcQ9AnxkLE1K0cpP7XQDtUgWTP qsL9+OLTl13KhVM2TMK7EkAm00WCOl1aX3E7g9Qgw+4fUm308v77OSDe77dY8hohZWPRTwjemaHA 2QIDAQABo4IDDDCCAwgwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUddqeUDWjVXqV3PSfTyzAmlFD TDMwHwYDVR0jBBgwFoAUyF8jl8Jbn9TohwSTF77f5QNJd18wDgYDVR0PAQH/BAQDAgbAMBEGA1Ud EQQKMAiCBmlkcC5pdDAWBgNVHRIEDzANggtzcGlkLmdvdi5pdDA/BgNVHR8EODA2MDSgMqAwhi5o dHRwczovL2VpZGFzLmFnaWQuZ292Lml0L2NybC9jcmxfU1BJRF9JZFAuY3JsMGoGCCsGAQUFBwEB BF4wXDBEBggrBgEFBQcwAoY4aHR0cDovL2VpZGFzLmFnaWQuZ292Lml0L2NlcnRpZmljYXRpL1N1 Yl9DQV9TUElEX0lkUC5jZXIwFAYIKwYBBQUHMAGGCGh0dHBzOi8vMIIBzgYDVR0gBIIBxTCCAcEw CQYHBACORgEGAjCBlQYEK0wQBjCBjDBEBggrBgEFBQcCAjA4GjZFbGVjdHJvbmljIGNlcnRpZmlj YXRlIGNvbmZvcm1pbmcgd2l0aCBBR0lEIEd1aWRlbGluZXMwRAYIKwYBBQUHAgIwOBo2Q2VydGlm aWNhdG8gZWxldHRyb25pY28gY29uZm9ybWUgYWxsZSBMaW5lZSBndWlkYSBBZ0lEMHIGBitMEAQB AjBoMDkGCCsGAQUFBwICMC0aK1NQSUQ6IGdlc3RvcmUgZGVsbGUgaWRlbnRpdOAgZGlnaXRhbGkg KElkUCkwKwYIKwYBBQUHAgIwHxodU1BJRDogSWRlbnRpdHkgUHJvdmlkZXIgKElkUCkwCAYGBACP egEDME0GBCtMEAQwRTBDBggrBgEFBQcCARY3aHR0cHM6Ly9laWRhcy5hZ2lkLmdvdi5pdC9jcHMv QWdJRF9lSURBU19yb290Q0FfY3BzLnBkZjBPBgYEAI5GAQUwRTBDBggrBgEFBQcCARY3aHR0cHM6 Ly9laWRhcy5hZ2lkLmdvdi5pdC9jcHMvQWdJRF9lSURBU19yb290Q0FfY3BzLnBkZjANBgkqhkiG 9w0BAQ0FAAOCAgEAoYZlSArAwFZDknzUG5Z3NQQUT3JKaOTT8TrNi/F8yL4mz0qjaJaJURMQauKZ eNQiGlGvNyGp3SlgGYFHasZ9FrtpxbxGXVkNreer61kFhY/I3ZdU4DjGW2qPs9csP+W06R4k3OFF hua7DFyyoxAWQYIFisucT3E3+N32XuLQPDqjMwnvSdT4FLE6c4QIpJl3fQYlCsyhAxrNWlrndP1Q 1f97oF6oB7tWR5Ae1/ixDN0q5QJeEnapNaDjvS2wEzVNRYW/RzbHPPZQ1Zs0jLEfXsuwD3A0iJiy D0GSgXYUibqH3VExCqQ1yjEDwjq3zF8bcSaoAQm2fRY3KIYSbI18kpPhFmNTJWbv303dQe6MzIOR LUzs0tSHfB+mtclrHgqqaKwZZmHiGUYTV3bziWjMDacG9gRJtyS04LYZdkSBcSOn3dYXSM18F58p bKifcdajFmUicUWlI/2TFArDguh5TUekLQKsTi4tMnmk5RWA4oMLjZ+q2r4jMNVuoZ0+FGFbrfdh z+Kyo3gWdyZyY+Uqr1aiL+QTnht8hVTVrgOf4RJW/3z5hgYLSyx3INT6GDtaSr5V+orYfSpbvU1X linz+iP4vfYKmpFdF1cxjTYkNQB7/DW9nXYC4PwXjI5253rha8g/BLdsIEWD73Q1GM1HieSVX+tN PBbjHpKLz2UVZEM= + + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + + + + + + + + + + + + + + + + + + + + + + + + + InfoCamere S.C.p.A. + InfoCamere S.C.p.A. + https://www.infocamere.it/ + + + + + + + + + + + + + + ix5zJ0s5HicXBtbud2nW7dwhwEVB6jZnzhFkbFLAYVs= + + + EdhsS12CrldyKtXkWCHY7PlrD8Uc2HyKd2a40aNsEabBJxH0gsKfzO85HSRw1jLBVf0352moDNAp vqrH24ImHV9umqzxqY5SAXx7ISeGl56kmWB4CWGPK7X7Vb0iDosDzoI60vHlipVmdbaqlwOZQG79 xEoyo4bU/IxhdFhr0wl8b3SnGTWlFS3iThaz4g2dmWlzcjVcf+s5CigClhqToedKxPbY2CGl+U78 sgNTlR2cGIe9gjRlQIboXUr14SzDJgIOLkFIGyuIlgA7vk85/HDSXGhEIa5r/N9Tb+dTc+PXPxV9 Lk9Oy88WbYOqfvOKnkzVjmWj026DTT2N9uBPmg== + + + MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4 fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1 MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0 uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc= + + + + + + + + + + + MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4 fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1 MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0 uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc= + + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + + + + + + + + + + + + + + + + + + + + + Poste Italiane SpA + Poste Italiane SpA + https://www.poste.it + + + + + + + + + + + + + + D/A8yDFktAAd8ZdH4txugRyfui6Yy9cYlS/ilyzB6qg= + + + YN5NOuJNo8+3p5j+vQ+l0tA8hsvgfqwHu4amDbJeV3ltCa2ev2chti18Tekswx/FjkpVo7Xu1Thi3jcxRalyeoY2XAPhhEigI+JSA6+JcJUC91Gm+b9+LO6mnKba+epGBdfoDoj66tBCeSXD1AOSid1WcCEjEoFfMwIx2TJQVhz/Vx6JhAPYjbjyiXgus7hI4JPFQla3msjrrCJ8umU635e1dyFPqxTt1jIRP5oZnSGx0moP5dGRMhU+mu2mtcJOGiz02km+TtmxIRgACJ8HB3sEP3HDwtQmVguhDCUluY94UfU42dIsaKOZB2mVEVjHDzCVxGGYPAYaY8lu1ZDO5g== + + + MIIDazCCAlOgAwIBAgIED8R+MDANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJJVDELMAkGA1UECBMCRkkxETAPBgNVBAcTCGZsb3JlbmNlMREwDwYDVQQKEwhyZWdpc3RlcjERMA8GA1UECxMIcmVnaXN0ZXIxETAPBgNVBAMTCHJlZ2lzdGVyMB4XDTE3MDcxMDEwMzM0OVoXDTI3MDcwODEwMzM0OVowZjELMAkGA1UEBhMCSVQxCzAJBgNVBAgTAkZJMREwDwYDVQQHEwhmbG9yZW5jZTERMA8GA1UEChMIcmVnaXN0ZXIxETAPBgNVBAsTCHJlZ2lzdGVyMREwDwYDVQQDEwhyZWdpc3RlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANkYXHbm3q6xt3wrLAXnytswtj2JE1MM8aYmNXkTgDMCwO/+ahQOoQru6IBTbjfWH9jr+Woy54FDdX6bHl+5/mO6l/yAB/bKgwe5HmUjZJ5oakJjWucsSm+VkEwN2HquBZoN+mktju00xvLX5VAjmDHvZc/b8NhNr/FRKlYITboygkhGiUwGI3wLf3IaB76J0o7ugpW2WNLcywpX+p1VWZAMCdHBveBe/e42hh6WnWPqdwYUWHOgJ8HX4IzCHifiS1n6eUMgtoTQOmSvTQDwSjD0WWJE8tWSYt+txXg1t+3A3tbZOFu7T442wE7DtMdUL4+8gimQS+e8PxDK1uTqIPUCAwEAAaMhMB8wHQYDVR0OBBYEFMCgo1gzCIcUThQIs5g5ikfv1D7eMA0GCSqGSIb3DQEBCwUAA4IBAQBnGw3i3hQ37L8vyelkyZMeO3tLK65Cqti4oVrQZxClGV5zNA6fIMDY8Mci1UhLwjzp29POd/sez0vuHZ/Vmmygzoye4jTKr6c3jAh0u81FTzefBU+vIietm9RuV3sd7D9xq6EqOY1NDL+rkvBcTFtiwLEUm2kHYu/U67jk73pxOtmqxQvQeMU8oi42tehMZGLIGp3U5lGS8YGGl+GtkkQ2Z5/PSm67HGP81kTArG/QX+bX+ykypTJVg9hfb9zOFQidp1HkCRIez6YhDiP/ZLurd6Grt/wVfZPNBO8EOgy25AkRZlp+UD686BFg7qq5KKEbz3qmPrj8deHL3duacZcp + + + + + + + + MIIDazCCAlOgAwIBAgIED8R+MDANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJJVDELMAkGA1UECBMCRkkxETAPBgNVBAcTCGZsb3JlbmNlMREwDwYDVQQKEwhyZWdpc3RlcjERMA8GA1UECxMIcmVnaXN0ZXIxETAPBgNVBAMTCHJlZ2lzdGVyMB4XDTE3MDcxMDEwMzM0OVoXDTI3MDcwODEwMzM0OVowZjELMAkGA1UEBhMCSVQxCzAJBgNVBAgTAkZJMREwDwYDVQQHEwhmbG9yZW5jZTERMA8GA1UEChMIcmVnaXN0ZXIxETAPBgNVBAsTCHJlZ2lzdGVyMREwDwYDVQQDEwhyZWdpc3RlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANkYXHbm3q6xt3wrLAXnytswtj2JE1MM8aYmNXkTgDMCwO/+ahQOoQru6IBTbjfWH9jr+Woy54FDdX6bHl+5/mO6l/yAB/bKgwe5HmUjZJ5oakJjWucsSm+VkEwN2HquBZoN+mktju00xvLX5VAjmDHvZc/b8NhNr/FRKlYITboygkhGiUwGI3wLf3IaB76J0o7ugpW2WNLcywpX+p1VWZAMCdHBveBe/e42hh6WnWPqdwYUWHOgJ8HX4IzCHifiS1n6eUMgtoTQOmSvTQDwSjD0WWJE8tWSYt+txXg1t+3A3tbZOFu7T442wE7DtMdUL4+8gimQS+e8PxDK1uTqIPUCAwEAAaMhMB8wHQYDVR0OBBYEFMCgo1gzCIcUThQIs5g5ikfv1D7eMA0GCSqGSIb3DQEBCwUAA4IBAQBnGw3i3hQ37L8vyelkyZMeO3tLK65Cqti4oVrQZxClGV5zNA6fIMDY8Mci1UhLwjzp29POd/sez0vuHZ/Vmmygzoye4jTKr6c3jAh0u81FTzefBU+vIietm9RuV3sd7D9xq6EqOY1NDL+rkvBcTFtiwLEUm2kHYu/U67jk73pxOtmqxQvQeMU8oi42tehMZGLIGp3U5lGS8YGGl+GtkkQ2Z5/PSm67HGP81kTArG/QX+bX+ykypTJVg9hfb9zOFQidp1HkCRIez6YhDiP/ZLurd6Grt/wVfZPNBO8EOgy25AkRZlp+UD686BFg7qq5KKEbz3qmPrj8deHL3duacZcp + + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + + + + + + + + + + + + + + + + + + + + + + + + + Register.it S.p.A. + Register.it S.p.A. + https//www.register.it + + + + + + + + + + + + + + khZostyVOFwCtkt5rHSLJ9UxgM6rKAR+7O+yLQ++5jI= + + + rnN5Omq7oWmuqqW13KbMr+taRMdqJ85W9+WpcWLX2Wsax26kTHBgD78vVfVWKuejMKeK6F8oSTkiipMlnGLXMniQplvI9rZJO3fj3ygG3qdwPCqFqJ7e9iYPZ5gIMjLuePyoAfcvSdAQiMBxeTX7nwjpLrzB51RaxGNTmJNJv44zbtdR++I1my8nSDRycq5o6+uR+k/SEOiR65+uQbiBvL9Or/N4sEoJyFx23AbQjurWiBzqgHwHPf8tDLBbDa8mjPhReXGK7aePymQU4GlSeZBxSHcSad04gQjlcgayp4d+O43SBczmtueV6szrAqURnhdj6L1PRvyusfNNk04bZA== + + + MIIINTCCBh2gAwIBAgIIJz+ujRbSAYwwDQYJKoZIhvcNAQENBQAwgfsxCzAJBgNV BAYTAklUMQ0wCwYDVQQHDARSb21lMSYwJAYDVQQKDB1BZ2VuemlhIHBlciBsJ0l0 YWxpYSBEaWdpdGFsZTEwMC4GA1UECwwnU2Vydml6aW8gQWNjcmVkaXRhbWVudG8g ZSBwcm9nZXR0byBTUElEMTwwOgYDVQQDDDNQcm9nZXR0byBTUElEIC0gR2VzdG9y aSBkaSBJZGVudGl0w6AgRGlnaXRhbGUgKElkUCkxKTAnBgkqhkiG9w0BCQEWGnBy b3RvY29sbG9AcGVjLmFnaWQuZ292Lml0MRowGAYDVQQFExFWQVRJVC05NzczNTAy MDU4NDAeFw0yMjA1MTAwMDAwMDBaFw0zMjA1MDkyMzU5NTlaMIGrMRowGAYDVQRh DBFWQVRJVC0wMTAzNTMxMDQxNDEcMBoGA1UEAwwTc3BpZC50ZWFtc3lzdGVtLmNv bTEaMBgGA1UECgwRVGVhbVN5c3RlbSBTLnAuQS4xKDAmBgNVBFMMH2h0dHBzOi8v c3BpZC50ZWFtc3lzdGVtLmNvbS9pZHAxCzAJBgNVBAYTAklUMQ8wDQYDVQQHDAZQ ZXNhcm8xCzAJBgNVBAgMAlBVMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEAyNJMgyn+iquzTvLR5Z/eYBfOoyJIfI3rYcj5WOSlTzlqXXBCzdcROm/JKgrf 3MOTEzH8RAn6XkSHXtJDtMpD7GlwYB0mo8scqDNtpszbhm/UXapJTrP7gy/UI3yf n99n4hvqkGOdld7w5vaAPS0w9PdcaRxY/7X4olHKBAx2cHAwiqhKuiFEDhfACRWs bw4gaIjVM7NuUtL/jG+PJV1NHrEn10vizE7IneMxDNqiQ14IjLL7pJMEPXwbXedz ZsModKKAXIX5reNSegEU1Y386BCkmg4IMWd+DglmMJ4uuzcga1AppgjDuqb8yFDa NOKy/0Jivh2rs7u9boE4cLVBPQIDAQABo4IDCTCCAwUwCQYDVR0TBAIwADAdBgNV HQ4EFgQU/q5NWlPmylmZTsX0C2MwZkrx3b4wHwYDVR0jBBgwFoAUyF8jl8Jbn9To hwSTF77f5QNJd18wDgYDVR0PAQH/BAQDAgbAMBEGA1UdEQQKMAiCBmlkcC5pdDAW BgNVHRIEDzANggtzcGlkLmdvdi5pdDA/BgNVHR8EODA2MDSgMqAwhi5odHRwczov L2VpZGFzLmFnaWQuZ292Lml0L2NybC9jcmxfU1BJRF9JZFAuY3JsMGoGCCsGAQUF BwEBBF4wXDBEBggrBgEFBQcwAoY4aHR0cDovL2VpZGFzLmFnaWQuZ292Lml0L2Nl cnRpZmljYXRpL1N1Yl9DQV9TUElEX0lkUC5jZXIwFAYIKwYBBQUHMAGGCGh0dHBz Oi8vMIIBzgYDVR0gBIIBxTCCAcEwCQYHBACORgEGAjCBlQYEK0wQBjCBjDBEBggr BgEFBQcCAjA4GjZFbGVjdHJvbmljIGNlcnRpZmljYXRlIGNvbmZvcm1pbmcgd2l0 aCBBR0lEIEd1aWRlbGluZXMwRAYIKwYBBQUHAgIwOBo2Q2VydGlmaWNhdG8gZWxl dHRyb25pY28gY29uZm9ybWUgYWxsZSBMaW5lZSBndWlkYSBBZ0lEMHIGBitMEAQB AjBoMDkGCCsGAQUFBwICMC0aK1NQSUQ6IGdlc3RvcmUgZGVsbGUgaWRlbnRpdOAg ZGlnaXRhbGkgKElkUCkwKwYIKwYBBQUHAgIwHxodU1BJRDogSWRlbnRpdHkgUHJv dmlkZXIgKElkUCkwCAYGBACPegEDME0GBCtMEAQwRTBDBggrBgEFBQcCARY3aHR0 cHM6Ly9laWRhcy5hZ2lkLmdvdi5pdC9jcHMvQWdJRF9lSURBU19yb290Q0FfY3Bz LnBkZjBPBgYEAI5GAQUwRTBDBggrBgEFBQcCARY3aHR0cHM6Ly9laWRhcy5hZ2lk Lmdvdi5pdC9jcHMvQWdJRF9lSURBU19yb290Q0FfY3BzLnBkZjANBgkqhkiG9w0B AQ0FAAOCAgEAG9XZeAkIuqSmYb6bq5WrcI2FQtVrfbMH1CXGDKytZUsH5phkGfk/ 8UaIfkbHhnWakM4H9J2gnvfhKorfMt2FHyXFFJ38hlWR8MhFziqthXLUxyLZpUMn h8CcNQyFpNz7xbZk/qN5yFfJyY4Rggm1qdgCNR1LsVI3hjuaORTAzvy4kLjfuU5r nVYPcxpHF7feJKlN03d8JRKYaIi5U+QVYtYJpTcE7jeYmn4Ewfry2BDCOsnljeYl gm3fF8EEVpMfHIhvJg8evATWmKWHpXL2BRtVrl7TfhvtWqKv4tLff+Lv2YqRpmYu oApA48/MB4QxwAPUBnmQb3CxVGs6OCbE/tdUfda9HuHP5MXYLtTVbRYu8pHEPnaN jPA8y90KRw2wiedgjgOG8BxOkhVF/cYs3yH+0hbPS5Oji27t0P2g9eG/p9TOy4AI gUykFimVFk6HV9znknrFSdgsePSp+T5zy45Jdi1z4/RgJN10szJfqEBuvd8MhUu4 meVgfDqXrqavCVzGpSLuicdk41sTOviBz+PEgbQ/qP9KHQv67SHoF4US9Pp9tkyj VFUs7lBnrlFAPpOzd97XdiZfotCA5umibqlxLshy4UK7yl2LZFllpxrfiXTCDASM KlMMIcIsWx0lU/qw5KPpqvXELiya791kohJTi+9pyG7LXIOHHA0whr0= + + + + + + https://www.spid.gov.it/SpidL1 + https://www.spid.gov.it/SpidL2 + + + P + LP + PG + PF + PX + + + + + + + MIIINTCCBh2gAwIBAgIIJz+ujRbSAYwwDQYJKoZIhvcNAQENBQAwgfsxCzAJBgNV BAYTAklUMQ0wCwYDVQQHDARSb21lMSYwJAYDVQQKDB1BZ2VuemlhIHBlciBsJ0l0 YWxpYSBEaWdpdGFsZTEwMC4GA1UECwwnU2Vydml6aW8gQWNjcmVkaXRhbWVudG8g ZSBwcm9nZXR0byBTUElEMTwwOgYDVQQDDDNQcm9nZXR0byBTUElEIC0gR2VzdG9y aSBkaSBJZGVudGl0w6AgRGlnaXRhbGUgKElkUCkxKTAnBgkqhkiG9w0BCQEWGnBy b3RvY29sbG9AcGVjLmFnaWQuZ292Lml0MRowGAYDVQQFExFWQVRJVC05NzczNTAy MDU4NDAeFw0yMjA1MTAwMDAwMDBaFw0zMjA1MDkyMzU5NTlaMIGrMRowGAYDVQRh DBFWQVRJVC0wMTAzNTMxMDQxNDEcMBoGA1UEAwwTc3BpZC50ZWFtc3lzdGVtLmNv bTEaMBgGA1UECgwRVGVhbVN5c3RlbSBTLnAuQS4xKDAmBgNVBFMMH2h0dHBzOi8v c3BpZC50ZWFtc3lzdGVtLmNvbS9pZHAxCzAJBgNVBAYTAklUMQ8wDQYDVQQHDAZQ ZXNhcm8xCzAJBgNVBAgMAlBVMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEAyNJMgyn+iquzTvLR5Z/eYBfOoyJIfI3rYcj5WOSlTzlqXXBCzdcROm/JKgrf 3MOTEzH8RAn6XkSHXtJDtMpD7GlwYB0mo8scqDNtpszbhm/UXapJTrP7gy/UI3yf n99n4hvqkGOdld7w5vaAPS0w9PdcaRxY/7X4olHKBAx2cHAwiqhKuiFEDhfACRWs bw4gaIjVM7NuUtL/jG+PJV1NHrEn10vizE7IneMxDNqiQ14IjLL7pJMEPXwbXedz ZsModKKAXIX5reNSegEU1Y386BCkmg4IMWd+DglmMJ4uuzcga1AppgjDuqb8yFDa NOKy/0Jivh2rs7u9boE4cLVBPQIDAQABo4IDCTCCAwUwCQYDVR0TBAIwADAdBgNV HQ4EFgQU/q5NWlPmylmZTsX0C2MwZkrx3b4wHwYDVR0jBBgwFoAUyF8jl8Jbn9To hwSTF77f5QNJd18wDgYDVR0PAQH/BAQDAgbAMBEGA1UdEQQKMAiCBmlkcC5pdDAW BgNVHRIEDzANggtzcGlkLmdvdi5pdDA/BgNVHR8EODA2MDSgMqAwhi5odHRwczov L2VpZGFzLmFnaWQuZ292Lml0L2NybC9jcmxfU1BJRF9JZFAuY3JsMGoGCCsGAQUF BwEBBF4wXDBEBggrBgEFBQcwAoY4aHR0cDovL2VpZGFzLmFnaWQuZ292Lml0L2Nl cnRpZmljYXRpL1N1Yl9DQV9TUElEX0lkUC5jZXIwFAYIKwYBBQUHMAGGCGh0dHBz Oi8vMIIBzgYDVR0gBIIBxTCCAcEwCQYHBACORgEGAjCBlQYEK0wQBjCBjDBEBggr BgEFBQcCAjA4GjZFbGVjdHJvbmljIGNlcnRpZmljYXRlIGNvbmZvcm1pbmcgd2l0 aCBBR0lEIEd1aWRlbGluZXMwRAYIKwYBBQUHAgIwOBo2Q2VydGlmaWNhdG8gZWxl dHRyb25pY28gY29uZm9ybWUgYWxsZSBMaW5lZSBndWlkYSBBZ0lEMHIGBitMEAQB AjBoMDkGCCsGAQUFBwICMC0aK1NQSUQ6IGdlc3RvcmUgZGVsbGUgaWRlbnRpdOAg ZGlnaXRhbGkgKElkUCkwKwYIKwYBBQUHAgIwHxodU1BJRDogSWRlbnRpdHkgUHJv dmlkZXIgKElkUCkwCAYGBACPegEDME0GBCtMEAQwRTBDBggrBgEFBQcCARY3aHR0 cHM6Ly9laWRhcy5hZ2lkLmdvdi5pdC9jcHMvQWdJRF9lSURBU19yb290Q0FfY3Bz LnBkZjBPBgYEAI5GAQUwRTBDBggrBgEFBQcCARY3aHR0cHM6Ly9laWRhcy5hZ2lk Lmdvdi5pdC9jcHMvQWdJRF9lSURBU19yb290Q0FfY3BzLnBkZjANBgkqhkiG9w0B AQ0FAAOCAgEAG9XZeAkIuqSmYb6bq5WrcI2FQtVrfbMH1CXGDKytZUsH5phkGfk/ 8UaIfkbHhnWakM4H9J2gnvfhKorfMt2FHyXFFJ38hlWR8MhFziqthXLUxyLZpUMn h8CcNQyFpNz7xbZk/qN5yFfJyY4Rggm1qdgCNR1LsVI3hjuaORTAzvy4kLjfuU5r nVYPcxpHF7feJKlN03d8JRKYaIi5U+QVYtYJpTcE7jeYmn4Ewfry2BDCOsnljeYl gm3fF8EEVpMfHIhvJg8evATWmKWHpXL2BRtVrl7TfhvtWqKv4tLff+Lv2YqRpmYu oApA48/MB4QxwAPUBnmQb3CxVGs6OCbE/tdUfda9HuHP5MXYLtTVbRYu8pHEPnaN jPA8y90KRw2wiedgjgOG8BxOkhVF/cYs3yH+0hbPS5Oji27t0P2g9eG/p9TOy4AI gUykFimVFk6HV9znknrFSdgsePSp+T5zy45Jdi1z4/RgJN10szJfqEBuvd8MhUu4 meVgfDqXrqavCVzGpSLuicdk41sTOviBz+PEgbQ/qP9KHQv67SHoF4US9Pp9tkyj VFUs7lBnrlFAPpOzd97XdiZfotCA5umibqlxLshy4UK7yl2LZFllpxrfiXTCDASM KlMMIcIsWx0lU/qw5KPpqvXELiya791kohJTi+9pyG7LXIOHHA0whr0= + + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + + + + + + + + + + + + + + + + + + + + + + + + + TeamSystem s.p.a. + TeamSystem s.p.a. + TeamSystem + TeamSystem + https://www.teamsystem.com + https://international.teamsystem.com/ww/ + + + \ No newline at end of file diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/AssertionSimpleClientTestUtils.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/AssertionSimpleClientTestUtils.java deleted file mode 100644 index baa87018..00000000 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/AssertionSimpleClientTestUtils.java +++ /dev/null @@ -1,170 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.spring; - -import static org.mockserver.model.HttpRequest.request; -import static org.mockserver.model.HttpResponse.response; - -import java.text.SimpleDateFormat; -import java.util.Date; -import org.mockserver.client.MockServerClient; -import org.mockserver.model.Header; - -public class AssertionSimpleClientTestUtils { - - public static final String RESPONSE_STRING = - "{\"response_xml\": \" " - + " https://posteid.poste.it" - + " " - + " " - + " " - + " " - + " " - + " " - + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" - + " " - + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" - + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" - + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" - + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" - + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " - + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" - + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" - + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" - + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" - + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" - + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" - + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" - + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" - + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" - + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" - + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" - + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" - + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" - + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" - + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" - + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" - + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" - + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" - + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" - + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" - + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" - + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" - + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" - + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" - + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" - + " " - + " " - + " " - + " https://posteid.poste.it " - + " " - + " " - + " " - + " " - + " " - + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" - + " " - + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" - + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" - + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" - + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" - + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " - + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" - + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" - + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" - + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" - + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" - + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" - + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" - + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" - + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" - + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" - + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" - + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" - + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" - + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" - + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" - + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" - + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" - + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" - + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" - + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" - + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" - + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" - + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" - + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" - + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" - + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" - + " " - + " " - + " " - + " " - + " https://app-backend.io.italia.it" - + " " - + " https://www.spid.gov.it/SpidL2" - + " " - + " TINIT-AAAAAA89S20I111X" - + " " - + " \"}"; - public static final String ASSERTION_REF = "sha256-_ZzL8qeuAM5kQ9pbMB4tn7IDSQZCVXAkW9fm4P7ULPI"; - public static final String WRONG_ASSERTION_REF = - "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfXXXXX"; - public static final String JWT = "aValidJWT"; - - public static void createExpectationAssertionFound() { - new MockServerClient("localhost", 3000) - .when( - request() - .withMethod("GET") - .withPath("/assertions/{assertion}") - .withPathParameter("assertion", ASSERTION_REF) - .withHeaders( - new Header("Accept", "application/json"), - new Header("x-pagopa-lollipop-auth", JWT))) - .respond(response().withStatusCode(200).withBody(RESPONSE_STRING)); - } - - public static void createExpectationAssertionNotFound() { - new MockServerClient("localhost", 2000) - .when( - request() - .withMethod("GET") - .withPath("/assertions/{assertion}") - .withPathParameter("assertion", WRONG_ASSERTION_REF) - .withHeaders( - new Header("Accept", "application/json"), - new Header("x-pagopa-lollipop-auth", JWT))) - .respond(response().withStatusCode(404).withBody("{}")); - } -} diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java index e665b819..76282702 100644 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/HttpVerifierHandlerInterceptorIntegrationTest.java @@ -1,13 +1,13 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.spring; +import static it.pagopa.tech.lollipop.consumer.spring.SimpleClientsTestUtils.*; import static org.mockserver.integration.ClientAndServer.startClientAndServer; -import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; -import it.pagopa.tech.lollipop.consumer.helper.LollipopConsumerFactoryHelper; -import it.pagopa.tech.lollipop.consumer.service.impl.MockAssertionVerifierService; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; import it.pagopa.tech.lollipop.consumer.spring.config.HttpVerifierConfiguration; import it.pagopa.tech.lollipop.consumer.spring.config.SpringLollipopConsumerRequestConfig; +import java.io.IOException; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -35,31 +35,35 @@ public class HttpVerifierHandlerInterceptorIntegrationTest { @LocalServerPort private int port; @Autowired private TestRestTemplate restTemplate; - @Autowired private LollipopConsumerFactoryHelper factoryHelper; + @Autowired private SpringLollipopConsumerRequestConfig springLollipopConsumerRequestConfig; + @Autowired private HttpVerifierHandlerInterceptor interceptor; + @Autowired private IdpCertSimpleClientConfig idpCertSimpleClientConfig; + + private static ClientAndServer mockServer; + + private static final String CONTENT_DIGEST = + "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"; + private static final String USER_ID = "GDNNWA12H81Y874F"; + private static final String SIGNATURE_INPUT = + "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + private static final String SIGNATURE = + "sig123=:6scl8sMzJdyG/OrnJXHRM9ajmIjrJ/zrLUDqvfOxj2h51DUKztTua3vR1kSUj/c/VT1ioDlt1QIMARABhquewg==:"; @BeforeAll public static void startServer() { - mockServer = startClientAndServer(3000); + mockServer = startClientAndServer(3000, 3001); } - private static ClientAndServer mockServer; - - @Autowired private HttpVerifierHandlerInterceptor interceptor; - @Test - void testWithValidRequestReturnsSuccess() { - AssertionSimpleClientTestUtils.createExpectationAssertionFound(); - factoryHelper.setAssertionVerifierService( - new MockAssertionVerifierService( - factoryHelper.getIdpCertProviderFactory().create(), - factoryHelper.getAssertionServiceFactory().create(), - LollipopConsumerRequestConfig.builder().build())); - - String signatureInput = - "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" - + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; - var signature = - "sig123=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + void testWithValidRequestReturnsSuccess() throws IOException { + SimpleClientsTestUtils.createExpectationAssertionFound(); + SimpleClientsTestUtils.createExpectationIdpFound(); + springLollipopConsumerRequestConfig.setAssertionNotBeforeDateFormat( + "yyyy-MM-dd'T'HH:mm:ss'Z'"); + springLollipopConsumerRequestConfig.setAssertionInstantDateFormat( + "yyyy-MM-dd'T'HH:mm:ss'Z'"); + idpCertSimpleClientConfig.setBaseUri("http://localhost:3001"); RestTemplate exec = restTemplate.getRestTemplate(); exec.getClientHttpRequestInitializers() @@ -67,30 +71,54 @@ void testWithValidRequestReturnsSuccess() { request -> { request.getHeaders() .add( - "Content-Digest", - "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"); + springLollipopConsumerRequestConfig + .getContentDigestHeader(), + CONTENT_DIGEST); + request.getHeaders() + .add( + springLollipopConsumerRequestConfig + .getOriginalURLHeader(), + springLollipopConsumerRequestConfig + .getExpectedFirstLcOriginalUrl()); + request.getHeaders() + .add( + springLollipopConsumerRequestConfig + .getOriginalMethodHeader(), + springLollipopConsumerRequestConfig + .getExpectedFirstLcOriginalMethod()); + request.getHeaders() + .add( + springLollipopConsumerRequestConfig + .getPublicKeyHeader(), + VALID_PUBLIC_KEY); + request.getHeaders() + .add( + springLollipopConsumerRequestConfig + .getAssertionRefHeader(), + ASSERTION_REF); + request.getHeaders() + .add( + springLollipopConsumerRequestConfig + .getAssertionTypeHeader(), + "SAML"); request.getHeaders() .add( - "x-pagopa-lollipop-original-url", - "https://api-app.io.pagopa.it/first-lollipop/sign"); - request.getHeaders().add("x-pagopa-lollipop-original-method", "POST"); + springLollipopConsumerRequestConfig.getAuthJWTHeader(), + JWT); request.getHeaders() .add( - "x-pagopa-lollipop-public-key", - "eyJrdHkiOiJFQyIsIngiOiJGcUZEd" - + "XdFZ3U0TVVYRVJQTVZMLTg1cEd2MkQzWW1MNEoxZ2ZNa2RiYzI0IiwieSI6Im" - + "hkVjBveG1XRlN4TW9KVURwZGlocjc2clM4VlJCRXFNRmViWXlBZks5LWsiLCJjcnYiO" - + "iJQLTI1NiJ9"); + springLollipopConsumerRequestConfig.getUserIdHeader(), + USER_ID); request.getHeaders() .add( - "x-pagopa-lollipop-assertion-ref", - "sha256-_ZzL8qeuAM5kQ9pbMB4tn7IDSQZCVXAkW9fm4P7ULPI"); - request.getHeaders().add("x-pagopa-lollipop-assertion-type", "SAML"); - request.getHeaders().add("x-pagopa-lollipop-auth-jwt", "aValidJWT"); + springLollipopConsumerRequestConfig + .getSignatureInputHeader(), + SIGNATURE_INPUT); request.getHeaders() - .add("x-pagopa-lollipop-user-id", "AAAAAA89S20I111X"); - request.getHeaders().add("Signature-Input", signatureInput); - request.getHeaders().add("Signature", signature); + .add( + springLollipopConsumerRequestConfig + .getSignatureHeader(), + SIGNATURE); }); ResponseEntity response = @@ -103,14 +131,8 @@ void testWithValidRequestReturnsSuccess() { } @Test - void testWithinvalidPayloadRequestReturnsUnauthorized() { - AssertionSimpleClientTestUtils.createExpectationAssertionFound(); - - String signatureInput = - "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" - + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; - var signature = - "sig123=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + void testWithInvalidPayloadRequestReturnsUnauthorized() throws IOException { + SimpleClientsTestUtils.createExpectationAssertionFound(); RestTemplate exec = restTemplate.getRestTemplate(); exec.getClientHttpRequestInitializers() @@ -118,30 +140,54 @@ void testWithinvalidPayloadRequestReturnsUnauthorized() { request -> { request.getHeaders() .add( - "Content-Digest", - "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"); + springLollipopConsumerRequestConfig + .getContentDigestHeader(), + CONTENT_DIGEST); + request.getHeaders() + .add( + springLollipopConsumerRequestConfig + .getOriginalURLHeader(), + springLollipopConsumerRequestConfig + .getExpectedFirstLcOriginalUrl()); + request.getHeaders() + .add( + springLollipopConsumerRequestConfig + .getOriginalMethodHeader(), + springLollipopConsumerRequestConfig + .getExpectedFirstLcOriginalMethod()); + request.getHeaders() + .add( + springLollipopConsumerRequestConfig + .getPublicKeyHeader(), + VALID_PUBLIC_KEY); + request.getHeaders() + .add( + springLollipopConsumerRequestConfig + .getAssertionRefHeader(), + ASSERTION_REF); + request.getHeaders() + .add( + springLollipopConsumerRequestConfig + .getAssertionTypeHeader(), + "SAML"); request.getHeaders() .add( - "x-pagopa-lollipop-original-url", - "https://api-app.io.pagopa.it/first-lollipop/sign"); - request.getHeaders().add("x-pagopa-lollipop-original-method", "POST"); + springLollipopConsumerRequestConfig.getAuthJWTHeader(), + JWT); request.getHeaders() .add( - "x-pagopa-lollipop-public-key", - "eyJrdHkiOiJFQyIsIngiOiJGcUZEd" - + "XdFZ3U0TVVYRVJQTVZMLTg1cEd2MkQzWW1MNEoxZ2ZNa2RiYzI0IiwieSI6Im" - + "hkVjBveG1XRlN4TW9KVURwZGlocjc2clM4VlJCRXFNRmViWXlBZks5LWsiLCJjcnYiO" - + "iJQLTI1NiJ9"); + springLollipopConsumerRequestConfig.getUserIdHeader(), + USER_ID); request.getHeaders() .add( - "x-pagopa-lollipop-assertion-ref", - "sha256-_ZzL8qeuAM5kQ9pbMB4tn7IDSQZCVXAkW9fm4P7ULPI"); - request.getHeaders().add("x-pagopa-lollipop-assertion-type", "SAML"); - request.getHeaders().add("x-pagopa-lollipop-auth-jwt", "aValidJWT"); + springLollipopConsumerRequestConfig + .getSignatureInputHeader(), + SIGNATURE_INPUT); request.getHeaders() - .add("x-pagopa-lollipop-user-id", "AAAAAA89S20I111X"); - request.getHeaders().add("Signature-Input", signatureInput); - request.getHeaders().add("Signature", signature); + .add( + springLollipopConsumerRequestConfig + .getSignatureHeader(), + SIGNATURE); }); ResponseEntity response = diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/SimpleClientsTestUtils.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/SimpleClientsTestUtils.java new file mode 100644 index 00000000..42b69912 --- /dev/null +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/SimpleClientsTestUtils.java @@ -0,0 +1,283 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.spring; + +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +import org.mockserver.client.MockServerClient; +import org.mockserver.model.Header; + +public class SimpleClientsTestUtils { + + public static final String VALID_ASSERTION_XML = + "{\"response_xml\": \"\\n" + + " https:\\/\\/spid-testenv2:8088<\\/saml:Issuer><\\/ds:Transforms>s\\/DqYePHC7eCXX5ncsiFYNLyKbzS6P5C8331H1b8e30=<\\/ds:DigestValue><\\/ds:Reference><\\/ds:SignedInfo>WcasorooElvhmK0kxFUdBVCqyRYi0SCNGRSZZnC9Q2sZHOYGZbERe4\\/T8OSuRKbSrEivXIHRgNr8WskZTM2CiywfWChHfGvhERsLuPJE8oh9CR3eicX\\/eg0ynJqwx4IoYhTb2NOwqMFc66nnutMhG\\/Smdtjs4SFz0RQYYVeZ5Ho51iTHd94uBV9ZHXjqcvs3EitUsJ0Zg1Pkw352tt8y7niUcGjAd8nydI72S12sF5ePv05AunFp7vZpYbKqi62fQLORCn1ZP7WKFD75hL0bCvZaSRF285GkfSnLfe1S4tLff2SlTQWevOMU\\/wCkHJmQwHT1LMwcWRnMvv4V+vd1XQ==<\\/ds:SignatureValue>MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR\\/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2\\/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI\\/sp\\n" + + "ILywgDxVMMtv\\/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAf\\n" + + "BgNVHSMEGDAWgBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH\\/MA0G\\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8\\/o13vMw4feGxro1hMeUilRtH52funrW\\n" + + "C+FgPrqk3o\\/8cZOnq+CqnFFDfILLiEb\\/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\n" + + "Da1fG\\/Pi0fG2F0yw\\/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk\\/ZbEHdKcofnziDyl0V8gglP2\\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n" + + "<\\/ds:X509Certificate><\\/ds:X509Data><\\/ds:KeyInfo><\\/ds:Signature>\\n" + + " \\n" + + " \\n" + + " <\\/samlp:Status>\\n" + + " \\n" + + " https:\\/\\/spid-testenv2:8088<\\/saml:Issuer><\\/ds:Transforms>4cqgG29TSKgNLy2\\/1eFPXhd5WRVPxZBGcd8DgTvd5Fo=<\\/ds:DigestValue><\\/ds:Reference><\\/ds:SignedInfo>WqxM+y+vtZDcEaIaw2WfcuMuwXUeTOY9ZjaXwzHw+RE8uUr5s8BE1tpaodcKmmqSJK1JQYNr8AUV+W9V79EKfmNtFvfaf0WYeUee7Td7E24QqiyVHjr1YgfDWhSdItFLYJfQUkotj2BepbdwVQGY5yN0Rw6Fq98hgNOgsxty7g6oqxG1OXB4WJ2He20iOoYWQl8ApxlbU\\/\\/hwnefFYe9ghDPy3rDbcNl3JetT07NR\\/+AzhKH4e+JCwKjTkdCBTW30fK4eiV9yBk74Lobip4hMaQhMaByl8egaU3A8AsnsZQuov2B6Wo2sDiQPjIulb8K3DOwFyL8PzEk8BB5YoAfwg==<\\/ds:SignatureValue>MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR\\/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2\\/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI\\/sp\\n" + + "ILywgDxVMMtv\\/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAf\\n" + + "BgNVHSMEGDAWgBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH\\/MA0G\\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8\\/o13vMw4feGxro1hMeUilRtH52funrW\\n" + + "C+FgPrqk3o\\/8cZOnq+CqnFFDfILLiEb\\/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\n" + + "Da1fG\\/Pi0fG2F0yw\\/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk\\/ZbEHdKcofnziDyl0V8gglP2\\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n" + + "<\\/ds:X509Certificate><\\/ds:X509Data><\\/ds:KeyInfo><\\/ds:Signature>\\n" + + " \\n" + + " id_48129c2a9d5e9077422591baf495747cfda668c5<\\/saml:NameID>\\n" + + " \\n" + + " \\n" + + " <\\/saml:SubjectConfirmation>\\n" + + " <\\/saml:Subject>\\n" + + " \\n" + + " \\n" + + " https:\\/\\/spid.agid.gov.it\\/cd<\\/saml:Audience>\\n" + + " <\\/saml:AudienceRestriction>\\n" + + " <\\/saml:Conditions>\\n" + + " \\n" + + " \\n" + + " " + + " https:\\/\\/www.spid.gov.it\\/SpidL2<\\/saml:AuthnContextClassRef>\\n" + + " <\\/saml:AuthnContext>\\n" + + " <\\/saml:AuthnStatement>\\n" + + " \\n" + + " \\n" + + " info@agid.gov.it<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " Mario<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " Bianchi<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " GDNNWA12H81Y874F<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " 1991-12-12<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " <\\/saml:AttributeStatement>\\n" + + " <\\/saml:Assertion>\\n" + + "<\\/samlp:Response>\"}"; + public static final String IDP_CLIENT_RESPONSE_STRING = + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + + " MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI/sp\n" + + "ILywgDxVMMtv/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA/L1/fd70ok+6xtDRF8A3HjAf\n" + + "BgNVHSMEGDAWgBQEVmzA/L1/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH/MA0G\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8/o13vMw4feGxro1hMeUilRtH52funrW\n" + + "C+FgPrqk3o/8cZOnq+CqnFFDfILLiEb/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\n" + + "Da1fG/Pi0fG2F0yw/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk/ZbEHdKcofnziDyl0V8gglP2\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " urn:oasis:names:tc:SAML:2.0:nameid-format:transient\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + public static final String ASSERTION_REF = "sha256-chG21HBOK-wJp2hHuYPrx7tAII2UGWVF-IFo0crUOtw"; + public static final String WRONG_ASSERTION_REF = + "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfXXXXX"; + public static final String JWT = "aValidJWT"; + public static final String VALID_PUBLIC_KEY = + "eyJrdHkiOiJFQyIsIngiOiJTaHlZa0ZyN1F3eE9rOE5BRXF6aklkTnc4dEVKODlZOVBlWFF1eVVOWDVjIiwieSI6InlULVJxNWc2VlVadENUd0ZnRExDM2RneGNuM2RsSmNGRjhnWGdxYWgyS0UiLCJjcnYiOiJQLTI1NiJ9"; + private static final String IDP_TAG = "latest"; + + public static void createExpectationAssertionFound() { + new MockServerClient("localhost", 3000) + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", JWT))) + .respond(response().withStatusCode(200).withBody(VALID_ASSERTION_XML)); + } + + public static void createExpectationAssertionNotFound() { + new MockServerClient("localhost", 2000) + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", WRONG_ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", JWT))) + .respond(response().withStatusCode(404).withBody("{}")); + } + + public static void createExpectationIdpFound() { + new MockServerClient("localhost", 3001) + .when(request().withMethod("GET").withPath("/idp-keys/spid")) + .respond(response().withStatusCode(200).withBody("[\"" + IDP_TAG + "\"]")); + new MockServerClient("localhost", 3001) + .when( + request() + .withMethod("GET") + .withPath("/idp-keys/spid/{tag}") + .withPathParameter("tag", IDP_TAG)) + .respond(response().withStatusCode(200).withBody(IDP_CLIENT_RESPONSE_STRING)); + } + + private SimpleClientsTestUtils() {} +} diff --git a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java index 201f80aa..c6ed5cbc 100644 --- a/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java +++ b/spring-impl/src/test/java/it/pagopa/tech/lollipop/consumer/spring/config/DemoServicesConfig.java @@ -42,7 +42,7 @@ public HttpMessageVerifierFactory httpMessageVerifierFactory() throws Exception public IdpCertProviderFactory idpCertProviderFactory() { return new IdpCertProviderFactoryImpl( new IdpCertSimpleClientProvider( - IdpCertSimpleClientConfig.builder().build(), + idpCertSimpleClientConfig(), new SimpleIdpCertStorageProvider(), new IdpCertStorageConfig())); } @@ -59,4 +59,9 @@ public AssertionServiceFactory assertionServiceFactory() { public StorageConfig storageConfig() { return new StorageConfig(); } + + @Bean + public IdpCertSimpleClientConfig idpCertSimpleClientConfig() { + return IdpCertSimpleClientConfig.builder().build(); + } } From 0d3b9d7d3f4d1484360c0e8b850479f64121a2a1 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 27 Apr 2023 12:04:30 +0200 Subject: [PATCH 302/403] [SLS-38] Introducing transcoding to valid format for ECSA Signature, to be used when in ASN.1 DER format --- gradle/verification-metadata.xml | 13 ++++++ http-verifier/build.gradle | 1 + .../visma/VismaHttpMessageVerifier.java | 38 +++++++++++++---- .../visma/VismaHttpMessageVerifierTest.java | 41 +++++++++++++++++++ 4 files changed, 86 insertions(+), 7 deletions(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 235af019..6a9e6fcb 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -5633,6 +5633,14 @@ + + + + + + + + @@ -5692,6 +5700,11 @@ + + + + + diff --git a/http-verifier/build.gradle b/http-verifier/build.gradle index cc4669c1..505068b6 100644 --- a/http-verifier/build.gradle +++ b/http-verifier/build.gradle @@ -56,6 +56,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.assertj:assertj-core:3.24.2' implementation 'com.nimbusds:nimbus-jose-jwt:9.31' + implementation 'org.slf4j:slf4j-api:2.0.5' implementation project(':core') } diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java index 296ecc76..fe5f30b7 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java @@ -2,6 +2,8 @@ package it.pagopa.tech.lollipop.consumer.http_verifier.visma; import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.JWSAlgorithm; +import com.nimbusds.jose.crypto.impl.ECDSA; import com.nimbusds.jose.jwk.JWK; import com.nimbusds.jose.jwk.KeyType; import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; @@ -16,14 +18,17 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; import net.visma.autopay.http.digest.DigestException; import net.visma.autopay.http.signature.*; +import net.visma.autopay.http.structured.StructuredBytes; /** * Implementation of the @HttpMessageVerifier using Visma-AutoPay http-signature of the * http-signature draft */ @AllArgsConstructor +@Slf4j public class VismaHttpMessageVerifier implements HttpMessageVerifier { String defaultEncoding; @@ -121,13 +126,6 @@ public boolean verifyHttpSignature( } } - var signatureContext = - SignatureContext.builder() - .headers(parameters) - .header("Signature-Input", signatureInputToProcess) - .header("Signature", signatureToProcess) - .build(); - /* Attempt to recover a valid key from the provided jwt */ PublicKey publicKey = null; try { @@ -135,6 +133,25 @@ public boolean verifyHttpSignature( KeyType keyType = jwk.getKeyType(); if (KeyType.EC.equals(keyType)) { publicKey = jwk.toECKey().toECPublicKey(); + try { + String[] signatureParts = signatureToProcess.split("=", 2); + String signatureValue = + StructuredBytes.of( + ECDSA.transcodeSignatureToConcat( + Base64.getMimeDecoder() + .decode( + signatureParts[1] + .getBytes()), + ECDSA.getSignatureByteArrayLength( + JWSAlgorithm.ES256))) + .toString(); + ECDSA.ensureLegalSignature( + Base64.getMimeDecoder().decode(signatureValue.getBytes()), + JWSAlgorithm.ES256); + signatureToProcess = signatureParts[0].concat("=").concat(signatureValue); + } catch (Exception e) { + log.debug("Could not convert EC signature to valid format"); + } } else if (KeyType.RSA.equals(keyType)) { publicKey = jwk.toRSAKey().toRSAPublicKey(); } @@ -144,6 +161,13 @@ public boolean verifyHttpSignature( "Missing Signature Algorithm"); } + var signatureContext = + SignatureContext.builder() + .headers(parameters) + .header("Signature-Input", signatureInputToProcess) + .header("Signature", signatureToProcess) + .build(); + /* Populate Visma Sign Validator*/ SignatureAlgorithm finalSignatureAlgorithm = signatureAlgorithm; PublicKey finalPublicKey = publicKey; diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java index 7872ffd2..ef1074b2 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java @@ -328,4 +328,45 @@ public void invalidLollipopMultipleSignatureWithLessInput() { .INVALID_SIGNATURE_NUMBER); }); } + + @Test + public void validLollipopSignatureCheckSingleEcdaSha256WithDer() { + + String signatureInput = + "sig1=(\"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1681473980;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-HiNolL87UYKQfaKISwIzyWY4swKPUzpaOWJCxaHy89M\""; + var signature = + "sig1=:MEUCIFiZHxuLhk2Jlt46E5kbB8hCx7fN7QeeAj2gaSK3Y+WzAiEAtggj3Jwu8RbTGdNmsDix2zymh0gKwKxoPlolL7j6VTg=:"; + + Map requestHeaders = + new HashMap<>( + Map.of( + "x-pagopa-lollipop-assertion-ref", + "sha256-HiNolL87UYKQfaKISwIzyWY4swKPUzpaOWJCxaHy89M", + "x-pagopa-lollipop-assertion-type", + "SAML", + "x-pagopa-lollipop-user-id", + "aFiscalCode", + "x-pagopa-lollipop-public-key", + "eyJrdHkiOiJFQyIsInkiOiJNdkVCMENsUHFnTlhrNVhIYm9xN1hZUnE2TnJTQkFTVmZhT2wzWnAxQmJzPSIsImNydiI6IlAtMjU2IiwieCI6InF6YTQzdGtLTnIrYWlTZFdNL0Q1cTdxMElmV3lZVUFIVEhSNng3dFByZEU9In0", + "x-pagopa-lollipop-auth-jwt", + "aValidJWT", + "x-pagopa-lollipop-original-method", + "POST", + "x-pagopa-lollipop-original-url", + "https://api-app.io.pagopa.it/first-lollipop/sign", + "content-digest", + "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:", + "Signature-Input", + signatureInput, + "Signature", + signature)); + + // execute & verify + assertThatNoException() + .isThrownBy( + () -> + vismaDigestVerifier.verifyHttpSignature( + signature, signatureInput, requestHeaders)); + } } From 530492cabf7d9e336f5c81403f46931e54da9726 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 27 Apr 2023 12:40:12 +0200 Subject: [PATCH 303/403] [SLS-38] Fixing code smells --- .../visma/VismaHttpMessageVerifier.java | 39 ++++++++++--------- .../visma/VismaHttpMessageVerifierTest.java | 2 +- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java index fe5f30b7..69c3fcb2 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java @@ -133,25 +133,7 @@ public boolean verifyHttpSignature( KeyType keyType = jwk.getKeyType(); if (KeyType.EC.equals(keyType)) { publicKey = jwk.toECKey().toECPublicKey(); - try { - String[] signatureParts = signatureToProcess.split("=", 2); - String signatureValue = - StructuredBytes.of( - ECDSA.transcodeSignatureToConcat( - Base64.getMimeDecoder() - .decode( - signatureParts[1] - .getBytes()), - ECDSA.getSignatureByteArrayLength( - JWSAlgorithm.ES256))) - .toString(); - ECDSA.ensureLegalSignature( - Base64.getMimeDecoder().decode(signatureValue.getBytes()), - JWSAlgorithm.ES256); - signatureToProcess = signatureParts[0].concat("=").concat(signatureValue); - } catch (Exception e) { - log.debug("Could not convert EC signature to valid format"); - } + signatureToProcess = transcodeSignature(signatureToProcess); } else if (KeyType.RSA.equals(keyType)) { publicKey = jwk.toRSAKey().toRSAPublicKey(); } @@ -195,4 +177,23 @@ public boolean verifyHttpSignature( return true; } + + private String transcodeSignature(String signatureToProcess) { + try { + String[] signatureParts = signatureToProcess.split("=", 2); + String signatureValue = + StructuredBytes.of( + ECDSA.transcodeSignatureToConcat( + Base64.getMimeDecoder() + .decode(signatureParts[1].getBytes()), + ECDSA.getSignatureByteArrayLength(JWSAlgorithm.ES256))) + .toString(); + ECDSA.ensureLegalSignature( + Base64.getMimeDecoder().decode(signatureValue.getBytes()), JWSAlgorithm.ES256); + signatureToProcess = signatureParts[0].concat("=").concat(signatureValue); + } catch (Exception e) { + log.debug("Could not convert EC signature to valid format"); + } + return signatureToProcess; + } } diff --git a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java index ef1074b2..0b856ae9 100644 --- a/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java +++ b/http-verifier/src/test/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifierTest.java @@ -330,7 +330,7 @@ public void invalidLollipopMultipleSignatureWithLessInput() { } @Test - public void validLollipopSignatureCheckSingleEcdaSha256WithDer() { + void validLollipopSignatureCheckSingleEcdaSha256WithDer() { String signatureInput = "sig1=(\"x-pagopa-lollipop-original-method\"" From 568c50d0c48917691bcb5bc852e5dc682f2c64a5 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 27 Apr 2023 12:58:05 +0200 Subject: [PATCH 304/403] [SLS-38] Applied spotless --- .../consumer/http_verifier/visma/VismaHttpMessageVerifier.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java index 95ee445f..05977f75 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java @@ -183,7 +183,7 @@ private String transcodeSignature(String signatureToProcess) { log.debug("Could not convert EC signature to valid format"); } return signatureToProcess; - } + } private static void isSignatureAlgorithmNotNull(SignatureAlgorithm signatureAlgorithm) throws LollipopSignatureException { From 1b82bc415e26e1222137fc394ea5ddd75fa1f627 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 27 Apr 2023 14:34:16 +0200 Subject: [PATCH 305/403] [1.0.0-RC1] Fixing code smells --- .../http_verifier/visma/VismaHttpMessageVerifier.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java index 05977f75..9dc66bc9 100644 --- a/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java +++ b/http-verifier/src/main/java/it/pagopa/tech/lollipop/consumer/http_verifier/visma/VismaHttpMessageVerifier.java @@ -210,14 +210,4 @@ private static void verifySignatureLength(String[] signatures, String[] signatur "Available signatures and signature-inputs differ in number"); } } - - private static PublicKey getPublicKey(JWK jwk, KeyType keyType) throws JOSEException { - PublicKey publicKey = null; - if (KeyType.EC.equals(keyType)) { - publicKey = jwk.toECKey().toECPublicKey(); - } else if (KeyType.RSA.equals(keyType)) { - publicKey = jwk.toRSAKey().toRSAPublicKey(); - } - return publicKey; - } } From 10d6765f14fe8a6260c2a30f205eeb059b01dcf9 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 27 Apr 2023 15:14:34 +0200 Subject: [PATCH 306/403] [rework_simple_assertion_storage] Updated SimpleAssertionStorage --- .../storage/SimpleAssertionStorage.java | 70 ++++++++++++------- .../storage/SimpleAssertionStorageTest.java | 11 +-- 2 files changed, 46 insertions(+), 35 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java index 2607df0d..e6d0b4f5 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java @@ -5,10 +5,7 @@ import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import java.lang.ref.SoftReference; import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.DelayQueue; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import javax.inject.Inject; @@ -30,12 +27,15 @@ public class SimpleAssertionStorage implements AssertionStorage { private AtomicInteger numberOfElements; private final StorageConfig storageConfig; + private Executor executor; + @Inject public SimpleAssertionStorage(StorageConfig storageConfig) { cache = new ConcurrentHashMap<>(); cleaningUpQueue = new DelayQueue<>(); initCleanerThread(); this.storageConfig = storageConfig; + executor = new ScheduledThreadPoolExecutor(1); numberOfElements = new AtomicInteger(0); } @@ -48,6 +48,7 @@ protected SimpleAssertionStorage( cleaningUpQueue = queue; initCleanerThread(); this.storageConfig = storageConfig; + executor = new ScheduledThreadPoolExecutor(1); numberOfElements = new AtomicInteger(0); } @@ -62,7 +63,12 @@ private void initCleanerThread() { this.cache.remove( delayedCacheObject.getKey(), delayedCacheObject.getReference()); - numberOfElements.decrementAndGet(); + CompletableFuture.supplyAsync( + () -> { + numberOfElements.decrementAndGet(); + return true; + }, + executor); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } @@ -89,7 +95,25 @@ public SamlAssertion getAssertion(String assertionRef) { return null; } - return Optional.ofNullable(cache.get(assertionRef)).map(SoftReference::get).orElse(null); + SamlAssertion samlAssertion = + Optional.ofNullable(cache.get(assertionRef)).map(SoftReference::get).orElse(null); + + if (samlAssertion != null) { + CompletableFuture.supplyAsync( + () -> { + cleaningUpQueue.removeIf( + cacheObject -> + cacheObject + .getKey() + .equals(samlAssertion.getAssertionRef())); + numberOfElements.decrementAndGet(); + saveAssertion(samlAssertion.getAssertionRef(), samlAssertion); + return true; + }, + executor); + } + + return samlAssertion; } /** @@ -116,28 +140,22 @@ public void saveAssertion(String assertionRef, SamlAssertion assertion) { } else { CompletableFuture.supplyAsync( () -> { - synchronized (numberOfElements) { - if (numberOfElements.get() >= storageConfig.getMaxNumberOfElements()) { - try { - cleaningUpQueue.take(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - long expiryTime = - System.currentTimeMillis() - + TimeUnit.MILLISECONDS.convert( - storageConfig.getStorageEvictionDelay(), - storageConfig - .getStorageEvictionDelayTimeUnit()); - SoftReference reference = new SoftReference<>(assertion); - cache.put(assertionRef, reference); - cleaningUpQueue.put( - new DelayedCacheObject<>(assertionRef, reference, expiryTime)); - numberOfElements.incrementAndGet(); + if (numberOfElements.get() >= storageConfig.getMaxNumberOfElements()) { + cleaningUpQueue.remove(); } + long expiryTime = + System.currentTimeMillis() + + TimeUnit.MILLISECONDS.convert( + storageConfig.getStorageEvictionDelay(), + storageConfig.getStorageEvictionDelayTimeUnit()); + SoftReference reference = new SoftReference<>(assertion); + cache.put(assertionRef, reference); + cleaningUpQueue.put( + new DelayedCacheObject<>(assertionRef, reference, expiryTime)); + numberOfElements.incrementAndGet(); return true; - }); + }, + executor); } } } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java index 982dc7e6..859d6090 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java @@ -79,19 +79,12 @@ void saveAssertionToMaximumCapacityWithStorageEnabled() sut = new SimpleAssertionStorage(assertionMap, delayedCacheObjects, storageConfigMock); SamlAssertion samlAssertion = new SamlAssertion(); - ExecutorService executor = Executors.newFixedThreadPool(10); - for (int i = 0; i < 101; i++) { - executor.submit(() -> sut.saveAssertion(ASSERTION_REF_1, samlAssertion)); + sut.saveAssertion(ASSERTION_REF_1 + i, samlAssertion); } - delayedCacheObjects.poll(100, TimeUnit.MILLISECONDS); + delayedCacheObjects.poll(150, TimeUnit.MILLISECONDS); assertEquals(100, delayedCacheObjects.size()); - assertEquals(samlAssertion, assertionMap.get(ASSERTION_REF_1).get()); - - // delayedCacheObjects.poll(1000, TimeUnit.MILLISECONDS); - // assertEquals(0, assertionMap.size()); - // assertEquals(0, delayedCacheObjects.size()); } @Test From 0b65731977a48cd4e52f1e807886764fa681096c Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 27 Apr 2023 16:36:18 +0200 Subject: [PATCH 307/403] [SLS-16] updated samples data and added idp mock configuration. updated build.gradle --- core/build.gradle | 1 - .../pagopa/tech/sample/ClientMocksConfig.java | 274 ++++++++++++++++++ .../pagopa/tech/sample/LollipopConstants.java | 41 +-- .../tech/sample/LollipopConsumerSample.java | 122 ++++---- samples/spring/build.gradle | 10 +- .../consumer/sample/SampleApplication.java | 32 -- .../config/AssertionMockServerConfig.java | 153 ++++++++++ .../sample/config/IdpMockServerConfig.java | 138 +++++++++ .../src/main/resources/application.properties | 6 + 9 files changed, 641 insertions(+), 136 deletions(-) create mode 100644 samples/simple/src/main/java/it/pagopa/tech/sample/ClientMocksConfig.java create mode 100644 samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/AssertionMockServerConfig.java create mode 100644 samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/IdpMockServerConfig.java diff --git a/core/build.gradle b/core/build.gradle index 2f887d00..915d7c5b 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -46,7 +46,6 @@ dependencies { implementation 'ch.qos.logback:logback-classic:1.4.6' implementation 'ch.qos.logback:logback-core:1.4.6' implementation 'org.codehaus.janino:janino:3.1.9' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.2' implementation 'org.apache.wss4j:wss4j-ws-security-common:2.4.1' implementation 'javax.servlet:javax.servlet-api:3.0.1' diff --git a/samples/simple/src/main/java/it/pagopa/tech/sample/ClientMocksConfig.java b/samples/simple/src/main/java/it/pagopa/tech/sample/ClientMocksConfig.java new file mode 100644 index 00000000..f6ad64f5 --- /dev/null +++ b/samples/simple/src/main/java/it/pagopa/tech/sample/ClientMocksConfig.java @@ -0,0 +1,274 @@ +package it.pagopa.tech.sample; + +import org.mockserver.client.MockServerClient; +import org.mockserver.model.Header; + +import static it.pagopa.tech.sample.LollipopConstants.*; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +public class ClientMocksConfig { + + public static final String VALID_ASSERTION_XML = + "{\"response_xml\": \"\\n" + + " https:\\/\\/spid-testenv2:8088<\\/saml:Issuer><\\/ds:Transforms>s\\/DqYePHC7eCXX5ncsiFYNLyKbzS6P5C8331H1b8e30=<\\/ds:DigestValue><\\/ds:Reference><\\/ds:SignedInfo>WcasorooElvhmK0kxFUdBVCqyRYi0SCNGRSZZnC9Q2sZHOYGZbERe4\\/T8OSuRKbSrEivXIHRgNr8WskZTM2CiywfWChHfGvhERsLuPJE8oh9CR3eicX\\/eg0ynJqwx4IoYhTb2NOwqMFc66nnutMhG\\/Smdtjs4SFz0RQYYVeZ5Ho51iTHd94uBV9ZHXjqcvs3EitUsJ0Zg1Pkw352tt8y7niUcGjAd8nydI72S12sF5ePv05AunFp7vZpYbKqi62fQLORCn1ZP7WKFD75hL0bCvZaSRF285GkfSnLfe1S4tLff2SlTQWevOMU\\/wCkHJmQwHT1LMwcWRnMvv4V+vd1XQ==<\\/ds:SignatureValue>MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR\\/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2\\/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI\\/sp\\n" + + "ILywgDxVMMtv\\/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAf\\n" + + "BgNVHSMEGDAWgBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH\\/MA0G\\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8\\/o13vMw4feGxro1hMeUilRtH52funrW\\n" + + "C+FgPrqk3o\\/8cZOnq+CqnFFDfILLiEb\\/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\n" + + "Da1fG\\/Pi0fG2F0yw\\/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk\\/ZbEHdKcofnziDyl0V8gglP2\\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n" + + "<\\/ds:X509Certificate><\\/ds:X509Data><\\/ds:KeyInfo><\\/ds:Signature>\\n" + + " \\n" + + " \\n" + + " <\\/samlp:Status>\\n" + + " \\n" + + " https:\\/\\/spid-testenv2:8088<\\/saml:Issuer><\\/ds:Transforms>4cqgG29TSKgNLy2\\/1eFPXhd5WRVPxZBGcd8DgTvd5Fo=<\\/ds:DigestValue><\\/ds:Reference><\\/ds:SignedInfo>WqxM+y+vtZDcEaIaw2WfcuMuwXUeTOY9ZjaXwzHw+RE8uUr5s8BE1tpaodcKmmqSJK1JQYNr8AUV+W9V79EKfmNtFvfaf0WYeUee7Td7E24QqiyVHjr1YgfDWhSdItFLYJfQUkotj2BepbdwVQGY5yN0Rw6Fq98hgNOgsxty7g6oqxG1OXB4WJ2He20iOoYWQl8ApxlbU\\/\\/hwnefFYe9ghDPy3rDbcNl3JetT07NR\\/+AzhKH4e+JCwKjTkdCBTW30fK4eiV9yBk74Lobip4hMaQhMaByl8egaU3A8AsnsZQuov2B6Wo2sDiQPjIulb8K3DOwFyL8PzEk8BB5YoAfwg==<\\/ds:SignatureValue>MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR\\/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2\\/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI\\/sp\\n" + + "ILywgDxVMMtv\\/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAf\\n" + + "BgNVHSMEGDAWgBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH\\/MA0G\\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8\\/o13vMw4feGxro1hMeUilRtH52funrW\\n" + + "C+FgPrqk3o\\/8cZOnq+CqnFFDfILLiEb\\/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\n" + + "Da1fG\\/Pi0fG2F0yw\\/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk\\/ZbEHdKcofnziDyl0V8gglP2\\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n" + + "<\\/ds:X509Certificate><\\/ds:X509Data><\\/ds:KeyInfo><\\/ds:Signature>\\n" + + " \\n" + + " id_48129c2a9d5e9077422591baf495747cfda668c5<\\/saml:NameID>\\n" + + " \\n" + + " \\n" + + " <\\/saml:SubjectConfirmation>\\n" + + " <\\/saml:Subject>\\n" + + " \\n" + + " \\n" + + " https:\\/\\/spid.agid.gov.it\\/cd<\\/saml:Audience>\\n" + + " <\\/saml:AudienceRestriction>\\n" + + " <\\/saml:Conditions>\\n" + + " \\n" + + " \\n" + + " " + + " https:\\/\\/www.spid.gov.it\\/SpidL2<\\/saml:AuthnContextClassRef>\\n" + + " <\\/saml:AuthnContext>\\n" + + " <\\/saml:AuthnStatement>\\n" + + " \\n" + + " \\n" + + " info@agid.gov.it<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " Mario<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " Bianchi<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " GDNNWA12H81Y874F<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " 1991-12-12<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " <\\/saml:AttributeStatement>\\n" + + " <\\/saml:Assertion>\\n" + + "<\\/samlp:Response>\"}"; + public static final String IDP_CLIENT_RESPONSE_STRING = + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + + " MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI/sp\n" + + "ILywgDxVMMtv/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA/L1/fd70ok+6xtDRF8A3HjAf\n" + + "BgNVHSMEGDAWgBQEVmzA/L1/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH/MA0G\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8/o13vMw4feGxro1hMeUilRtH52funrW\n" + + "C+FgPrqk3o/8cZOnq+CqnFFDfILLiEb/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\n" + + "Da1fG/Pi0fG2F0yw/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk/ZbEHdKcofnziDyl0V8gglP2\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " urn:oasis:names:tc:SAML:2.0:nameid-format:transient\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + + private static final String LOCALHOST = "localhost"; + + public static MockServerClient createExpectationAssertionFound() { + MockServerClient mockServerClient = new MockServerClient(LOCALHOST, 3000); + mockServerClient + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", VALID_ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", VALID_JWT))) + .respond(response().withStatusCode(200).withBody(VALID_ASSERTION_XML)); + return mockServerClient; + } + + public static MockServerClient createExpectationIdpTagsFound() { + MockServerClient mockServerClient = new MockServerClient(LOCALHOST, 3001); + mockServerClient + .when(request().withMethod("GET").withPath("/idp-keys/spid")) + .respond(response().withStatusCode(200).withBody("[\"" + IDP_TAG + "\"]")); + return mockServerClient; + } + + public static MockServerClient createExpectationIdpDataFound() { + MockServerClient mockServerClient = new MockServerClient(LOCALHOST, 3001); + mockServerClient + .when( + request() + .withMethod("GET") + .withPath("/idp-keys/spid/{tag}") + .withPathParameter("tag", IDP_TAG)) + .respond(response().withStatusCode(200).withBody(IDP_CLIENT_RESPONSE_STRING)); + return mockServerClient; + } + + private ClientMocksConfig() {} +} diff --git a/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConstants.java b/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConstants.java index d9bda442..14ae54d8 100644 --- a/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConstants.java +++ b/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConstants.java @@ -1,49 +1,33 @@ package it.pagopa.tech.sample; public class LollipopConstants { - public static final String CONTENT_DIGEST = "content-digest"; - public static final String CONTENT_ENCODING = "content-encoding"; - public static final String SIGNATURE_INPUT = "signature-input"; - public static final String SIGNATURE = "signature"; - - public static final String LOLLIPOP_KEY = "x-pagopa-lollipop-public-key"; - - public static final String LOLLIPOP_ORIGIN_METHOD = "x-pagopa-lollipop-original-method"; - - public static final String LOLLIPOP_ORIGIN_URL = "x-pagopa-lollipop-original-url"; - - public static final String EXPECTED_ORIGIN_METHOD = "POST"; - public static final String EXCPECTED_ORIGIN_URL = "https://api-app.io.pagopa.it/first-lollipop/sign"; public static final String VALID_ENCODING_UTF8 = "UTF-8"; public static final String INVALID_ENCODING_UTF_326 = "UTF-326"; public static final String VALID_CONTENT_DIGEST = "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"; public static final String INVALID_CONTENT_DIGEST = "sha-256=:fadsfeagsdage76ad564=:"; public static final String VALID_MESSAGE_PAYLOAD = "{\"message\":\"a valid message payload\"}"; public static final String INVALID_MESSAGE_PAYLOAD = "{\"message\":\"an invalid message payload\"}"; - public static final String SIGNATURE_HEADER_VALUE = "sig123=:lTuoRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + public static final String SIGNATURE_HEADER_VALUE = "sig123=:6scl8sMzJdyG/OrnJXHRM9ajmIjrJ/zrLUDqvfOxj2h51DUKztTua3vR1kSUj/c/VT1ioDlt1QIMARABhquewg==:"; public static final String INVALID_SIGNATURE_HEADER_VALUE = "sig123=:lTTTRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; public static final String SIGNATURE_INPUT_HEADER_VALUE = "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; - public static final String ECDSA_LOLLIPOP_JWT_KEY = "eyJrdHkiOiJFQyIsIngiOiJGcUZEd" - + "XdFZ3U0TVVYRVJQTVZMLTg1cEd2MkQzWW1MNEoxZ2ZNa2RiYzI0IiwieSI6Im" - + "hkVjBveG1XRlN4TW9KVURwZGlocjc2clM4VlJCRXFNRmViWXlBZks5LWsiLCJjcnYiO" - + "iJQLTI1NiJ9"; + public static final String ECDSA_LOLLIPOP_JWT_KEY = "eyJrdHkiOiJFQyIsIngiOiJTaHlZa0ZyN1F3eE9rOE5BRXF6aklkTnc4dEVKODlZOVBlWFF1eVVOWDVjIiwieSI6InlULVJxNWc2VlVadENUd0ZnRExDM2RneGNuM2RsSmNGRjhnWGdxYWgyS0UiLCJjcnYiOiJQLTI1NiJ9"; - public static String VALID_MULTI_ECDSA_IGNATURE_INPUT = + public static final String VALID_MULTI_ECDSA_SIGNATURE_INPUT = "sig1=(\"x-io-sign-qtspclauses\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\"," + " sig2=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + " \"x-pagopa-lollipop-original-url\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; - public static String VALID_MULTI_ECDSA_SIGNATURE = - "sig1=:dncsEeKERA9wzxBO0vbPIueMK7Izk4zZNX4D0jI+t17XQJ5YrhumR3MGvMiyarb+B8MPqn+rbOJwZt6dV+oXFA==:," - + " sig2=:nbmFduqX8AdhXzqkFX+UIvicn3ZV5yZXqUO+3bceOT8WFPXRTVRcoOcjF+0+W5KLihAZjSW5GXSgCxVVEW8pqQ==:"; + public static final String VALID_MULTI_ECDSA_SIGNATURE = + "sig1=:skaKScZj5n/mjhSUIbSadKvFnQze5+RihZlIwSdXsNrdtK07nek5fyZ4+8P8o6H9zPyyNj2Qc5HarO+lqg3UUQ==:," + + "sig2=:6scl8sMzJdyG/OrnJXHRM9ajmIjrJ/zrLUDqvfOxj2h51DUKztTua3vR1kSUj/c/VT1ioDlt1QIMARABhquewg==:"; - public static String VALID_RSA_PSS_SIGNATURE_INPUT = + public static final String VALID_RSA_PSS_SIGNATURE_INPUT = "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + " \"x-pagopa-lollipop-original-url\");created=1678814391;nonce=\"aNonce\";" + "alg=\"rsa-pss-sha256\";keyid=\"sha256-A3OhKGLYwSvdJ2txHi_SGQ3G-sHLh2Ibu91ErqFx_58\""; - public static String VALID_RSA_PSS_SIGNATURE = + public static final String VALID_RSA_PSS_SIGNATURE = "sig1=:q3Og7m8yL18HkrY+zgV92Gj05lrWaFMIEFSPg2PEnO5a46+2Tt/2n7kjqVaGjI1ZXtys+Wyh3cVXCdda" + "dNARizt0BpCRdT9S4r48xsGO79Ucq4IFwZyyHNudKu5WSH4/55j5yX/YmeCtH+Nt6Nun02OZynn3iQwg" + "LJB+CGe3h6X02iSvl4wJjKaMGE64RFHa5osE4MctoPD1j0tRkcOtgwrGmFMr282Kqrkabbx1vUpmO9T1k" + @@ -58,10 +42,11 @@ public class LollipopConstants { + "k2YURaSjdBOEx6bzBLU3kgIFpZb0E0ODVtcWNPMEdWQWRWdzlscTRhT1Q5djZkLW5iNGJuTmtRVmtsTFE" + "zZlZBdkptLXhkRE9wOUxDTkNONDhWICAycG5ET2tGVjYtVTluVjVveWM2WEkydyJ9"; - public static final String VALID_ASSERTION_REF = - "sha256-_ZzL8qeuAM5kQ9pbMB4tn7IDSQZCVXAkW9fm4P7ULPI"; - public static final String VALID_FISCAL_CODE = "AAAAAA89S20I111X"; + public static final String VALID_ASSERTION_REF = "sha256-chG21HBOK-wJp2hHuYPrx7tAII2UGWVF-IFo0crUOtw"; + public static final String VALID_FISCAL_CODE = "GDNNWA12H81Y874F"; public static final String VALID_JWT = "aValidJWT"; - public LollipopConstants() {} + public static final String IDP_TAG = "latest"; + + private LollipopConstants() {} } diff --git a/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java b/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java index 8ebab761..3cb43e5f 100644 --- a/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java +++ b/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java @@ -22,20 +22,14 @@ import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerServiceFactory; import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerServiceFactory; -import it.pagopa.tech.lollipop.consumer.model.CommandResult; import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; import it.pagopa.tech.lollipop.consumer.service.impl.LollipopConsumerRequestValidationServiceImpl; import org.mockserver.client.MockServerClient; import org.mockserver.integration.ClientAndServer; -import org.mockserver.model.Header; -import java.text.SimpleDateFormat; -import java.util.Date; import java.util.HashMap; import static it.pagopa.tech.sample.LollipopConstants.*; -import static org.mockserver.model.HttpRequest.request; -import static org.mockserver.model.HttpResponse.response; public class LollipopConsumerSample { @@ -43,55 +37,63 @@ public class LollipopConsumerSample { private static LollipopConsumerRequestConfig lollipopConsumerRequestConfig; public static void main(String[] args) throws Exception { - ClientAndServer clientAndServer = ClientAndServer.startClientAndServer(3000); - MockServerClient mockServerClient = createExpectationAssertionFound(); - LollipopConsumerFactoryHelper lollipopConsumerFactoryHelper = buildLollipopConsumerFactoryHelper(); - lollipopConsumerFactoryHelper.setAssertionVerifierService(new MockAssertionVerifierService( - lollipopConsumerFactoryHelper.getIdpCertProviderFactory().create(), - lollipopConsumerFactoryHelper.getAssertionServiceFactory().create(), LollipopConsumerRequestConfig.builder().build())); - LollipopConsumerCommandBuilder commandBuilder = new LollipopConsumerCommandBuilderImpl(lollipopConsumerFactoryHelper); - - commandBuilder.createCommand(buildLollipopRequest( - VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, - SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)) - .doExecute(); - - commandBuilder.createCommand(buildLollipopRequest( - INVALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, - SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)).doExecute(); - - commandBuilder.createCommand(buildLollipopRequest( - VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, INVALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, - SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)).doExecute(); - - commandBuilder.createCommand(buildLollipopRequest( - VALID_CONTENT_DIGEST, INVALID_ENCODING_UTF_326, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, - SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)).doExecute(); - - commandBuilder.createCommand(buildLollipopRequest( - VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, - SIGNATURE_INPUT_HEADER_VALUE, INVALID_SIGNATURE_HEADER_VALUE)).doExecute(); - - commandBuilder.createCommand(buildLollipopRequest( - VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, - VALID_MULTI_ECDSA_IGNATURE_INPUT, VALID_MULTI_ECDSA_SIGNATURE)).doExecute(); - - commandBuilder.createCommand(buildLollipopRequest( - VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, - LOLLIPOP_RSA_PUBKEY, VALID_RSA_PSS_SIGNATURE_INPUT, VALID_RSA_PSS_SIGNATURE)).doExecute(); - - clientAndServer.close(); - mockServerClient.close(); - return; + try (ClientAndServer clientAndServer = ClientAndServer.startClientAndServer(3000, 3001); + MockServerClient mockServerClientAssertion = ClientMocksConfig.createExpectationAssertionFound(); + MockServerClient mockServerClientIdpTag = ClientMocksConfig.createExpectationIdpTagsFound(); + MockServerClient mockServerClientIdpData = ClientMocksConfig.createExpectationIdpDataFound()) { + + LollipopConsumerFactoryHelper lollipopConsumerFactoryHelper = buildLollipopConsumerFactoryHelper(); + LollipopConsumerCommandBuilder commandBuilder = new LollipopConsumerCommandBuilderImpl(lollipopConsumerFactoryHelper); + + // Success + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)) + .doExecute(); + + // Request with invalid content digest + commandBuilder.createCommand(buildLollipopRequest( + INVALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)).doExecute(); + + // Request with invalid message payload + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, INVALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)).doExecute(); + + // Request with invalid encoding + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, INVALID_ENCODING_UTF_326, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)).doExecute(); + + // Request with invalid signature + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, INVALID_SIGNATURE_HEADER_VALUE)).doExecute(); + + // Success with multi signature + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + VALID_MULTI_ECDSA_SIGNATURE_INPUT, VALID_MULTI_ECDSA_SIGNATURE)).doExecute(); + + // thumbprint validation failed + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, + LOLLIPOP_RSA_PUBKEY, VALID_RSA_PSS_SIGNATURE_INPUT, VALID_RSA_PSS_SIGNATURE)).doExecute(); + + } } private static LollipopConsumerFactoryHelper buildLollipopConsumerFactoryHelper() throws Exception { - lollipopConsumerRequestConfig = new LollipopConsumerRequestConfig(); + lollipopConsumerRequestConfig = LollipopConsumerRequestConfig.builder() + .assertionNotBeforeDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") + .assertionInstantDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") + .build(); HttpMessageVerifierFactory messageVerifierFactory = new VismaHttpMessageVerifierFactory(VALID_ENCODING_UTF8, LollipopConsumerRequestConfig.builder().build()); AssertionStorageProvider assertionStorageProvider = new SimpleAssertionStorageProvider(); IdpCertProviderFactory idpCertProviderFactory = new IdpCertProviderFactoryImpl( - new IdpCertSimpleClientProvider(IdpCertSimpleClientConfig.builder().build(), + new IdpCertSimpleClientProvider(IdpCertSimpleClientConfig.builder().baseUri("http://localhost:3001").build(), new SimpleIdpCertStorageProvider(), new IdpCertStorageConfig())); AssertionClientProvider assertionClientProvider = new AssertionSimpleClientProvider(AssertionSimpleClientConfig.builder().build()); @@ -115,8 +117,8 @@ private static LollipopConsumerRequest buildLollipopRequest( lollipopHeaderParams.put(lollipopConsumerRequestConfig.getSignatureInputHeader(), signatureInput); lollipopHeaderParams.put(lollipopConsumerRequestConfig.getSignatureHeader(), signature); lollipopHeaderParams.put(lollipopConsumerRequestConfig.getPublicKeyHeader(), lollipopKey); - lollipopHeaderParams.put(lollipopConsumerRequestConfig.getOriginalMethodHeader(), EXPECTED_ORIGIN_METHOD); - lollipopHeaderParams.put(lollipopConsumerRequestConfig.getOriginalURLHeader(), EXCPECTED_ORIGIN_URL); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getOriginalMethodHeader(), lollipopConsumerRequestConfig.getExpectedFirstLcOriginalMethod()); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getOriginalURLHeader(), lollipopConsumerRequestConfig.getExpectedFirstLcOriginalUrl()); lollipopHeaderParams.put("X-io-sign-qtspclauses","anIoSignClauses"); lollipopHeaderParams.put(lollipopConsumerRequestConfig.getAssertionRefHeader(), VALID_ASSERTION_REF); lollipopHeaderParams.put(lollipopConsumerRequestConfig.getAssertionTypeHeader(), "SAML"); @@ -129,24 +131,4 @@ private static LollipopConsumerRequest buildLollipopRequest( .headerParams(lollipopHeaderParams) .build(); } - - private static String buildMessage(CommandResult commandResult, String s) { - return s + commandResult.getResultCode() + " and message: " + commandResult.getResultMessage(); - } - - private static MockServerClient createExpectationAssertionFound() { - String RESPONSE_STRING = "{\"response_xml\": \" " + " https://posteid.poste.it" + " " + " " + " " + " " + " " + " " + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" + " " + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + " " + " " + " " + " https://posteid.poste.it " + " " + " " + " " + " " + " " + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" + " " + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + " " + " " + " " + " " + " https://app-backend.io.italia.it" + " " + " https://www.spid.gov.it/SpidL2" + " " + " TINIT-AAAAAA89S20I111X" + " " + " \"}"; - - MockServerClient mockServerClient = new MockServerClient("localhost", 3000); - mockServerClient.when( - request() - .withMethod("GET") - .withPath("/assertions/{assertion}") - .withPathParameter("assertion", VALID_ASSERTION_REF) - .withHeaders( - new Header("Accept", "application/json"), - new Header("x-pagopa-lollipop-auth", VALID_JWT))) - .respond(response().withStatusCode(200).withBody(RESPONSE_STRING)); - return mockServerClient; - } } diff --git a/samples/spring/build.gradle b/samples/spring/build.gradle index 242f7897..0d766de3 100644 --- a/samples/spring/build.gradle +++ b/samples/spring/build.gradle @@ -35,11 +35,11 @@ repositories { } dependencies { - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:core:1.0.0-SNAPSHOT' - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:assertion-rest-client-native:1.0.0-SNAPSHOT' - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:identity-service-rest-client-native:1.0.0-SNAPSHOT' - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:http-verifier:1.0.0-SNAPSHOT' - implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:spring-impl:1.0.0-SNAPSHOT' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:core:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:assertion-rest-client-native:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:identity-service-rest-client-native:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:http-verifier:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:spring-impl:1.0.0-RC1' implementation 'org.mock-server:mockserver-netty:5.15.0' implementation 'org.springframework.boot:spring-boot-starter-web' diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java index 9a9ec6a1..dae8bbf8 100644 --- a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/SampleApplication.java @@ -1,44 +1,12 @@ package it.pagopa.tech.lollipop.consumer.sample; -import it.pagopa.tech.lollipop.consumer.spring.config.HttpVerifierConfiguration; -import it.pagopa.tech.lollipop.consumer.spring.config.SpringLollipopConsumerRequestConfig; -import org.mockserver.client.MockServerClient; -import org.mockserver.integration.ClientAndServer; -import org.mockserver.model.Header; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.properties.EnableConfigurationProperties; - -import java.text.SimpleDateFormat; -import java.util.Date; - -import static org.mockserver.model.HttpRequest.request; -import static org.mockserver.model.HttpResponse.response; @SpringBootApplication(scanBasePackages = "it.pagopa.tech") public class SampleApplication { public static void main(String[] args) { SpringApplication.run(SampleApplication.class, args); - //createExpectationAssertionFound(); - } - - private static void createExpectationAssertionFound() { - String ASSERTION_REF = "sha256-_ZzL8qeuAM5kQ9pbMB4tn7IDSQZCVXAkW9fm4P7ULPI"; - String JWT = "aValidJWT"; - String RESPONSE_STRING = "{\"response_xml\": \" " + " https://posteid.poste.it" + " " + " " + " " + " " + " " + " " + " IYCwE8NJNGLAGdL8zA/W/kuTLdlHMMXMeP2hei8LYqU=" + " " + " GI9CwzYfcmTBE9Lf7Hvqr2bgCkfbuq6vZPwZaaCmxq5cicDf7+k6TYussUx147iAdngl4vMixAjA" + " eABU0cSrZllLW0Gqxm+EPvylwMc4O1tNYlpvjnZzW7PIRns5M22KSzfHBDdGZG7Dq4uDHVbGCENu" + " TV5UaGNQJ2sNTD95Qaz6pmQtx0guehDc/m5ldFvChqZTKrOcVu+qTRFkW+OabbnkmKXPSWpTN9WE" + " 4RramWgWkNE/sn4z0Rwmnei8oEhcBKSpOMrenbMgpCYjoRto5lDGGJrMkeKsJ1PzD1ZCrE/GkzX9" + " HtXHIaYE6cZ7vBXQh4SVpl26JGQ87tu2YLeoZw== " + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + " " + " " + " " + " https://posteid.poste.it " + " " + " " + " " + " " + " " + " ViSjPfKj683dCuO7FdSzbQjw+vECYfoxgTeiVSgxr+I=" + " " + " O9lmrtHPudDz2fzzNH3DQxWy2rlXE56G54Siq7OPMYwps/cyo3wKo7+PwMJYNhhz1l57OYJ5e/MF" + " ctVtYyl2rWo3QZOidWhg8WINIEqtFXIpk+ht5i2t3P1132/iL/gnY+fgemhnbOV/otEspHA4Wsio" + " I8xWjekAFlHBTOTtO9vzzqTtf+yalf+6pZmRLtOYrMMV4W3QZ2oLr7C2vTgcl5eVXJyGf0U8Y2bf" + " 7OPRHJNnVs4S8ztWQEwqZLFA1SvyCx1Nx6f+xd9lT7Lo1h81MRMdvRTk3rAaWYaqAmU9mxVnzsw4" + " xaLjxR4rE2drY3eb+O8uHZbzFlOhPtaINRPILg== " + " MIIFgzCCA2ugAwIBAgIIJSppAZKg/XQwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCSVQxHjAc" + " BgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEaMBgGA1UEYQwRVkFUSVQtMDExMTQ2MDEwMDYx" + " GjAYBgNVBAMMEVBvc3RlIEl0YWxpYW5lIENBMB4XDTIxMDIxODExNDYzMVoXDTI0MDIxOTExNDYz" + " MVowQzELMAkGA1UEBhMCSVQxHjAcBgNVBAoMFVBvc3RlIEl0YWxpYW5lIFMucC5BLjEUMBIGA1UE" + " AwwLaWRwLXBvc3RlaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZFEtJoEHFAjpC" + " aZcj5DVWrRDyaLZyu31XApslbo87CyWz61OJMtw6QQU0MdCtrYbtSJ6vJwx7/6EUjsZ3u4x3EPLd" + " lkyiGOqukPwATv4c7TVOUVs5onIqTphM9b+AHRg4ehiMGesm/9d7RIaLuN79iPUvdLn6WP3idAfE" + " w+rhJ/wYEQ0h1Xm5osNUgtWcBGavZIjLssWNrDDfJYxXH3QZ0kI6feEvLCJwgjXLGkBuhFehNhM4" + " fhbX9iUCWwwkJ3JsP2++Rc/iTA0LZhiUsXNNq7gBcLAJ9UX2V1dWjTzBHevfHspzt4e0VgIIwbDR" + " qsRtF8VUPSDYYbLoqwbLt18XAgMBAAGjggFXMIIBUzA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH" + " MAGGI2h0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQvcGktb2NzcENBMB0GA1UdDgQWBBRL64pGUJHw" + " Y7ok6cRMUgXvMBoLMjAfBgNVHSMEGDAWgBRs0025F7hHd0d+ULyAaELPZ7w/eTA+BgNVHSAENzA1" + " MDMGCCtMMAEFAQEEMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wb3N0ZWNlcnQucG9zdGUuaXQwOAYD" + " VR0fBDEwLzAtoCugKYYnaHR0cDovL3Bvc3RlY2VydC5wb3N0ZS5pdC9waS1DQS9jcmwuY3JsMA4G" + " A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwJwYDVR0RBCAwHoEc" + " aWRwLXBvc3RlaWRAcG9zdGVpdGFsaWFuZS5pdDANBgkqhkiG9w0BAQsFAAOCAgEAp0EhITlTx+cO" + " aoXw//nBl6Q4y82MfSGfPJIw3ROV1z3tHBctaksi/RxAzyMD5beO2s8Q6lXx0sLMCcuUQmzHj3eJ" + " bqn+6sIUr000dSlX/iPgVUc2dvPIZZg9xu38J8NvCfrtgAGY5iMVFMd3CZLFw0ybr+Bx/1K/NhQO" + " 7jxn0RSGA1J4mM2syVhEDUODs9kz3T4kXYUofwwvPL1a9xB9RBqbp7plYtbBBdftEORUQrWzH1mz" + " NO4nlFkX9qgVrgFIIJJT2KadHoop1r65O9ffncK14qpNo3eTsNDq3hRlteb7ylmlJ8CoakUWZeXD" + " DP9ZboWxZkyp+9903OrToRvOgeWSc+YrqcRZOv7r6tTALTk4U9OTKDG9/eNWSGQqD7Qd/9rssfF0" + " uJEGHnbsk/Hvdxn8apgWN1Zwt6tsT7f/DO0Pdlaso9g7PVy8R+B3VkWAh76uCcICIPFBluC/ljaH" + " V8hI+VsCLpMClo83YMCEM6E6nAPD22+fDR/DF9P73P04yUvJVHx4cnHPrpxVrPbaJoKrr9mUOLFy" + " VRekX78ZRgiFiKYDNsiq9+148oRy+VehpmBoQ+T2EPeDFQ8JJ4xT8H7qdyr1swSk/9Lu4K0kw/yC" + " TSb9K/wCuiHiuoSB54rzJoQxz90gS868r/+JGahYwHY5dUh1RbA4g5N8H3TDThc=" + " SPID-d4de186b-e103-4b39-8209-0bccc7b1acdd" + " " + " " + " " + " " + " https://app-backend.io.italia.it" + " " + " https://www.spid.gov.it/SpidL2" + " " + " TINIT-AAAAAA89S20I111X" + " " + " \"}"; - - ClientAndServer.startClientAndServer(3000); - new MockServerClient("localhost", 3000) - .when( - request() - .withMethod("GET") - .withPath("/assertions/{assertion}") - .withPathParameter("assertion", ASSERTION_REF) - .withHeaders( - new Header("Accept", "application/json"), - new Header("x-pagopa-lollipop-auth", JWT))) - .respond(response().withStatusCode(200).withBody(RESPONSE_STRING)); } - } diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/AssertionMockServerConfig.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/AssertionMockServerConfig.java new file mode 100644 index 00000000..dfb7e8fd --- /dev/null +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/AssertionMockServerConfig.java @@ -0,0 +1,153 @@ +package it.pagopa.tech.lollipop.consumer.sample.config; + +import org.mockserver.client.MockServerClient; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.model.Header; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Component; + +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +@Component +@ConditionalOnProperty( + value="lollipop.assertion.client.mock.enabled", + havingValue = "true" +) +public class AssertionMockServerConfig { + + private static final String VALID_ASSERTION_XML = + "{\"response_xml\": \"\\n" + + " https:\\/\\/spid-testenv2:8088<\\/saml:Issuer><\\/ds:Transforms>s\\/DqYePHC7eCXX5ncsiFYNLyKbzS6P5C8331H1b8e30=<\\/ds:DigestValue><\\/ds:Reference><\\/ds:SignedInfo>WcasorooElvhmK0kxFUdBVCqyRYi0SCNGRSZZnC9Q2sZHOYGZbERe4\\/T8OSuRKbSrEivXIHRgNr8WskZTM2CiywfWChHfGvhERsLuPJE8oh9CR3eicX\\/eg0ynJqwx4IoYhTb2NOwqMFc66nnutMhG\\/Smdtjs4SFz0RQYYVeZ5Ho51iTHd94uBV9ZHXjqcvs3EitUsJ0Zg1Pkw352tt8y7niUcGjAd8nydI72S12sF5ePv05AunFp7vZpYbKqi62fQLORCn1ZP7WKFD75hL0bCvZaSRF285GkfSnLfe1S4tLff2SlTQWevOMU\\/wCkHJmQwHT1LMwcWRnMvv4V+vd1XQ==<\\/ds:SignatureValue>MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR\\/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2\\/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI\\/sp\\n" + + "ILywgDxVMMtv\\/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAf\\n" + + "BgNVHSMEGDAWgBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH\\/MA0G\\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8\\/o13vMw4feGxro1hMeUilRtH52funrW\\n" + + "C+FgPrqk3o\\/8cZOnq+CqnFFDfILLiEb\\/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\n" + + "Da1fG\\/Pi0fG2F0yw\\/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk\\/ZbEHdKcofnziDyl0V8gglP2\\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n" + + "<\\/ds:X509Certificate><\\/ds:X509Data><\\/ds:KeyInfo><\\/ds:Signature>\\n" + + " \\n" + + " \\n" + + " <\\/samlp:Status>\\n" + + " \\n" + + " https:\\/\\/spid-testenv2:8088<\\/saml:Issuer><\\/ds:Transforms>4cqgG29TSKgNLy2\\/1eFPXhd5WRVPxZBGcd8DgTvd5Fo=<\\/ds:DigestValue><\\/ds:Reference><\\/ds:SignedInfo>WqxM+y+vtZDcEaIaw2WfcuMuwXUeTOY9ZjaXwzHw+RE8uUr5s8BE1tpaodcKmmqSJK1JQYNr8AUV+W9V79EKfmNtFvfaf0WYeUee7Td7E24QqiyVHjr1YgfDWhSdItFLYJfQUkotj2BepbdwVQGY5yN0Rw6Fq98hgNOgsxty7g6oqxG1OXB4WJ2He20iOoYWQl8ApxlbU\\/\\/hwnefFYe9ghDPy3rDbcNl3JetT07NR\\/+AzhKH4e+JCwKjTkdCBTW30fK4eiV9yBk74Lobip4hMaQhMaByl8egaU3A8AsnsZQuov2B6Wo2sDiQPjIulb8K3DOwFyL8PzEk8BB5YoAfwg==<\\/ds:SignatureValue>MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR\\/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2\\/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI\\/sp\\n" + + "ILywgDxVMMtv\\/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAf\\n" + + "BgNVHSMEGDAWgBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH\\/MA0G\\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8\\/o13vMw4feGxro1hMeUilRtH52funrW\\n" + + "C+FgPrqk3o\\/8cZOnq+CqnFFDfILLiEb\\/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\n" + + "Da1fG\\/Pi0fG2F0yw\\/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk\\/ZbEHdKcofnziDyl0V8gglP2\\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n" + + "<\\/ds:X509Certificate><\\/ds:X509Data><\\/ds:KeyInfo><\\/ds:Signature>\\n" + + " \\n" + + " id_48129c2a9d5e9077422591baf495747cfda668c5<\\/saml:NameID>\\n" + + " \\n" + + " \\n" + + " <\\/saml:SubjectConfirmation>\\n" + + " <\\/saml:Subject>\\n" + + " \\n" + + " \\n" + + " https:\\/\\/spid.agid.gov.it\\/cd<\\/saml:Audience>\\n" + + " <\\/saml:AudienceRestriction>\\n" + + " <\\/saml:Conditions>\\n" + + " \\n" + + " \\n" + + " " + + " https:\\/\\/www.spid.gov.it\\/SpidL2<\\/saml:AuthnContextClassRef>\\n" + + " <\\/saml:AuthnContext>\\n" + + " <\\/saml:AuthnStatement>\\n" + + " \\n" + + " \\n" + + " info@agid.gov.it<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " Mario<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " Bianchi<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " GDNNWA12H81Y874F<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " 1991-12-12<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " <\\/saml:AttributeStatement>\\n" + + " <\\/saml:Assertion>\\n" + + "<\\/samlp:Response>\"}"; + private static final String ASSERTION_REF = "sha256-chG21HBOK-wJp2hHuYPrx7tAII2UGWVF-IFo0crUOtw"; + private static final String JWT = "aValidJWT"; + + public AssertionMockServerConfig() { + ClientAndServer.startClientAndServer(3000); + new MockServerClient("localhost", 3000) + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", JWT))) + .respond(response().withStatusCode(200).withBody(VALID_ASSERTION_XML)); + } +} diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/IdpMockServerConfig.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/IdpMockServerConfig.java new file mode 100644 index 00000000..86483ab0 --- /dev/null +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/IdpMockServerConfig.java @@ -0,0 +1,138 @@ +package it.pagopa.tech.lollipop.consumer.sample.config; + +import org.mockserver.client.MockServerClient; +import org.mockserver.integration.ClientAndServer; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Component; + +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +@Component +@ConditionalOnProperty( + value="lollipop.idp.client.mock.enabled", + havingValue = "true" +) +public class IdpMockServerConfig { + + private static final String IDP_CLIENT_RESPONSE_STRING = + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + + " MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI/sp\n" + + "ILywgDxVMMtv/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA/L1/fd70ok+6xtDRF8A3HjAf\n" + + "BgNVHSMEGDAWgBQEVmzA/L1/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH/MA0G\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8/o13vMw4feGxro1hMeUilRtH52funrW\n" + + "C+FgPrqk3o/8cZOnq+CqnFFDfILLiEb/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\n" + + "Da1fG/Pi0fG2F0yw/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk/ZbEHdKcofnziDyl0V8gglP2\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " urn:oasis:names:tc:SAML:2.0:nameid-format:transient\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + private static final String IDP_TAG = "latest"; + + public IdpMockServerConfig() { + ClientAndServer.startClientAndServer(3001); + new MockServerClient("localhost", 3001) + .when(request().withMethod("GET").withPath("/idp-keys/spid")) + .respond(response().withStatusCode(200).withBody("[\"" + IDP_TAG + "\"]")); + new MockServerClient("localhost", 3001) + .when( + request() + .withMethod("GET") + .withPath("/idp-keys/spid/{tag}") + .withPathParameter("tag", IDP_TAG)) + .respond(response().withStatusCode(200).withBody(IDP_CLIENT_RESPONSE_STRING)); + } +} diff --git a/samples/spring/src/main/resources/application.properties b/samples/spring/src/main/resources/application.properties index 6fc93cec..e81720c3 100644 --- a/samples/spring/src/main/resources/application.properties +++ b/samples/spring/src/main/resources/application.properties @@ -1,9 +1,15 @@ spring.application.name=spring-lollipop-consumer +##Client mocks config +lollipop.idp.client.mock.enabled=${IDP_CLIENT_MOCK_ENABLED:false} +lollipop.assertion.client.mock.enabled=${ASSERTION_CLIENT_MOCK_ENABLED:false} + ##General Lollipop Configs Sample lollipop.core.config.assertionExpireInDays=${LOLLIPOP_ASSERTION_EXPIRE_IN_DAYS:180} lollipop.core.config.expectedFirstLcOriginalUrl=${LOLLIPOP_EXPECTED_LC_ORIGINAL_URL:https://api-app.io.pagopa.it/first-lollipop/sign} lollipop.core.config.expectedFirstLcOriginalMethod=${LOLLIPOP_EXPECTED_LC_ORIGINAL_METHOD:POST} +lollipop.core.config.assertionNotBeforeDateFormat=${LOLLIPOP_ASSERTION_NOT_BEFORE_DATE_FORMAT:yyyy-MM-dd'T'HH:mm:ss.SSS'Z'} +lollipop.core.config.assertionInstantDateFormat=${LOLLIPOP_ASSERTION_INSTANT_DATE_FORMAT:yyyy-MM-dd'T'HH:mm:ss.SSS'Z'} ###Idp Client Configs lollipop.idp.rest.config.cieEntityId=${IDP_CLIENT_CIEID:https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO} From 776a5402a6c36d417bd2458092844a8c39b19fd1 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 27 Apr 2023 16:48:06 +0200 Subject: [PATCH 308/403] [rework_simple_assertion_storage] Updated SimpleAssertionStorage --- .../storage/SimpleAssertionStorage.java | 6 +++ .../storage/SimpleAssertionStorageTest.java | 44 ++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java index e6d0b4f5..71361b78 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java @@ -158,4 +158,10 @@ public void saveAssertion(String assertionRef, SamlAssertion assertion) { executor); } } + + public void close() { + this.cleanerThread.interrupt(); + this.cleaningUpQueue.clear(); + this.cache.clear(); + } } diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java index 859d6090..0fc8fc77 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java @@ -16,7 +16,7 @@ class SimpleAssertionStorageTest { private static final long EVICTION_DELAY = 5000L; private static StorageConfig storageConfigMock; - private AssertionStorage sut; + private SimpleAssertionStorage sut; private static final String ASSERTION_REF_1 = "assertionRef1"; @BeforeEach @@ -26,6 +26,38 @@ void setUp() { doReturn(TimeUnit.MILLISECONDS).when(storageConfigMock).getStorageEvictionDelayTimeUnit(); } + @Test + void getExistingAssertionAndResetScheduleEvictionWithStorageEnabled() + throws InterruptedException, ExecutionException { + doReturn(true).when(storageConfigMock).isAssertionStorageEnabled(); + doReturn(1000L).when(storageConfigMock).getStorageEvictionDelay(); + doReturn(TimeUnit.MILLISECONDS).when(storageConfigMock).getStorageEvictionDelayTimeUnit(); + doReturn(100L).when(storageConfigMock).getMaxNumberOfElements(); + + ConcurrentHashMap> assertionMap = + new ConcurrentHashMap<>(); + DelayQueue> delayedCacheObjects = new DelayQueue<>(); + + sut = new SimpleAssertionStorage(assertionMap, delayedCacheObjects, storageConfigMock); + SamlAssertion samlAssertion = new SamlAssertion(); + + sut.saveAssertion(ASSERTION_REF_1, samlAssertion); + delayedCacheObjects.poll(20, TimeUnit.MILLISECONDS); + + SamlAssertion result = sut.getAssertion(ASSERTION_REF_1); + + assertNotNull(result); + assertEquals(samlAssertion, result); + delayedCacheObjects.poll(20, TimeUnit.MILLISECONDS); + assertEquals(1, delayedCacheObjects.size()); + + delayedCacheObjects.poll(1000, TimeUnit.MILLISECONDS); + assertEquals(0, assertionMap.size()); + assertEquals(0, delayedCacheObjects.size()); + + sut.close(); + } + @Test void getNotExistingAssertionWithStorageEnabled() { doReturn(true).when(storageConfigMock).isAssertionStorageEnabled(); @@ -35,6 +67,8 @@ void getNotExistingAssertionWithStorageEnabled() { SamlAssertion result = sut.getAssertion(ASSERTION_REF_1); assertNull(result); + + sut.close(); } @Test @@ -62,6 +96,8 @@ void saveAssertionAndScheduleEvictionWithStorageEnabled() delayedCacheObjects.poll(1000, TimeUnit.MILLISECONDS); assertEquals(0, assertionMap.size()); assertEquals(0, delayedCacheObjects.size()); + + sut.close(); } @Test @@ -85,6 +121,8 @@ void saveAssertionToMaximumCapacityWithStorageEnabled() delayedCacheObjects.poll(150, TimeUnit.MILLISECONDS); assertEquals(100, delayedCacheObjects.size()); + + sut.close(); } @Test @@ -98,6 +136,8 @@ void getAssertionWithStorageDisabled() { SamlAssertion result = sut.getAssertion(ASSERTION_REF_1); assertNull(result); + + sut.close(); } @Test @@ -114,5 +154,7 @@ void savaAssertionWithStorageDisabled() { assertEquals(0, assertionMap.size()); assertEquals(0, delayedCacheObjects.size()); + + sut.close(); } } From 0f6fb6061020a6e7781842b9e29d67575a02d39e Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 27 Apr 2023 17:46:59 +0200 Subject: [PATCH 309/403] [SLS-16] Updated LollipopConstants --- .../src/main/java/it/pagopa/tech/sample/LollipopConstants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConstants.java b/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConstants.java index 14ae54d8..88cf1c13 100644 --- a/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConstants.java +++ b/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConstants.java @@ -19,7 +19,7 @@ public class LollipopConstants { + " sig2=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + " \"x-pagopa-lollipop-original-url\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; public static final String VALID_MULTI_ECDSA_SIGNATURE = - "sig1=:skaKScZj5n/mjhSUIbSadKvFnQze5+RihZlIwSdXsNrdtK07nek5fyZ4+8P8o6H9zPyyNj2Qc5HarO+lqg3UUQ==:," + "sig1=:8MB/iT9iZO2HfVjMds6WdFMQeutkPnoyBDhzeyvIQDhb/tX0nE6HeRSoRBsrl4GUzo6OItnzfzF43Sd14P7tAw==:," + "sig2=:6scl8sMzJdyG/OrnJXHRM9ajmIjrJ/zrLUDqvfOxj2h51DUKztTua3vR1kSUj/c/VT1ioDlt1QIMARABhquewg==:"; public static final String VALID_RSA_PSS_SIGNATURE_INPUT = From 2a99975d6819f2d2f1b97fb64a249b8d6f946048 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 27 Apr 2023 19:04:24 +0200 Subject: [PATCH 310/403] [SLS-16] Updated LollipopConstants --- .../src/main/java/it/pagopa/tech/sample/LollipopConstants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConstants.java b/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConstants.java index 88cf1c13..79e11c95 100644 --- a/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConstants.java +++ b/samples/simple/src/main/java/it/pagopa/tech/sample/LollipopConstants.java @@ -20,7 +20,7 @@ public class LollipopConstants { + " \"x-pagopa-lollipop-original-url\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; public static final String VALID_MULTI_ECDSA_SIGNATURE = "sig1=:8MB/iT9iZO2HfVjMds6WdFMQeutkPnoyBDhzeyvIQDhb/tX0nE6HeRSoRBsrl4GUzo6OItnzfzF43Sd14P7tAw==:," - + "sig2=:6scl8sMzJdyG/OrnJXHRM9ajmIjrJ/zrLUDqvfOxj2h51DUKztTua3vR1kSUj/c/VT1ioDlt1QIMARABhquewg==:"; + + "sig2=:ZDWu2x+6APQG0Ioj10uNzTBv+5JbFBYnjhqcpL66oGFtwznROAUouXkx80ekzUY5h0HoJWE/ecqxRK2OVeHTiQ==:"; public static final String VALID_RSA_PSS_SIGNATURE_INPUT = "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" From 6f7c02f5e00a7051ab05402fba58e5618508e6be Mon Sep 17 00:00:00 2001 From: svariant Date: Thu, 27 Apr 2023 18:28:00 +0200 Subject: [PATCH 311/403] [SLS-16] Defined docker-compose.yaml --- Dockerfile | 3 ++- docker-compose.yaml | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 docker-compose.yaml diff --git a/Dockerfile b/Dockerfile index 7dfb8d45..f8650c80 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,9 +7,10 @@ FROM eclipse-temurin:11-jdk-alpine as runtime WORKDIR /app COPY --from=build /build/build/libs/*.jar /app/app.jar +COPY --from=build /build/build/resources/main/application.properties /app/application.properties RUN addgroup -S appuser && adduser -S appuser -G appuser USER appuser EXPOSE 8080 -ENTRYPOINT [ "java","-jar","/app/app.jar" ] \ No newline at end of file +ENTRYPOINT [ "java","-jar","/app/app.jar", "/app/application.properties" ] \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 00000000..94a892bc --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,12 @@ +version: "3.9" +services: + web: + build: . + ports: + - "8080:8080" + environment: + ASSERTION_CLIENT_MOCK_ENABLED : false + IDP_CLIENT_MOCK_ENABLED: false + IDP_CLIENT_BASE_URI: "http://localhost:3001" + LOLLIPOP_ASSERTION_NOT_BEFORE_DATE_FORMAT: "yyyy-MM-dd'T'HH:mm:ss'Z'" + LOLLIPOP_ASSERTION_INSTANT_DATE_FORMAT: "yyyy-MM-dd'T'HH:mm:ss'Z'" \ No newline at end of file From acab8ba750a44acabacb2a985a0180f87b12ef3b Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 28 Apr 2023 09:15:38 +0200 Subject: [PATCH 312/403] [SLS-16] Fixed HttpServletResponse intercepted sendError call --- .../lollipop/consumer/utils/LollipopConsumerConverter.java | 3 ++- .../consumer/utils/LollipopConsumerConverterTest.java | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverter.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverter.java index 81a6dfd6..fd40d2df 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverter.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverter.java @@ -57,7 +57,8 @@ public static HttpServletResponse interceptResult( CommandResult commandResult, HttpServletResponse httpResponse) throws IOException { if (!commandResult.getResultCode().equals(VERIFICATION_SUCCESS_CODE)) { - httpResponse.sendError(401, commandResult.getResultMessage()); + httpResponse.setStatus(401); + httpResponse.getWriter().write(commandResult.getResultMessage()); } return httpResponse; diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverterTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverterTest.java index 8957468d..7ce16b5f 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverterTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/utils/LollipopConsumerConverterTest.java @@ -77,7 +77,7 @@ void convertUnauthorizedResponse() throws IOException { LollipopConsumerConverter.interceptResult(result, mockResponse); Assertions.assertEquals(401, response.getStatus()); - Assertions.assertSame( - COMMAND_RESPONSE_FAILED, ((MockHttpServletResponse) response).getErrorMessage()); + Assertions.assertEquals( + COMMAND_RESPONSE_FAILED, ((MockHttpServletResponse) response).getContentAsString()); } } From 4044dbe57a603474497ba306c0640000f44b853e Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 28 Apr 2023 09:59:36 +0200 Subject: [PATCH 313/403] [SLS-16] Added all environment variables to docker-compose.yaml with default values - defined .env.dev for testing --- .env | 0 .env.dev | 5 +++++ docker-compose.yaml | 35 ++++++++++++++++++++++++++++++----- 3 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 .env create mode 100644 .env.dev diff --git a/.env b/.env new file mode 100644 index 00000000..e69de29b diff --git a/.env.dev b/.env.dev new file mode 100644 index 00000000..8df0b3d3 --- /dev/null +++ b/.env.dev @@ -0,0 +1,5 @@ +ASSERTION_CLIENT_MOCK_ENABLED = true +IDP_CLIENT_MOCK_ENABLED = true +IDP_CLIENT_BASE_URI = "http://localhost:3001" +LOLLIPOP_ASSERTION_NOT_BEFORE_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'" +LOLLIPOP_ASSERTION_INSTANT_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'" \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 94a892bc..2d37c8a3 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -5,8 +5,33 @@ services: ports: - "8080:8080" environment: - ASSERTION_CLIENT_MOCK_ENABLED : false - IDP_CLIENT_MOCK_ENABLED: false - IDP_CLIENT_BASE_URI: "http://localhost:3001" - LOLLIPOP_ASSERTION_NOT_BEFORE_DATE_FORMAT: "yyyy-MM-dd'T'HH:mm:ss'Z'" - LOLLIPOP_ASSERTION_INSTANT_DATE_FORMAT: "yyyy-MM-dd'T'HH:mm:ss'Z'" \ No newline at end of file + ##Client mocks config + ASSERTION_CLIENT_MOCK_ENABLED: ${ASSERTION_CLIENT_MOCK_ENABLED} + IDP_CLIENT_MOCK_ENABLED: ${IDP_CLIENT_MOCK_ENABLED} + + ##General Lollipop Configs Sample + LOLLIPOP_ASSERTION_EXPIRE_IN_DAYS: ${LOLLIPOP_ASSERTION_EXPIRE_IN_DAYS:-180} + LOLLIPOP_EXPECTED_LC_ORIGINAL_URL: ${LOLLIPOP_EXPECTED_LC_ORIGINAL_URL:-https://api-app.io.pagopa.it/first-lollipop/sign} + LOLLIPOP_EXPECTED_LC_ORIGINAL_METHOD: ${LOLLIPOP_EXPECTED_LC_ORIGINAL_METHOD:-POST} + LOLLIPOP_ASSERTION_NOT_BEFORE_DATE_FORMAT: ${LOLLIPOP_ASSERTION_NOT_BEFORE_DATE_FORMAT:-yyyy-MM-dd'T'HH:mm:ss.SSS'Z'} + LOLLIPOP_ASSERTION_INSTANT_DATE_FORMAT: ${LOLLIPOP_ASSERTION_INSTANT_DATE_FORMAT:-yyyy-MM-dd'T'HH:mm:ss.SSS'Z'} + + ###Idp Client Configs + IDP_CLIENT_CIEID: ${IDP_CLIENT_CIEID:-https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO} + IDP_CLIENT_BASE_URI: ${IDP_CLIENT_BASE_URI:-https://api.is.eng.pagopa.it} + IDP_CLIENT_CIE_ENDPOINT: ${IDP_CLIENT_CIE_ENDPOINT:-/idp-keys/cie} + IDP_CLIENT_SPID_ENDPOINT: ${IDP_CLIENT_SPID_ENDPOINT:-/idp-keys/spid} + + ###Idp Storage Configs + IDP_STORAGE_ENABLED: ${IDP_STORAGE_ENABLED:-true} + IDP_STORAGE_EVICTION_DELAY: ${IDP_STORAGE_EVICTION_DELAY:-1} + + ##Assertion Client Configs + ASSERTION_REST_URI: ${ASSERTION_REST_URI:-http://localhost:3000} + ASSERTION_REST_ENDPOINT: ${ASSERTION_REST_ENDPOINT:-/assertions} + + ##Assertion Storage Configs + ASSERTION_STORAGE_ENABLED: ${ASSERTION_STORAGE_ENABLED:-true} + ASSERTION_STORAGE_EVICTION_DELAY: ${ASSERTION_STORAGE_EVICTION_DELAY:-1} + + From a9b6703ab2616618783bf0358ac6b7dfff1c726e Mon Sep 17 00:00:00 2001 From: giomella Date: Fri, 28 Apr 2023 10:38:59 +0200 Subject: [PATCH 314/403] [SLS-16] added e2e test collection. removed useless class. --- e2e/automatic-test.js | 10 + .../LollipopSDKTest.postman_collection.json | 686 ++++ ...ronment variables.postman_environment.json | 19 + e2e/package-lock.json | 3108 +++++++++++++++++ e2e/package.json | 15 + .../sample/MockAssertionVerifierService.java | 31 - 6 files changed, 3838 insertions(+), 31 deletions(-) create mode 100644 e2e/automatic-test.js create mode 100644 e2e/collections/LollipopSDKTest.postman_collection.json create mode 100644 e2e/env/Lollipop environment variables.postman_environment.json create mode 100644 e2e/package-lock.json create mode 100644 e2e/package.json delete mode 100644 samples/simple/src/main/java/it/pagopa/tech/sample/MockAssertionVerifierService.java diff --git a/e2e/automatic-test.js b/e2e/automatic-test.js new file mode 100644 index 00000000..eef19b37 --- /dev/null +++ b/e2e/automatic-test.js @@ -0,0 +1,10 @@ +const newman = require('newman'); + +newman.run({ + collection: require('./collections/LollipopSDKTest.postman_collection.json'), + environment: './env/Lollipop environment variables.postman_environment.json', + reporters: 'htmlextra' +}, function (err, summary) { + if (err) { throw err; } + console.info('collection run complete!'); +}); \ No newline at end of file diff --git a/e2e/collections/LollipopSDKTest.postman_collection.json b/e2e/collections/LollipopSDKTest.postman_collection.json new file mode 100644 index 00000000..b1017b51 --- /dev/null +++ b/e2e/collections/LollipopSDKTest.postman_collection.json @@ -0,0 +1,686 @@ +{ + "info": { + "_postman_id": "d72dcca1-95d6-43bf-9272-da8a4efa16e1", + "name": "LollipopSDKTest", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "26867059" + }, + "item": [ + { + "name": "Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Expected HTTP Status\", function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Digest", + "value": "{{validContentDigest}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-original-url", + "value": "{{expectedOriginalURL}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-original-method", + "value": "{{expectedOriginalMethod}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-public-key", + "value": "{{validPublicKey}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-assertion-ref", + "value": "{{validAssertionRef}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-assertion-type", + "value": "{{validAssertionType}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-auth-jwt", + "value": "{{validAuthJWT}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-user-id", + "value": "{{validUserId}}", + "type": "text" + }, + { + "key": "Signature-Input", + "value": "{{validSignatureInput}}", + "type": "text" + }, + { + "key": "Signature", + "value": "{{validSignature}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\"message\":\"a valid message payload\"}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{PROTOCOL}}{{BASE_URL}}", + "host": [ + "{{PROTOCOL}}{{BASE_URL}}" + ] + } + }, + "response": [] + }, + { + "name": "Success with multi signaure", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Expected HTTP Status\", function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Digest", + "value": "{{validContentDigest}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-original-url", + "value": "{{expectedOriginalURL}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-original-method", + "value": "{{expectedOriginalMethod}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-public-key", + "value": "{{validPublicKey}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-assertion-ref", + "value": "{{validAssertionRef}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-assertion-type", + "value": "{{validAssertionType}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-auth-jwt", + "value": "{{validAuthJWT}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-user-id", + "value": "{{validUserId}}", + "type": "text" + }, + { + "key": "Signature-Input", + "value": "sig1=(\"x-io-sign-qtspclauses\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\", sig2=(\"content-digest\" \"x-pagopa-lollipop-original-method\" \"x-pagopa-lollipop-original-url\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\"", + "type": "text" + }, + { + "key": "Signature", + "value": "sig1=:8MB/iT9iZO2HfVjMds6WdFMQeutkPnoyBDhzeyvIQDhb/tX0nE6HeRSoRBsrl4GUzo6OItnzfzF43Sd14P7tAw==:,sig2=:ZDWu2x+6APQG0Ioj10uNzTBv+5JbFBYnjhqcpL66oGFtwznROAUouXkx80ekzUY5h0HoJWE/ecqxRK2OVeHTiQ==:", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\"message\":\"a valid message payload\"}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{PROTOCOL}}{{BASE_URL}}", + "host": [ + "{{PROTOCOL}}{{BASE_URL}}" + ] + } + }, + "response": [] + }, + { + "name": "Failed with invalid content digest", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Expected HTTP Status\", function () {\r", + " pm.response.to.have.status(401);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Digest", + "value": "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskyXXXXX=:", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-original-url", + "value": "{{expectedOriginalURL}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-original-method", + "value": "{{expectedOriginalMethod}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-public-key", + "value": "{{validPublicKey}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-assertion-ref", + "value": "{{validAssertionRef}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-assertion-type", + "value": "{{validAssertionType}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-auth-jwt", + "value": "{{validAuthJWT}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-user-id", + "value": "{{validUserId}}", + "type": "text" + }, + { + "key": "Signature-Input", + "value": "{{validSignatureInput}}", + "type": "text" + }, + { + "key": "Signature", + "value": "{{validSignature}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\"message\":\"a valid message payload\"}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{PROTOCOL}}{{BASE_URL}}", + "host": [ + "{{PROTOCOL}}{{BASE_URL}}" + ] + } + }, + "response": [] + }, + { + "name": "Failed with invalid body", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Expected HTTP Status\", function () {\r", + " pm.response.to.have.status(401);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Digest", + "value": "{{validContentDigest}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-original-url", + "value": "{{expectedOriginalURL}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-original-method", + "value": "{{expectedOriginalMethod}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-public-key", + "value": "{{validPublicKey}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-assertion-ref", + "value": "{{validAssertionRef}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-assertion-type", + "value": "{{validAssertionType}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-auth-jwt", + "value": "{{validAuthJWT}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-user-id", + "value": "{{validUserId}}", + "type": "text" + }, + { + "key": "Signature-Input", + "value": "{{validSignatureInput}}", + "type": "text" + }, + { + "key": "Signature", + "value": "{{validSignature}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\"message\":\"an invalid message payload\"}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{PROTOCOL}}{{BASE_URL}}", + "host": [ + "{{PROTOCOL}}{{BASE_URL}}" + ] + } + }, + "response": [] + }, + { + "name": "Failed with invalid encoding", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Expected HTTP Status\", function () {\r", + " pm.response.to.have.status(401);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Digest", + "value": "{{validContentDigest}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-original-url", + "value": "{{expectedOriginalURL}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-original-method", + "value": "{{expectedOriginalMethod}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-public-key", + "value": "{{validPublicKey}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-assertion-ref", + "value": "{{validAssertionRef}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-assertion-type", + "value": "{{validAssertionType}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-auth-jwt", + "value": "{{validAuthJWT}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-user-id", + "value": "{{validUserId}}", + "type": "text" + }, + { + "key": "Signature-Input", + "value": "{{validSignatureInput}}", + "type": "text" + }, + { + "key": "Signature", + "value": "{{validSignature}}", + "type": "text" + }, + { + "key": "content-encoding", + "value": "UTF-326", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\"message\":\"a valid message payload\"}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{PROTOCOL}}{{BASE_URL}}", + "host": [ + "{{PROTOCOL}}{{BASE_URL}}" + ] + } + }, + "response": [] + }, + { + "name": "Failed with invalid signature", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Expected HTTP Status\", function () {\r", + " pm.response.to.have.status(401);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Digest", + "value": "{{validContentDigest}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-original-url", + "value": "{{expectedOriginalURL}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-original-method", + "value": "{{expectedOriginalMethod}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-public-key", + "value": "{{validPublicKey}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-assertion-ref", + "value": "{{validAssertionRef}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-assertion-type", + "value": "{{validAssertionType}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-auth-jwt", + "value": "{{validAuthJWT}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-user-id", + "value": "{{validUserId}}", + "type": "text" + }, + { + "key": "Signature-Input", + "value": "{{validSignatureInput}}", + "type": "text" + }, + { + "key": "Signature", + "value": "sig123=:lTTTRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\"message\":\"a valid message payload\"}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{PROTOCOL}}{{BASE_URL}}", + "host": [ + "{{PROTOCOL}}{{BASE_URL}}" + ] + } + }, + "response": [] + }, + { + "name": "Failed on thumprint validation", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Expected HTTP Status\", function () {\r", + " pm.response.to.have.status(401);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Digest", + "value": "{{validContentDigest}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-original-url", + "value": "{{expectedOriginalURL}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-original-method", + "value": "{{expectedOriginalMethod}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-public-key", + "value": "eyJrdHkiOiJSU0EiLCJlIjoiQVFBQiIsImtpZCI6InRlc3Qta2V5LXJzYS1wc3MiLCJuIjoicjR0bW0zcjIwV2RfUGJxdlAxczItUUV0dnB1UmFWOFlxNDBnalVSOHkyUmp4YTZkcEcyR1hIYlBmdk0gIHM4Y3QtTGgxR0g0NXgyOFJ3M1J5NTNtbS1vQVhqeVE4Nk9uRGtaNU44bFliZ2dENE8zdzZNNnBBdkxraGs5NUFuICBkVHJpZmJJRlBOVThQUE1PN095ckZBSHFnRHN6bmpQRm1UT3RDRWNOMloxRnBXZ2Nod3VZTFBMLVdva3FsdGQxMSAgbnFxemktYko5Y3ZTS0FEWWRVQUFONVdVdHpkcGl5NkxiVGdTeFA3b2NpVTRUbjBnNUk2YURaSjdBOEx6bzBLU3kgIFpZb0E0ODVtcWNPMEdWQWRWdzlscTRhT1Q5djZkLW5iNGJuTmtRVmtsTFEzZlZBdkptLXhkRE9wOUxDTkNONDhWICAycG5ET2tGVjYtVTluVjVveWM2WEkydyJ9", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-assertion-ref", + "value": "{{validAssertionRef}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-assertion-type", + "value": "{{validAssertionType}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-auth-jwt", + "value": "{{validAuthJWT}}", + "type": "text" + }, + { + "key": "x-pagopa-lollipop-user-id", + "value": "{{validUserId}}", + "type": "text" + }, + { + "key": "Signature-Input", + "value": "sig1=(\\\"content-digest\\\" \\\"x-pagopa-lollipop-original-method\\\" \\\"x-pagopa-lollipop-original-url\\\");created=1678814391;nonce=\\\"aNonce\\\";alg=\\\"rsa-pss-sha256\\\";keyid=\\\"sha256-A3OhKGLYwSvdJ2txHi_SGQ3G-sHLh2Ibu91ErqFx_58\\\"", + "type": "text" + }, + { + "key": "Signature", + "value": "sig1=:q3Og7m8yL18HkrY+zgV92Gj05lrWaFMIEFSPg2PEnO5a46+2Tt/2n7kjqVaGjI1ZXtys+Wyh3cVXCddadNARizt0BpCRdT9S4r48xsGO79Ucq4IFwZyyHNudKu5WSH4/55j5yX/YmeCtH+Nt6Nun02OZynn3iQwgLJB+CGe3h6X02iSvl4wJjKaMGE64RFHa5osE4MctoPD1j0tRkcOtgwrGmFMr282Kqrkabbx1vUpmO9T1khjouxIryfUln9zIaZ+wWmukpAZv7TKO3CltNWgfx1XT9m/iwzHiGmtvcHbWVExdAyey8lH23MgLY43AM7ytLQNSlk1s/bPNbGmPwg==:", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\"message\":\"a valid message payload\"}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{PROTOCOL}}{{BASE_URL}}", + "host": [ + "{{PROTOCOL}}{{BASE_URL}}" + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "validContentDigest", + "value": "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:" + }, + { + "key": "expectedOriginalURL", + "value": "https://api-app.io.pagopa.it/first-lollipop/sign" + }, + { + "key": "expectedOriginalMethod", + "value": "POST" + }, + { + "key": "validPublicKey", + "value": "eyJrdHkiOiJFQyIsIngiOiJTaHlZa0ZyN1F3eE9rOE5BRXF6aklkTnc4dEVKODlZOVBlWFF1eVVOWDVjIiwieSI6InlULVJxNWc2VlVadENUd0ZnRExDM2RneGNuM2RsSmNGRjhnWGdxYWgyS0UiLCJjcnYiOiJQLTI1NiJ9" + }, + { + "key": "validAssertionRef", + "value": "sha256-chG21HBOK-wJp2hHuYPrx7tAII2UGWVF-IFo0crUOtw" + }, + { + "key": "validAssertionType", + "value": "SAML" + }, + { + "key": "validAuthJWT", + "value": "aValidJWT" + }, + { + "key": "validUserId", + "value": "GDNNWA12H81Y874F" + }, + { + "key": "validSignatureInput", + "value": "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\" \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\"" + }, + { + "key": "validSignature", + "value": "sig123=:6scl8sMzJdyG/OrnJXHRM9ajmIjrJ/zrLUDqvfOxj2h51DUKztTua3vR1kSUj/c/VT1ioDlt1QIMARABhquewg==:" + } + ] +} \ No newline at end of file diff --git a/e2e/env/Lollipop environment variables.postman_environment.json b/e2e/env/Lollipop environment variables.postman_environment.json new file mode 100644 index 00000000..3d2b6c88 --- /dev/null +++ b/e2e/env/Lollipop environment variables.postman_environment.json @@ -0,0 +1,19 @@ +{ + "id": "63e9abaf-4412-47e8-8002-6ec9c1663245", + "name": "Lollipop environment variables", + "values": [ + { + "key": "PROTOCOL", + "value": "http://", + "enabled": true + }, + { + "key": "BASE_URL", + "value": "localhost:8080/", + "enabled": true + } + ], + "_postman_variable_scope": "environment", + "_postman_exported_at": "2023-04-28T08:00:59.996Z", + "_postman_exported_using": "Postman/10.13.5" +} \ No newline at end of file diff --git a/e2e/package-lock.json b/e2e/package-lock.json new file mode 100644 index 00000000..3531988e --- /dev/null +++ b/e2e/package-lock.json @@ -0,0 +1,3108 @@ +{ + "name": "lollipop-e2e-test", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "lollipop-e2e-test", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "newman": "^5.3.2", + "newman-reporter-htmlextra": "^1.22.11" + } + }, + "node_modules/@budibase/handlebars-helpers": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@budibase/handlebars-helpers/-/handlebars-helpers-0.11.8.tgz", + "integrity": "sha512-ggWJUt0GqsHFAEup5tlWlcrmYML57nKhpNGGLzVsqXVYN8eVmf3xluYmmMe7fDYhQH0leSprrdEXmsdFQF3HAQ==", + "dependencies": { + "array-sort": "^1.0.0", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "for-in": "^1.0.2", + "get-object": "^0.2.0", + "get-value": "^3.0.1", + "handlebars": "^4.7.7", + "handlebars-utils": "^1.0.6", + "has-value": "^2.0.2", + "helper-md": "^0.2.2", + "html-tag": "^2.0.0", + "is-even": "^1.0.0", + "is-glob": "^4.0.1", + "kind-of": "^6.0.3", + "micromatch": "^3.1.5", + "relative": "^3.0.2", + "striptags": "^3.1.1", + "to-gfm-code-block": "^0.1.1", + "year": "^0.2.1" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/@postman/form-data": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@postman/form-data/-/form-data-3.1.1.tgz", + "integrity": "sha512-vjh8Q2a8S6UCm/KKs31XFJqEEgmbjBmpPNVV2eVav6905wyFAwaUOBGA1NPBI4ERH9MMZc6w0umFgM6WbEPMdg==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@postman/tunnel-agent": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@postman/tunnel-agent/-/tunnel-agent-0.6.3.tgz", + "integrity": "sha512-k57fzmAZ2PJGxfOA4SGR05ejorHbVAa/84Hxh/2nAztjNXc4ZjOm9NUIk6/Z6LCrBvJZqjRZbN8e/nROVUPVdg==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dependencies": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-sort/node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-sort/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/async": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/autolinker": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-0.28.1.tgz", + "integrity": "sha512-zQAFO1Dlsn69eXaO6+7YZc+v84aquQKbwpzCE3L0stj56ERn9hutFxPopViLjo9G+rWwjozRhgS5KJ25Xy19cQ==", + "dependencies": { + "gulp-header": "^1.7.1" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bluebird": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "integrity": "sha512-UfFSr22dmHPQqPP9XWHRhq+gWnHCYguQGkXQlbyPtW5qTnhFWA8/iXg765tH0cAjy7l/zPJ1aBTO0g5XgA7kvQ==" + }, + "node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/braces/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/brotli": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", + "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", + "dependencies": { + "base64-js": "^1.1.2" + } + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cache-base/node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cache-base/node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cache-base/node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cache-base/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cache-base/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cache-base/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chardet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-1.4.0.tgz", + "integrity": "sha512-NpwMDdSIprbYx1CLnfbxEIarI0Z+s9MssEgggMNheGM+WD68yOhV7IEA/3r6tr0yTRgQD0HuZJDw32s99i6L+A==" + }, + "node_modules/charset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz", + "integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cli-progress": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.10.0.tgz", + "integrity": "sha512-kLORQrhYCAtUPLZxqsAt2YJGOvRdt34+O6jl5cQGb7iF3dM55FQZlTR+rQyIK9JUcO9bBMwZsTlND+3dmFU2Cw==", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cli-table3": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.1.tgz", + "integrity": "sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "colors": "1.4.0" + } + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "node_modules/concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + }, + "node_modules/csv-parse": { + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-4.16.3.tgz", + "integrity": "sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dependencies": { + "kind-of": "^5.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-compare/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==" + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/faker": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz", + "integrity": "sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/filesize": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", + "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fill-range/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fill-range/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fill-range/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/flatted": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==" + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "engines": { + "node": "*" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fs-exists-sync": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/get-object": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/get-object/-/get-object-0.2.0.tgz", + "integrity": "sha512-7P6y6k6EzEFmO/XyUyFlXm1YLJy9xeA1x/grNV8276abX5GuwUtYgKFkRFkLixw4hf4Pz9q2vgv/8Ar42R0HuQ==", + "dependencies": { + "is-number": "^2.0.2", + "isobject": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/get-object/node_modules/isobject": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-0.2.0.tgz", + "integrity": "sha512-VaWq6XYAsbvM0wf4dyBO7WH9D7GosB7ZZlqrawI9BBiTMINBeCyqSKBa35m870MY3O4aM31pYyZi9DfGrYMJrQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/get-value": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-3.0.1.tgz", + "integrity": "sha512-mKZj9JLQrwMBtj5wxi6MH8Z5eSKaERpAwjg43dPtlGI1ZVEgH/qC7T8/6R2OBSUA+zzHBZgICsVJaEIV2tKTDA==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/gulp-header": { + "version": "1.8.12", + "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", + "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", + "deprecated": "Removed event-stream from gulp-header", + "dependencies": { + "concat-with-sourcemaps": "*", + "lodash.template": "^4.4.0", + "through2": "^2.0.0" + } + }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars-utils": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/handlebars-utils/-/handlebars-utils-1.0.6.tgz", + "integrity": "sha512-d5mmoQXdeEqSKMtQQZ9WkiUcO1E3tPbWxluCK9hVgIDPzQa9WsKo3Lbe/sGflTe7TomHEeZaOgwIkyIr1kfzkw==", + "dependencies": { + "kind-of": "^6.0.0", + "typeof-article": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-value": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-2.0.2.tgz", + "integrity": "sha512-ybKOlcRsK2MqrM3Hmz/lQxXHZ6ejzSPzpNabKB45jb5qDgJvKPa3SdapTsTLwEb9WltgWpOmNax7i+DzNOk4TA==", + "dependencies": { + "get-value": "^3.0.0", + "has-values": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has-values": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-2.0.1.tgz", + "integrity": "sha512-+QdH3jOmq9P8GfdjFg0eJudqx1FqU62NQJ4P16rOEHeRdl7ckgwn6uqQjzYE0ZoHVV/e5E2esuJ5Gl5+HUW19w==", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/helper-md": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/helper-md/-/helper-md-0.2.2.tgz", + "integrity": "sha512-49TaQzK+Ic7ZVTq4i1UZxRUJEmAilTk8hz7q4I0WNUaTclLR8ArJV5B3A1fe1xF2HtsDTr2gYKLaVTof/Lt84Q==", + "dependencies": { + "ent": "^2.2.0", + "extend-shallow": "^2.0.1", + "fs-exists-sync": "^0.1.0", + "remarkable": "^1.6.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/helper-md/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/helper-md/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/html-tag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-tag/-/html-tag-2.0.0.tgz", + "integrity": "sha512-XxzooSo6oBoxBEUazgjdXj7VwTn/iSTSZzTYKzYY6I916tkaYzypHxy+pbVU1h+0UQ9JlVf5XkNQyxOAiiQO1g==", + "dependencies": { + "is-self-closing": "^1.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-reasons": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/http-reasons/-/http-reasons-0.1.0.tgz", + "integrity": "sha512-P6kYh0lKZ+y29T2Gqz+RlC9WBLhKe8kDmcJ+A+611jFfxdPsbMRQ5aNmFRM3lENqFkK+HTTL+tlQviAiv0AbLQ==" + }, + "node_modules/http-signature": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", + "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.14.1" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/httpntlm": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.7.7.tgz", + "integrity": "sha512-Pv2Rvrz8H0qv1Dne5mAdZ9JegG1uc6Vu5lwLflIY6s8RKHdZQbW39L4dYswSgqMDT0pkJILUTKjeyU0VPNRZjA==", + "dependencies": { + "httpreq": ">=0.4.22", + "underscore": "~1.12.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/httpreq": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.5.2.tgz", + "integrity": "sha512-2Jm+x9WkExDOeFRrdBCBSpLPT5SokTcRHkunV3pjKmX/cx6av8zQ0WtHUMDrYb6O4hBFzNU6sxJEypvRUVYKnw==", + "engines": { + "node": ">= 6.15.1" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-even": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-even/-/is-even-1.0.0.tgz", + "integrity": "sha512-LEhnkAdJqic4Dbqn58A0y52IXoHWlsueqQkKfMfdEnIYG8A1sm/GHidKkS6yvXlMoRrkM34csHnXQtOqcb+Jzg==", + "dependencies": { + "is-odd": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-odd": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-0.1.2.tgz", + "integrity": "sha512-Ri7C2K7o5IrUU9UEI8losXJCCD/UtsaIrkR5sxIcFg4xQ9cRJXlWA5DQvTE0yDc0krvSNLsRGXN11UPS6KyfBw==", + "dependencies": { + "is-number": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-odd/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-odd/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-self-closing": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-self-closing/-/is-self-closing-1.0.1.tgz", + "integrity": "sha512-E+60FomW7Blv5GXTlYee2KDrnG6srxF7Xt1SjrhWUGUEsTFIqY/nq2y3DaftCsgUMdh89V07IVfhY9KIJhLezg==", + "dependencies": { + "self-closing-tags": "^1.0.1" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, + "node_modules/js-sha512": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha512/-/js-sha512-0.8.0.tgz", + "integrity": "sha512-PWsmefG6Jkodqt+ePTvBZCSMFgN7Clckjd0O7su3I0+BW2QWUTJNzjktHsztGLhncP2h8mcF9V9Y2Ha59pAViQ==" + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "node_modules/jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/liquid-json": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/liquid-json/-/liquid-json-0.3.1.tgz", + "integrity": "sha512-wUayTU8MS827Dam6MxgD72Ui+KOSF+u/eIqpatOtjnvgJ0+mnDq33uC2M7J0tPK+upe/DpUAuK4JUU89iBoNKQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==" + }, + "node_modules/lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dependencies": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "node_modules/lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dependencies": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-format": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mime-format/-/mime-format-2.0.1.tgz", + "integrity": "sha512-XxU3ngPbEnrYnNbIX+lYSaYg0M01v6p2ntd2YaFksTu0vayaw5OJvbdRyWs07EYRlLED5qadUZ+xo+XhOvFhwg==", + "dependencies": { + "charset": "^1.0.0" + } + }, + "node_modules/mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "dependencies": { + "mime-db": "1.51.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.35", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.35.tgz", + "integrity": "sha512-cY/pBOEXepQvlgli06ttCTKcIf8cD1nmNwOKQQAdHBqYApQSpAqotBMX0RJZNgMp6i0PlZuf1mFtnlyEkwyvFw==", + "dependencies": { + "moment": ">= 2.9.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/newman": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/newman/-/newman-5.3.2.tgz", + "integrity": "sha512-cWy8pV0iwvMOZLTw3hkAHcwo2ZA0GKkXm8oUMn1Ltii3ZI2nKpnrg9QGdIT0hGHChRkX6prY5e3Aar7uykMGNg==", + "dependencies": { + "async": "3.2.3", + "chardet": "1.4.0", + "cli-progress": "3.10.0", + "cli-table3": "0.6.1", + "colors": "1.4.0", + "commander": "7.2.0", + "csv-parse": "4.16.3", + "eventemitter3": "4.0.7", + "filesize": "8.0.7", + "lodash": "4.17.21", + "mkdirp": "1.0.4", + "postman-collection": "4.1.1", + "postman-collection-transformer": "4.1.6", + "postman-request": "2.88.1-postman.31", + "postman-runtime": "7.29.0", + "pretty-ms": "7.0.1", + "semver": "7.3.5", + "serialised-error": "1.1.3", + "tough-cookie": "3.0.1", + "word-wrap": "1.2.3", + "xmlbuilder": "15.1.1" + }, + "bin": { + "newman": "bin/newman.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/newman-reporter-htmlextra": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/newman-reporter-htmlextra/-/newman-reporter-htmlextra-1.22.11.tgz", + "integrity": "sha512-7Kp2y8U9kUy14dVVX3AxRPsI/d1RiFt3AG0dw8EW+INSCRV9AWEp4AY0j/nE6m3cCMylUKJVKBYYenReo/qssA==", + "dependencies": { + "@budibase/handlebars-helpers": "0.11.8", + "chalk": "4.1.2", + "cli-progress": "3.10.0", + "commander": "6.2.1", + "filesize": "6.4.0", + "handlebars": "4.7.7", + "lodash": "4.17.21", + "moment-timezone": "0.5.35", + "pretty-ms": "7.0.1" + }, + "bin": { + "newman-reporter-htmlextra": "bin/htmlextra.js" + }, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "newman": "^5.1.2" + } + }, + "node_modules/newman-reporter-htmlextra/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/newman-reporter-htmlextra/node_modules/filesize": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.4.0.tgz", + "integrity": "sha512-mjFIpOHC4jbfcTfoh4rkWpI31mF7viw9ikj/JyLoKzqlwG/YsefKfvYlYhdYdg/9mtK2z1AzgN/0LvVQ3zdlSQ==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/node-oauth1": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/node-oauth1/-/node-oauth1-1.3.0.tgz", + "integrity": "sha512-0yggixNfrA1KcBwvh/Hy2xAS1Wfs9dcg6TdFf2zN7gilcAigMdrtZ4ybrBSXBgLvGDw9V1p2MRnGBMq7XjTWLg==" + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz", + "integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==", + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", + "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postman-collection": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-4.1.1.tgz", + "integrity": "sha512-ODpJtlf8r99DMcTU7gFmi/yvQYckFzcuE6zL/fWnyrFT34ugdCBFlX+DN7M+AnP6lmR822fv5s60H4DnL4+fAg==", + "dependencies": { + "faker": "5.5.3", + "file-type": "3.9.0", + "http-reasons": "0.1.0", + "iconv-lite": "0.6.3", + "liquid-json": "0.3.1", + "lodash": "4.17.21", + "mime-format": "2.0.1", + "mime-types": "2.1.34", + "postman-url-encoder": "3.0.5", + "semver": "7.3.5", + "uuid": "8.3.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postman-collection-transformer": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/postman-collection-transformer/-/postman-collection-transformer-4.1.6.tgz", + "integrity": "sha512-xvdQb6sZoWcG9xZXUPSuxocjcd6WCZlINlGGiuHdSfxhgiwQhj9qhF0JRFbagZ8xB0+pYUairD5MiCENc6DEVA==", + "dependencies": { + "commander": "8.3.0", + "inherits": "2.0.4", + "lodash": "4.17.21", + "semver": "7.3.5", + "strip-json-comments": "3.1.1" + }, + "bin": { + "postman-collection-transformer": "bin/transform-collection.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postman-collection-transformer/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/postman-request": { + "version": "2.88.1-postman.31", + "resolved": "https://registry.npmjs.org/postman-request/-/postman-request-2.88.1-postman.31.tgz", + "integrity": "sha512-OJbYqP7ItxQ84yHyuNpDywCZB0HYbpHJisMQ9lb1cSL3N5H3Td6a2+3l/a74UMd3u82BiGC5yQyYmdOIETP/nQ==", + "dependencies": { + "@postman/form-data": "~3.1.1", + "@postman/tunnel-agent": "^0.6.3", + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "brotli": "~1.3.2", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "har-validator": "~5.1.3", + "http-signature": "~1.3.1", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "stream-length": "^1.0.2", + "tough-cookie": "~2.5.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postman-request/node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/postman-request/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/postman-runtime": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/postman-runtime/-/postman-runtime-7.29.0.tgz", + "integrity": "sha512-eXxHREE/fUpohkGPRgBY1YccSGx9cyW3mtGiPyIE4zD5fYzasgBHqW6kbEND3Xrd3yf/uht/YI1H8O7J1+A1+w==", + "dependencies": { + "async": "3.2.3", + "aws4": "1.11.0", + "handlebars": "4.7.7", + "httpntlm": "1.7.7", + "js-sha512": "0.8.0", + "lodash": "4.17.21", + "mime-types": "2.1.34", + "node-oauth1": "1.3.0", + "performance-now": "2.1.0", + "postman-collection": "4.1.1", + "postman-request": "2.88.1-postman.31", + "postman-sandbox": "4.0.6", + "postman-url-encoder": "3.0.5", + "serialised-error": "1.1.3", + "tough-cookie": "3.0.1", + "uuid": "8.3.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postman-runtime/node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, + "node_modules/postman-sandbox": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/postman-sandbox/-/postman-sandbox-4.0.6.tgz", + "integrity": "sha512-PPRanSNEE4zy3kO7CeSBHmAfJnGdD9ecHY/Mjh26CQuZZarGkNO8c0U/n+xX3+5M1BRNc82UYq6YCtdsSDqcng==", + "dependencies": { + "lodash": "4.17.21", + "teleport-javascript": "1.0.0", + "uvm": "2.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postman-url-encoder": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/postman-url-encoder/-/postman-url-encoder-3.0.5.tgz", + "integrity": "sha512-jOrdVvzUXBC7C+9gkIkpDJ3HIxOHTIqjpQ4C1EMt1ZGeMvSEpbFCKq23DEfgsj46vMnDgyQf+1ZLp2Wm+bKSsA==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pretty-ms": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", + "integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==", + "dependencies": { + "parse-ms": "^2.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/relative": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/relative/-/relative-3.0.2.tgz", + "integrity": "sha512-Q5W2qeYtY9GbiR8z1yHNZ1DGhyjb4AnLEjt8iE6XfcC1QIu+FAtj3HQaO0wH28H1mX6cqNLvAqWhP402dxJGyA==", + "dependencies": { + "isobject": "^2.0.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/relative/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/remarkable": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/remarkable/-/remarkable-1.7.4.tgz", + "integrity": "sha512-e6NKUXgX95whv7IgddywbeN/ItCkWbISmc2DiqHJb0wTrqZIexqdco5b8Z3XZoo/48IdNVKM9ZCvTPJ4F5uvhg==", + "dependencies": { + "argparse": "^1.0.10", + "autolinker": "~0.28.0" + }, + "bin": { + "remarkable": "bin/remarkable.js" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", + "deprecated": "https://github.com/lydell/resolve-url#deprecated" + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "engines": { + "node": ">=0.12" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/self-closing-tags": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/self-closing-tags/-/self-closing-tags-1.0.1.tgz", + "integrity": "sha512-7t6hNbYMxM+VHXTgJmxwgZgLGktuXtVVD5AivWzNTdJBM4DBjnDKDzkf2SrNjihaArpeJYNjxkELBu1evI4lQA==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialised-error": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/serialised-error/-/serialised-error-1.1.3.tgz", + "integrity": "sha512-vybp3GItaR1ZtO2nxZZo8eOo7fnVaNtP3XE2vJKgzkKR2bagCkdJ1EpYYhEMd3qu/80DwQk9KjsNSxE3fXWq0g==", + "dependencies": { + "object-hash": "^1.1.2", + "stack-trace": "0.0.9", + "uuid": "^3.0.0" + } + }, + "node_modules/serialised-error/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated" + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stack-trace": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", + "integrity": "sha512-vjUc6sfgtgY0dxCdnc40mK6Oftjo9+2K8H/NG81TMhgL392FtiPA9tn9RLyTxXmTLPJPjF3VyzFp6bsWFLisMQ==", + "engines": { + "node": "*" + } + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stream-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-length/-/stream-length-1.0.2.tgz", + "integrity": "sha512-aI+qKFiwoDV4rsXiS7WRoCt+v2RX1nUj17+KJC5r2gfh5xoSJIfP6Y3Do/HtvesFcTSWthIuJ3l1cvKQY/+nZg==", + "dependencies": { + "bluebird": "^2.6.2" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/striptags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/striptags/-/striptags-3.2.0.tgz", + "integrity": "sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw==" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/teleport-javascript": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/teleport-javascript/-/teleport-javascript-1.0.0.tgz", + "integrity": "sha512-j1llvWVFyEn/6XIFDfX5LAU43DXe0GCt3NfXDwJ8XpRRMkS+i50SAkonAONBy+vxwPFBd50MFU8a2uj8R/ccLg==" + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/to-gfm-code-block": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/to-gfm-code-block/-/to-gfm-code-block-0.1.1.tgz", + "integrity": "sha512-LQRZWyn8d5amUKnfR9A9Uu7x9ss7Re8peuWR2gkh1E+ildOfv2aF26JpuDg8JtvCduu5+hOrMIH+XstZtnagqg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tough-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", + "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==", + "dependencies": { + "ip-regex": "^2.1.0", + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, + "node_modules/typeof-article": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/typeof-article/-/typeof-article-0.1.1.tgz", + "integrity": "sha512-Vn42zdX3FhmUrzEmitX3iYyLb+Umwpmv8fkZRIknYh84lmdrwqZA5xYaoKiIj2Rc5i/5wcDrpUmZcbk1U51vTw==", + "dependencies": { + "kind-of": "^3.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/typeof-article/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/union-value/node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/union-value/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", + "deprecated": "Please see https://github.com/lydell/urix#deprecated" + }, + "node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/uvm": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/uvm/-/uvm-2.0.2.tgz", + "integrity": "sha512-Ra+aPiS5GXAbwXmyNExqdS42sTqmmx4XWEDF8uJlsTfOkKf9Rd9xNgav1Yckv4HfVEZg4iOFODWHFYuJ+9Fzfg==", + "dependencies": { + "flatted": "3.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/year": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/year/-/year-0.2.1.tgz", + "integrity": "sha512-9GnJUZ0QM4OgXuOzsKNzTJ5EOkums1Xc+3YQXp+Q+UxFjf7zLucp9dQ8QMIft0Szs1E1hUiXFim1OYfEKFq97w==", + "engines": { + "node": ">=0.8" + } + } + } +} diff --git a/e2e/package.json b/e2e/package.json new file mode 100644 index 00000000..d06cf4db --- /dev/null +++ b/e2e/package.json @@ -0,0 +1,15 @@ +{ + "name": "lollipop-e2e-test", + "version": "1.0.0", + "description": "Project for Lollipop SDK end-to-end automatic tests", + "main": "automatic-test.js", + "scripts": { + "execute-test": "node automatic-test.js" + }, + "author": "", + "license": "ISC", + "dependencies": { + "newman": "^5.3.2", + "newman-reporter-htmlextra": "^1.22.11" + } +} diff --git a/samples/simple/src/main/java/it/pagopa/tech/sample/MockAssertionVerifierService.java b/samples/simple/src/main/java/it/pagopa/tech/sample/MockAssertionVerifierService.java deleted file mode 100644 index 4611c4c4..00000000 --- a/samples/simple/src/main/java/it/pagopa/tech/sample/MockAssertionVerifierService.java +++ /dev/null @@ -1,31 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.sample; - -import it.pagopa.tech.lollipop.consumer.assertion.AssertionService; -import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; -import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; -import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerService; -import it.pagopa.tech.lollipop.consumer.model.IdpCertData; -import it.pagopa.tech.lollipop.consumer.service.impl.AssertionVerifierServiceImpl; -import org.w3c.dom.Document; - -import java.util.List; - -public class MockAssertionVerifierService extends AssertionVerifierServiceImpl { - - public MockAssertionVerifierService( - IdpCertProvider idpCertProvider, - AssertionService assertionService, - LollipopConsumerRequestConfig lollipopRequestConfig) { - super( - new LollipopLogbackLoggerService(), - idpCertProvider, - assertionService, - lollipopRequestConfig); - } - - @Override - protected boolean validateSignature(Document assertionDoc, List idpCertDataList) { - return true; - } -} From 7cbea900b7daf374b0f2a07c68ee04897a47db49 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 28 Apr 2023 10:54:42 +0200 Subject: [PATCH 315/403] [rework_simple_assertion_storage] Updated SimpleAssertionStorage --- .../storage/SimpleAssertionStorage.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java index 71361b78..05c80143 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java @@ -4,10 +4,12 @@ import it.pagopa.tech.lollipop.consumer.model.DelayedCacheObject; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import java.lang.ref.SoftReference; +import java.util.Objects; import java.util.Optional; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import javax.inject.Inject; +import lombok.extern.slf4j.Slf4j; /** * Implementation of the {@link AssertionStorage} interface as a simple in memory storage. @@ -18,6 +20,7 @@ * eviction operations, every time an assertion is accessed the associated eviction operation is * rescheduled. */ +@Slf4j public class SimpleAssertionStorage implements AssertionStorage { private final ConcurrentHashMap> cache; @@ -141,7 +144,18 @@ public void saveAssertion(String assertionRef, SamlAssertion assertion) { CompletableFuture.supplyAsync( () -> { if (numberOfElements.get() >= storageConfig.getMaxNumberOfElements()) { - cleaningUpQueue.remove(); + DelayedCacheObject delayedCacheObject = + cleaningUpQueue.remove(); + if (delayedCacheObject != null) { + SoftReference removedElement = + cache.remove(delayedCacheObject.getKey()); + if (removedElement != null && removedElement.get() != null) { + log.trace( + "Removed object: " + + Objects.requireNonNull(removedElement.get()) + .getAssertionRef()); + } + } } long expiryTime = System.currentTimeMillis() From ea5d214cd2d7fad15c70b16172523ff4426ad17f Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 28 Apr 2023 11:16:31 +0200 Subject: [PATCH 316/403] [SLS-16] Fixed multisignature test --- .../LollipopSDKTest.postman_collection.json | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/e2e/collections/LollipopSDKTest.postman_collection.json b/e2e/collections/LollipopSDKTest.postman_collection.json index b1017b51..48649221 100644 --- a/e2e/collections/LollipopSDKTest.postman_collection.json +++ b/e2e/collections/LollipopSDKTest.postman_collection.json @@ -1,9 +1,9 @@ { "info": { - "_postman_id": "d72dcca1-95d6-43bf-9272-da8a4efa16e1", + "_postman_id": "3b7deb11-2758-4c4f-9c1d-4ff1b9d627b4", "name": "LollipopSDKTest", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "26867059" + "_exporter_id": "25397617" }, "item": [ { @@ -94,7 +94,7 @@ "response": [] }, { - "name": "Success with multi signaure", + "name": "Success with multi signature", "event": [ { "listen": "test", @@ -151,6 +151,11 @@ "value": "{{validUserId}}", "type": "text" }, + { + "key": "x-io-sign-qtspclauses", + "value": "anIoSignClauses", + "type": "text" + }, { "key": "Signature-Input", "value": "sig1=(\"x-io-sign-qtspclauses\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\", sig2=(\"content-digest\" \"x-pagopa-lollipop-original-method\" \"x-pagopa-lollipop-original-url\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\"", From 8c0573b9f70fa1ccff1bea79b9cb319dbb3c8b82 Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 28 Apr 2023 11:18:59 +0200 Subject: [PATCH 317/403] [SLS-16] Added node_modules and test reports to gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 89912179..396fd4ac 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,7 @@ # Ignore Gradle build output directory build + +# Ignore newman node modules and test reports +e2e/newman +e2e/node_modules \ No newline at end of file From 12f2f8c80a3cdc8f7b72ea58eeea3a48b70cbb5b Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 28 Apr 2023 11:38:10 +0200 Subject: [PATCH 318/403] [SLS-16] Added pr_scan tasks to run e2e tests --- .github/workflows/pr_scan.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index f88cb992..b23b5c3c 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -84,3 +84,11 @@ jobs: -Dsonar.java.libraries="**/*.jar" -Dsonar.login=${{ env.SONAR_TOKEN }} -Dsonar.branch.name=${{ github.head_ref }} + - name: Run docker compose dev + run: docker compose --env-file .env.dev up + - name: Install node modules + run: cd e2e && npm install + - name: Execute e2e tests + run: npm run execute-test + - name: Shutdown docker compose + run: docker compose down From f3aec80e3270548948152b8da8bc4a88ef26c0bd Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 28 Apr 2023 11:51:36 +0200 Subject: [PATCH 319/403] [SLS-16] Added build tasks - commented tasks for testing --- .github/workflows/pr_scan.yml | 128 ++++++++++++++++++---------------- 1 file changed, 66 insertions(+), 62 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index b23b5c3c..85189aa4 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -24,69 +24,73 @@ jobs: uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 with: fetch-depth: 0 - - name: Setup Gradle - uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 - - name: Cache SonarCloud packages - uses: actions/cache@v1 - with: - path: ~/.sonar-project.properties/cache - key: ${{ runner.os }}-sonar-project.properties - restore-keys: ${{ runner.os }}-sonar-project.properties - - name: Make gradlew executable - run: chmod +x ./gradlew - - name: Run build with Gradle Wrapper - run: ./gradlew build testCodeCoverageReport - - name: Add coverage to PR - id: jacoco - uses: madrapps/jacoco-report@7a334255fbce42f385d7567c25d986a9c62e2971 - with: - paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml - token: ${{ secrets.GITHUB_TOKEN }} - min-coverage-overall: 40 - min-coverage-changed-files: 60 - - name: Build the Docker image - run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest - - name: Run the Anchore Grype scan action - uses: anchore/scan-action@d5aa5b6cb9414b0c7771438046ff5bcfa2854ed7 - id: scan - with: - image: "localbuild/testimage:latest" - fail-build: true - severity-cutoff: "high" - - name: Upload Anchore Scan Report - uses: github/codeql-action/upload-sarif@9885f86fab4879632b7e44514f19148225dfbdcd - if: always() - with: - sarif_file: ${{ steps.scan.outputs.sarif }} - - name: Run Sonar Scanner on Pull Request - if: ${{ github.event_name == 'pull_request' }} - run: ./gradlew sonar --info - -Dsonar.organization=pagopa - -Dsonar.projectKey=${{ env.PROJECT_KEY }} - -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml - -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" - -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" - -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 }} - -Dsonar.pullrequest.base=${{ github.base_ref }} - - name: Run Sonar Scanner - if: ${{ github.event_name != 'pull_request' }} - run: ./gradlew sonar --info - -Dsonar.organization=pagopa - -Dsonar.projectKey=${{ env.PROJECT_KEY }} - -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml - -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" - -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" - -Dsonar.host.url=https://sonarcloud.io - -Dsonar.java.libraries="**/*.jar" - -Dsonar.login=${{ env.SONAR_TOKEN }} - -Dsonar.branch.name=${{ github.head_ref }} - - name: Run docker compose dev +# - name: Setup Gradle +# uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 +# - name: Cache SonarCloud packages +# uses: actions/cache@v1 +# with: +# path: ~/.sonar-project.properties/cache +# key: ${{ runner.os }}-sonar-project.properties +# restore-keys: ${{ runner.os }}-sonar-project.properties +# - name: Make gradlew executable +# run: chmod +x ./gradlew +# - name: Run build with Gradle Wrapper +# run: ./gradlew build testCodeCoverageReport +# - name: Add coverage to PR +# id: jacoco +# uses: madrapps/jacoco-report@7a334255fbce42f385d7567c25d986a9c62e2971 +# with: +# paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml +# token: ${{ secrets.GITHUB_TOKEN }} +# min-coverage-overall: 40 +# min-coverage-changed-files: 60 +# - name: Build the Docker image +# run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest +# - name: Run the Anchore Grype scan action +# uses: anchore/scan-action@d5aa5b6cb9414b0c7771438046ff5bcfa2854ed7 +# id: scan +# with: +# image: "localbuild/testimage:latest" +# fail-build: true +# severity-cutoff: "high" +# - name: Upload Anchore Scan Report +# uses: github/codeql-action/upload-sarif@9885f86fab4879632b7e44514f19148225dfbdcd +# if: always() +# with: +# sarif_file: ${{ steps.scan.outputs.sarif }} +# - name: Run Sonar Scanner on Pull Request +# if: ${{ github.event_name == 'pull_request' }} +# run: ./gradlew sonar --info +# -Dsonar.organization=pagopa +# -Dsonar.projectKey=${{ env.PROJECT_KEY }} +# -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml +# -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" +# -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" +# -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 }} +# -Dsonar.pullrequest.base=${{ github.base_ref }} +# - name: Run Sonar Scanner +# if: ${{ github.event_name != 'pull_request' }} +# run: ./gradlew sonar --info +# -Dsonar.organization=pagopa +# -Dsonar.projectKey=${{ env.PROJECT_KEY }} +# -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml +# -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" +# -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" +# -Dsonar.host.url=https://sonarcloud.io +# -Dsonar.java.libraries="**/*.jar" +# -Dsonar.login=${{ env.SONAR_TOKEN }} +# -Dsonar.branch.name=${{ github.head_ref }} + - name: Build Spring Sample + run: cd samples/spring && ./gradlew bootJar + - name: Build Docker compose + run: docker compose build + - name: Run Docker compose dev run: docker compose --env-file .env.dev up - - name: Install node modules + - name: Install Node Modules run: cd e2e && npm install - name: Execute e2e tests run: npm run execute-test From 8193d439a6efa094b27448980491ac3aa5e71f03 Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 28 Apr 2023 11:54:24 +0200 Subject: [PATCH 320/403] [SLS-16] Decommented gradle tasks --- .github/workflows/pr_scan.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 85189aa4..b1cc5a34 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -32,8 +32,8 @@ jobs: # path: ~/.sonar-project.properties/cache # key: ${{ runner.os }}-sonar-project.properties # restore-keys: ${{ runner.os }}-sonar-project.properties -# - name: Make gradlew executable -# run: chmod +x ./gradlew + - name: Make gradlew executable + run: chmod +x ./gradlew # - name: Run build with Gradle Wrapper # run: ./gradlew build testCodeCoverageReport # - name: Add coverage to PR @@ -85,7 +85,7 @@ jobs: # -Dsonar.login=${{ env.SONAR_TOKEN }} # -Dsonar.branch.name=${{ github.head_ref }} - name: Build Spring Sample - run: cd samples/spring && ./gradlew bootJar + run: cd samples/spring && gradlew bootJar - name: Build Docker compose run: docker compose build - name: Run Docker compose dev From cb875f59b3de94cc5e559ec82cebcb554c738362 Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 28 Apr 2023 11:55:53 +0200 Subject: [PATCH 321/403] [SLS-16] Fixed gradlew command --- .github/workflows/pr_scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index b1cc5a34..ae9137da 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -85,7 +85,7 @@ jobs: # -Dsonar.login=${{ env.SONAR_TOKEN }} # -Dsonar.branch.name=${{ github.head_ref }} - name: Build Spring Sample - run: cd samples/spring && gradlew bootJar + run: cd samples/spring && ./gradlew bootJar - name: Build Docker compose run: docker compose build - name: Run Docker compose dev From 4f6099700eb0e1fedf0d9481eb542e03ef73a8e1 Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 28 Apr 2023 11:59:53 +0200 Subject: [PATCH 322/403] [SLS-16] Decommented gradle action --- .github/workflows/pr_scan.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index ae9137da..f2ba14a3 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -24,8 +24,8 @@ jobs: uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 with: fetch-depth: 0 -# - name: Setup Gradle -# uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 + - name: Setup Gradle + uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 # - name: Cache SonarCloud packages # uses: actions/cache@v1 # with: From 1801f406544ee960242abe5349e46c21cb3eff13 Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 28 Apr 2023 12:06:26 +0200 Subject: [PATCH 323/403] [SLS-16] Defined working directories for tasks --- .github/workflows/pr_scan.yml | 152 +++++++++++++++++----------------- 1 file changed, 76 insertions(+), 76 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index f2ba14a3..2d334ccf 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -20,79 +20,79 @@ jobs: pull-requests: write steps: - - name: Checkout project sources - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - with: - fetch-depth: 0 - - name: Setup Gradle - uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 -# - name: Cache SonarCloud packages -# uses: actions/cache@v1 -# with: -# path: ~/.sonar-project.properties/cache -# key: ${{ runner.os }}-sonar-project.properties -# restore-keys: ${{ runner.os }}-sonar-project.properties - - name: Make gradlew executable - run: chmod +x ./gradlew -# - name: Run build with Gradle Wrapper -# run: ./gradlew build testCodeCoverageReport -# - name: Add coverage to PR -# id: jacoco -# uses: madrapps/jacoco-report@7a334255fbce42f385d7567c25d986a9c62e2971 -# with: -# paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml -# token: ${{ secrets.GITHUB_TOKEN }} -# min-coverage-overall: 40 -# min-coverage-changed-files: 60 -# - name: Build the Docker image -# run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest -# - name: Run the Anchore Grype scan action -# uses: anchore/scan-action@d5aa5b6cb9414b0c7771438046ff5bcfa2854ed7 -# id: scan -# with: -# image: "localbuild/testimage:latest" -# fail-build: true -# severity-cutoff: "high" -# - name: Upload Anchore Scan Report -# uses: github/codeql-action/upload-sarif@9885f86fab4879632b7e44514f19148225dfbdcd -# if: always() -# with: -# sarif_file: ${{ steps.scan.outputs.sarif }} -# - name: Run Sonar Scanner on Pull Request -# if: ${{ github.event_name == 'pull_request' }} -# run: ./gradlew sonar --info -# -Dsonar.organization=pagopa -# -Dsonar.projectKey=${{ env.PROJECT_KEY }} -# -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml -# -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" -# -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" -# -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 }} -# -Dsonar.pullrequest.base=${{ github.base_ref }} -# - name: Run Sonar Scanner -# if: ${{ github.event_name != 'pull_request' }} -# run: ./gradlew sonar --info -# -Dsonar.organization=pagopa -# -Dsonar.projectKey=${{ env.PROJECT_KEY }} -# -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml -# -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" -# -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" -# -Dsonar.host.url=https://sonarcloud.io -# -Dsonar.java.libraries="**/*.jar" -# -Dsonar.login=${{ env.SONAR_TOKEN }} -# -Dsonar.branch.name=${{ github.head_ref }} - - name: Build Spring Sample - run: cd samples/spring && ./gradlew bootJar - - name: Build Docker compose - run: docker compose build - - name: Run Docker compose dev - run: docker compose --env-file .env.dev up - - name: Install Node Modules - run: cd e2e && npm install - - name: Execute e2e tests - run: npm run execute-test - - name: Shutdown docker compose - run: docker compose down + - name: Checkout project sources + uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + with: + fetch-depth: 0 + - name: Setup Gradle + uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 + # - name: Cache SonarCloud packages + # uses: actions/cache@v1 + # with: + # path: ~/.sonar-project.properties/cache + # key: ${{ runner.os }}-sonar-project.properties + # restore-keys: ${{ runner.os }}-sonar-project.properties + - name: Make gradlew executable + run: chmod +x ./gradlew + # - name: Run build with Gradle Wrapper + # run: ./gradlew build testCodeCoverageReport + # - name: Add coverage to PR + # id: jacoco + # uses: madrapps/jacoco-report@7a334255fbce42f385d7567c25d986a9c62e2971 + # with: + # paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml + # token: ${{ secrets.GITHUB_TOKEN }} + # min-coverage-overall: 40 + # min-coverage-changed-files: 60 + # - name: Build the Docker image + # run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest + # - name: Run the Anchore Grype scan action + # uses: anchore/scan-action@d5aa5b6cb9414b0c7771438046ff5bcfa2854ed7 + # id: scan + # with: + # image: "localbuild/testimage:latest" + # fail-build: true + # severity-cutoff: "high" + # - name: Upload Anchore Scan Report + # uses: github/codeql-action/upload-sarif@9885f86fab4879632b7e44514f19148225dfbdcd + # if: always() + # with: + # sarif_file: ${{ steps.scan.outputs.sarif }} + # - name: Run Sonar Scanner on Pull Request + # if: ${{ github.event_name == 'pull_request' }} + # run: ./gradlew sonar --info + # -Dsonar.organization=pagopa + # -Dsonar.projectKey=${{ env.PROJECT_KEY }} + # -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml + # -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" + # -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" + # -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 }} + # -Dsonar.pullrequest.base=${{ github.base_ref }} + # - name: Run Sonar Scanner + # if: ${{ github.event_name != 'pull_request' }} + # run: ./gradlew sonar --info + # -Dsonar.organization=pagopa + # -Dsonar.projectKey=${{ env.PROJECT_KEY }} + # -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml + # -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" + # -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" + # -Dsonar.host.url=https://sonarcloud.io + # -Dsonar.java.libraries="**/*.jar" + # -Dsonar.login=${{ env.SONAR_TOKEN }} + # -Dsonar.branch.name=${{ github.head_ref }} + - name: Build Spring Sample + working-directory: ./samples/spring + run: chmod +x ./gradlew && ./gradlew bootJar + - name: Build Docker compose + run: docker compose build + - name: Run Docker compose dev + run: docker compose --env-file .env.dev up + - name: Install node modules and execute e2e tests + working-directory: ./e2e + run: npm install && npm run execute-test + - name: Shutdown docker compose + run: docker compose down From ab70da3eb7ded1811c3245c27116b80104b3080e Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 28 Apr 2023 12:08:45 +0200 Subject: [PATCH 324/403] [rework_simple_assertion_storage] Updated SimpleAssertionStorage --- .../storage/SimpleAssertionStorage.java | 27 ++++++------ .../storage/SimpleAssertionStorageTest.java | 41 ++++++++++++++++--- 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java index 05c80143..c01bf5da 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorage.java @@ -144,18 +144,7 @@ public void saveAssertion(String assertionRef, SamlAssertion assertion) { CompletableFuture.supplyAsync( () -> { if (numberOfElements.get() >= storageConfig.getMaxNumberOfElements()) { - DelayedCacheObject delayedCacheObject = - cleaningUpQueue.remove(); - if (delayedCacheObject != null) { - SoftReference removedElement = - cache.remove(delayedCacheObject.getKey()); - if (removedElement != null && removedElement.get() != null) { - log.trace( - "Removed object: " - + Objects.requireNonNull(removedElement.get()) - .getAssertionRef()); - } - } + removeDelayedObject(); } long expiryTime = System.currentTimeMillis() @@ -173,6 +162,20 @@ public void saveAssertion(String assertionRef, SamlAssertion assertion) { } } + protected void removeDelayedObject() { + DelayedCacheObject delayedCacheObject = cleaningUpQueue.peek(); + boolean isRemoved = cleaningUpQueue.remove(delayedCacheObject); + if (isRemoved) { + assert delayedCacheObject != null; + SoftReference removedElement = cache.remove(delayedCacheObject.getKey()); + if (removedElement != null && removedElement.get() != null) { + log.trace( + "Removed object: " + + Objects.requireNonNull(removedElement.get()).getAssertionRef()); + } + } + } + public void close() { this.cleanerThread.interrupt(); this.cleaningUpQueue.clear(); diff --git a/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java index 0fc8fc77..819971bb 100644 --- a/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java +++ b/core/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/storage/SimpleAssertionStorageTest.java @@ -93,7 +93,7 @@ void saveAssertionAndScheduleEvictionWithStorageEnabled() assertEquals(1, delayedCacheObjects.size()); assertEquals(samlAssertion, assertionMap.get(ASSERTION_REF_1).get()); - delayedCacheObjects.poll(1000, TimeUnit.MILLISECONDS); + delayedCacheObjects.poll(1100, TimeUnit.MILLISECONDS); assertEquals(0, assertionMap.size()); assertEquals(0, delayedCacheObjects.size()); @@ -101,8 +101,7 @@ void saveAssertionAndScheduleEvictionWithStorageEnabled() } @Test - void saveAssertionToMaximumCapacityWithStorageEnabled() - throws InterruptedException, ExecutionException { + void saveAssertionToMaximumCapacityWithStorageEnabled() throws InterruptedException { doReturn(true).when(storageConfigMock).isAssertionStorageEnabled(); doReturn(1000L).when(storageConfigMock).getStorageEvictionDelay(); doReturn(TimeUnit.MILLISECONDS).when(storageConfigMock).getStorageEvictionDelayTimeUnit(); @@ -113,12 +112,14 @@ void saveAssertionToMaximumCapacityWithStorageEnabled() DelayQueue> delayedCacheObjects = new DelayQueue<>(); sut = new SimpleAssertionStorage(assertionMap, delayedCacheObjects, storageConfigMock); - SamlAssertion samlAssertion = new SamlAssertion(); + SamlAssertion samlAssertion; - for (int i = 0; i < 101; i++) { + for (int i = 0; i < 120; i++) { + samlAssertion = new SamlAssertion(); + samlAssertion.setAssertionRef(ASSERTION_REF_1 + i); sut.saveAssertion(ASSERTION_REF_1 + i, samlAssertion); } - delayedCacheObjects.poll(150, TimeUnit.MILLISECONDS); + delayedCacheObjects.poll(200, TimeUnit.MILLISECONDS); assertEquals(100, delayedCacheObjects.size()); @@ -157,4 +158,32 @@ void savaAssertionWithStorageDisabled() { sut.close(); } + + @Test + void removedCacheObjectIfNotNull() throws InterruptedException { + doReturn(true).when(storageConfigMock).isAssertionStorageEnabled(); + doReturn(10000L).when(storageConfigMock).getStorageEvictionDelay(); + doReturn(TimeUnit.MILLISECONDS).when(storageConfigMock).getStorageEvictionDelayTimeUnit(); + doReturn(100L).when(storageConfigMock).getMaxNumberOfElements(); + + ConcurrentHashMap> assertionMap = + new ConcurrentHashMap<>(); + DelayQueue> delayedCacheObjects = new DelayQueue<>(); + + sut = new SimpleAssertionStorage(assertionMap, delayedCacheObjects, storageConfigMock); + SamlAssertion samlAssertion = new SamlAssertion(); + + sut.saveAssertion(ASSERTION_REF_1, samlAssertion); + delayedCacheObjects.poll(100, TimeUnit.MILLISECONDS); + + assertEquals(1, assertionMap.size()); + assertEquals(1, delayedCacheObjects.size()); + + sut.removeDelayedObject(); + + assertEquals(0, assertionMap.size()); + assertEquals(0, delayedCacheObjects.size()); + + sut.close(); + } } From 3b13852699a9bbb8a8b62782aaa263bb6d2c6689 Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 28 Apr 2023 12:09:05 +0200 Subject: [PATCH 325/403] [SLS-16] Added publish to maven local --- .github/workflows/pr_scan.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 2d334ccf..f6ead435 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -84,6 +84,8 @@ jobs: # -Dsonar.java.libraries="**/*.jar" # -Dsonar.login=${{ env.SONAR_TOKEN }} # -Dsonar.branch.name=${{ github.head_ref }} + - name: Publish to Maven Local + run: ./gradlew publishToMavenLocal - name: Build Spring Sample working-directory: ./samples/spring run: chmod +x ./gradlew && ./gradlew bootJar From 43046ed83fb8cd858383135dc411854c9bc5df66 Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 28 Apr 2023 12:15:09 +0200 Subject: [PATCH 326/403] [SLS-16] Docker compose up run in foreground --- .github/workflows/pr_scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index f6ead435..79183cd0 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -92,7 +92,7 @@ jobs: - name: Build Docker compose run: docker compose build - name: Run Docker compose dev - run: docker compose --env-file .env.dev up + run: docker compose --env-file .env.dev up -d - name: Install node modules and execute e2e tests working-directory: ./e2e run: npm install && npm run execute-test From 8713b456c1e8fcc6fdf455e05f226e456b2162b3 Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 28 Apr 2023 12:20:07 +0200 Subject: [PATCH 327/403] [SLS-16] Merged docker compose up and build --- .github/workflows/pr_scan.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 79183cd0..28e157ad 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -89,10 +89,8 @@ jobs: - name: Build Spring Sample working-directory: ./samples/spring run: chmod +x ./gradlew && ./gradlew bootJar - - name: Build Docker compose - run: docker compose build - - name: Run Docker compose dev - run: docker compose --env-file .env.dev up -d + - name: Run Docker compose with .env.dev + run: docker compose --env-file .env.dev up -d --build - name: Install node modules and execute e2e tests working-directory: ./e2e run: npm install && npm run execute-test From ef4cbfd19eebcbd23b73fadcb793c19292f10f0e Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 28 Apr 2023 12:38:15 +0200 Subject: [PATCH 328/403] [SLS-16] Newman failed assertion test --- e2e/automatic-test.js | 3 ++- e2e/collections/LollipopSDKTest.postman_collection.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/e2e/automatic-test.js b/e2e/automatic-test.js index eef19b37..2a33fcd5 100644 --- a/e2e/automatic-test.js +++ b/e2e/automatic-test.js @@ -3,7 +3,8 @@ const newman = require('newman'); newman.run({ collection: require('./collections/LollipopSDKTest.postman_collection.json'), environment: './env/Lollipop environment variables.postman_environment.json', - reporters: 'htmlextra' + reporters: 'cli', + bail: true }, function (err, summary) { if (err) { throw err; } console.info('collection run complete!'); diff --git a/e2e/collections/LollipopSDKTest.postman_collection.json b/e2e/collections/LollipopSDKTest.postman_collection.json index 48649221..14dc96d1 100644 --- a/e2e/collections/LollipopSDKTest.postman_collection.json +++ b/e2e/collections/LollipopSDKTest.postman_collection.json @@ -154,7 +154,8 @@ { "key": "x-io-sign-qtspclauses", "value": "anIoSignClauses", - "type": "text" + "type": "text", + "disabled": true }, { "key": "Signature-Input", From e0259eaeadcafe73b71b84324be3b6f5f11f15a9 Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 28 Apr 2023 12:42:30 +0200 Subject: [PATCH 329/403] [SLS-16] Throwing error test --- e2e/automatic-test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/e2e/automatic-test.js b/e2e/automatic-test.js index 2a33fcd5..e9f3b3d8 100644 --- a/e2e/automatic-test.js +++ b/e2e/automatic-test.js @@ -6,6 +6,5 @@ newman.run({ reporters: 'cli', bail: true }, function (err, summary) { - if (err) { throw err; } - console.info('collection run complete!'); + throw err; }); \ No newline at end of file From 126a312d3b48984a81470c13f948efcaa4d6a4e7 Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 28 Apr 2023 13:10:28 +0200 Subject: [PATCH 330/403] [SLS-16] Throw errors when collection tests failes --- e2e/automatic-test.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/e2e/automatic-test.js b/e2e/automatic-test.js index e9f3b3d8..f4b508af 100644 --- a/e2e/automatic-test.js +++ b/e2e/automatic-test.js @@ -3,8 +3,16 @@ const newman = require('newman'); newman.run({ collection: require('./collections/LollipopSDKTest.postman_collection.json'), environment: './env/Lollipop environment variables.postman_environment.json', - reporters: 'cli', + reporters: ['cli', 'htmlextra'], bail: true }, function (err, summary) { - throw err; + if (err) { throw err; } + if(summary?.run?.error){ throw 'collection run encountered an error.';} + + if(summary?.run?.failures?.length > 0){ + const errors = summary.run.failures; + throw `following collection tests failed: ${errors.map((er) => `\n${er.source.name}`)}`; + } + + console.info('collection run completed.'); }); \ No newline at end of file From e3829db5237534105c01361fbe3217b55d52b59a Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 28 Apr 2023 13:18:33 +0200 Subject: [PATCH 331/403] [SLS-16] Decommented PR scan tests - re-committed right postman collection --- .github/workflows/pr_scan.yml | 112 +++++++++--------- .../LollipopSDKTest.postman_collection.json | 3 +- 2 files changed, 57 insertions(+), 58 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 28e157ad..abf8e474 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -26,64 +26,64 @@ jobs: fetch-depth: 0 - name: Setup Gradle uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 - # - name: Cache SonarCloud packages - # uses: actions/cache@v1 - # with: - # path: ~/.sonar-project.properties/cache - # key: ${{ runner.os }}-sonar-project.properties - # restore-keys: ${{ runner.os }}-sonar-project.properties + - name: Cache SonarCloud packages + uses: actions/cache@v1 + with: + path: ~/.sonar-project.properties/cache + key: ${{ runner.os }}-sonar-project.properties + restore-keys: ${{ runner.os }}-sonar-project.properties - name: Make gradlew executable run: chmod +x ./gradlew - # - name: Run build with Gradle Wrapper - # run: ./gradlew build testCodeCoverageReport - # - name: Add coverage to PR - # id: jacoco - # uses: madrapps/jacoco-report@7a334255fbce42f385d7567c25d986a9c62e2971 - # with: - # paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml - # token: ${{ secrets.GITHUB_TOKEN }} - # min-coverage-overall: 40 - # min-coverage-changed-files: 60 - # - name: Build the Docker image - # run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest - # - name: Run the Anchore Grype scan action - # uses: anchore/scan-action@d5aa5b6cb9414b0c7771438046ff5bcfa2854ed7 - # id: scan - # with: - # image: "localbuild/testimage:latest" - # fail-build: true - # severity-cutoff: "high" - # - name: Upload Anchore Scan Report - # uses: github/codeql-action/upload-sarif@9885f86fab4879632b7e44514f19148225dfbdcd - # if: always() - # with: - # sarif_file: ${{ steps.scan.outputs.sarif }} - # - name: Run Sonar Scanner on Pull Request - # if: ${{ github.event_name == 'pull_request' }} - # run: ./gradlew sonar --info - # -Dsonar.organization=pagopa - # -Dsonar.projectKey=${{ env.PROJECT_KEY }} - # -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml - # -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" - # -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" - # -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 }} - # -Dsonar.pullrequest.base=${{ github.base_ref }} - # - name: Run Sonar Scanner - # if: ${{ github.event_name != 'pull_request' }} - # run: ./gradlew sonar --info - # -Dsonar.organization=pagopa - # -Dsonar.projectKey=${{ env.PROJECT_KEY }} - # -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml - # -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" - # -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" - # -Dsonar.host.url=https://sonarcloud.io - # -Dsonar.java.libraries="**/*.jar" - # -Dsonar.login=${{ env.SONAR_TOKEN }} - # -Dsonar.branch.name=${{ github.head_ref }} + - name: Run build with Gradle Wrapper + run: ./gradlew build testCodeCoverageReport + - name: Add coverage to PR + id: jacoco + uses: madrapps/jacoco-report@7a334255fbce42f385d7567c25d986a9c62e2971 + with: + paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml + token: ${{ secrets.GITHUB_TOKEN }} + min-coverage-overall: 40 + min-coverage-changed-files: 60 + - name: Build the Docker image + run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest + - name: Run the Anchore Grype scan action + uses: anchore/scan-action@d5aa5b6cb9414b0c7771438046ff5bcfa2854ed7 + id: scan + with: + image: "localbuild/testimage:latest" + fail-build: true + severity-cutoff: "high" + - name: Upload Anchore Scan Report + uses: github/codeql-action/upload-sarif@9885f86fab4879632b7e44514f19148225dfbdcd + if: always() + with: + sarif_file: ${{ steps.scan.outputs.sarif }} + - name: Run Sonar Scanner on Pull Request + if: ${{ github.event_name == 'pull_request' }} + run: ./gradlew sonar --info + -Dsonar.organization=pagopa + -Dsonar.projectKey=${{ env.PROJECT_KEY }} + -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml + -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" + -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" + -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 }} + -Dsonar.pullrequest.base=${{ github.base_ref }} + - name: Run Sonar Scanner + if: ${{ github.event_name != 'pull_request' }} + run: ./gradlew sonar --info + -Dsonar.organization=pagopa + -Dsonar.projectKey=${{ env.PROJECT_KEY }} + -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml + -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" + -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" + -Dsonar.host.url=https://sonarcloud.io + -Dsonar.java.libraries="**/*.jar" + -Dsonar.login=${{ env.SONAR_TOKEN }} + -Dsonar.branch.name=${{ github.head_ref }} - name: Publish to Maven Local run: ./gradlew publishToMavenLocal - name: Build Spring Sample diff --git a/e2e/collections/LollipopSDKTest.postman_collection.json b/e2e/collections/LollipopSDKTest.postman_collection.json index 14dc96d1..48649221 100644 --- a/e2e/collections/LollipopSDKTest.postman_collection.json +++ b/e2e/collections/LollipopSDKTest.postman_collection.json @@ -154,8 +154,7 @@ { "key": "x-io-sign-qtspclauses", "value": "anIoSignClauses", - "type": "text", - "disabled": true + "type": "text" }, { "key": "Signature-Input", From 7870cad8579801b202b3ef0d1f0bb6e7e30140b5 Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 28 Apr 2023 13:22:51 +0200 Subject: [PATCH 332/403] [SLS-16] Added path matcher to interceptor sample spring --- .../consumer/sample/config/SampleWebConfigurer.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleWebConfigurer.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleWebConfigurer.java index dc7bc1fa..e6df8b7d 100644 --- a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleWebConfigurer.java +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleWebConfigurer.java @@ -4,6 +4,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; +import org.springframework.util.AntPathMatcher; import org.springframework.web.filter.CommonsRequestLoggingFilter; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -24,8 +25,11 @@ public CommonsRequestLoggingFilter loggingFilter() { return filter; } + @Override public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(interceptor); + registry.addInterceptor(interceptor) + .addPathPatterns("/") + .pathMatcher(new AntPathMatcher()); } } From a2cf555b377503df112460d07e7faa2135361fa4 Mon Sep 17 00:00:00 2001 From: giomella Date: Tue, 2 May 2023 10:30:56 +0200 Subject: [PATCH 333/403] [SLS-16] added config for spring sample endpoint. --- .../sample/config/SampleLollipopConsumerConfig.java | 13 +++++++++++++ .../sample/config/SampleServicesConfig.java | 5 +---- .../consumer/sample/config/SampleWebConfigurer.java | 4 +++- .../sample/controller/SampleController.java | 4 ++-- .../src/main/resources/application.properties | 2 ++ 5 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleLollipopConsumerConfig.java diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleLollipopConsumerConfig.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleLollipopConsumerConfig.java new file mode 100644 index 00000000..ab2ec0cd --- /dev/null +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleLollipopConsumerConfig.java @@ -0,0 +1,13 @@ +package it.pagopa.tech.lollipop.consumer.sample.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; + +@ConfigurationProperties(prefix = "sample.lollipop.consumer.config") +@ConfigurationPropertiesScan +@Data +public class SampleLollipopConsumerConfig { + + private String endpoint; +} diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java index e460f4cc..0baec8b3 100644 --- a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleServicesConfig.java @@ -1,12 +1,9 @@ package it.pagopa.tech.lollipop.consumer.sample.config; import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; -import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientConfig; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientProvider; import it.pagopa.tech.lollipop.consumer.assertion.impl.AssertionServiceFactoryImpl; import it.pagopa.tech.lollipop.consumer.assertion.storage.SimpleAssertionStorageProvider; -import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; -import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; import it.pagopa.tech.lollipop.consumer.http_verifier.visma.VismaHttpMessageVerifierFactory; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; @@ -24,7 +21,7 @@ @Configuration @EnableConfigurationProperties(value = {SpringLollipopConsumerRequestConfig.class, SpringAssertionStorageConfig.class, - SpringAssertionSimpleClientConfig.class, SpringIdpCertSimpleClientConfig.class, SpringIdpCertStorageConfig.class}) + SpringAssertionSimpleClientConfig.class, SpringIdpCertSimpleClientConfig.class, SpringIdpCertStorageConfig.class, SampleLollipopConsumerConfig.class}) public class SampleServicesConfig { @Bean diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleWebConfigurer.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleWebConfigurer.java index e6df8b7d..c2b583fb 100644 --- a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleWebConfigurer.java +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/config/SampleWebConfigurer.java @@ -14,6 +14,8 @@ public class SampleWebConfigurer implements WebMvcConfigurer { @Autowired private HttpVerifierHandlerInterceptor interceptor; + @Autowired + private SampleLollipopConsumerConfig sampleLollipopConsumerConfig; @Bean public CommonsRequestLoggingFilter loggingFilter() { @@ -29,7 +31,7 @@ public CommonsRequestLoggingFilter loggingFilter() { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(interceptor) - .addPathPatterns("/") + .addPathPatterns(sampleLollipopConsumerConfig.getEndpoint()) .pathMatcher(new AntPathMatcher()); } } diff --git a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/controller/SampleController.java b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/controller/SampleController.java index 68125252..80b7ffbf 100644 --- a/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/controller/SampleController.java +++ b/samples/spring/src/main/java/it/pagopa/tech/lollipop/consumer/sample/controller/SampleController.java @@ -7,6 +7,6 @@ @RestController public class SampleController { - @RequestMapping("/") - public @ResponseBody String sample() { return "Sample";}; + @RequestMapping("${sample.lollipop.consumer.config.endpoint}") + public @ResponseBody String sample() { return "Sample";} } diff --git a/samples/spring/src/main/resources/application.properties b/samples/spring/src/main/resources/application.properties index e81720c3..091162b0 100644 --- a/samples/spring/src/main/resources/application.properties +++ b/samples/spring/src/main/resources/application.properties @@ -1,5 +1,7 @@ spring.application.name=spring-lollipop-consumer +sample.lollipop.consumer.config.endpoint=${SAMPLE_LOLLIPOP_CONSUMER_ENDPOINT:/api/v1/lollipop-consumer} + ##Client mocks config lollipop.idp.client.mock.enabled=${IDP_CLIENT_MOCK_ENABLED:false} lollipop.assertion.client.mock.enabled=${ASSERTION_CLIENT_MOCK_ENABLED:false} From b8bf510e2eae8c0f30dd3bb83f55ca2393316825 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 2 May 2023 12:31:08 +0200 Subject: [PATCH 334/403] [SLS-16] Added Mockoon to mock spring sample on docker --- .env.dev | 5 +- docker-compose.yaml | 14 ++- e2e/mockoon/mockoonAssertions.json | 117 +++++++++++++++++++++++++ e2e/mockoon/mockoonIDP.json | 135 +++++++++++++++++++++++++++++ 4 files changed, 266 insertions(+), 5 deletions(-) create mode 100644 e2e/mockoon/mockoonAssertions.json create mode 100644 e2e/mockoon/mockoonIDP.json diff --git a/.env.dev b/.env.dev index 8df0b3d3..46b3031e 100644 --- a/.env.dev +++ b/.env.dev @@ -1,5 +1,4 @@ -ASSERTION_CLIENT_MOCK_ENABLED = true -IDP_CLIENT_MOCK_ENABLED = true -IDP_CLIENT_BASE_URI = "http://localhost:3001" +ASSERTION_REST_URI = "http://mockserverAssertion:3000" +IDP_CLIENT_BASE_URI = "http://mockserverIDP:3001" LOLLIPOP_ASSERTION_NOT_BEFORE_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'" LOLLIPOP_ASSERTION_INSTANT_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'" \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 2d37c8a3..7682462c 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,13 +1,23 @@ version: "3.9" services: + mockserverAssertion: + image: mockoon/cli:latest + command: [ "--data", "data", "--port", "3000" ] + volumes: + - ./e2e/mockoon/mockoonAssertions.json:/data:readonly + mockserverIDP: + image: mockoon/cli:latest + command: [ "--data", "data", "--port", "3001" ] + volumes: + - ./e2e/mockoon/mockoonIDP.json:/data:readonly web: build: . ports: - "8080:8080" environment: ##Client mocks config - ASSERTION_CLIENT_MOCK_ENABLED: ${ASSERTION_CLIENT_MOCK_ENABLED} - IDP_CLIENT_MOCK_ENABLED: ${IDP_CLIENT_MOCK_ENABLED} + ASSERTION_CLIENT_MOCK_ENABLED: ${ASSERTION_CLIENT_MOCK_ENABLED:-false} + IDP_CLIENT_MOCK_ENABLED: ${IDP_CLIENT_MOCK_ENABLED:-false} ##General Lollipop Configs Sample LOLLIPOP_ASSERTION_EXPIRE_IN_DAYS: ${LOLLIPOP_ASSERTION_EXPIRE_IN_DAYS:-180} diff --git a/e2e/mockoon/mockoonAssertions.json b/e2e/mockoon/mockoonAssertions.json new file mode 100644 index 00000000..55597bb5 --- /dev/null +++ b/e2e/mockoon/mockoonAssertions.json @@ -0,0 +1,117 @@ +{ + "uuid": "6d242ea2-aae5-47a5-8d9e-4ef378de066f", + "lastMigration": 27, + "name": "MockoonAssertions", + "endpointPrefix": "", + "latency": 0, + "port": 3000, + "hostname": "", + "folders": [], + "routes": [ + { + "uuid": "2b4e835e-84d9-46f0-9940-ae12b0f3d97e", + "type": "http", + "documentation": "", + "method": "get", + "endpoint": "assertions/:assertion", + "responses": [ + { + "uuid": "92f402d5-0421-4e92-9218-093d655430b8", + "body": "{\n \"response_xml\": \"\\n https://spid-testenv2:8088s/DqYePHC7eCXX5ncsiFYNLyKbzS6P5C8331H1b8e30=WcasorooElvhmK0kxFUdBVCqyRYi0SCNGRSZZnC9Q2sZHOYGZbERe4/T8OSuRKbSrEivXIHRgNr8WskZTM2CiywfWChHfGvhERsLuPJE8oh9CR3eicX/eg0ynJqwx4IoYhTb2NOwqMFc66nnutMhG/Smdtjs4SFz0RQYYVeZ5Ho51iTHd94uBV9ZHXjqcvs3EitUsJ0Zg1Pkw352tt8y7niUcGjAd8nydI72S12sF5ePv05AunFp7vZpYbKqi62fQLORCn1ZP7WKFD75hL0bCvZaSRF285GkfSnLfe1S4tLff2SlTQWevOMU/wCkHJmQwHT1LMwcWRnMvv4V+vd1XQ==MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\nBAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\nBhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\nXGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\ndUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\nEKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\nIhh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI/sp\\nILywgDxVMMtv/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\nfhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA/L1/fd70ok+6xtDRF8A3HjAf\\nBgNVHSMEGDAWgBQEVmzA/L1/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH/MA0G\\nCSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\nwTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8/o13vMw4feGxro1hMeUilRtH52funrW\\nC+FgPrqk3o/8cZOnq+CqnFFDfILLiEb/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\nDa1fG/Pi0fG2F0yw/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\njJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk/ZbEHdKcofnziDyl0V8gglP2\\nSxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n\\n \\n \\n \\n \\n https://spid-testenv2:80884cqgG29TSKgNLy2/1eFPXhd5WRVPxZBGcd8DgTvd5Fo=WqxM+y+vtZDcEaIaw2WfcuMuwXUeTOY9ZjaXwzHw+RE8uUr5s8BE1tpaodcKmmqSJK1JQYNr8AUV+W9V79EKfmNtFvfaf0WYeUee7Td7E24QqiyVHjr1YgfDWhSdItFLYJfQUkotj2BepbdwVQGY5yN0Rw6Fq98hgNOgsxty7g6oqxG1OXB4WJ2He20iOoYWQl8ApxlbU//hwnefFYe9ghDPy3rDbcNl3JetT07NR/+AzhKH4e+JCwKjTkdCBTW30fK4eiV9yBk74Lobip4hMaQhMaByl8egaU3A8AsnsZQuov2B6Wo2sDiQPjIulb8K3DOwFyL8PzEk8BB5YoAfwg==MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\nBAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\nBhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\nXGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\ndUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\nEKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\nIhh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI/sp\\nILywgDxVMMtv/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\nfhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA/L1/fd70ok+6xtDRF8A3HjAf\\nBgNVHSMEGDAWgBQEVmzA/L1/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH/MA0G\\nCSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\nwTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8/o13vMw4feGxro1hMeUilRtH52funrW\\nC+FgPrqk3o/8cZOnq+CqnFFDfILLiEb/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\nDa1fG/Pi0fG2F0yw/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\njJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk/ZbEHdKcofnziDyl0V8gglP2\\nSxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n\\n \\n id_48129c2a9d5e9077422591baf495747cfda668c5\\n \\n \\n \\n \\n \\n \\n https://spid.agid.gov.it/cd\\n \\n \\n \\n \\n https://www.spid.gov.it/SpidL2\\n \\n \\n \\n \\n info@agid.gov.it\\n \\n \\n Mario\\n \\n \\n Bianchi\\n \\n \\n GDNNWA12H81Y874F\\n \\n \\n 1991-12-12\\n \\n \\n \\n\"\n}", + "latency": 0, + "statusCode": 200, + "label": "", + "headers": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "bodyType": "INLINE", + "filePath": "", + "databucketID": "", + "sendFileAsBody": false, + "rules": [ + { + "target": "params", + "modifier": "assertion", + "value": "sha256-chG21HBOK-wJp2hHuYPrx7tAII2UGWVF-IFo0crUOtw", + "invert": false, + "operator": "equals" + }, + { + "target": "header", + "modifier": "Accept", + "value": "application/json", + "invert": false, + "operator": "equals" + }, + { + "target": "header", + "modifier": "x-pagopa-lollipop-auth", + "value": "aValidJWT", + "invert": false, + "operator": "equals" + } + ], + "rulesOperator": "AND", + "disableTemplating": false, + "fallbackTo404": true, + "default": false + }, + { + "uuid": "7813cda7-31fb-449c-9538-3b7e4b3bd827", + "body": "{}", + "latency": 0, + "statusCode": 400, + "label": "", + "headers": [], + "bodyType": "INLINE", + "filePath": "", + "databucketID": "", + "sendFileAsBody": false, + "rules": [], + "rulesOperator": "OR", + "disableTemplating": false, + "fallbackTo404": false, + "default": true + } + ], + "enabled": true, + "responseMode": null + } + ], + "rootChildren": [ + { + "type": "route", + "uuid": "2b4e835e-84d9-46f0-9940-ae12b0f3d97e" + } + ], + "proxyMode": false, + "proxyHost": "", + "proxyRemovePrefix": false, + "tlsOptions": { + "enabled": false, + "type": "CERT", + "pfxPath": "", + "certPath": "", + "keyPath": "", + "caPath": "", + "passphrase": "" + }, + "cors": true, + "headers": [], + "proxyReqHeaders": [ + { + "key": "", + "value": "" + } + ], + "proxyResHeaders": [ + { + "key": "", + "value": "" + } + ], + "data": [] +} \ No newline at end of file diff --git a/e2e/mockoon/mockoonIDP.json b/e2e/mockoon/mockoonIDP.json new file mode 100644 index 00000000..04742ba0 --- /dev/null +++ b/e2e/mockoon/mockoonIDP.json @@ -0,0 +1,135 @@ +{ + "uuid": "a85748d7-4867-4cf5-9166-071c9b27f67c", + "lastMigration": 27, + "name": "MockoonIDP", + "endpointPrefix": "", + "latency": 0, + "port": 3001, + "hostname": "", + "folders": [], + "routes": [ + { + "uuid": "ab9a156b-88e3-4977-aca0-a00eaf6607ec", + "type": "http", + "documentation": "", + "method": "get", + "endpoint": "idp-keys/spid", + "responses": [ + { + "uuid": "83d6e1e7-26d5-47d3-aa4b-0da9b01708b7", + "body": "[\"latest\"]", + "latency": 0, + "statusCode": 200, + "label": "", + "headers": [], + "bodyType": "INLINE", + "filePath": "", + "databucketID": "", + "sendFileAsBody": false, + "rules": [], + "rulesOperator": "OR", + "disableTemplating": false, + "fallbackTo404": true, + "default": true + } + ], + "enabled": true, + "responseMode": null + }, + { + "uuid": "f462f924-74d0-4bb5-b1b7-c37f0ebd76e1", + "type": "http", + "documentation": "", + "method": "get", + "endpoint": "idp-keys/spid/:tag", + "responses": [ + { + "uuid": "7b267bd3-98c5-40dd-a6b0-87ffa42462b6", + "body": " MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR/tXzNplfdw8ZtZugSSmHZBxVrR8aA08 dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+ Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI/sp ILywgDxVMMtv/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7 fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA/L1/fd70ok+6xtDRF8A3HjAf BgNVHSMEGDAWgBQEVmzA/L1/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH/MA0G CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8/o13vMw4feGxro1hMeUilRtH52funrW C+FgPrqk3o/8cZOnq+CqnFFDfILLiEb/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY Da1fG/Pi0fG2F0yw/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk/ZbEHdKcofnziDyl0V8gglP2 SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ urn:oasis:names:tc:SAML:2.0:nameid-format:transient ", + "latency": 0, + "statusCode": 200, + "label": "", + "headers": [ + { + "key": "Content-Type", + "value": "application/xml" + } + ], + "bodyType": "INLINE", + "filePath": "", + "databucketID": "", + "sendFileAsBody": false, + "rules": [ + { + "target": "params", + "modifier": "tag", + "value": "latest", + "invert": false, + "operator": "equals" + } + ], + "rulesOperator": "OR", + "disableTemplating": false, + "fallbackTo404": true, + "default": false + }, + { + "uuid": "0df14f3a-d523-4679-b0c0-f8c09f38d07d", + "body": "{}", + "latency": 0, + "statusCode": 400, + "label": "", + "headers": [], + "bodyType": "INLINE", + "filePath": "", + "databucketID": "", + "sendFileAsBody": false, + "rules": [], + "rulesOperator": "OR", + "disableTemplating": false, + "fallbackTo404": false, + "default": true + } + ], + "enabled": true, + "responseMode": null + } + ], + "rootChildren": [ + { + "type": "route", + "uuid": "ab9a156b-88e3-4977-aca0-a00eaf6607ec" + }, + { + "type": "route", + "uuid": "f462f924-74d0-4bb5-b1b7-c37f0ebd76e1" + } + ], + "proxyMode": false, + "proxyHost": "", + "proxyRemovePrefix": false, + "tlsOptions": { + "enabled": false, + "type": "CERT", + "pfxPath": "", + "certPath": "", + "keyPath": "", + "caPath": "", + "passphrase": "" + }, + "cors": true, + "headers": [], + "proxyReqHeaders": [ + { + "key": "", + "value": "" + } + ], + "proxyResHeaders": [ + { + "key": "", + "value": "" + } + ], + "data": [] +} \ No newline at end of file From e9b07ede1b734ff7db8f18994c09f431928e6aa1 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 2 May 2023 15:27:28 +0200 Subject: [PATCH 335/403] [SLS-16] Moved env files into e2e folder --- .github/workflows/pr_scan.yml | 2 +- .env => e2e/.env | 0 .env.dev => e2e/.env.dev | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename .env => e2e/.env (100%) rename .env.dev => e2e/.env.dev (100%) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index abf8e474..df22cef9 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -90,7 +90,7 @@ jobs: working-directory: ./samples/spring run: chmod +x ./gradlew && ./gradlew bootJar - name: Run Docker compose with .env.dev - run: docker compose --env-file .env.dev up -d --build + run: docker compose --env-file e2e/.env.dev up -d --build - name: Install node modules and execute e2e tests working-directory: ./e2e run: npm install && npm run execute-test diff --git a/.env b/e2e/.env similarity index 100% rename from .env rename to e2e/.env diff --git a/.env.dev b/e2e/.env.dev similarity index 100% rename from .env.dev rename to e2e/.env.dev From 376f8768782037568888728ede8ec8d581463c1a Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 2 May 2023 15:49:11 +0200 Subject: [PATCH 336/403] [SLS-16] Fixed base url in newman env --- e2e/env/Lollipop environment variables.postman_environment.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/env/Lollipop environment variables.postman_environment.json b/e2e/env/Lollipop environment variables.postman_environment.json index 3d2b6c88..8ff15b84 100644 --- a/e2e/env/Lollipop environment variables.postman_environment.json +++ b/e2e/env/Lollipop environment variables.postman_environment.json @@ -9,7 +9,7 @@ }, { "key": "BASE_URL", - "value": "localhost:8080/", + "value": "localhost:8080/api/v1/lollipop-consumer", "enabled": true } ], From 58dd84ded5f59513b7d3c94bb2fdd5cad629f01c Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 2 May 2023 16:42:51 +0200 Subject: [PATCH 337/403] [SLS-16] Added endpoint config variable to docker yaml --- docker-compose.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docker-compose.yaml b/docker-compose.yaml index 7682462c..8964965b 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -19,6 +19,9 @@ services: ASSERTION_CLIENT_MOCK_ENABLED: ${ASSERTION_CLIENT_MOCK_ENABLED:-false} IDP_CLIENT_MOCK_ENABLED: ${IDP_CLIENT_MOCK_ENABLED:-false} + ##Sample controller endpoint + SAMPLE_LOLLIPOP_CONSUMER_ENDPOINT: ${SAMPLE_LOLLIPOP_CONSUMER_ENDPOINT:-/api/v1/lollipop-consumer} + ##General Lollipop Configs Sample LOLLIPOP_ASSERTION_EXPIRE_IN_DAYS: ${LOLLIPOP_ASSERTION_EXPIRE_IN_DAYS:-180} LOLLIPOP_EXPECTED_LC_ORIGINAL_URL: ${LOLLIPOP_EXPECTED_LC_ORIGINAL_URL:-https://api-app.io.pagopa.it/first-lollipop/sign} From 032191430cd68cac87ba03796586f5c70b6110a0 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 2 May 2023 16:56:56 +0200 Subject: [PATCH 338/403] [SLS-16] Test for pr scan --- .github/workflows/pr_scan.yml | 116 +++++++++--------- e2e/automatic-test.js | 7 +- ...> lollipopSDKTest.postman_collection.json} | 0 ...ronmentVariables.postman_environment.json} | 0 4 files changed, 63 insertions(+), 60 deletions(-) rename e2e/collections/{LollipopSDKTest.postman_collection.json => lollipopSDKTest.postman_collection.json} (100%) rename e2e/env/{Lollipop environment variables.postman_environment.json => lollipopEnvironmentVariables.postman_environment.json} (100%) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index df22cef9..187a4f43 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -26,64 +26,64 @@ jobs: fetch-depth: 0 - name: Setup Gradle uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 - - name: Cache SonarCloud packages - uses: actions/cache@v1 - with: - path: ~/.sonar-project.properties/cache - key: ${{ runner.os }}-sonar-project.properties - restore-keys: ${{ runner.os }}-sonar-project.properties - - name: Make gradlew executable - run: chmod +x ./gradlew - - name: Run build with Gradle Wrapper - run: ./gradlew build testCodeCoverageReport - - name: Add coverage to PR - id: jacoco - uses: madrapps/jacoco-report@7a334255fbce42f385d7567c25d986a9c62e2971 - with: - paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml - token: ${{ secrets.GITHUB_TOKEN }} - min-coverage-overall: 40 - min-coverage-changed-files: 60 - - name: Build the Docker image - run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest - - name: Run the Anchore Grype scan action - uses: anchore/scan-action@d5aa5b6cb9414b0c7771438046ff5bcfa2854ed7 - id: scan - with: - image: "localbuild/testimage:latest" - fail-build: true - severity-cutoff: "high" - - name: Upload Anchore Scan Report - uses: github/codeql-action/upload-sarif@9885f86fab4879632b7e44514f19148225dfbdcd - if: always() - with: - sarif_file: ${{ steps.scan.outputs.sarif }} - - name: Run Sonar Scanner on Pull Request - if: ${{ github.event_name == 'pull_request' }} - run: ./gradlew sonar --info - -Dsonar.organization=pagopa - -Dsonar.projectKey=${{ env.PROJECT_KEY }} - -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml - -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" - -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" - -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 }} - -Dsonar.pullrequest.base=${{ github.base_ref }} - - name: Run Sonar Scanner - if: ${{ github.event_name != 'pull_request' }} - run: ./gradlew sonar --info - -Dsonar.organization=pagopa - -Dsonar.projectKey=${{ env.PROJECT_KEY }} - -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml - -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" - -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" - -Dsonar.host.url=https://sonarcloud.io - -Dsonar.java.libraries="**/*.jar" - -Dsonar.login=${{ env.SONAR_TOKEN }} - -Dsonar.branch.name=${{ github.head_ref }} +# - name: Cache SonarCloud packages +# uses: actions/cache@v1 +# with: +# path: ~/.sonar-project.properties/cache +# key: ${{ runner.os }}-sonar-project.properties +# restore-keys: ${{ runner.os }}-sonar-project.properties +# - name: Make gradlew executable +# run: chmod +x ./gradlew +# - name: Run build with Gradle Wrapper +# run: ./gradlew build testCodeCoverageReport +# - name: Add coverage to PR +# id: jacoco +# uses: madrapps/jacoco-report@7a334255fbce42f385d7567c25d986a9c62e2971 +# with: +# paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml +# token: ${{ secrets.GITHUB_TOKEN }} +# min-coverage-overall: 40 +# min-coverage-changed-files: 60 +# - name: Build the Docker image +# run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest +# - name: Run the Anchore Grype scan action +# uses: anchore/scan-action@d5aa5b6cb9414b0c7771438046ff5bcfa2854ed7 +# id: scan +# with: +# image: "localbuild/testimage:latest" +# fail-build: true +# severity-cutoff: "high" +# - name: Upload Anchore Scan Report +# uses: github/codeql-action/upload-sarif@9885f86fab4879632b7e44514f19148225dfbdcd +# if: always() +# with: +# sarif_file: ${{ steps.scan.outputs.sarif }} +# - name: Run Sonar Scanner on Pull Request +# if: ${{ github.event_name == 'pull_request' }} +# run: ./gradlew sonar --info +# -Dsonar.organization=pagopa +# -Dsonar.projectKey=${{ env.PROJECT_KEY }} +# -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml +# -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" +# -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" +# -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 }} +# -Dsonar.pullrequest.base=${{ github.base_ref }} +# - name: Run Sonar Scanner +# if: ${{ github.event_name != 'pull_request' }} +# run: ./gradlew sonar --info +# -Dsonar.organization=pagopa +# -Dsonar.projectKey=${{ env.PROJECT_KEY }} +# -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml +# -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" +# -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" +# -Dsonar.host.url=https://sonarcloud.io +# -Dsonar.java.libraries="**/*.jar" +# -Dsonar.login=${{ env.SONAR_TOKEN }} +# -Dsonar.branch.name=${{ github.head_ref }} - name: Publish to Maven Local run: ./gradlew publishToMavenLocal - name: Build Spring Sample diff --git a/e2e/automatic-test.js b/e2e/automatic-test.js index f4b508af..3435ee5a 100644 --- a/e2e/automatic-test.js +++ b/e2e/automatic-test.js @@ -1,8 +1,8 @@ const newman = require('newman'); newman.run({ - collection: require('./collections/LollipopSDKTest.postman_collection.json'), - environment: './env/Lollipop environment variables.postman_environment.json', + collection: require('./collections/lollipopSDKTest.postman_collection.json'), + environment: './env/lollipopEnvironmentVariables.postman_environment.json', reporters: ['cli', 'htmlextra'], bail: true }, function (err, summary) { @@ -10,7 +10,10 @@ newman.run({ if(summary?.run?.error){ throw 'collection run encountered an error.';} if(summary?.run?.failures?.length > 0){ + console.log(summary); + console.log(summary.run); const errors = summary.run.failures; + console.log(errors); throw `following collection tests failed: ${errors.map((er) => `\n${er.source.name}`)}`; } diff --git a/e2e/collections/LollipopSDKTest.postman_collection.json b/e2e/collections/lollipopSDKTest.postman_collection.json similarity index 100% rename from e2e/collections/LollipopSDKTest.postman_collection.json rename to e2e/collections/lollipopSDKTest.postman_collection.json diff --git a/e2e/env/Lollipop environment variables.postman_environment.json b/e2e/env/lollipopEnvironmentVariables.postman_environment.json similarity index 100% rename from e2e/env/Lollipop environment variables.postman_environment.json rename to e2e/env/lollipopEnvironmentVariables.postman_environment.json From fcd9931b324feaab17780b80fce97828b4c9620d Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 2 May 2023 16:58:43 +0200 Subject: [PATCH 339/403] [SLS-16] Test pr scan --- .github/workflows/pr_scan.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 187a4f43..7ecf096b 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -32,10 +32,10 @@ jobs: # path: ~/.sonar-project.properties/cache # key: ${{ runner.os }}-sonar-project.properties # restore-keys: ${{ runner.os }}-sonar-project.properties -# - name: Make gradlew executable -# run: chmod +x ./gradlew -# - name: Run build with Gradle Wrapper -# run: ./gradlew build testCodeCoverageReport + - name: Make gradlew executable + run: chmod +x ./gradlew + - name: Run build with Gradle Wrapper + run: ./gradlew build testCodeCoverageReport # - name: Add coverage to PR # id: jacoco # uses: madrapps/jacoco-report@7a334255fbce42f385d7567c25d986a9c62e2971 From d1fd5e137294e157284b33f7e277e8de83560339 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 2 May 2023 17:07:02 +0200 Subject: [PATCH 340/403] [SLS-16] Test pr scan - decommented tasks --- .github/workflows/pr_scan.yml | 108 +++++++++++++++++----------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 7ecf096b..df22cef9 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -26,64 +26,64 @@ jobs: fetch-depth: 0 - name: Setup Gradle uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 -# - name: Cache SonarCloud packages -# uses: actions/cache@v1 -# with: -# path: ~/.sonar-project.properties/cache -# key: ${{ runner.os }}-sonar-project.properties -# restore-keys: ${{ runner.os }}-sonar-project.properties + - name: Cache SonarCloud packages + uses: actions/cache@v1 + with: + path: ~/.sonar-project.properties/cache + key: ${{ runner.os }}-sonar-project.properties + restore-keys: ${{ runner.os }}-sonar-project.properties - name: Make gradlew executable run: chmod +x ./gradlew - name: Run build with Gradle Wrapper run: ./gradlew build testCodeCoverageReport -# - name: Add coverage to PR -# id: jacoco -# uses: madrapps/jacoco-report@7a334255fbce42f385d7567c25d986a9c62e2971 -# with: -# paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml -# token: ${{ secrets.GITHUB_TOKEN }} -# min-coverage-overall: 40 -# min-coverage-changed-files: 60 -# - name: Build the Docker image -# run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest -# - name: Run the Anchore Grype scan action -# uses: anchore/scan-action@d5aa5b6cb9414b0c7771438046ff5bcfa2854ed7 -# id: scan -# with: -# image: "localbuild/testimage:latest" -# fail-build: true -# severity-cutoff: "high" -# - name: Upload Anchore Scan Report -# uses: github/codeql-action/upload-sarif@9885f86fab4879632b7e44514f19148225dfbdcd -# if: always() -# with: -# sarif_file: ${{ steps.scan.outputs.sarif }} -# - name: Run Sonar Scanner on Pull Request -# if: ${{ github.event_name == 'pull_request' }} -# run: ./gradlew sonar --info -# -Dsonar.organization=pagopa -# -Dsonar.projectKey=${{ env.PROJECT_KEY }} -# -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml -# -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" -# -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" -# -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 }} -# -Dsonar.pullrequest.base=${{ github.base_ref }} -# - name: Run Sonar Scanner -# if: ${{ github.event_name != 'pull_request' }} -# run: ./gradlew sonar --info -# -Dsonar.organization=pagopa -# -Dsonar.projectKey=${{ env.PROJECT_KEY }} -# -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml -# -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" -# -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" -# -Dsonar.host.url=https://sonarcloud.io -# -Dsonar.java.libraries="**/*.jar" -# -Dsonar.login=${{ env.SONAR_TOKEN }} -# -Dsonar.branch.name=${{ github.head_ref }} + - name: Add coverage to PR + id: jacoco + uses: madrapps/jacoco-report@7a334255fbce42f385d7567c25d986a9c62e2971 + with: + paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml + token: ${{ secrets.GITHUB_TOKEN }} + min-coverage-overall: 40 + min-coverage-changed-files: 60 + - name: Build the Docker image + run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest + - name: Run the Anchore Grype scan action + uses: anchore/scan-action@d5aa5b6cb9414b0c7771438046ff5bcfa2854ed7 + id: scan + with: + image: "localbuild/testimage:latest" + fail-build: true + severity-cutoff: "high" + - name: Upload Anchore Scan Report + uses: github/codeql-action/upload-sarif@9885f86fab4879632b7e44514f19148225dfbdcd + if: always() + with: + sarif_file: ${{ steps.scan.outputs.sarif }} + - name: Run Sonar Scanner on Pull Request + if: ${{ github.event_name == 'pull_request' }} + run: ./gradlew sonar --info + -Dsonar.organization=pagopa + -Dsonar.projectKey=${{ env.PROJECT_KEY }} + -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml + -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" + -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" + -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 }} + -Dsonar.pullrequest.base=${{ github.base_ref }} + - name: Run Sonar Scanner + if: ${{ github.event_name != 'pull_request' }} + run: ./gradlew sonar --info + -Dsonar.organization=pagopa + -Dsonar.projectKey=${{ env.PROJECT_KEY }} + -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml + -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" + -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" + -Dsonar.host.url=https://sonarcloud.io + -Dsonar.java.libraries="**/*.jar" + -Dsonar.login=${{ env.SONAR_TOKEN }} + -Dsonar.branch.name=${{ github.head_ref }} - name: Publish to Maven Local run: ./gradlew publishToMavenLocal - name: Build Spring Sample From 0662e268c5ccf92f640a64aaedfc75ea81d846da Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 2 May 2023 17:17:43 +0200 Subject: [PATCH 341/403] [SLS-16] Test pr scan --- .github/workflows/pr_scan.yml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index df22cef9..2a2ec06f 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -44,20 +44,20 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} min-coverage-overall: 40 min-coverage-changed-files: 60 - - name: Build the Docker image - run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest - - name: Run the Anchore Grype scan action - uses: anchore/scan-action@d5aa5b6cb9414b0c7771438046ff5bcfa2854ed7 - id: scan - with: - image: "localbuild/testimage:latest" - fail-build: true - severity-cutoff: "high" - - name: Upload Anchore Scan Report - uses: github/codeql-action/upload-sarif@9885f86fab4879632b7e44514f19148225dfbdcd - if: always() - with: - sarif_file: ${{ steps.scan.outputs.sarif }} +# - name: Build the Docker image +# run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest +# - name: Run the Anchore Grype scan action +# uses: anchore/scan-action@d5aa5b6cb9414b0c7771438046ff5bcfa2854ed7 +# id: scan +# with: +# image: "localbuild/testimage:latest" +# fail-build: true +# severity-cutoff: "high" +# - name: Upload Anchore Scan Report +# uses: github/codeql-action/upload-sarif@9885f86fab4879632b7e44514f19148225dfbdcd +# if: always() +# with: +# sarif_file: ${{ steps.scan.outputs.sarif }} - name: Run Sonar Scanner on Pull Request if: ${{ github.event_name == 'pull_request' }} run: ./gradlew sonar --info From 5c29be98143f36c1706329aaaf756ef49e71e369 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 2 May 2023 17:29:34 +0200 Subject: [PATCH 342/403] [SLS-16] Test pr scan --- .github/workflows/pr_scan.yml | 64 +++++++++++++++++------------------ 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 2a2ec06f..5fdfc6d4 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -26,12 +26,12 @@ jobs: fetch-depth: 0 - name: Setup Gradle uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 - - name: Cache SonarCloud packages - uses: actions/cache@v1 - with: - path: ~/.sonar-project.properties/cache - key: ${{ runner.os }}-sonar-project.properties - restore-keys: ${{ runner.os }}-sonar-project.properties +# - name: Cache SonarCloud packages +# uses: actions/cache@v1 +# with: +# path: ~/.sonar-project.properties/cache +# key: ${{ runner.os }}-sonar-project.properties +# restore-keys: ${{ runner.os }}-sonar-project.properties - name: Make gradlew executable run: chmod +x ./gradlew - name: Run build with Gradle Wrapper @@ -58,32 +58,32 @@ jobs: # if: always() # with: # sarif_file: ${{ steps.scan.outputs.sarif }} - - name: Run Sonar Scanner on Pull Request - if: ${{ github.event_name == 'pull_request' }} - run: ./gradlew sonar --info - -Dsonar.organization=pagopa - -Dsonar.projectKey=${{ env.PROJECT_KEY }} - -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml - -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" - -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" - -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 }} - -Dsonar.pullrequest.base=${{ github.base_ref }} - - name: Run Sonar Scanner - if: ${{ github.event_name != 'pull_request' }} - run: ./gradlew sonar --info - -Dsonar.organization=pagopa - -Dsonar.projectKey=${{ env.PROJECT_KEY }} - -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml - -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" - -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" - -Dsonar.host.url=https://sonarcloud.io - -Dsonar.java.libraries="**/*.jar" - -Dsonar.login=${{ env.SONAR_TOKEN }} - -Dsonar.branch.name=${{ github.head_ref }} +# - name: Run Sonar Scanner on Pull Request +# if: ${{ github.event_name == 'pull_request' }} +# run: ./gradlew sonar --info +# -Dsonar.organization=pagopa +# -Dsonar.projectKey=${{ env.PROJECT_KEY }} +# -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml +# -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" +# -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" +# -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 }} +# -Dsonar.pullrequest.base=${{ github.base_ref }} +# - name: Run Sonar Scanner +# if: ${{ github.event_name != 'pull_request' }} +# run: ./gradlew sonar --info +# -Dsonar.organization=pagopa +# -Dsonar.projectKey=${{ env.PROJECT_KEY }} +# -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml +# -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" +# -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" +# -Dsonar.host.url=https://sonarcloud.io +# -Dsonar.java.libraries="**/*.jar" +# -Dsonar.login=${{ env.SONAR_TOKEN }} +# -Dsonar.branch.name=${{ github.head_ref }} - name: Publish to Maven Local run: ./gradlew publishToMavenLocal - name: Build Spring Sample From d222b58cf874690ee85f7b7796c1cb59b65573e4 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 2 May 2023 17:37:39 +0200 Subject: [PATCH 343/403] [SLS-16] Test pr scan --- .github/workflows/pr_scan.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 5fdfc6d4..7ecf096b 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -36,14 +36,14 @@ jobs: run: chmod +x ./gradlew - name: Run build with Gradle Wrapper run: ./gradlew build testCodeCoverageReport - - name: Add coverage to PR - id: jacoco - uses: madrapps/jacoco-report@7a334255fbce42f385d7567c25d986a9c62e2971 - with: - paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml - token: ${{ secrets.GITHUB_TOKEN }} - min-coverage-overall: 40 - min-coverage-changed-files: 60 +# - name: Add coverage to PR +# id: jacoco +# uses: madrapps/jacoco-report@7a334255fbce42f385d7567c25d986a9c62e2971 +# with: +# paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml +# token: ${{ secrets.GITHUB_TOKEN }} +# min-coverage-overall: 40 +# min-coverage-changed-files: 60 # - name: Build the Docker image # run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest # - name: Run the Anchore Grype scan action From 9ce7c1c39f2740d49f89c301fb0e5d7bee639e23 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 2 May 2023 17:42:27 +0200 Subject: [PATCH 344/403] [SLS-16] Added --wait to docker compose --- .github/workflows/pr_scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 7ecf096b..58e5ab31 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -90,7 +90,7 @@ jobs: working-directory: ./samples/spring run: chmod +x ./gradlew && ./gradlew bootJar - name: Run Docker compose with .env.dev - run: docker compose --env-file e2e/.env.dev up -d --build + run: docker compose --env-file e2e/.env.dev up -d --build --wait - name: Install node modules and execute e2e tests working-directory: ./e2e run: npm install && npm run execute-test From b47dfa56434c89241d897a92cf80db235791b1ec Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 2 May 2023 17:59:47 +0200 Subject: [PATCH 345/403] [SLS-16] Added actuator spring sample - added healtcheck and wait to docker compose --- Dockerfile | 2 ++ docker-compose.yaml | 6 ++++++ samples/spring/build.gradle | 2 ++ 3 files changed, 10 insertions(+) diff --git a/Dockerfile b/Dockerfile index f8650c80..0ec93a18 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,6 +9,8 @@ WORKDIR /app COPY --from=build /build/build/libs/*.jar /app/app.jar COPY --from=build /build/build/resources/main/application.properties /app/application.properties +RUN apk --update --no-cache add curl + RUN addgroup -S appuser && adduser -S appuser -G appuser USER appuser diff --git a/docker-compose.yaml b/docker-compose.yaml index 8964965b..5e79e165 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -14,6 +14,12 @@ services: build: . ports: - "8080:8080" + healthcheck: + test: [ "CMD-SHELL", "curl -f http://localhost:8080/actuator/health || exit 1" ] + interval: 10s + timeout: 5s + retries: 2 + start_period: 15s environment: ##Client mocks config ASSERTION_CLIENT_MOCK_ENABLED: ${ASSERTION_CLIENT_MOCK_ENABLED:-false} diff --git a/samples/spring/build.gradle b/samples/spring/build.gradle index 0d766de3..dd574b67 100644 --- a/samples/spring/build.gradle +++ b/samples/spring/build.gradle @@ -41,6 +41,8 @@ dependencies { implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:http-verifier:1.0.0-RC1' implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:spring-impl:1.0.0-RC1' + implementation 'org.springframework.boot:spring-boot-starter-actuator' + implementation 'org.mock-server:mockserver-netty:5.15.0' implementation 'org.springframework.boot:spring-boot-starter-web' testImplementation 'ch.qos.logback:logback-classic:1.2.11' From d4881b1e514114944a8ae69e4cdbae21609fb074 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 2 May 2023 18:10:37 +0200 Subject: [PATCH 346/403] [SLS-16] Removed docker build - added tag image to docker compose --- .github/workflows/pr_scan.yml | 106 +++++++++++++++++----------------- docker-compose.yaml | 1 + 2 files changed, 53 insertions(+), 54 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 58e5ab31..10b78342 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -26,64 +26,50 @@ jobs: fetch-depth: 0 - name: Setup Gradle uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 -# - name: Cache SonarCloud packages -# uses: actions/cache@v1 -# with: -# path: ~/.sonar-project.properties/cache -# key: ${{ runner.os }}-sonar-project.properties -# restore-keys: ${{ runner.os }}-sonar-project.properties + - name: Cache SonarCloud packages + uses: actions/cache@v1 + with: + path: ~/.sonar-project.properties/cache + key: ${{ runner.os }}-sonar-project.properties + restore-keys: ${{ runner.os }}-sonar-project.properties - name: Make gradlew executable run: chmod +x ./gradlew - name: Run build with Gradle Wrapper run: ./gradlew build testCodeCoverageReport -# - name: Add coverage to PR -# id: jacoco -# uses: madrapps/jacoco-report@7a334255fbce42f385d7567c25d986a9c62e2971 -# with: -# paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml -# token: ${{ secrets.GITHUB_TOKEN }} -# min-coverage-overall: 40 -# min-coverage-changed-files: 60 -# - name: Build the Docker image -# run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest -# - name: Run the Anchore Grype scan action -# uses: anchore/scan-action@d5aa5b6cb9414b0c7771438046ff5bcfa2854ed7 -# id: scan -# with: -# image: "localbuild/testimage:latest" -# fail-build: true -# severity-cutoff: "high" -# - name: Upload Anchore Scan Report -# uses: github/codeql-action/upload-sarif@9885f86fab4879632b7e44514f19148225dfbdcd -# if: always() -# with: -# sarif_file: ${{ steps.scan.outputs.sarif }} -# - name: Run Sonar Scanner on Pull Request -# if: ${{ github.event_name == 'pull_request' }} -# run: ./gradlew sonar --info -# -Dsonar.organization=pagopa -# -Dsonar.projectKey=${{ env.PROJECT_KEY }} -# -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml -# -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" -# -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" -# -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 }} -# -Dsonar.pullrequest.base=${{ github.base_ref }} -# - name: Run Sonar Scanner -# if: ${{ github.event_name != 'pull_request' }} -# run: ./gradlew sonar --info -# -Dsonar.organization=pagopa -# -Dsonar.projectKey=${{ env.PROJECT_KEY }} -# -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml -# -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" -# -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" -# -Dsonar.host.url=https://sonarcloud.io -# -Dsonar.java.libraries="**/*.jar" -# -Dsonar.login=${{ env.SONAR_TOKEN }} -# -Dsonar.branch.name=${{ github.head_ref }} + - name: Add coverage to PR + id: jacoco + uses: madrapps/jacoco-report@7a334255fbce42f385d7567c25d986a9c62e2971 + with: + paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml + token: ${{ secrets.GITHUB_TOKEN }} + min-coverage-overall: 40 + min-coverage-changed-files: 60 + - name: Run Sonar Scanner on Pull Request + if: ${{ github.event_name == 'pull_request' }} + run: ./gradlew sonar --info + -Dsonar.organization=pagopa + -Dsonar.projectKey=${{ env.PROJECT_KEY }} + -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml + -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" + -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" + -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 }} + -Dsonar.pullrequest.base=${{ github.base_ref }} + - name: Run Sonar Scanner + if: ${{ github.event_name != 'pull_request' }} + run: ./gradlew sonar --info + -Dsonar.organization=pagopa + -Dsonar.projectKey=${{ env.PROJECT_KEY }} + -Dsonar.coverage.jacoco.xmlReportPaths=**/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml + -Dsonar.coverage.exclusions="**/config/*","**/*Mock*","**/model/**","**/entity/*","**/*Stub*","**/*Config*,**/*Exception*" + -Dsonar.cpd.exclusions="**/model/**,**/entity/**,**/simple/internal/**" + -Dsonar.host.url=https://sonarcloud.io + -Dsonar.java.libraries="**/*.jar" + -Dsonar.login=${{ env.SONAR_TOKEN }} + -Dsonar.branch.name=${{ github.head_ref }} - name: Publish to Maven Local run: ./gradlew publishToMavenLocal - name: Build Spring Sample @@ -96,3 +82,15 @@ jobs: run: npm install && npm run execute-test - name: Shutdown docker compose run: docker compose down + - name: Run the Anchore Grype scan action + uses: anchore/scan-action@d5aa5b6cb9414b0c7771438046ff5bcfa2854ed7 + id: scan + with: + image: "localbuild/testimage:latest" + fail-build: true + severity-cutoff: "high" + - name: Upload Anchore Scan Report + uses: github/codeql-action/upload-sarif@9885f86fab4879632b7e44514f19148225dfbdcd + if: always() + with: + sarif_file: ${{ steps.scan.outputs.sarif }} diff --git a/docker-compose.yaml b/docker-compose.yaml index 5e79e165..fb04a564 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -12,6 +12,7 @@ services: - ./e2e/mockoon/mockoonIDP.json:/data:readonly web: build: . + image: localbuild/testimage:latest ports: - "8080:8080" healthcheck: From e480449cbc5a49478e50ff320faa994c7ba3f610 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 2 May 2023 18:27:52 +0200 Subject: [PATCH 347/403] [SLS-16] Revert docker build commit --- .github/workflows/pr_scan.yml | 26 ++++++++++++++------------ docker-compose.yaml | 1 - 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index 10b78342..c4a09e78 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -44,6 +44,20 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} min-coverage-overall: 40 min-coverage-changed-files: 60 + - name: Build the Docker image + run: docker build . --file ${{ env.DOCKERFILE }} --tag localbuild/testimage:latest + - name: Run the Anchore Grype scan action + uses: anchore/scan-action@d5aa5b6cb9414b0c7771438046ff5bcfa2854ed7 + id: scan + with: + image: "localbuild/testimage:latest" + fail-build: true + severity-cutoff: "high" + - name: Upload Anchore Scan Report + uses: github/codeql-action/upload-sarif@9885f86fab4879632b7e44514f19148225dfbdcd + if: always() + with: + sarif_file: ${{ steps.scan.outputs.sarif }} - name: Run Sonar Scanner on Pull Request if: ${{ github.event_name == 'pull_request' }} run: ./gradlew sonar --info @@ -82,15 +96,3 @@ jobs: run: npm install && npm run execute-test - name: Shutdown docker compose run: docker compose down - - name: Run the Anchore Grype scan action - uses: anchore/scan-action@d5aa5b6cb9414b0c7771438046ff5bcfa2854ed7 - id: scan - with: - image: "localbuild/testimage:latest" - fail-build: true - severity-cutoff: "high" - - name: Upload Anchore Scan Report - uses: github/codeql-action/upload-sarif@9885f86fab4879632b7e44514f19148225dfbdcd - if: always() - with: - sarif_file: ${{ steps.scan.outputs.sarif }} diff --git a/docker-compose.yaml b/docker-compose.yaml index fb04a564..5e79e165 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -12,7 +12,6 @@ services: - ./e2e/mockoon/mockoonIDP.json:/data:readonly web: build: . - image: localbuild/testimage:latest ports: - "8080:8080" healthcheck: From f45945b1de89702464d7ea5987b115a206ddbf28 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 2 May 2023 18:40:47 +0200 Subject: [PATCH 348/403] [SLS-16] Added sleep to pr scan tasks --- .github/workflows/pr_scan.yml | 3 +++ e2e/automatic-test.js | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr_scan.yml b/.github/workflows/pr_scan.yml index c4a09e78..2d4a51b2 100644 --- a/.github/workflows/pr_scan.yml +++ b/.github/workflows/pr_scan.yml @@ -91,6 +91,9 @@ jobs: run: chmod +x ./gradlew && ./gradlew bootJar - name: Run Docker compose with .env.dev run: docker compose --env-file e2e/.env.dev up -d --build --wait + - name: Sleep for 30 seconds + run: sleep 30s + shell: bash - name: Install node modules and execute e2e tests working-directory: ./e2e run: npm install && npm run execute-test diff --git a/e2e/automatic-test.js b/e2e/automatic-test.js index 3435ee5a..d4cba588 100644 --- a/e2e/automatic-test.js +++ b/e2e/automatic-test.js @@ -10,10 +10,7 @@ newman.run({ if(summary?.run?.error){ throw 'collection run encountered an error.';} if(summary?.run?.failures?.length > 0){ - console.log(summary); - console.log(summary.run); const errors = summary.run.failures; - console.log(errors); throw `following collection tests failed: ${errors.map((er) => `\n${er.source.name}`)}`; } From fe2fe8215181e6db76b56c86a4f88d01139e74ea Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 2 May 2023 18:48:48 +0200 Subject: [PATCH 349/403] [SLS-16] Newman verbose --- e2e/automatic-test.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/e2e/automatic-test.js b/e2e/automatic-test.js index d4cba588..f711411d 100644 --- a/e2e/automatic-test.js +++ b/e2e/automatic-test.js @@ -4,13 +4,15 @@ newman.run({ collection: require('./collections/lollipopSDKTest.postman_collection.json'), environment: './env/lollipopEnvironmentVariables.postman_environment.json', reporters: ['cli', 'htmlextra'], - bail: true + bail: true, + verbose: true }, function (err, summary) { if (err) { throw err; } if(summary?.run?.error){ throw 'collection run encountered an error.';} if(summary?.run?.failures?.length > 0){ const errors = summary.run.failures; + throw `following collection tests failed: ${errors.map((er) => `\n${er.source.name}`)}`; } From 50b3bb10cc45818a08434991202af0df1fcb7a58 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 3 May 2023 16:13:56 +0200 Subject: [PATCH 350/403] [SLS-39] Introducing baseline for general README.md --- README.md | Bin 70 -> 17494 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index bad273a2ca9b9556185d4b08ba737141b6cd8c0c..3af97bed814d08adf2b38fc1431552a71e4f7b52 100644 GIT binary patch literal 17494 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 UUX8jXHl*g#%@a5>2jIzn0sFZzfB*mh delta 6 NcmccC!RR)@4FC!50(<}f From 0e0f729d68f4d46f286012029ee7a5517ce2b280 Mon Sep 17 00:00:00 2001 From: svariant Date: Wed, 3 May 2023 16:45:39 +0200 Subject: [PATCH 351/403] [SLS-39] End-to-end and Spring sample README --- e2e/README.md | 73 ++++++++++++++++++++++++++++++++++++++++ samples/spring/README.md | 55 ++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 e2e/README.md create mode 100644 samples/spring/README.md diff --git a/e2e/README.md b/e2e/README.md new file mode 100644 index 00000000..e27b10b9 --- /dev/null +++ b/e2e/README.md @@ -0,0 +1,73 @@ +# eng-lollipop-consumer-java-sdk + +## End-to-end test + +### Testing models + ++ #### Publish library dependencies to maven local +In the root folder run + +```bash +./gradlew publishToMavenLocal +``` + ++ #### Build spring sample application +Change directory to ./samples/spring folder and build the sample with + +```bash +cd samples/spring +./gradlew bootJar +``` + ++ #### Run docker container +Return to root folder and run docker compose in the e2e folder with + +```bash +cd .. +cd e2e +docker compose --env-file .env.dev up --build +``` + ++ ##### Prepare newman +Staying in the e2e folder, install [newman](https://www.npmjs.com/package/newman) with npm + +```bash +npm i newman +``` + ++ #### Run tests +Finally, when all docker's containers are healthy, you can run the tests with + +```bash +npm run execute-test +``` + ++ #### View report +Newman generates a detailed report in the "newman" folder, you can open it with your preferred browser + +### Configuration +The sample configuration can be changed with environment variables in the .env.dev files +(or using a different .env file in the docker compose command) + +The configurable variables are the following: + +| VARIABLE | DEFAULT | USAGE | +|-------------------------------------------|-----------------------------------------------------------------------|--------------------------------------------------------------------| +| ASSERTION_CLIENT_MOCK_ENABLED | false | Enable Mockserver client | +| IDP_CLIENT_MOCK_ENABLED | false | Enable Mockserver client | +| SAMPLE_LOLLIPOP_CONSUMER_ENDPOINT | /api/v1/lollipop-consumer | Define sample controller endpoint | +| LOLLIPOP_ASSERTION_EXPIRE_IN_DAYS | 180 | Define after how many days assertion expires | +| LOLLIPOP_EXPECTED_LC_ORIGINAL_URL | https://api-app.io.pagopa.it/first-lollipop/sign | Define original url expected in request's header | +| LOLLIPOP_EXPECTED_LC_ORIGINAL_METHOD | POST | Define original method expected in request's header | +| LOLLIPOP_ASSERTION_NOT_BEFORE_DATE_FORMAT | yyyy-MM-dd'T'HH:mm:ss.SSS'Z' | Define the date format used in the Assertion's notBefore field | +| LOLLIPOP_ASSERTION_INSTANT_DATE_FORMAT | yyyy-MM-dd'T'HH:mm:ss.SSS'Z' | Define the date format used in the Assertion's Issue Instant field | +| IDP_CLIENT_CIEID | https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO | Define entity id for CIE identity provider | +| IDP_CLIENT_BASE_URI | https://api.is.eng.pagopa.it | Define base uri to retrieve IDP certification data | +| IDP_CLIENT_CIE_ENDPOINT | /idp-keys/cie | Define endpoint to IDP_CLIENT_BASE_URI for CIE's certification | +| IDP_CLIENT_SPID_ENDPOINT | /idp-keys/spid | Define endpoint to IDP_CLIENT_BASE_URI for SPID's certification | +| IDP_STORAGE_ENABLED | true | Enable internal cache storage for IDP certification data | +| IDP_STORAGE_EVICTION_DELAY | 1 | Define storage eviction delay for IDP's storage | +| ASSERTION_REST_URI | http://localhost:3000 | Define base uri to retrieve the Assertion | +| ASSERTION_REST_ENDPOINT | /assertions | Define endpoint to ASSERTION_REST_URI | +| ASSERTION_STORAGE_ENABLED | true | Enable internal cache storage for assertions | +| ASSERTION_STORAGE_ENABLED | 1 | Define storage eviction delay for assertion's storage | \ No newline at end of file diff --git a/samples/spring/README.md b/samples/spring/README.md new file mode 100644 index 00000000..a0409013 --- /dev/null +++ b/samples/spring/README.md @@ -0,0 +1,55 @@ +# eng-lollipop-consumer-java-sdk + +## Spring sample application + +### Run the sample + ++ #### Publish library dependencies to maven local +In the project root folder run + +```bash +./gradlew publishToMavenLocal +``` + ++ #### Define environment variables for the sample +To run the application with the existing examples, define the following variables in the sample run configuration: + +| VARIABLE | VALUE | +|-------------------------------------------|---------------------------| +| ASSERTION_CLIENT_MOCK_ENABLED | true | +| IDP_CLIENT_MOCK_ENABLED | true | +| IDP_CLIENT_BASE_URI | http://localhost:3001 | +| LOLLIPOP_ASSERTION_NOT_BEFORE_DATE_FORMAT | yyyy-MM-dd'T'HH:mm:ss.'Z' | +| LOLLIPOP_ASSERTION_INSTANT_DATE_FORMAT | yyyy-MM-dd'T'HH:mm:ss.'Z' | + +You can configure these variables for your custom usage (see "Configuration" paragraph) + ++ #### Run the sample +You can now run the sample, it will be exposed to http://localhost:8080/api/v1/lollipop-consumer + +To test the sample you can use our examples with these postman [environment](https://github.com/pagopa/eng-lollipop-consumer-java-sdk/blob/0f92a666b0f5e71ec13f11560e435be82df0f5e9/e2e/env/lollipopEnvironmentVariables.postman_environment.json) +and [collection](https://github.com/pagopa/eng-lollipop-consumer-java-sdk/blob/0f92a666b0f5e71ec13f11560e435be82df0f5e9/e2e/collections/lollipopSDKTest.postman_collection.json) + +### Configuration +The configurable variables are the following: + +| VARIABLE | DEFAULT | USAGE | +|-------------------------------------------|-----------------------------------------------------------------------|--------------------------------------------------------------------| +| ASSERTION_CLIENT_MOCK_ENABLED | false | Enable Mockserver client | +| IDP_CLIENT_MOCK_ENABLED | false | Enable Mockserver client | +| SAMPLE_LOLLIPOP_CONSUMER_ENDPOINT | /api/v1/lollipop-consumer | Define sample controller endpoint | +| LOLLIPOP_ASSERTION_EXPIRE_IN_DAYS | 180 | Define after how many days assertion expires | +| LOLLIPOP_EXPECTED_LC_ORIGINAL_URL | https://api-app.io.pagopa.it/first-lollipop/sign | Define original url expected in request's header | +| LOLLIPOP_EXPECTED_LC_ORIGINAL_METHOD | POST | Define original method expected in request's header | +| LOLLIPOP_ASSERTION_NOT_BEFORE_DATE_FORMAT | yyyy-MM-dd'T'HH:mm:ss.SSS'Z' | Define the date format used in the Assertion's notBefore field | +| LOLLIPOP_ASSERTION_INSTANT_DATE_FORMAT | yyyy-MM-dd'T'HH:mm:ss.SSS'Z' | Define the date format used in the Assertion's Issue Instant field | +| IDP_CLIENT_CIEID | https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO | Define entity id for CIE identity provider | +| IDP_CLIENT_BASE_URI | https://api.is.eng.pagopa.it | Define base uri to retrieve IDP certification data | +| IDP_CLIENT_CIE_ENDPOINT | /idp-keys/cie | Define endpoint to IDP_CLIENT_BASE_URI for CIE's certification | +| IDP_CLIENT_SPID_ENDPOINT | /idp-keys/spid | Define endpoint to IDP_CLIENT_BASE_URI for SPID's certification | +| IDP_STORAGE_ENABLED | true | Enable internal cache storage for IDP certification data | +| IDP_STORAGE_EVICTION_DELAY | 1 | Define storage eviction delay for IDP's storage | +| ASSERTION_REST_URI | http://localhost:3000 | Define base uri to retrieve the Assertion | +| ASSERTION_REST_ENDPOINT | /assertions | Define endpoint to ASSERTION_REST_URI | +| ASSERTION_STORAGE_ENABLED | true | Enable internal cache storage for assertions | +| ASSERTION_STORAGE_ENABLED | 1 | Define storage eviction delay for assertion's storage | \ No newline at end of file From 3a01b430a038a47d6f50ebace67007f138cca704 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 3 May 2023 19:50:23 +0200 Subject: [PATCH 352/403] [SLS-39] Updated core README.md --- README.md | Bin 17494 -> 52788 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index 3af97bed814d08adf2b38fc1431552a71e4f7b52..c49290419fc24e2459e150ee85ad955043ae77b3 100644 GIT binary patch literal 52788 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 delta 27 jcmdlohxu9u Date: Wed, 3 May 2023 20:02:01 +0200 Subject: [PATCH 353/403] [SLS-39] Updated core README.md --- README.md | Bin 52788 -> 53926 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index c49290419fc24e2459e150ee85ad955043ae77b3..3a979bb951cd89df07e802125185dc74fccbd1fd 100644 GIT binary patch delta 113 zcmdlohk4mj<_$*kHXF=4$2B==kJe_nZ3>K&H?Ueww%fi1OzRvGnw+pjX7a4<5n%qm zBLb5Pj`RW9E|Vc_xycIdJd?wA%4}v@nZ(Sj!Js+$ptJDgvNbl08k;w+ImolQVCOcT J%__$PH~=WDFtY#v delta 46 zcmV+}0MY-Zr318_1F$llvoxN}3X^P`2(xajUIUZDLlTqXuspLMvA_(o;=QyCvzW>b E2>y;0<^TWy From 2afbb495afd9f87cddfe97a6509da90bfca5ee7f Mon Sep 17 00:00:00 2001 From: svariant Date: Thu, 4 May 2023 09:59:28 +0200 Subject: [PATCH 354/403] [SLS-39] Readme of the clients' modules --- assertion-rest-client-native/README.md | 17 +++++++++++ identity-service-rest-client-native/README.md | 28 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 assertion-rest-client-native/README.md create mode 100644 identity-service-rest-client-native/README.md diff --git a/assertion-rest-client-native/README.md b/assertion-rest-client-native/README.md new file mode 100644 index 00000000..6f92ebee --- /dev/null +++ b/assertion-rest-client-native/README.md @@ -0,0 +1,17 @@ +# eng-lollipop-consumer-java-sdk + +## Assertion rest client +This module is used to obtain the user's assertion. + +The parameters needed to get the assertion are the jwt and the assertion's ref, +both retrieved from the http request's headers. + +At this moment only SAML assertion are supported, OIDC claims are not. + +## Configuration +The client uri, endpoints and the entity id of the CIE identity provider are configurable and are configured by default as follows: + +| VARIABLE | DEFAULT VALUE | USAGE | +|--------------------------|-----------------------|---------------------------------------------------| +| baseUri | http://localhost:3000 | base uri of the api for retrieving the assertions | +| assertionRequestEndpoint | /assertions | endpoint of the request | diff --git a/identity-service-rest-client-native/README.md b/identity-service-rest-client-native/README.md new file mode 100644 index 00000000..c7a7f485 --- /dev/null +++ b/identity-service-rest-client-native/README.md @@ -0,0 +1,28 @@ +# eng-lollipop-consumer-java-sdk + +## Identity service rest client +This module is used to obtain the identity provider certification data. + +The parameters needed to find the right certificate are the entity id and the assertion's issue instant, +both retrieved from the assertion. + +First we fetch the certificates' tag list (a list of certification by their issue instant) and we find the two tags +that could be used for the assertion verification; we compare the tags with the assertion's instant as timestamp in seconds and +the two eligible tags are the ones right before and after the provided assertion's instant. + +Then for each of the found tags the corresponding certification as xml is fetched, +the xml contains various elements called EntityDescriptor for each entity id, +so we will filter these elements by the entity id provided in first instance. + +Finally, from the EntityDescriptor of the right identity provider we will extract the signature that will be used to +verify the assertion. + +## Configuration +The client uri, endpoints and the entity id of the CIE identity provider are configurable and are configured by default as follows: + +| VARIABLE | DEFAULT VALUE | USAGE | +|---------------------|-----------------------------------------------------------------------|-------------------------------------------------------| +| cieEntityId | https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO | entity id of the CIE identity provider | +| baseUri | https://api.is.eng.pagopa.it | base uri of the api for retrieving the certifications | +| idpKeysCieEndpoint | /idp-keys/cie | endpoint for CIE certifications | +| idpKeysSpidEndpoint | /idp-keys/spid | endpoint for SPID certifications | From e36e5dd9f478d06bd4d0448301f8a748a8380fc2 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 4 May 2023 10:00:42 +0200 Subject: [PATCH 355/403] [SLS-39] Updated core README.md with references to the E2E testing document --- README.md | Bin 53926 -> 55650 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index 3a979bb951cd89df07e802125185dc74fccbd1fd..293c2d804e83fc505bbf3dfb403b14487d7e5e02 100644 GIT binary patch delta 1123 zcma)5O-oc^6h3hcWI(i;{6frk7D2%{7aSeLXyjr;3yC1wi7?mhRVPOs?uViar5_L| zXBpV4c3IRqaFH7cqE_Ove^9HIJ?DMB^I;`%xpUt+=bm$(^E}Ue{mT0O-g;L&;BOz( zABqR{ajv}Sv=u!jpF)bLN^7)4U6j&ydsNXnEs~;$e^|r(^Ztzqh4({5o*=VE9>q9C z=;R@`KwJ2Y5w9YKs`Cjs9@d~q(->mSjGoQzi;O*kel=Xa?q@JHF)EV$2C@OU zK2cZOXwT18kuNTI?>fK<`KW%psm`Lkg}%lgd(npvc!F}j$QU4g^Togr4GKK^B0 z=Ze$8M=uBX^f+CR*)7u=6f9|g-Z`E+o-yFcI(hzLXQ$UeQiK&GqVSaYKF*P@t0BIv zcTo86Qyo|W}~XEWq+z+A@ogAMPE4bmC63mWQeFJv|Uh>9wC-2Tj6KdW_af$z3aexQW?-D z)(KD Date: Thu, 4 May 2023 10:01:36 +0200 Subject: [PATCH 356/403] [SLS-39] fixed typo --- README.md | Bin 55650 -> 55644 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index 293c2d804e83fc505bbf3dfb403b14487d7e5e02..150d8d6b078ee4e9b271aa7ca65b3c0b1c30dcfb 100644 GIT binary patch delta 30 ocmV+(0O9}QvIE?*1F(G7lY%=GlakgflN3`xlaR_1vlQ1(0_l$p-2eap delta 32 qcmV+*0N?-IvIF9>1F(G7lL9yvlaSUd0brAX5kr%Z$`Z2<*G>ZWNe$xw From d38402d2dd60b4b47428e352b7a137050f7ba14b Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 4 May 2023 10:05:05 +0200 Subject: [PATCH 357/403] [SLS-39] fixed broken references in root README.md --- README.md | Bin 55644 -> 55694 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index 150d8d6b078ee4e9b271aa7ca65b3c0b1c30dcfb..277ab7e58a009f055b769de2814ee09b8b6caca9 100644 GIT binary patch delta 30 ocmV+(0O9}KvICB@1F+z*lRz96li;vYle{DnlV~Rlvox_NDB=1ID*ylh delta 24 gcmeC%%zS4P^M(f-7&Rv!bQYe>wb5>K%0?{>0FD0&kN^Mx From 2aa969df009066577ec130a6782c07229025a096 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 4 May 2023 10:52:03 +0200 Subject: [PATCH 358/403] [SLS-39] updated README.md with guidelines on how to generate new versions of the Rest Clients through the usage of the openapi-generator toolkit plugin. --- README.md | Bin 55694 -> 61368 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index 277ab7e58a009f055b769de2814ee09b8b6caca9..134e26ddf2b3fa4c556c343a8caf3d8ee4c1da88 100644 GIT binary patch delta 3422 zcmb7H-)~c882(@?$k@-W>k6wqt&?pcoj6c1nb>TIpmS4+7#FqOdNu~#I@8mwA{#En!sVl*kR8HlUrP8Lq# z%oLucwOm?d^&T55$FR#%V~|K=bwb&|vM4DZ^heJOw3fKp#wS~S2vHlNMOCLZXyudG zKv04c>@dD&@J1-!kHNsKddl;~Max6JfE`qw1%{0sd^0;NJm>H>s%)9s5tMgYHp!{^ z`m1wSHg0`_%6UDGpQZNctu_>;v5AIGas*%KcBna=N*7O+l6tA=xrp zFMrpxO8xmZX}{ShFAlUy$JVxpYdFozI*0}Z2Fb~Nk%j_R^6EHD9>bGHD|IP179=Tc zB7s#p?mE05gbd?-K%+8d!@$XDq>RQS>*Sug$MqLJkw!y?i$ooiEaERCX1xWdG#+w@ z4}q!5@X656;>(*Fu57gGR*5n-`vJlzqyb6#h+rs8&h_l~N2d#hnWS6p=rQbf3<4cC zo+p6Qtx3Qh8M+wW=0&5cOgi4FGlL!Dj^o;TNe%>LQ{RRX130e9nu455Lrz<1-WmD| z8nOmIdPSQIgS^-pDt%0_%(iGcvd*)WA4tdEC(qWT`WN;%JkBx%TIt_hklsVolR8^1+=J z_{nJ>iEmc3677u*q5?G7p?-Tgu<&{!#)h+iEfx5VQ z7VA54J+0!h^Ur84Glda^CDe)j#MmB%Rm&o5O?Blo+ zTBor&13g2U1+BRR)ddK+E}4KMcS8r>8POvEVWtkiQ{+{!x8z4)e2Wf-mMN=T5kd7-8Oy5kBa+!^ z9k&VaHv@E&m(lb~hDk-} z<8V+*?KDl`4LHQ4=Q(Msz38D#=!zLegDGKWXQ=>_S;~}ThtKLX$UD}IVvT8%S<(3( zWJP6n0Wy9%-qiv7ME_;-ne;oP4_o$ql>U3p$(w?Tl}JfJ$jhn)g%yW9bpklD?DmTz zKtoouz9h4wMb5s^yxoEUemado%5nV+_au{d+K}b=KspfiM`s=o;+C+a{ zcs(TXrYHM{v};uMzaen6Tg+Y=xwrigogal-HjPT6`TJM(k#-b8FQRk0z42vWa758F zjY(D{z~){CmNZrOLz3&Au#9%y_9V6#>Lil?_~IJcfzC|9XYmtt{<{J9_M>rrqU3x5HCg%*O*H!Bjty8jc zay}@(KGQ6Xch)EUe3<0$jzkqM*ljr5SB+V6{nF-Ib8wDQpEUgzd9*UHfh{?>&@Pu3 zESZ~ck>SNIr2e=kA|rY@oKgKi&V!wPpg6;~-2P%pQlGEy^IFvNV0lE&X(T!moXJ^k zTn@^aYwhxOAWO8(tDwokwMc^(g{=N^F(?~v*7vZjaBL-~EC8~>GBT4fIWPl>Q#e}h jh9BDG+vWq338YrgUH%^lC_VDe_noyK-6+@S+JyQKl_j|0 delta 14 WcmdmSpSf={^M;Ofn+-OwX#)T@ng)pg From b1ab11db0a2b04187426660b33e1b64fbe704277 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 4 May 2023 11:01:34 +0200 Subject: [PATCH 359/403] [SLS-39] Fixed wrong reference --- README.md | Bin 61368 -> 61446 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index 134e26ddf2b3fa4c556c343a8caf3d8ee4c1da88..c14261d89a7363ca202a17572384da04189b4980 100644 GIT binary patch delta 142 zcmdmSpSkS;^M-%ylOM2fO)i+uG1)*VXmZ`;zRh)$xfnNbmN8CVpu#mdp^Ig67Iy$M zR2ARm6MRSfy5j$;P$_%=V|3t-;tASA@Nd6$?E)8-YTK=Bo# he4FJY1DGctm@crnL&lGJ^8@)syBUi&H{Na)0RT3c9B2Rl From d43e0fc2407b8634ad7ab936ac9383e2a4d9bb6a Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 4 May 2023 11:20:30 +0200 Subject: [PATCH 360/403] [SLS-39] Updated README.md with paragraphs regarding core configuration class, and a CommandResult utilization example --- README.md | Bin 61446 -> 65624 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index c14261d89a7363ca202a17572384da04189b4980..23d667842f2e887d1b0bf5767588f73b67ef7ce4 100644 GIT binary patch delta 2176 zcmZuyT}+#06h3u08Bp3$x{h@~VF|WTN*A|iI-^-&s27UzqcL$IrIga7w5%;m{0Vax zyHXQ&Zk!>QT`P(qCYoq;amHP+4dS9pjAIzDi5RbpQJ?31`-9rN`TD)zdCz-(p7Wg3 z3wQV2K3B7HVM*WY|D)9@b;4&@CM6*O8Izdgu}e!zGP=3o)yR_#dad{1o|NR((dW^3 zpXl<1p?MN|0hy4jJf6^y5x@dlgF z%1Bms8oau)UE|2=50AFiPvMk$SsB-lk99cH*u`X=F-cOtIOUtC=NzO{Mc)D3co}yR zkY=EphCGk+8GOefeGuPiykjzJt>D{65|C-=<*`!8K4mg5$ecliS&c)J(dLa_#_G9u zDbi3@7tVXT2?NbBuxS$to$d-9r{&c2Ovt0R7aN@c1X(EBdqsC{dN1}j>;C@#J**Xop6xyET2aQ`Z-3^;cI7SkW0OrJF?3F(fyIUnUdB zJB>AGkWWcLAGqt^Pk6=<5m9FBIjz6Zu7AGQq)qFc$K&ux#FNFWg4kza&1O%#0rO3! z=Hx7_fT{Y{CI69G<820VA`mn6;(Hp4Oa@Bo_}aIcTm8VH6UnG6DEG^=G60Z=u?y+O zXI@8G6Um$oyx-IZQ5H<5V5YW5I##3CSMJmGwY~KtrDCD*J6BsnG_Xqdtq0vw z)6hP(r_C9go?bBwbn}M)2n)n6$QkK>?bGj^c3<}E@0Si}qhvVB5Oca)N1*X)L!bPsUiZ zzIVe=niMn8Hhs&vyRTeEz4D_+x0jnWyy1R05Ad_-KU!qJTC%bG*=+>O=4`dflp*!> zw{M#C(54%+q)|WIs?~EFhhD5qR)WlU3jo(rz4`>Ek1==|$9xGO66RB$Rge@(N{_we z{}@OasU--fj4idTP4(gyqfy7tzIsc7pma!FU284#VKb)+G6@1eK!Y2aXKJ<&< Date: Thu, 4 May 2023 11:21:16 +0200 Subject: [PATCH 361/403] [SLS-39] Fixed broken reference --- README.md | Bin 65624 -> 65626 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index 23d667842f2e887d1b0bf5767588f73b67ef7ce4..d371226040c1d5cbc7370f16875d689953a03037 100644 GIT binary patch delta 18 acmcc7z;dgBWkbXK$?w|uHuuawlK=o(4+*IN delta 14 WcmccBz;dI3WkbXK%}w)fBme+6L Date: Thu, 4 May 2023 11:58:10 +0200 Subject: [PATCH 362/403] [SLS-39] Introducing example paragraph regarding the httpMessageVerifier service --- README.md | Bin 65626 -> 68690 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index d371226040c1d5cbc7370f16875d689953a03037..cfa50f1ea0c78def30cdf3cc4b29f54d666b1e77 100644 GIT binary patch delta 1063 zcmZWoUr5tY6uxWI%rTv<{qqn05YkCYSrJOI$PA4#V`{x<KHA}oR;Bsx%8Q-N(yv(Y!!QWW{SFG__^bWuh-<#kZBwdRCD5q@z=bkiCV zk@%AlZHoSw@QU8wZ9UZ{bGHZ(tWY^8`RPcnP%&MVUv^RM`zQ_(&P0OLD#$pkmnE94 zj!3+N5Ih|6z(%>c;fiC~l{3A4QA?Wo|L;a;yl0 zNQdW$35V--Sbyu(l;F!7lcovhrVgMsrebltSue9VQ&b{0vm5V*GVp2HhC}yl`d;eC zUE4(zXU`O;u%C*0^Om0XI@_)x`lW1W`y&i9#8N+_cdu4{G!d)7*oUiw8bSdo|IC2X_iD7^hv zEG-veeLfe7VGC~0+3<2GEx%K`5usYXC57%UsfK+Dqh>S@^%FKX-=s?8!KgxBvbz!K zc~Gt);?25P--hSX2ihT3aIKlJxSEEHg;WfTI;4NCqqZC;;TyBiN&TXK>RF@aYrdun zvF}z`#w=Kxv!Hpxi1vOX_Ra1>%T%HHKeklw#?@EFP#zc!K4R*pt~>({d`MU^{v!=P zwHCa-XVj9r@HosE=yMVqBX&+^XKiszkiVENv!i8?F7u!1#Hk7U4xR=%qqvoDgVgM2 zHSEfUCY3x&#>rXkC0r$s*l9V#7+lM-^XuTp)<*Y8Pm)g-b?hf%w&d6z_h$o!S zOgbH)UUXZCt=RFrDt9|SRQX0`&E(Fb%mQ&*G>U4mSCoqa;e_Xo8;c1g{^IU&t9}!R R`ET}k?KAaYd~$U-^%olvA9Mf! delta 116 zcmcaKgXLBO%Z98)im4103?&Sy40#MGKr)3vfgzb8har)n7zh;@G8ytF@7EBYJgG@; z^QOgrST>*A93rk7#^A`{!{Eu_!Vu5k%HYS~%-|1XdjeVRK#@>}5C%5}i^+`##5cR0 P&aq-F-oBBQaUmN3vD+ZT From 95c63bad4bac65ae8b43d41fd10992d07cf01e8c Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 4 May 2023 12:26:26 +0200 Subject: [PATCH 363/403] [SLS-39] Introducing example paragraph regarding the lollipop request formal validation and logging. --- README.md | Bin 68690 -> 73708 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index cfa50f1ea0c78def30cdf3cc4b29f54d666b1e77..8189bcf786663a121030cbd52770f0f3992aa1cd 100644 GIT binary patch delta 1539 zcmah}T}+c#7=D`;1Z|=AM*>~(s~AOrVq>yy#;J$_jne=#F~-dJQL0ocU<=#4Frrzu zo5e(*3rxIWKbUYK78`dZKiw`|!~`Ll5icZ=xC^sv##>GFIbYjIK_w^OcXHly-uHdp z=Q;10zGnG%%#xT%;-`i!sD88#>+DfmT*4BQZzLii31eqtK<$+H<&@~O>as~}veNkK zqyuw9Yl9Jqi^gw(pS01Ew)Yr2YTYfJ{Oi)i5tVaT+rH7Hqi(ta$7hQ$Kjbj`MMElB zTA21>9-O@s#B^#4`iK1+BaHB&s4BZo+#zYl+!d#--B`C7nBwsDmJ}+~9XxXe`t=HI z@3-P%eOWOx%3+?;EVt}vYbeL-ftA=bqZtSlL({1iIL7>$bv0tc z+wkI#HTY-Hj>`>p*rzISY-Ds*E=Lunqj>YMO7V;PBcEMZ%;qvo8LVk?g8apZQ{#Ms z|0w5^91+%al4~_<7fVNMsvFp)?QZycMQdKMoTNJ@`t(7rIk3C0iH{xed7hDd^5pe?z|hlE{iYg zu#av{bgAdjm?7gHx^@fYzxktC34QNo$eS%lomqUL{P_C02Rr^RNOlZ$n5c>3x{P`_ z)NIz|3rwY)2LA^W8_<;)!tGxjxRG$#(qUVfFeIn@0#=g`E%Tq?c$Eb^hAUTSESJ{@ z&98mf{QTXh>)k=Uk zY3*ShY$Az6|6%KeY;|e5YBTa>U`eeZRftwazVfeKlp&tYk!iu4vWQ5&XtL193w8|PXp&BF2y-_n(|K-JlUtFIr zQH#vyWM?xi@#cw5m>qN{XOgiM$-Q@ zn-g7ue6%z;lE+35+OWIP&ybtd%ag}j&KEK;;YQJ90q#D{zDwD6$WpA4x&;HbCQFm! c6Q35~QL4$L;o|ra?3z_i*81d^kMo0X0r^dsx&QzG delta 134 zcmV;10D1rHzXZ~l1hCk%v+l)m2b0Ve=96H`2D47h>;VN0015y>lW)KmlMtN@laSB^ zlT=0!v(C^?4U?SX6qA0-9Fwl%6q6u^4wEq85VQ8*=m(P|<|vc?=P;9O-UyTC;1-jx o1wxZ-^bnJv(GZiKvm5~|lL5FflW^Y Date: Thu, 4 May 2023 12:45:54 +0200 Subject: [PATCH 364/403] [SLS-39] Updated format in submodules README.md files, introduced spring-impl README.md --- assertion-rest-client-native/README.md | 6 ++-- e2e/README.md | 4 +-- identity-service-rest-client-native/README.md | 4 +-- spring-impl/README.md | 33 +++++++++++++++++++ 4 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 spring-impl/README.md diff --git a/assertion-rest-client-native/README.md b/assertion-rest-client-native/README.md index 6f92ebee..8d302af2 100644 --- a/assertion-rest-client-native/README.md +++ b/assertion-rest-client-native/README.md @@ -1,7 +1,5 @@ -# eng-lollipop-consumer-java-sdk - -## Assertion rest client -This module is used to obtain the user's assertion. +# Assertion rest client +This module is used to obtain the user's SAML assertion. The parameters needed to get the assertion are the jwt and the assertion's ref, both retrieved from the http request's headers. diff --git a/e2e/README.md b/e2e/README.md index e27b10b9..0c87d382 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -1,6 +1,4 @@ -# eng-lollipop-consumer-java-sdk - -## End-to-end test +# End-to-end test ### Testing models diff --git a/identity-service-rest-client-native/README.md b/identity-service-rest-client-native/README.md index c7a7f485..0217438b 100644 --- a/identity-service-rest-client-native/README.md +++ b/identity-service-rest-client-native/README.md @@ -1,6 +1,4 @@ -# eng-lollipop-consumer-java-sdk - -## Identity service rest client +# Identity service rest client This module is used to obtain the identity provider certification data. The parameters needed to find the right certificate are the entity id and the assertion's issue instant, diff --git a/spring-impl/README.md b/spring-impl/README.md new file mode 100644 index 00000000..6b0e40c6 --- /dev/null +++ b/spring-impl/README.md @@ -0,0 +1,33 @@ +# Lollipop SDK Spring Implementations + +This module contains implementations of general utility of the core SDK, to be used in the context of a Spring +application. + +## Configurations + +An extension of the configuration class within the core module is provided, in order to enable property loading +through the Spring functionalities. Other configurations are expected to be provided from the application using +this specific implementation (See the [spring-sample](../samples/spring) as a reference for a complete setup +of the other classes, as well as the application.properties file to be used). + +## Interceptor Registry Example + +In order to use the provided Http Interceptor it is required to register in the application context, providing +a configuration for the Spring application to use in order to determine which endpoints should be validated using +the library functionalities + +``` +@Component +public class SampleWebConfigurer implements WebMvcConfigurer { + + @Autowired + private HttpVerifierHandlerInterceptor interceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(interceptor) + .addPathPatterns("/") + .pathMatcher(new AntPathMatcher()); + } +} +``` \ No newline at end of file From 9c426b7a9bd64d01ca4d2f88f494638c534b7d45 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 4 May 2023 15:42:02 +0200 Subject: [PATCH 365/403] [SLS-39] Updated README.md with references to native build and paragraphs regarding the storage services --- README.md | Bin 73708 -> 80506 bytes assertion-rest-client-native/build.gradle | 4 ++-- .../simple/AssertionSimpleClientTest.java | 1 - .../build.gradle | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8189bcf786663a121030cbd52770f0f3992aa1cd..1d726eb55ef7cf543db6169add50ca7b0699de6d 100644 GIT binary patch delta 1869 zcmeHIUrbYH6h9vYqeQNye{OAS;nKcX25p^Lh)aNonoazZsfmekODJuTno^J!6B1*_ z9`IHDP4A;48xKs}fJS3@VJ_L5`s9N?80KQKg-n6Om+b*P=UxS>zHHg!a&!Bge&2Wg z{m$>4`{!Kc-!CesW;%iqGUzZRsYqEmOBw#xK|?I(D2@6=LrseMsgDM%oeUoD4&t-M zI%s=0m>a8=zAsC8R!Q=kFEi4^YJ;rU#3x1SwG5x)og_awcGSoF11t^EDas;w$nS`e zfjcdJoPMU&*HHC)Y<8~(cBVa2)hqt6dm$SCWYz9*I>dH6X)hh%HA@BSH_vO)@|)v0 z(wKh~bnt49=qgfQmLFeVpGJ;`%`sj19Bj$_T~|AT>reNrM~1raWX_A+O28|r53!vz zTeH^;4Ki{*zd>EJngqqyeBp7Uzdc5hw!DYgLeYXupp)7dlww*o6chLk~~>Zd%eedI?juBljQykk$cR597Msnl_E(uvKZ zVI+Qa;+#8&Kkj)DxO)(;*%&_mNkig#!u&a?bo7qt`1p%Jixklv_?RO)}Jk+MRA}o&2y$P&$d}5jTuc z4Pob-P!lENMzzAZ3tFl3hw}+#~up&7_^-u$*`2-2(paO>&RHn zW5+i>Ozm^wLClGzaUEaJ8#wwj>@cVmN1pC%h%t2~?z4PbtQ_NtNW6BG+o^ztQ9o{% zbS%t$uVV05gi=zg0^gTj5*i9U^VH1$GyICSptXj8WGJ*gTpXt59ydmO7HsRQJUi;Ddgs(^t5ch;#(Xm2 zHLq?{8njEy0*f6*EM068S#CL@&o=(I6nS(d@-OL;FuOy_BcYm?L&}Qte_Fgn3-=JS zOITa^l4y2f~H;Kb%oGb0Gx%M^C*qbC|cn@htOL`hCFagsgBF z%ZpwIa~;#;L2r3)$$aUj9xPvqY%!SaG7XdbS>cE=a?6bui!OXOvDHl1s4y;nRaeX3 z5!%nKWj7NiiHX0OTg9P0pzOrct6wJjD^Z@Y-Fz~zq{UMhYxUO3h_IVh#=6*@pYWER I|FUx86{3*Xj{pDw delta 57 zcmezMh2_nDmJOSnHm`Cs%al}L$Ym&HC}t>OP+&-6NClE0UMfS%=KJgIIT=$n%kEq& Ku({^JzeoUDQWV?( diff --git a/assertion-rest-client-native/build.gradle b/assertion-rest-client-native/build.gradle index cd735ddd..7bb20a06 100644 --- a/assertion-rest-client-native/build.gradle +++ b/assertion-rest-client-native/build.gradle @@ -52,9 +52,9 @@ dependencies { implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.2' implementation 'com.google.code.findbugs:jsr305:3.0.2' - implementation 'org.mock-server:mockserver-client-java:5.15.0' implementation 'javax.inject:javax.inject:1' - implementation 'junit:junit:4.13.2' + testImplementation 'org.mock-server:mockserver-client-java:5.15.0' + testImplementation 'junit:junit:4.13.2' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.assertj:assertj-core:3.24.2' diff --git a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java index d887ed96..14e8f951 100644 --- a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java +++ b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java @@ -3,7 +3,6 @@ import static it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientTestUtils.*; import static org.mockserver.integration.ClientAndServer.startClientAndServer; -import static org.mockserver.model.HttpResponse.response; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; diff --git a/identity-service-rest-client-native/build.gradle b/identity-service-rest-client-native/build.gradle index 54368b11..773ce75a 100644 --- a/identity-service-rest-client-native/build.gradle +++ b/identity-service-rest-client-native/build.gradle @@ -59,7 +59,7 @@ dependencies { implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.2' implementation 'com.google.code.findbugs:jsr305:3.0.2' - implementation 'org.mock-server:mockserver-client-java:5.15.0' + testImplementation 'org.mock-server:mockserver-client-java:5.15.0' implementation 'javax.inject:javax.inject:1' // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' From fc6573bc92b7edf638c8964098c1dd3bf97fdbb9 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 4 May 2023 16:08:28 +0200 Subject: [PATCH 366/403] [SLS-39] Updated README.md with references to the Assertion rest client implementation --- README.md | Bin 80506 -> 83290 bytes assertion-rest-client-native/README.md | 10 ++++++++++ build.gradle | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1d726eb55ef7cf543db6169add50ca7b0699de6d..63250efedb1fa60677f7039d3ac42a573b8a77c0 100644 GIT binary patch delta 403 zcmX|6Pbh9F~yZm(qK9-k$e)dfw;r!>p%E_jGLCyO2xE@I1%yl$os7XpQ2u zN(nKQB%wNIMe0$3Z@vu9kcxHPjgkk4NuwC1GWF#e4U(~+-L^x{JDI_@pzx|@!+BRJ zt}ZRmz8zfaWpV7LEr{BJD4coWJ6F(l{!f5xoc1q-201Nm}EZG^KbI- z>3$|dI{x8>R;73N(h;Ws diff --git a/assertion-rest-client-native/README.md b/assertion-rest-client-native/README.md index 8d302af2..8a11118f 100644 --- a/assertion-rest-client-native/README.md +++ b/assertion-rest-client-native/README.md @@ -13,3 +13,13 @@ The client uri, endpoints and the entity id of the CIE identity provider are con |--------------------------|-----------------------|---------------------------------------------------| | baseUri | http://localhost:3000 | base uri of the api for retrieving the assertions | | assertionRequestEndpoint | /assertions | endpoint of the request | + +## Example + +In order to create a new instance of the client using the provider and an instance of the configuration class: + +``` +AssertionClientConfig config = AssertionSimpleClientConfig.builder().build(); +AssertionClientProvider assertionClientProvider = + new AssertionSimpleClientProvider(config); +``` diff --git a/build.gradle b/build.gradle index a76c3f38..a45e4f45 100644 --- a/build.gradle +++ b/build.gradle @@ -54,7 +54,7 @@ allprojects { format 'misc', { // define the files to apply `misc` to - target '*.gradle', '*.md', '.gitignore' + target '*.gradle', '.gitignore' // define the steps to apply to those files trimTrailingWhitespace() From 4d1c85b29526605e90c4b8182a65221e5e66e85c Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Thu, 4 May 2023 16:20:04 +0200 Subject: [PATCH 367/403] [SLS-39] Updated README.md with references to the IdP rest client implementation --- README.md | Bin 83290 -> 85482 bytes identity-service-rest-client-native/README.md | 12 ++++++++++++ 2 files changed, 12 insertions(+) diff --git a/README.md b/README.md index 63250efedb1fa60677f7039d3ac42a573b8a77c0..c2e31e6c231d8632fa9bf9b56d6336ab32f4e195 100644 GIT binary patch delta 170 zcmccB#rkSC>xLcA7_BxJKEKI4xyp-YvdATn%#U|$npP2k^uioT>M=j!>3@Ho& z49*Ox3`Gnj3<^MAB9Km;Ecn=Sa>X^i$qB+d)8(8PS8O(T(!s=NHQE2REJ%!5fgyAH zLMKMa$@`wOF+!NrKR7W8Og?p6U^CN;6^yLB3|tJ+lmFj!pZw>p*Yqp8KslpVPLu9= SOkVeD4$whdn`2)8iv$3np+g=3 delta 36 ucmV+<0NelSn+4j61+cj0lgimPljzT+myi$v4729utOJweyb`nQ^Zr?Z Date: Thu, 4 May 2023 16:41:50 +0200 Subject: [PATCH 368/403] [SLS-39] Updated README.md --- README.md | Bin 85482 -> 92418 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index c2e31e6c231d8632fa9bf9b56d6336ab32f4e195..be19c4f29fb62c3312878fb9d94bcfb1a1e2f0f0 100644 GIT binary patch delta 1503 zcmb_cZAe>Z6n@`DW7H(Q$xY0niC(SRbakyxSc}rJfs|>#Z2t{LX{Y5I_&pcwoxR)(i*q!&U{rSLEt3Dm9aJ3{*s^!AaU zaPZ94;82^a;+z_u-7QT@SPnyvoiK9J=i+TK748y6aHUb-+(#LbqMuef6^$rGn6$>A zY0*djDOyhm6P~ zJG0YrTdwX}NJ3RhEgaNe!_sEygni#T;q4#S!pqTg%an{^!)_UbzQ-Eeo+yD!-#KA! z)(3}|@4TRPI1?td?$y{~Zp^(dojF)r(MdI#bp4NnKCovvqZ2ZJ$Ke7!KU+3nX;KMU zyei~NkjL>i~oNNEN!;HuT)A7so5f(Ce}^aZ@nUA|u!mkOo{n?tp>85DfY9f@!67itg;456E5J~iIZau@XYHx83k$b1H;|= zrULH7-UzM;M{YM2-zahKVuwS+RlU#}S(*(v^UG!!T5x+}6vwlbrh9^Rm~f!kUtkrJ z#6QE*zpF)8$B$|XF#K0AY^bC>cqS3;Q$~#{U`hf{zSIlXkl=o+AD2SX z0VfuG8>nD{?iO(c-@SSm5!Tj~Sjl4NYre>uhsy7C`#nd^)O{c!%bWjH1 zKmKmFjC6XU2u~TZ4L_`+L0KHl!}dzKD|=IxXJ3(f*#8FH8?~!dj?r*mH5Fbz?!c)M LY2=ok{`20yZqT#) delta 15 XcmZp=#QJJB>xM_4xBuc} Date: Thu, 4 May 2023 18:47:05 +0200 Subject: [PATCH 369/403] [SLS-27] Introducing skeleton for Redis client storage --- .../simple/AssertionSimpleClientTest.java | 1 - gradle/verification-metadata.xml | 85 +++++++++++++++++++ redis-storage/build.gradle | 1 + .../consumer/storage/redis/RedisStorage.java | 21 +++++ .../redis/RedisStorageProvisioner.java | 17 ++++ .../storage/redis/builder/ClientBuilder.java | 9 ++ .../builder/DefaultRedisClientBuilder.java | 69 +++++++++++++++ .../redis/idp/RedisIdpCertStorage.java | 67 +++++++++++++++ .../idp/RedisIdpCertStorageProvider.java | 24 ++++++ .../redis/storage/ClusteredRedisStorage.java | 30 +++++++ .../redis/storage/SimpleRedisStorage.java | 46 ++++++++++ redis-storage/src/main/resources/dummydata | 0 .../redis/idp/RedisIdpCertStorageTest.java | 4 + redis-storage/src/test/resources/dummydata | 0 14 files changed, 373 insertions(+), 1 deletion(-) create mode 100644 redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorage.java create mode 100644 redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorageProvisioner.java create mode 100644 redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/ClientBuilder.java create mode 100644 redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/DefaultRedisClientBuilder.java create mode 100644 redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorage.java create mode 100644 redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageProvider.java create mode 100644 redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorage.java create mode 100644 redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java delete mode 100644 redis-storage/src/main/resources/dummydata create mode 100644 redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageTest.java delete mode 100644 redis-storage/src/test/resources/dummydata diff --git a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java index d887ed96..14e8f951 100644 --- a/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java +++ b/assertion-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/AssertionSimpleClientTest.java @@ -3,7 +3,6 @@ import static it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientTestUtils.*; import static org.mockserver.integration.ClientAndServer.startClientAndServer; -import static org.mockserver.model.HttpResponse.response; import it.pagopa.tech.lollipop.consumer.assertion.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.exception.LollipopAssertionNotFoundException; diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 6a9e6fcb..31ab8913 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1906,6 +1906,14 @@ + + + + + + + + @@ -1928,6 +1936,14 @@ + + + + + + + + @@ -1948,6 +1964,14 @@ + + + + + + + + @@ -2028,6 +2052,14 @@ + + + + + + + + @@ -2048,6 +2080,14 @@ + + + + + + + + @@ -2083,6 +2123,11 @@ + + + + + @@ -2100,6 +2145,14 @@ + + + + + + + + @@ -2172,6 +2225,14 @@ + + + + + + + + @@ -2192,6 +2253,14 @@ + + + + + + + + @@ -2208,6 +2277,14 @@ + + + + + + + + @@ -5562,6 +5639,14 @@ + + + + + + + + diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle index dcab70e8..ec805a6b 100644 --- a/redis-storage/build.gradle +++ b/redis-storage/build.gradle @@ -52,6 +52,7 @@ dependencies { implementation project(path: ':core') // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + implementation 'io.lettuce:lettuce-core:6.2.3.RELEASE' } tasks.named('test') { diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorage.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorage.java new file mode 100644 index 00000000..91e37e59 --- /dev/null +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorage.java @@ -0,0 +1,21 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.storage.redis; + +import io.lettuce.core.AbstractRedisClient; +import lombok.Data; + +@Data +public abstract class RedisStorage { + + private AbstractRedisClient redisClient; + + public RedisStorage(AbstractRedisClient redisClient) { + this.redisClient = redisClient; + } + + public abstract Object get(String key); + + public abstract void save(String key, Object value); + + public abstract void delete(String key); +} diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorageProvisioner.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorageProvisioner.java new file mode 100644 index 00000000..d6710c29 --- /dev/null +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorageProvisioner.java @@ -0,0 +1,17 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.storage.redis; + +import it.pagopa.tech.lollipop.consumer.storage.redis.builder.ClientBuilder; + +public class RedisStorageProvisioner { + + private final ClientBuilder clientBuilder; + + public RedisStorageProvisioner(ClientBuilder clientBuilder) { + this.clientBuilder = clientBuilder; + } + + public RedisStorage getStorage() { + return clientBuilder.createStorage(); + } +} diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/ClientBuilder.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/ClientBuilder.java new file mode 100644 index 00000000..d71b1d06 --- /dev/null +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/ClientBuilder.java @@ -0,0 +1,9 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.storage.redis.builder; + +import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorage; + +public interface ClientBuilder { + + RedisStorage createStorage(); +} diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/DefaultRedisClientBuilder.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/DefaultRedisClientBuilder.java new file mode 100644 index 00000000..02627d8a --- /dev/null +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/DefaultRedisClientBuilder.java @@ -0,0 +1,69 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.storage.redis.builder; + +import io.lettuce.core.ClientOptions; +import io.lettuce.core.RedisClient; +import io.lettuce.core.RedisURI; +import io.lettuce.core.SocketOptions; +import io.lettuce.core.cluster.ClusterClientOptions; +import io.lettuce.core.cluster.RedisClusterClient; +import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorage; +import it.pagopa.tech.lollipop.consumer.storage.redis.storage.SimpleRedisStorage; + +public class DefaultRedisClientBuilder implements ClientBuilder { + + @Override + public RedisStorage createStorage() { + return new SimpleRedisStorage(createRedisClient("TBD", 9000, "TBD", "TBD")); + } + + private RedisClient createRedisClient( + String hostName, int port, String username, String password) { + + // Build Redis URI with host and authentication details. + RedisURI redisURI = + RedisURI.Builder.redis(hostName) + .withPort(port) + .withSsl(true) + .withAuthentication(username, password) + .withClientName("LettuceClient") + .build(); + + // Create Lettuce Redis Client + RedisClient client = RedisClient.create(redisURI); + + // Configure the client options. + client.setOptions( + ClientOptions.builder() + .autoReconnect(true) + .socketOptions(SocketOptions.builder().keepAlive(true).build()) + .build()); + + return client; + } + + private RedisClusterClient createRedisClusterClient( + String hostName, int port, String username, String password) { + + // Build Redis URI with host and authentication details. + RedisURI redisURI = + RedisURI.Builder.redis(hostName) + .withPort(port) + .withSsl(true) + .withAuthentication(username, password) + .withClientName("LettuceClient") + .build(); + + // Create Lettuce Redis Client + RedisClusterClient client = RedisClusterClient.create(redisURI); + + // Configure the client options. + client.setOptions( + ClusterClientOptions.builder() + .autoReconnect(true) + .socketOptions(SocketOptions.builder().keepAlive(true).build()) + .build()); + + return client; + } +} diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorage.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorage.java new file mode 100644 index 00000000..bb7922a7 --- /dev/null +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorage.java @@ -0,0 +1,67 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.storage.redis.idp; + +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorage; + +/** + * Implementation of the {@link IdpCertStorage} interface as a simple in memory storage. + * + *

The storage can be configured via the {@link IdpCertStorageConfig} configuration class. + * + *

It store in a in memory {@link java.util.HashMap} the assertions and the associated scheduled + * eviction operations, every time an assertion is accessed the associated eviction operation is + * rescheduled. + */ +public class RedisIdpCertStorage implements IdpCertStorage { + + private final RedisStorage redisStorage; + private final IdpCertStorageConfig storageConfig; + + public RedisIdpCertStorage( + RedisStorage redisStorage, IdpCertStorageConfig idpCertStorageConfig) { + this.redisStorage = redisStorage; + this.storageConfig = idpCertStorageConfig; + } + + /** + * Retrieve the idpCertData associated with the provided tag if the storage is enabled {@link + * IdpCertStorageConfig}, otherwise no operation is performed. + * + *

Before the list of idpCertData is returned the associated eviction operation is + * rescheduled with the delay configured via {@link IdpCertStorageConfig} + * + * @param tag the idpCertData issue instant + * @return the list of cert data if found, null if no cert data are present in the storage or + * the storage is disabled + */ + @Override + public IdpCertData getIdpCertData(String tag) { + if (!storageConfig.isIdpCertDataStorageEnabled()) { + return null; + } + + return (IdpCertData) redisStorage.get(tag); + } + + /** + * Store the idpCertData if the storage is enabled {@link IdpCertStorageConfig}, otherwise no + * operation is performed. + * + *

Once the idpCertData is stored an eviction operation is scheduled with a delay configured + * via {@link IdpCertStorageConfig} + * + * @param tag the idpCertData issue instant + * @param idpCertData + */ + @Override + public void saveIdpCertData(String tag, IdpCertData idpCertData) { + if (!storageConfig.isIdpCertDataStorageEnabled()) { + return; + } + + redisStorage.save(tag, idpCertData); + } +} diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageProvider.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageProvider.java new file mode 100644 index 00000000..48b93f8f --- /dev/null +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageProvider.java @@ -0,0 +1,24 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.storage.redis.idp; + +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageProvider; +import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorageProvisioner; + +/** Implementation of {@link IdpCertStorageProvider} interface. It provides an instance of the */ +public class RedisIdpCertStorageProvider implements IdpCertStorageProvider { + + private RedisStorageProvisioner redisStorageProvisioner; + + /** + * {@inheritDoc} + * + * @param storageConfig the storage configuration + * @return an instance of {@link SimpleIdpCertStorage} + */ + @Override + public IdpCertStorage provideStorage(IdpCertStorageConfig storageConfig) { + return new RedisIdpCertStorage(redisStorageProvisioner.getStorage(), storageConfig); + } +} diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorage.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorage.java new file mode 100644 index 00000000..6e773a3e --- /dev/null +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorage.java @@ -0,0 +1,30 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.storage.redis.storage; + +import io.lettuce.core.cluster.RedisClusterClient; +import io.lettuce.core.cluster.api.StatefulRedisClusterConnection; +import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorage; + +public class ClusteredRedisStorage extends RedisStorage { + + public ClusteredRedisStorage(RedisClusterClient redisClient) { + super(redisClient); + } + + @Override + public Object get(String key) { + StatefulRedisClusterConnection statefulConnection = + ((RedisClusterClient) getRedisClient()).connect(); + try { + return statefulConnection.sync().get(key); + } finally { + statefulConnection.closeAsync(); + } + } + + @Override + public void save(String key, Object value) {} + + @Override + public void delete(String key) {} +} diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java new file mode 100644 index 00000000..b950ca0b --- /dev/null +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java @@ -0,0 +1,46 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.storage.redis.storage; + +import io.lettuce.core.RedisClient; +import io.lettuce.core.api.StatefulRedisConnection; +import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorage; + +public class SimpleRedisStorage extends RedisStorage { + + public SimpleRedisStorage(RedisClient redisClient) { + super(redisClient); + } + + @Override + public Object get(String key) { + + StatefulRedisConnection statefulConnection = + ((RedisClient) getRedisClient()).connect(); + try { + return statefulConnection.sync().get(key); + } finally { + statefulConnection.closeAsync(); + } + } + + @Override + public void save(String key, Object value) { + StatefulRedisConnection statefulRedisConnection = + ((RedisClient) getRedisClient()).connect(); + ((RedisClient) getRedisClient()) + .connect() + .async() + .set(key, String.valueOf(value)) + .thenAccept( + result -> { + if ("OK".equals(result)) { + statefulRedisConnection.async().expire(key, 1000L); + } + }); + } + + @Override + public void delete(String key) { + ((RedisClient) getRedisClient()).connect().async().del(key); + } +} diff --git a/redis-storage/src/main/resources/dummydata b/redis-storage/src/main/resources/dummydata deleted file mode 100644 index e69de29b..00000000 diff --git a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageTest.java b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageTest.java new file mode 100644 index 00000000..5112287b --- /dev/null +++ b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageTest.java @@ -0,0 +1,4 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.storage.redis.idp; + +class RedisIdpCertStorageTest {} diff --git a/redis-storage/src/test/resources/dummydata b/redis-storage/src/test/resources/dummydata deleted file mode 100644 index e69de29b..00000000 From 45b87d51f32869cff230796d7fe65677f64e1492 Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 5 May 2023 10:44:43 +0200 Subject: [PATCH 370/403] [SLS-39] Added prerequisite to e2e test readme --- e2e/README.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/e2e/README.md b/e2e/README.md index 0c87d382..2e5cbe14 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -1,24 +1,34 @@ +# eng-lollipop-consumer-java-sdk + # End-to-end test +### Prerequisites ++ [Node.js](https://nodejs.org/en/download) ++ [Gradle](https://gradle.org/install/) ++ [Docker Compose](https://docs.docker.com/compose/) + ### Testing models + #### Publish library dependencies to maven local -In the root folder run +In the root folder, update gradlew permission and publish the dependencies ```bash +chmod +x ./gradlew ./gradlew publishToMavenLocal ``` + #### Build spring sample application -Change directory to ./samples/spring folder and build the sample with +Change directory to ./samples/spring folder, +update also this gradlew file permission and build the sample ```bash cd samples/spring +chmod +x ./gradlew ./gradlew bootJar ``` + #### Run docker container -Return to root folder and run docker compose in the e2e folder with +Return to root folder and run docker compose in the e2e folder ```bash cd .. @@ -44,7 +54,7 @@ npm run execute-test Newman generates a detailed report in the "newman" folder, you can open it with your preferred browser ### Configuration -The sample configuration can be changed with environment variables in the .env.dev files +The sample configuration can be changed with environment variables in the .env.dev file (or using a different .env file in the docker compose command) The configurable variables are the following: From b26bbfa68382875077f071f00c9dd5ce3a48fd29 Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 5 May 2023 11:10:12 +0200 Subject: [PATCH 371/403] [SLS-39] Added info on the usage of docker for users with arc64 cpus --- e2e/README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/e2e/README.md b/e2e/README.md index 2e5cbe14..e24772ca 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -78,4 +78,14 @@ The configurable variables are the following: | ASSERTION_REST_URI | http://localhost:3000 | Define base uri to retrieve the Assertion | | ASSERTION_REST_ENDPOINT | /assertions | Define endpoint to ASSERTION_REST_URI | | ASSERTION_STORAGE_ENABLED | true | Enable internal cache storage for assertions | -| ASSERTION_STORAGE_ENABLED | 1 | Define storage eviction delay for assertion's storage | \ No newline at end of file +| ASSERTION_STORAGE_EVICTION_DELAY | 1 | Define storage eviction delay for assertion's storage | + +### Troubleshooting + +- ##### Docker image incompatibility + + The docker image [eclipse-temurin:11-jdk-alpine](https://hub.docker.com/layers/library/eclipse-temurin/11-jdk-alpine/images/sha256-ea0ec99f8cfbaff4d61fec32af9430097e152860ec58b3cf2cb06454d75c61b0?context=explore) + used to build the sample is compatible only with amd64 cpus and not with + apple's silicon cpus (arc64), if you have an arc cpu and having trouble building the docker image + change it in the Dockerfile to [eclipse-temurin:11-jre-jammy](https://hub.docker.com/layers/library/eclipse-temurin/11-jre-jammy/images/sha256-18c3e334425f4fbf3a53f2f0df713e4d206894fb00ab2edde6df0311f5b63550?context=explore). + From 4ef1bb11b46800e5545f0918111abca302be68e1 Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 5 May 2023 11:12:52 +0200 Subject: [PATCH 372/403] [SLS-39] Removed repository title on e2e readme --- e2e/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/e2e/README.md b/e2e/README.md index e24772ca..90313b78 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -1,5 +1,3 @@ -# eng-lollipop-consumer-java-sdk - # End-to-end test ### Prerequisites From 85a0adce502561ea0b172e518c9a255494341456 Mon Sep 17 00:00:00 2001 From: svariant Date: Fri, 5 May 2023 11:33:04 +0200 Subject: [PATCH 373/403] [SLS-39] Added info on github environment variables --- e2e/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/e2e/README.md b/e2e/README.md index 90313b78..20154f70 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -4,6 +4,9 @@ + [Node.js](https://nodejs.org/en/download) + [Gradle](https://gradle.org/install/) + [Docker Compose](https://docs.docker.com/compose/) ++ Define in your system the following environment variables: + + GITHUB_ACTOR : [github username](https://github.com/settings/profile) + + GITHUB_TOKEN : [github personal access token (classic)](https://github.com/settings/tokens) with read permissions ### Testing models From d409a609e09ba2b1218d72df674fc16a13bf48df Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Fri, 5 May 2023 19:54:25 +0200 Subject: [PATCH 374/403] [SLS-27] Introducing redis storage implementation --- .../lollipop/consumer/model/IdpCertData.java | 3 +- gradle/verification-metadata.xml | 32 ++++ redis-storage/build.gradle | 10 +- .../consumer/storage/redis/RedisStorage.java | 34 +++- .../redis/RedisStorageProvisioner.java | 9 + .../storage/redis/builder/ClientBuilder.java | 1 + .../builder/DefaultRedisClientBuilder.java | 89 +++++++-- .../redis/config/RedisStorageConfig.java | 35 ++++ .../redis/idp/RedisIdpCertStorage.java | 39 +++- .../idp/RedisIdpCertStorageProvider.java | 11 +- .../redis/storage/ClusteredRedisStorage.java | 67 ++++++- .../redis/storage/SimpleRedisStorage.java | 62 +++++- .../RedisIdpCertStorageIntegrationTest.java | 180 ++++++++++++++++++ .../redis/idp/RedisIdpCertStorageTest.java | 4 - .../ClusteredRedisStorageUnitTest.java | 89 +++++++++ .../redis/storage/SimpleRedisStorageTest.java | 63 ++++++ 16 files changed, 677 insertions(+), 51 deletions(-) create mode 100644 redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/config/RedisStorageConfig.java create mode 100644 redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java delete mode 100644 redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageTest.java create mode 100644 redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorageUnitTest.java create mode 100644 redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorageTest.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java index 23b3a90b..ad69d217 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java @@ -2,6 +2,7 @@ package it.pagopa.tech.lollipop.consumer.model; import java.util.List; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import lombok.ToString; @@ -9,8 +10,8 @@ @Getter @Setter @ToString +@EqualsAndHashCode public class IdpCertData { - private String entityId; private String tag; private List certData; diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 31ab8913..64a8a8b9 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -986,6 +986,14 @@ + + + + + + + + @@ -5954,6 +5962,14 @@ + + + + + + + + @@ -6014,6 +6030,14 @@ + + + + + + + + @@ -6031,6 +6055,14 @@ + + + + + + + + diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle index ec805a6b..4b9c848d 100644 --- a/redis-storage/build.gradle +++ b/redis-storage/build.gradle @@ -51,8 +51,16 @@ dependencies { } implementation project(path: ':core') // Use JUnit Jupiter for testing. - testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' implementation 'io.lettuce:lettuce-core:6.2.3.RELEASE' + implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.14.2' + implementation 'org.openapitools:jackson-databind-nullable:0.2.6' + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.2' + // Use JUnit Jupiter for testing. + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + testImplementation 'org.mockito:mockito-core:5.2.0' + testImplementation 'org.mockito:mockito-junit-jupiter:5.2.0' + testImplementation 'org.assertj:assertj-core:3.24.2' + testImplementation 'com.github.codemonstur:embedded-redis:1.0.0' } tasks.named('test') { diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorage.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorage.java index 91e37e59..3cc7cdb2 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorage.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorage.java @@ -4,6 +4,10 @@ import io.lettuce.core.AbstractRedisClient; import lombok.Data; +/** + * Abstract class to be used in order to define a redis storage using a Lettuce implementation of + * the AbstractRedisClient + */ @Data public abstract class RedisStorage { @@ -13,9 +17,35 @@ public RedisStorage(AbstractRedisClient redisClient) { this.redisClient = redisClient; } - public abstract Object get(String key); + /** + * Attempts to recover a value from the redis instance, using the provided key + * + * @param key key to be used in order to attempt the retreival of a value from redis + * @return if found the String value obtained from redis, null otherwise + */ + public abstract String get(String key); - public abstract void save(String key, Object value); + /** + * Saves a value in the redis using the provided key + * + * @param key key to be used when saving the value + * @param value value to be stored in the redis instance + */ + public abstract void save(String key, String value); + /** + * Saves a value in the redis using the provided key, with a defined TTL + * + * @param key key to be used when saving the value + * @param value value to be stored in the redis instance + * @param delayTime seconds defining the stored data TTL + */ + public abstract void save(String key, String value, Long delayTime); + + /** + * Deletes a value from redis using the provided key + * + * @param key key to be used for content deletion from redis + */ public abstract void delete(String key); } diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorageProvisioner.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorageProvisioner.java index d6710c29..0de87c0e 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorageProvisioner.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorageProvisioner.java @@ -3,6 +3,10 @@ import it.pagopa.tech.lollipop.consumer.storage.redis.builder.ClientBuilder; +/** + * This class provides a simple way to generate an instance of a RedisStorage, from the provided + * ClientBuilder interface + */ public class RedisStorageProvisioner { private final ClientBuilder clientBuilder; @@ -11,6 +15,11 @@ public RedisStorageProvisioner(ClientBuilder clientBuilder) { this.clientBuilder = clientBuilder; } + /** + * Provides an instance of the RedisStorage, produced by the defined clientBuilder + * + * @return an instance of the RedisStorage + */ public RedisStorage getStorage() { return clientBuilder.createStorage(); } diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/ClientBuilder.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/ClientBuilder.java index d71b1d06..212712b5 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/ClientBuilder.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/ClientBuilder.java @@ -3,6 +3,7 @@ import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorage; +/** Interface abstracting a builder of RedisStorage instances */ public interface ClientBuilder { RedisStorage createStorage(); diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/DefaultRedisClientBuilder.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/DefaultRedisClientBuilder.java index 02627d8a..9797d556 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/DefaultRedisClientBuilder.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/DefaultRedisClientBuilder.java @@ -8,26 +8,50 @@ import io.lettuce.core.cluster.ClusterClientOptions; import io.lettuce.core.cluster.RedisClusterClient; import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorage; +import it.pagopa.tech.lollipop.consumer.storage.redis.config.RedisStorageConfig; +import it.pagopa.tech.lollipop.consumer.storage.redis.storage.ClusteredRedisStorage; import it.pagopa.tech.lollipop.consumer.storage.redis.storage.SimpleRedisStorage; +import java.util.ArrayList; +import java.util.List; +/** + * An implementation of the {@link ClientBuilder} interface, to be used in order to define instances + * of Lettuce Redis clients + */ public class DefaultRedisClientBuilder implements ClientBuilder { + private final RedisStorageConfig redisStorageConfig; + + public DefaultRedisClientBuilder(RedisStorageConfig redisStorageConfig) { + this.redisStorageConfig = redisStorageConfig; + } + + /** + * Creates an instance of {@link RedisStorage} using the generated RedisClient, depending on the + * configured parameter it will be used a Clustered or Simple instance + * + * @return an instance of a RedisStorage + */ @Override public RedisStorage createStorage() { - return new SimpleRedisStorage(createRedisClient("TBD", 9000, "TBD", "TBD")); + return redisStorageConfig.isClusterConnection() + ? new ClusteredRedisStorage(createRedisClusterClient()) + : new SimpleRedisStorage(createRedisClient()); } - private RedisClient createRedisClient( - String hostName, int port, String username, String password) { + /** + * Creates a simple Redis Client using the provided configurations + * + * @return a RedisClient + */ + private RedisClient createRedisClient() { // Build Redis URI with host and authentication details. + RedisURI redisURI = - RedisURI.Builder.redis(hostName) - .withPort(port) - .withSsl(true) - .withAuthentication(username, password) - .withClientName("LettuceClient") - .build(); + getRedisURI( + redisStorageConfig.getMainNode().getHostname(), + redisStorageConfig.getMainNode().getPort()); // Create Lettuce Redis Client RedisClient client = RedisClient.create(redisURI); @@ -42,20 +66,27 @@ private RedisClient createRedisClient( return client; } - private RedisClusterClient createRedisClusterClient( - String hostName, int port, String username, String password) { + /** + * Creates a Clustered Redis Client using the provided configurations + * + * @return a RedisClient + */ + private RedisClusterClient createRedisClusterClient() { - // Build Redis URI with host and authentication details. - RedisURI redisURI = - RedisURI.Builder.redis(hostName) - .withPort(port) - .withSsl(true) - .withAuthentication(username, password) - .withClientName("LettuceClient") - .build(); + List redisURIList = new ArrayList<>(); + redisURIList.add( + getRedisURI( + redisStorageConfig.getMainNode().getHostname(), + redisStorageConfig.getMainNode().getPort())); + + if (redisStorageConfig.getClusterNodeList() != null) { + for (RedisStorageConfig.RedisNode redisNode : redisStorageConfig.getClusterNodeList()) { + redisURIList.add(getRedisURI(redisNode.getHostname(), redisNode.getPort())); + } + } // Create Lettuce Redis Client - RedisClusterClient client = RedisClusterClient.create(redisURI); + RedisClusterClient client = RedisClusterClient.create(redisURIList); // Configure the client options. client.setOptions( @@ -66,4 +97,22 @@ private RedisClusterClient createRedisClusterClient( return client; } + + private RedisURI getRedisURI(String hostname, Integer port) { + // Build Redis URI with host and authentication details. + RedisURI.Builder builder = + RedisURI.Builder.redis(hostname) + .withPort(port) + .withSsl(redisStorageConfig.isWithSsl()); + + if (redisStorageConfig.isWithAuth()) { + builder.withAuthentication( + redisStorageConfig.getUsername(), redisStorageConfig.getPassword()); + } + + builder.withClientName(redisStorageConfig.getClientName()); + + RedisURI redisURI = builder.build(); + return redisURI; + } } diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/config/RedisStorageConfig.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/config/RedisStorageConfig.java new file mode 100644 index 00000000..a1859b32 --- /dev/null +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/config/RedisStorageConfig.java @@ -0,0 +1,35 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.storage.redis.config; + +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class RedisStorageConfig { + + @Builder.Default private RedisNode mainNode = new RedisNode(); + @Builder.Default private boolean withAuth = false; + @Builder.Default private String username = "username"; + @Builder.Default private String password = "password"; + @Builder.Default private boolean clusterConnection = false; + @Builder.Default private boolean withSsl = false; + @Builder.Default private String clientName = "LettuceClient"; + @Builder.Default private Long defaultDelay = 60L; + private List clusterNodeList; + + @NoArgsConstructor + @AllArgsConstructor + @Builder + @Data + public static class RedisNode { + + @Builder.Default private String hostname = "localhost"; + @Builder.Default private Integer port = 6370; + } +} diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorage.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorage.java index bb7922a7..4225aca7 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorage.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorage.java @@ -1,49 +1,64 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.storage.redis.idp; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorage; +import lombok.SneakyThrows; +import org.openapitools.jackson.nullable.JsonNullableModule; /** - * Implementation of the {@link IdpCertStorage} interface as a simple in memory storage. + * Implementation of the {@link IdpCertStorage} interface as a redis storage. * *

The storage can be configured via the {@link IdpCertStorageConfig} configuration class. - * - *

It store in a in memory {@link java.util.HashMap} the assertions and the associated scheduled - * eviction operations, every time an assertion is accessed the associated eviction operation is - * rescheduled. */ public class RedisIdpCertStorage implements IdpCertStorage { private final RedisStorage redisStorage; private final IdpCertStorageConfig storageConfig; + private ObjectMapper objectMapper; + public RedisIdpCertStorage( RedisStorage redisStorage, IdpCertStorageConfig idpCertStorageConfig) { this.redisStorage = redisStorage; this.storageConfig = idpCertStorageConfig; + this.objectMapper = new ObjectMapper(); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.registerModule(new JsonNullableModule()); } /** * Retrieve the idpCertData associated with the provided tag if the storage is enabled {@link * IdpCertStorageConfig}, otherwise no operation is performed. * - *

Before the list of idpCertData is returned the associated eviction operation is - * rescheduled with the delay configured via {@link IdpCertStorageConfig} - * * @param tag the idpCertData issue instant * @return the list of cert data if found, null if no cert data are present in the storage or * the storage is disabled */ + @SneakyThrows @Override public IdpCertData getIdpCertData(String tag) { if (!storageConfig.isIdpCertDataStorageEnabled()) { return null; } - return (IdpCertData) redisStorage.get(tag); + String objString = redisStorage.get(tag); + + return objString == null ? null : objectMapper.readValue(objString, IdpCertData.class); } /** @@ -56,12 +71,16 @@ public IdpCertData getIdpCertData(String tag) { * @param tag the idpCertData issue instant * @param idpCertData */ + @SneakyThrows @Override public void saveIdpCertData(String tag, IdpCertData idpCertData) { if (!storageConfig.isIdpCertDataStorageEnabled()) { return; } - redisStorage.save(tag, idpCertData); + redisStorage.save( + tag, + objectMapper.writeValueAsString(idpCertData), + storageConfig.getStorageEvictionDelay()); } } diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageProvider.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageProvider.java index 48b93f8f..b30510ac 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageProvider.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageProvider.java @@ -5,8 +5,15 @@ import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageProvider; import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorageProvisioner; +import lombok.AllArgsConstructor; +import lombok.Data; -/** Implementation of {@link IdpCertStorageProvider} interface. It provides an instance of the */ +/** + * Implementation of {@link IdpCertStorageProvider} interface. It provides an instance of {@link + * RedisIdpCertStorage} + */ +@Data +@AllArgsConstructor public class RedisIdpCertStorageProvider implements IdpCertStorageProvider { private RedisStorageProvisioner redisStorageProvisioner; @@ -15,7 +22,7 @@ public class RedisIdpCertStorageProvider implements IdpCertStorageProvider { * {@inheritDoc} * * @param storageConfig the storage configuration - * @return an instance of {@link SimpleIdpCertStorage} + * @return an instance of {@link RedisIdpCertStorage} */ @Override public IdpCertStorage provideStorage(IdpCertStorageConfig storageConfig) { diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorage.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorage.java index 6e773a3e..4e5e8d1c 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorage.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorage.java @@ -1,18 +1,33 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.storage.redis.storage; +import io.lettuce.core.RedisClient; import io.lettuce.core.cluster.RedisClusterClient; import io.lettuce.core.cluster.api.StatefulRedisClusterConnection; import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorage; +/** Implements commands to a Redis Cluster using Lettuce */ public class ClusteredRedisStorage extends RedisStorage { + private Long defaultDelayTimeSeconds = 60L; + public ClusteredRedisStorage(RedisClusterClient redisClient) { super(redisClient); } + public ClusteredRedisStorage(RedisClient redisClient, Long defaultDelayTimeSeconds) { + super(redisClient); + this.defaultDelayTimeSeconds = defaultDelayTimeSeconds; + } + + /** + * Attempts to recover a value from the redis instance, using the provided key + * + * @param key key to be used in order to attempt the retreival of a value from redis + * @return if found the String value obtained from redis, null otherwise + */ @Override - public Object get(String key) { + public String get(String key) { StatefulRedisClusterConnection statefulConnection = ((RedisClusterClient) getRedisClient()).connect(); try { @@ -22,9 +37,55 @@ public Object get(String key) { } } + /** + * Saves the key-value pair in the Redis instance, using a default TTL + * + * @param key key to be used when saving the value + * @param value value to be stored in the redis instance + */ @Override - public void save(String key, Object value) {} + public void save(String key, String value) { + save(key, value, defaultDelayTimeSeconds); + } + /** + * Saves asynchronously the key-value pair in the Redis instance, using the provided TTL + * + * @param key key to be used when saving the value + * @param value value to be stored in the redis instance + * @param delayTime seconds defining the stored data TTL + */ @Override - public void delete(String key) {} + public void save(String key, String value, Long delayTime) { + StatefulRedisClusterConnection statefulRedisConnection = + ((RedisClusterClient) getRedisClient()).connect(); + statefulRedisConnection + .async() + .set(key, String.valueOf(value)) + .thenAccept( + result -> { + if ("OK".equals(result)) { + statefulRedisConnection.async().expire(key, delayTime); + } + statefulRedisConnection.closeAsync(); + }); + } + + /** + * Deletes asynchronously a value from the Redis instance using the provided key + * + * @param key key to be used for content deletion from redis + */ + @Override + public void delete(String key) { + StatefulRedisClusterConnection statefulRedisConnection = + ((RedisClusterClient) getRedisClient()).connect(); + statefulRedisConnection + .async() + .del(key) + .thenAccept( + result -> { + statefulRedisConnection.closeAsync(); + }); + } } diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java index b950ca0b..3d46550e 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java @@ -1,19 +1,34 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.storage.redis.storage; +import io.lettuce.core.AbstractRedisClient; import io.lettuce.core.RedisClient; import io.lettuce.core.api.StatefulRedisConnection; import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorage; +/** Implements commands to a simple Redis instance using Lettuce */ public class SimpleRedisStorage extends RedisStorage { - public SimpleRedisStorage(RedisClient redisClient) { + private Long defaultDelayTimeSeconds = 60L; + + public SimpleRedisStorage(AbstractRedisClient redisClient) { super(redisClient); } - @Override - public Object get(String key) { + public SimpleRedisStorage(RedisClient redisClient, Long defaultDelayTimeSeconds) { + super(redisClient); + this.defaultDelayTimeSeconds = defaultDelayTimeSeconds; + } + /** + * Retrieves from a synchronous connection the value stored in the Redis instance using the + * provided key, closes the connection asynchronously + * + * @param key key to be used in order to attempt the retreival of a value from redis + * @return value stored in the Redis instance + */ + @Override + public String get(String key) { StatefulRedisConnection statefulConnection = ((RedisClient) getRedisClient()).connect(); try { @@ -23,24 +38,55 @@ public Object get(String key) { } } + /** + * Saves the key-value pair in the Redis instance, using a default TTL + * + * @param key key to be used when saving the value + * @param value value to be stored in the redis instance + */ + @Override + public void save(String key, String value) { + save(key, value, defaultDelayTimeSeconds); + } + + /** + * Saves asynchronously the key-value pair in the Redis instance, using the provided TTL + * + * @param key key to be used when saving the value + * @param value value to be stored in the redis instance + * @param delayTime seconds defining the stored data TTL + */ @Override - public void save(String key, Object value) { + public void save(String key, String value, Long delayTime) { StatefulRedisConnection statefulRedisConnection = ((RedisClient) getRedisClient()).connect(); - ((RedisClient) getRedisClient()) - .connect() + statefulRedisConnection .async() .set(key, String.valueOf(value)) .thenAccept( result -> { if ("OK".equals(result)) { - statefulRedisConnection.async().expire(key, 1000L); + statefulRedisConnection.async().expire(key, delayTime); } + statefulRedisConnection.closeAsync(); }); } + /** + * Deletes asynchronously a value from the Redis instance using the provided key + * + * @param key key to be used for content deletion from redis + */ @Override public void delete(String key) { - ((RedisClient) getRedisClient()).connect().async().del(key); + StatefulRedisConnection statefulRedisConnection = + ((RedisClient) getRedisClient()).connect(); + statefulRedisConnection + .async() + .del(key) + .thenAccept( + result -> { + statefulRedisConnection.closeAsync(); + }); } } diff --git a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java new file mode 100644 index 00000000..29e93aa0 --- /dev/null +++ b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java @@ -0,0 +1,180 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.storage.redis.idp; + +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorageProvisioner; +import it.pagopa.tech.lollipop.consumer.storage.redis.builder.DefaultRedisClientBuilder; +import it.pagopa.tech.lollipop.consumer.storage.redis.config.RedisStorageConfig; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import lombok.SneakyThrows; +import org.junit.jupiter.api.*; +import redis.embedded.RedisServer; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class RedisIdpCertStorageIntegrationTest { + + private static final String VALID_ASSERTION_XML = + "{\"response_xml\": \"\\n" + + " https:\\/\\/spid-testenv2:8088<\\/saml:Issuer><\\/ds:Transforms>s\\/DqYePHC7eCXX5ncsiFYNLyKbzS6P5C8331H1b8e30=<\\/ds:DigestValue><\\/ds:Reference><\\/ds:SignedInfo>WcasorooElvhmK0kxFUdBVCqyRYi0SCNGRSZZnC9Q2sZHOYGZbERe4\\/T8OSuRKbSrEivXIHRgNr8WskZTM2CiywfWChHfGvhERsLuPJE8oh9CR3eicX\\/eg0ynJqwx4IoYhTb2NOwqMFc66nnutMhG\\/Smdtjs4SFz0RQYYVeZ5Ho51iTHd94uBV9ZHXjqcvs3EitUsJ0Zg1Pkw352tt8y7niUcGjAd8nydI72S12sF5ePv05AunFp7vZpYbKqi62fQLORCn1ZP7WKFD75hL0bCvZaSRF285GkfSnLfe1S4tLff2SlTQWevOMU\\/wCkHJmQwHT1LMwcWRnMvv4V+vd1XQ==<\\/ds:SignatureValue>MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR\\/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2\\/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI\\/sp\\n" + + "ILywgDxVMMtv\\/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAf\\n" + + "BgNVHSMEGDAWgBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH\\/MA0G\\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8\\/o13vMw4feGxro1hMeUilRtH52funrW\\n" + + "C+FgPrqk3o\\/8cZOnq+CqnFFDfILLiEb\\/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\n" + + "Da1fG\\/Pi0fG2F0yw\\/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk\\/ZbEHdKcofnziDyl0V8gglP2\\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n" + + "<\\/ds:X509Certificate><\\/ds:X509Data><\\/ds:KeyInfo><\\/ds:Signature>\\n" + + " \\n" + + " \\n" + + " <\\/samlp:Status>\\n" + + " \\n" + + " https:\\/\\/spid-testenv2:8088<\\/saml:Issuer><\\/ds:Transforms>4cqgG29TSKgNLy2\\/1eFPXhd5WRVPxZBGcd8DgTvd5Fo=<\\/ds:DigestValue><\\/ds:Reference><\\/ds:SignedInfo>WqxM+y+vtZDcEaIaw2WfcuMuwXUeTOY9ZjaXwzHw+RE8uUr5s8BE1tpaodcKmmqSJK1JQYNr8AUV+W9V79EKfmNtFvfaf0WYeUee7Td7E24QqiyVHjr1YgfDWhSdItFLYJfQUkotj2BepbdwVQGY5yN0Rw6Fq98hgNOgsxty7g6oqxG1OXB4WJ2He20iOoYWQl8ApxlbU\\/\\/hwnefFYe9ghDPy3rDbcNl3JetT07NR\\/+AzhKH4e+JCwKjTkdCBTW30fK4eiV9yBk74Lobip4hMaQhMaByl8egaU3A8AsnsZQuov2B6Wo2sDiQPjIulb8K3DOwFyL8PzEk8BB5YoAfwg==<\\/ds:SignatureValue>MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR\\/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2\\/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI\\/sp\\n" + + "ILywgDxVMMtv\\/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAf\\n" + + "BgNVHSMEGDAWgBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH\\/MA0G\\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8\\/o13vMw4feGxro1hMeUilRtH52funrW\\n" + + "C+FgPrqk3o\\/8cZOnq+CqnFFDfILLiEb\\/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\n" + + "Da1fG\\/Pi0fG2F0yw\\/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk\\/ZbEHdKcofnziDyl0V8gglP2\\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n" + + "<\\/ds:X509Certificate><\\/ds:X509Data><\\/ds:KeyInfo><\\/ds:Signature>\\n" + + " \\n" + + " id_48129c2a9d5e9077422591baf495747cfda668c5<\\/saml:NameID>\\n" + + " \\n" + + " \\n" + + " <\\/saml:SubjectConfirmation>\\n" + + " <\\/saml:Subject>\\n" + + " \\n" + + " \\n" + + " https:\\/\\/spid.agid.gov.it\\/cd<\\/saml:Audience>\\n" + + " <\\/saml:AudienceRestriction>\\n" + + " <\\/saml:Conditions>\\n" + + " \\n" + + " \\n" + + " " + + " https:\\/\\/www.spid.gov.it\\/SpidL2<\\/saml:AuthnContextClassRef>\\n" + + " <\\/saml:AuthnContext>\\n" + + " <\\/saml:AuthnStatement>\\n" + + " \\n" + + " \\n" + + " info@agid.gov.it<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " Mario<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " Bianchi<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " GDNNWA12H81Y874F<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " 1991-12-12<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " <\\/saml:AttributeStatement>\\n" + + " <\\/saml:Assertion>\\n" + + "<\\/samlp:Response>\"}"; + private RedisServer redisServer; + private IdpCertStorage redisStorage; + + @BeforeAll + public void setUp() throws IOException { + redisServer = RedisServer.newRedisServer().port(6999).build(); + redisServer.start(); + redisStorage = + new RedisIdpCertStorageProvider( + new RedisStorageProvisioner( + new DefaultRedisClientBuilder( + RedisStorageConfig.builder() + .mainNode( + RedisStorageConfig.RedisNode + .builder() + .port(6999) + .build()) + .build()))) + .provideStorage(new IdpCertStorageConfig()); + } + + @SneakyThrows + @Test + public void successfulOperationsOnRedisStorage() { + IdpCertData idpCertDataToSave = new IdpCertData(); + idpCertDataToSave.setTag("aTag"); + idpCertDataToSave.setEntityId("anEntityId"); + idpCertDataToSave.setCertData( + new ArrayList<>(Collections.singletonList(VALID_ASSERTION_XML))); + redisStorage.saveIdpCertData("test-key", idpCertDataToSave); + Thread.sleep(100); + IdpCertData result = redisStorage.getIdpCertData("test-key"); + Assertions.assertEquals(idpCertDataToSave, result); + Thread.sleep(1100); + result = redisStorage.getIdpCertData("test-key"); + Assertions.assertNull(result); + } + + @AfterAll + public void tearDown() throws IOException { + redisServer.stop(); + } +} diff --git a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageTest.java b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageTest.java deleted file mode 100644 index 5112287b..00000000 --- a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageTest.java +++ /dev/null @@ -1,4 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.storage.redis.idp; - -class RedisIdpCertStorageTest {} diff --git a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorageUnitTest.java b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorageUnitTest.java new file mode 100644 index 00000000..f243e61c --- /dev/null +++ b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorageUnitTest.java @@ -0,0 +1,89 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.storage.redis.storage; + +import static org.assertj.core.api.Assertions.assertThatNoException; + +import io.lettuce.core.cluster.RedisClusterClient; +import io.lettuce.core.cluster.api.StatefulRedisClusterConnection; +import io.lettuce.core.cluster.api.async.RedisAdvancedClusterAsyncCommands; +import io.lettuce.core.cluster.api.sync.RedisAdvancedClusterCommands; +import io.lettuce.core.protocol.AsyncCommand; +import it.pagopa.tech.lollipop.consumer.storage.redis.builder.DefaultRedisClientBuilder; +import it.pagopa.tech.lollipop.consumer.storage.redis.config.RedisStorageConfig; +import java.io.IOException; +import java.util.ArrayList; +import lombok.SneakyThrows; +import org.junit.jupiter.api.*; +import org.mockito.Mockito; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class ClusteredRedisStorageUnitTest { + + private ClusteredRedisStorage redisStorage; + + RedisClusterClient redisClusterClient; + + StatefulRedisClusterConnection redisClusterConnection; + + RedisAdvancedClusterAsyncCommands redisAdvancedClusterAsyncCommands; + + RedisAdvancedClusterCommands redisAdvancedClusterCommands; + + @BeforeAll + public void setUp() throws IOException { + + redisStorage = + (ClusteredRedisStorage) + new DefaultRedisClientBuilder( + RedisStorageConfig.builder() + .clusterConnection(true) + .mainNode( + RedisStorageConfig.RedisNode.builder() + .port(6669) + .build()) + .clusterNodeList(new ArrayList<>()) + .build()) + .createStorage(); + redisClusterClient = Mockito.mock(RedisClusterClient.class); + redisClusterConnection = Mockito.mock(StatefulRedisClusterConnection.class); + redisAdvancedClusterAsyncCommands = Mockito.mock(RedisAdvancedClusterAsyncCommands.class); + redisAdvancedClusterCommands = Mockito.mock(RedisAdvancedClusterCommands.class); + + Mockito.when(redisClusterClient.connect()).thenReturn(redisClusterConnection); + Mockito.when(redisClusterConnection.async()).thenReturn(redisAdvancedClusterAsyncCommands); + Mockito.when(redisClusterConnection.sync()).thenReturn(redisAdvancedClusterCommands); + + Mockito.when(redisAdvancedClusterAsyncCommands.set(Mockito.any(), Mockito.any())) + .thenReturn(Mockito.mock(AsyncCommand.class)); + Mockito.when(redisAdvancedClusterAsyncCommands.del(Mockito.any())) + .thenReturn(Mockito.mock(AsyncCommand.class)); + Mockito.when(redisAdvancedClusterCommands.get(Mockito.any())).thenReturn("test"); + + redisStorage.setRedisClient(redisClusterClient); + } + + @SneakyThrows + @Test + public void testThatCallsSave() { + + assertThatNoException().isThrownBy(() -> redisStorage.save("test-key", "test")); + } + + @SneakyThrows + @Test + public void testThatCallsGet() { + + assertThatNoException().isThrownBy(() -> redisStorage.get("test-key")); + } + + @SneakyThrows + @Test + public void testThatCallsDelete() { + assertThatNoException().isThrownBy(() -> redisStorage.delete("test-key")); + } + + @AfterAll + public void wrapDown() throws IOException { + redisStorage.getRedisClient().close(); + } +} diff --git a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorageTest.java b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorageTest.java new file mode 100644 index 00000000..d9c80bae --- /dev/null +++ b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorageTest.java @@ -0,0 +1,63 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.storage.redis.storage; + +import it.pagopa.tech.lollipop.consumer.storage.redis.builder.DefaultRedisClientBuilder; +import it.pagopa.tech.lollipop.consumer.storage.redis.config.RedisStorageConfig; +import java.io.IOException; +import lombok.SneakyThrows; +import org.junit.jupiter.api.*; +import redis.embedded.RedisServer; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class SimpleRedisStorageTest { + + private RedisServer redisServer; + private SimpleRedisStorage redisStorage; + + @BeforeAll + public void setUp() throws IOException { + redisServer = RedisServer.newRedisServer().port(6999).build(); + redisServer.start(); + redisStorage = + (SimpleRedisStorage) + new DefaultRedisClientBuilder( + RedisStorageConfig.builder() + .mainNode( + RedisStorageConfig.RedisNode.builder() + .port(6999) + .build()) + .build()) + .createStorage(); + } + + @SneakyThrows + @Test + public void successfulOperationsOnRedisStorage() { + redisStorage.save("test-key", "test"); + Thread.sleep(30); + String result = redisStorage.get("test-key"); + Assertions.assertEquals("test", result); + redisStorage.delete("test-key"); + Thread.sleep(30); + result = redisStorage.get("test-key"); + Assertions.assertNull(result); + } + + @SneakyThrows + @Test + public void successfulEvictOps() { + redisStorage.save("test-key", "test", 1L); + Thread.sleep(30); + String result = redisStorage.get("test-key"); + Assertions.assertEquals("test", result); + Thread.sleep(1000); + result = redisStorage.get("test-key"); + Assertions.assertNull(result); + } + + @AfterAll + public void tearDown() throws IOException { + redisStorage.getRedisClient().close(); + redisServer.stop(); + } +} From 5b2fec70b88e049fd877585cd8769ffc16aeeed3 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Mon, 8 May 2023 10:05:42 +0200 Subject: [PATCH 375/403] [Dockerfile] Updated Dockerfile.test-only in order to update dependencies for security reasons --- Dockerfile.test-only | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile.test-only b/Dockerfile.test-only index 12491d05..8da464d0 100644 --- a/Dockerfile.test-only +++ b/Dockerfile.test-only @@ -1,5 +1,6 @@ FROM amazoncorretto:11 +RUN yum update -y --security RUN mkdir /app COPY core/build/libs/*.jar /app/ From 32a8ab1482609d13572d6717d68a5b980e7cd32b Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 8 May 2023 11:09:10 +0200 Subject: [PATCH 376/403] [SLS-39] fix Readme typo. --- README.md | Bin 92418 -> 92422 bytes e2e/README.md | 12 ++++++------ samples/spring/README.md | 4 ++-- spring-impl/README.md | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index be19c4f29fb62c3312878fb9d94bcfb1a1e2f0f0..f73f23060fb41f47a0cec294c9548615325b1354 100644 GIT binary patch delta 67 zcmV-J0KET#(glXn1+Z=u4@m$-08juR0Av7R0CWIhvw;*R0h81Y5|eIV5|hs9CbRAp ZFyEKj3jqw1-X#XJF7@^ Date: Mon, 8 May 2023 15:45:13 +0200 Subject: [PATCH 377/403] [redis extra] Introducing extra configurations for connection pooling on the Redis Storage and sentinel --- e2e/README.md | 8 +- gradle/verification-metadata.xml | 13 +++ identity-service-rest-client-native/README.md | 4 +- redis-storage/build.gradle | 1 + .../consumer/storage/redis/RedisStorage.java | 8 +- .../builder/DefaultRedisClientBuilder.java | 27 ++++-- .../redis/config/RedisStorageConfig.java | 4 + .../redis/idp/RedisIdpCertStorage.java | 5 +- .../redis/storage/SimpleRedisStorage.java | 90 +++++++++++++++---- .../RedisIdpCertStorageIntegrationTest.java | 14 +-- .../redis/storage/SimpleRedisStorageTest.java | 84 ++++++++++++++++- spring-impl/README.md | 2 +- 12 files changed, 217 insertions(+), 43 deletions(-) diff --git a/e2e/README.md b/e2e/README.md index 20154f70..4bce6f90 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -14,7 +14,7 @@ In the root folder, update gradlew permission and publish the dependencies ```bash -chmod +x ./gradlew +chmod +x ./gradlew ./gradlew publishToMavenLocal ``` @@ -24,7 +24,7 @@ update also this gradlew file permission and build the sample ```bash cd samples/spring -chmod +x ./gradlew +chmod +x ./gradlew ./gradlew bootJar ``` @@ -85,8 +85,8 @@ The configurable variables are the following: - ##### Docker image incompatibility - The docker image [eclipse-temurin:11-jdk-alpine](https://hub.docker.com/layers/library/eclipse-temurin/11-jdk-alpine/images/sha256-ea0ec99f8cfbaff4d61fec32af9430097e152860ec58b3cf2cb06454d75c61b0?context=explore) + The docker image [eclipse-temurin:11-jdk-alpine](https://hub.docker.com/layers/library/eclipse-temurin/11-jdk-alpine/images/sha256-ea0ec99f8cfbaff4d61fec32af9430097e152860ec58b3cf2cb06454d75c61b0?context=explore) used to build the sample is compatible only with amd64 cpus and not with apple's silicon cpus (arc64), if you have an arc cpu and having trouble building the docker image change it in the Dockerfile to [eclipse-temurin:11-jre-jammy](https://hub.docker.com/layers/library/eclipse-temurin/11-jre-jammy/images/sha256-18c3e334425f4fbf3a53f2f0df713e4d206894fb00ab2edde6df0311f5b63550?context=explore). - + diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 64a8a8b9..0152a0fa 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -3473,6 +3473,14 @@ + + + + + + + + @@ -4590,6 +4598,11 @@ + + + + + diff --git a/identity-service-rest-client-native/README.md b/identity-service-rest-client-native/README.md index 0e73d783..0795983b 100644 --- a/identity-service-rest-client-native/README.md +++ b/identity-service-rest-client-native/README.md @@ -8,11 +8,11 @@ First we fetch the certificates' tag list (a list of certification by their issu that could be used for the assertion verification; we compare the tags with the assertion's instant as timestamp in seconds and the two eligible tags are the ones right before and after the provided assertion's instant. -Then for each of the found tags the corresponding certification as xml is fetched, +Then for each of the found tags the corresponding certification as xml is fetched, the xml contains various elements called EntityDescriptor for each entity id, so we will filter these elements by the entity id provided in first instance. -Finally, from the EntityDescriptor of the right identity provider we will extract the signature that will be used to +Finally, from the EntityDescriptor of the right identity provider we will extract the signature that will be used to verify the assertion. ## Configuration diff --git a/redis-storage/build.gradle b/redis-storage/build.gradle index 4b9c848d..dafa591d 100644 --- a/redis-storage/build.gradle +++ b/redis-storage/build.gradle @@ -61,6 +61,7 @@ dependencies { testImplementation 'org.mockito:mockito-junit-jupiter:5.2.0' testImplementation 'org.assertj:assertj-core:3.24.2' testImplementation 'com.github.codemonstur:embedded-redis:1.0.0' + implementation 'org.apache.commons:commons-pool2:2.11.1' } tasks.named('test') { diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorage.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorage.java index 3cc7cdb2..1b21cfda 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorage.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/RedisStorage.java @@ -23,7 +23,7 @@ public RedisStorage(AbstractRedisClient redisClient) { * @param key key to be used in order to attempt the retreival of a value from redis * @return if found the String value obtained from redis, null otherwise */ - public abstract String get(String key); + public abstract String get(String key) throws Exception; /** * Saves a value in the redis using the provided key @@ -31,7 +31,7 @@ public RedisStorage(AbstractRedisClient redisClient) { * @param key key to be used when saving the value * @param value value to be stored in the redis instance */ - public abstract void save(String key, String value); + public abstract void save(String key, String value) throws Exception; /** * Saves a value in the redis using the provided key, with a defined TTL @@ -40,12 +40,12 @@ public RedisStorage(AbstractRedisClient redisClient) { * @param value value to be stored in the redis instance * @param delayTime seconds defining the stored data TTL */ - public abstract void save(String key, String value, Long delayTime); + public abstract void save(String key, String value, Long delayTime) throws Exception; /** * Deletes a value from redis using the provided key * * @param key key to be used for content deletion from redis */ - public abstract void delete(String key); + public abstract void delete(String key) throws Exception; } diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/DefaultRedisClientBuilder.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/DefaultRedisClientBuilder.java index 9797d556..a4b401b5 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/DefaultRedisClientBuilder.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/DefaultRedisClientBuilder.java @@ -36,7 +36,10 @@ public DefaultRedisClientBuilder(RedisStorageConfig redisStorageConfig) { public RedisStorage createStorage() { return redisStorageConfig.isClusterConnection() ? new ClusteredRedisStorage(createRedisClusterClient()) - : new SimpleRedisStorage(createRedisClient()); + : new SimpleRedisStorage( + createRedisClient(), + redisStorageConfig.getDefaultDelay(), + redisStorageConfig.isWithConnectionPooling()); } /** @@ -99,11 +102,22 @@ private RedisClusterClient createRedisClusterClient() { } private RedisURI getRedisURI(String hostname, Integer port) { - // Build Redis URI with host and authentication details. RedisURI.Builder builder = - RedisURI.Builder.redis(hostname) - .withPort(port) - .withSsl(redisStorageConfig.isWithSsl()); + !redisStorageConfig.isWithSentinel() + ? RedisURI.Builder.redis(hostname).withPort(port) + : RedisURI.Builder.sentinel(hostname, port); + + builder.withSsl(redisStorageConfig.isWithSsl()); + + if (redisStorageConfig.getSentinelHostList() != null + && !redisStorageConfig.isClusterConnection()) { + redisStorageConfig.getSentinelHostList().forEach(builder::withSentinel); + } + + if (redisStorageConfig.getMasterIds() != null + && !redisStorageConfig.isClusterConnection()) { + redisStorageConfig.getMasterIds().forEach(builder::withSentinelMasterId); + } if (redisStorageConfig.isWithAuth()) { builder.withAuthentication( @@ -112,7 +126,6 @@ private RedisURI getRedisURI(String hostname, Integer port) { builder.withClientName(redisStorageConfig.getClientName()); - RedisURI redisURI = builder.build(); - return redisURI; + return builder.build(); } } diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/config/RedisStorageConfig.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/config/RedisStorageConfig.java index a1859b32..ee1a1e0a 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/config/RedisStorageConfig.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/config/RedisStorageConfig.java @@ -21,7 +21,11 @@ public class RedisStorageConfig { @Builder.Default private boolean withSsl = false; @Builder.Default private String clientName = "LettuceClient"; @Builder.Default private Long defaultDelay = 60L; + @Builder.Default private boolean withConnectionPooling = false; + @Builder.Default private boolean withSentinel = false; private List clusterNodeList; + private List sentinelHostList; + private List masterIds; @NoArgsConstructor @AllArgsConstructor diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorage.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorage.java index 4225aca7..f75e4f09 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorage.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorage.java @@ -10,6 +10,7 @@ import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorage; +import java.util.concurrent.TimeUnit; import lombok.SneakyThrows; import org.openapitools.jackson.nullable.JsonNullableModule; @@ -81,6 +82,8 @@ public void saveIdpCertData(String tag, IdpCertData idpCertData) { redisStorage.save( tag, objectMapper.writeValueAsString(idpCertData), - storageConfig.getStorageEvictionDelay()); + TimeUnit.SECONDS.convert( + storageConfig.getStorageEvictionDelay(), + storageConfig.getStorageEvictionDelayTimeUnit())); } } diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java index 3d46550e..7e02baf4 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java @@ -4,12 +4,19 @@ import io.lettuce.core.AbstractRedisClient; import io.lettuce.core.RedisClient; import io.lettuce.core.api.StatefulRedisConnection; +import io.lettuce.core.support.ConnectionPoolSupport; import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorage; +import lombok.*; +import org.apache.commons.pool2.impl.GenericObjectPool; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +@Getter +@Setter /** Implements commands to a simple Redis instance using Lettuce */ public class SimpleRedisStorage extends RedisStorage { private Long defaultDelayTimeSeconds = 60L; + private Boolean withConnectionPool = false; public SimpleRedisStorage(AbstractRedisClient redisClient) { super(redisClient); @@ -20,6 +27,13 @@ public SimpleRedisStorage(RedisClient redisClient, Long defaultDelayTimeSeconds) this.defaultDelayTimeSeconds = defaultDelayTimeSeconds; } + public SimpleRedisStorage( + RedisClient redisClient, Long defaultDelayTimeSeconds, Boolean withConnectionPool) { + super(redisClient); + this.defaultDelayTimeSeconds = defaultDelayTimeSeconds; + this.withConnectionPool = withConnectionPool; + } + /** * Retrieves from a synchronous connection the value stored in the Redis instance using the * provided key, closes the connection asynchronously @@ -28,13 +42,21 @@ public SimpleRedisStorage(RedisClient redisClient, Long defaultDelayTimeSeconds) * @return value stored in the Redis instance */ @Override - public String get(String key) { - StatefulRedisConnection statefulConnection = - ((RedisClient) getRedisClient()).connect(); - try { - return statefulConnection.sync().get(key); - } finally { - statefulConnection.closeAsync(); + public String get(String key) throws Exception { + RedisClient redisClient = (RedisClient) getRedisClient(); + if (!withConnectionPool) { + try (StatefulRedisConnection statefulConnection = + redisClient.connect()) { + return statefulConnection.sync().get(key); + } + } else { + try (GenericObjectPool> pool = + ConnectionPoolSupport.createGenericObjectPool( + redisClient::connect, new GenericObjectPoolConfig<>()); + StatefulRedisConnection statefulConnection = + pool.borrowObject()) { + return statefulConnection.sync().get(key); + } } } @@ -45,7 +67,7 @@ public String get(String key) { * @param value value to be stored in the redis instance */ @Override - public void save(String key, String value) { + public void save(String key, String value) throws Exception { save(key, value, defaultDelayTimeSeconds); } @@ -57,9 +79,28 @@ public void save(String key, String value) { * @param delayTime seconds defining the stored data TTL */ @Override - public void save(String key, String value, Long delayTime) { - StatefulRedisConnection statefulRedisConnection = - ((RedisClient) getRedisClient()).connect(); + public void save(String key, String value, Long delayTime) throws Exception { + + RedisClient redisClient = (RedisClient) getRedisClient(); + if (!withConnectionPool) { + try (StatefulRedisConnection statefulConnection = + redisClient.connect()) { + executeSetMethod(key, value, delayTime, statefulConnection); + } + } else { + GenericObjectPool> pool = + ConnectionPoolSupport.createGenericObjectPool( + redisClient::connect, new GenericObjectPoolConfig<>()); + StatefulRedisConnection statefulConnection = pool.borrowObject(); + executeSetMethod(key, value, delayTime, statefulConnection); + } + } + + private void executeSetMethod( + String key, + String value, + Long delayTime, + StatefulRedisConnection statefulRedisConnection) { statefulRedisConnection .async() .set(key, String.valueOf(value)) @@ -78,15 +119,32 @@ public void save(String key, String value, Long delayTime) { * @param key key to be used for content deletion from redis */ @Override - public void delete(String key) { - StatefulRedisConnection statefulRedisConnection = - ((RedisClient) getRedisClient()).connect(); - statefulRedisConnection + public void delete(String key) throws Exception { + + RedisClient redisClient = (RedisClient) getRedisClient(); + if (!withConnectionPool) { + try (StatefulRedisConnection statefulConnection = + redisClient.connect()) { + executeAsyncDel(key, statefulConnection); + } + } else { + GenericObjectPool> pool = + ConnectionPoolSupport.createGenericObjectPool( + redisClient::connect, new GenericObjectPoolConfig<>()); + StatefulRedisConnection statefulConnection = pool.borrowObject(); + executeAsyncDel(key, statefulConnection); + } + } + + private void executeAsyncDel( + String key, StatefulRedisConnection statefulConnection) { + statefulConnection .async() .del(key) .thenAccept( result -> { - statefulRedisConnection.closeAsync(); + statefulConnection.closeAsync(); }); + ; } } diff --git a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java index 29e93aa0..8c94a53d 100644 --- a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java +++ b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java @@ -10,6 +10,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.concurrent.TimeUnit; import lombok.SneakyThrows; import org.junit.jupiter.api.*; import redis.embedded.RedisServer; @@ -140,7 +141,10 @@ class RedisIdpCertStorageIntegrationTest { @BeforeAll public void setUp() throws IOException { - redisServer = RedisServer.newRedisServer().port(6999).build(); + IdpCertStorageConfig idpCertStorageConfig = new IdpCertStorageConfig(); + idpCertStorageConfig.setStorageEvictionDelay(1); + idpCertStorageConfig.setStorageEvictionDelayTimeUnit(TimeUnit.SECONDS); + redisServer = RedisServer.newRedisServer().build(); redisServer.start(); redisStorage = new RedisIdpCertStorageProvider( @@ -150,10 +154,10 @@ public void setUp() throws IOException { .mainNode( RedisStorageConfig.RedisNode .builder() - .port(6999) + .port(6379) .build()) .build()))) - .provideStorage(new IdpCertStorageConfig()); + .provideStorage(idpCertStorageConfig); } @SneakyThrows @@ -165,10 +169,10 @@ public void successfulOperationsOnRedisStorage() { idpCertDataToSave.setCertData( new ArrayList<>(Collections.singletonList(VALID_ASSERTION_XML))); redisStorage.saveIdpCertData("test-key", idpCertDataToSave); - Thread.sleep(100); + Thread.sleep(150); IdpCertData result = redisStorage.getIdpCertData("test-key"); Assertions.assertEquals(idpCertDataToSave, result); - Thread.sleep(1100); + Thread.sleep(1500); result = redisStorage.getIdpCertData("test-key"); Assertions.assertNull(result); } diff --git a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorageTest.java b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorageTest.java index d9c80bae..f046bb37 100644 --- a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorageTest.java +++ b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorageTest.java @@ -4,27 +4,49 @@ import it.pagopa.tech.lollipop.consumer.storage.redis.builder.DefaultRedisClientBuilder; import it.pagopa.tech.lollipop.consumer.storage.redis.config.RedisStorageConfig; import java.io.IOException; +import java.util.Collections; import lombok.SneakyThrows; import org.junit.jupiter.api.*; +import redis.embedded.RedisSentinel; import redis.embedded.RedisServer; @TestInstance(TestInstance.Lifecycle.PER_CLASS) class SimpleRedisStorageTest { + private String bindAddress; + private RedisServer redisServer; + private RedisSentinel redisSentinel; private SimpleRedisStorage redisStorage; + private SimpleRedisStorage sentinelRedisStoragere; + @BeforeAll public void setUp() throws IOException { - redisServer = RedisServer.newRedisServer().port(6999).build(); + + redisServer = RedisServer.newRedisServer().build(); + redisSentinel = RedisSentinel.newRedisSentinel().build(); redisServer.start(); + redisSentinel.start(); redisStorage = (SimpleRedisStorage) new DefaultRedisClientBuilder( RedisStorageConfig.builder() .mainNode( RedisStorageConfig.RedisNode.builder() - .port(6999) + .port(6379) + .build()) + .build()) + .createStorage(); + sentinelRedisStoragere = + (SimpleRedisStorage) + new DefaultRedisClientBuilder( + RedisStorageConfig.builder() + .withSentinel(true) + .masterIds(Collections.singletonList("mymaster")) + .mainNode( + RedisStorageConfig.RedisNode.builder() + .port(26379) .build()) .build()) .createStorage(); @@ -47,17 +69,73 @@ public void successfulOperationsOnRedisStorage() { @Test public void successfulEvictOps() { redisStorage.save("test-key", "test", 1L); + Thread.sleep(100); + String result = redisStorage.get("test-key"); + Assertions.assertEquals("test", result); + Thread.sleep(1100); + result = redisStorage.get("test-key"); + Assertions.assertNull(result); + } + + @SneakyThrows + @Test + public void successfulOperationsOnRedisStorageWithConnectionPool() { + redisStorage.setWithConnectionPool(true); + redisStorage.save("test-key", "test"); + Thread.sleep(100); + String result = redisStorage.get("test-key"); + Assertions.assertEquals("test", result); + redisStorage.delete("test-key"); Thread.sleep(30); + result = redisStorage.get("test-key"); + Assertions.assertNull(result); + } + + @SneakyThrows + @Test + public void successfulEvictOpsWithConnectionPool() { + redisStorage.setWithConnectionPool(true); + redisStorage.save("test-key", "test", 1L); + Thread.sleep(100); String result = redisStorage.get("test-key"); Assertions.assertEquals("test", result); - Thread.sleep(1000); + Thread.sleep(1100); result = redisStorage.get("test-key"); Assertions.assertNull(result); } + @SneakyThrows + @Test + public void successfulOperationsOnRedisStorageWithConnectionPoolAndSentinel() { + sentinelRedisStoragere.setWithConnectionPool(true); + sentinelRedisStoragere.save("test-key", "test"); + Thread.sleep(100); + String result = sentinelRedisStoragere.get("test-key"); + Assertions.assertEquals("test", result); + sentinelRedisStoragere.delete("test-key"); + Thread.sleep(30); + result = sentinelRedisStoragere.get("test-key"); + Assertions.assertNull(result); + } + + @SneakyThrows + @Test + public void successfulEvictOpsWithConnectionPoolAndSentinel() { + sentinelRedisStoragere.setWithConnectionPool(true); + sentinelRedisStoragere.save("test-key", "test", 1L); + Thread.sleep(100); + String result = sentinelRedisStoragere.get("test-key"); + Assertions.assertEquals("test", result); + Thread.sleep(1200); + result = sentinelRedisStoragere.get("test-key"); + Assertions.assertNull(result); + } + @AfterAll public void tearDown() throws IOException { redisStorage.getRedisClient().close(); + sentinelRedisStoragere.getRedisClient().close(); redisServer.stop(); + redisSentinel.stop(); } } diff --git a/spring-impl/README.md b/spring-impl/README.md index 6b0e40c6..de5197c8 100644 --- a/spring-impl/README.md +++ b/spring-impl/README.md @@ -6,7 +6,7 @@ application. ## Configurations An extension of the configuration class within the core module is provided, in order to enable property loading -through the Spring functionalities. Other configurations are expected to be provided from the application using +through the Spring functionalities. Other configurations are expected to be provided from the application using this specific implementation (See the [spring-sample](../samples/spring) as a reference for a complete setup of the other classes, as well as the application.properties file to be used). From a0c8ff263ce547e2acb8de02f67e017120b168e4 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Mon, 8 May 2023 16:02:42 +0200 Subject: [PATCH 378/403] [redis extra] Updated verification-metadata.xml with sha1 --- gradle/verification-metadata.xml | 131 +++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 0152a0fa..7bc1a650 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -23,9 +23,11 @@ + + @@ -43,9 +45,11 @@ + + @@ -58,6 +62,7 @@ + @@ -377,6 +382,7 @@ + @@ -458,6 +464,7 @@ + @@ -531,6 +538,7 @@ + @@ -939,6 +947,7 @@ + @@ -988,9 +997,11 @@ + + @@ -1187,9 +1198,11 @@ + + @@ -1218,6 +1231,7 @@ + @@ -1276,9 +1290,11 @@ + + @@ -1324,6 +1340,7 @@ + @@ -1753,9 +1770,11 @@ + + @@ -1785,9 +1804,11 @@ + + @@ -1835,9 +1856,11 @@ + + @@ -1851,6 +1874,7 @@ + @@ -1916,9 +1940,11 @@ + + @@ -1946,9 +1972,11 @@ + + @@ -1974,9 +2002,11 @@ + + @@ -2062,9 +2092,11 @@ + + @@ -2090,9 +2122,11 @@ + + @@ -2133,6 +2167,7 @@ + @@ -2155,9 +2190,11 @@ + + @@ -2235,9 +2272,11 @@ + + @@ -2263,9 +2302,11 @@ + + @@ -2287,9 +2328,11 @@ + + @@ -2933,9 +2976,11 @@ + + @@ -2961,9 +3006,11 @@ + + @@ -3239,14 +3286,17 @@ + + + @@ -3344,11 +3394,13 @@ + + @@ -3470,14 +3522,17 @@ + + + @@ -3495,29 +3550,35 @@ + + + + + + @@ -3759,9 +3820,11 @@ + + @@ -3803,9 +3866,11 @@ + + @@ -3886,19 +3951,23 @@ + + + + @@ -3985,9 +4054,11 @@ + + @@ -4041,9 +4112,11 @@ + + @@ -4074,22 +4147,27 @@ + + + + + @@ -4170,9 +4248,11 @@ + + @@ -4453,9 +4533,11 @@ + + @@ -4600,6 +4682,7 @@ + @@ -4722,12 +4805,15 @@ + + + @@ -4863,12 +4949,15 @@ + + + @@ -5341,9 +5430,11 @@ + + @@ -5357,9 +5448,11 @@ + + @@ -5373,6 +5466,7 @@ + @@ -5383,9 +5477,11 @@ + + @@ -5399,9 +5495,11 @@ + + @@ -5415,9 +5513,11 @@ + + @@ -5431,9 +5531,11 @@ + + @@ -5447,9 +5549,11 @@ + + @@ -5463,9 +5567,11 @@ + + @@ -5479,9 +5585,11 @@ + + @@ -5495,9 +5603,11 @@ + + @@ -5511,41 +5621,51 @@ + + + + + + + + + + @@ -5559,9 +5679,11 @@ + + @@ -5662,9 +5784,11 @@ + + @@ -5733,17 +5857,21 @@ + + + + @@ -5803,11 +5931,13 @@ + + @@ -6002,6 +6132,7 @@ + From fba4fd77e336bfa6cd10d3fee035fdc00a7a8d83 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Mon, 8 May 2023 16:34:38 +0200 Subject: [PATCH 379/403] [redis extra] Updated verification-metadata.xml --- gradle/verification-metadata.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 7bc1a650..2a55ab91 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -4685,6 +4685,9 @@ + + + From 8add6f427d0803e9a01ae80f68d9aae3fcb39a38 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Mon, 8 May 2023 16:52:17 +0200 Subject: [PATCH 380/403] [redis extra] Updated verification-metadata.xml --- gradle/verification-metadata.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 2a55ab91..9f31ff91 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -4686,7 +4686,7 @@ - + From f9f4fbd6536c9c528c4f3090bcf40d8165851550 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Mon, 8 May 2023 17:18:26 +0200 Subject: [PATCH 381/403] [redis extra] Updated ClusteredRedisStorage, README.md and RedisIdpCertStorageIntegrationTest --- redis-storage/README.md | 5 +++++ .../storage/redis/storage/ClusteredRedisStorage.java | 2 +- .../redis/idp/RedisIdpCertStorageIntegrationTest.java | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 redis-storage/README.md diff --git a/redis-storage/README.md b/redis-storage/README.md new file mode 100644 index 00000000..d1ea668d --- /dev/null +++ b/redis-storage/README.md @@ -0,0 +1,5 @@ +# Lollipop SDK Redis Storage + +This module contains implementations of the storage interfaces using a Redis Client with the Lettuce implementation. + +## Example for the Idp interface \ No newline at end of file diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorage.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorage.java index 4e5e8d1c..ab9ba3e4 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorage.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorage.java @@ -65,7 +65,7 @@ public void save(String key, String value, Long delayTime) { .thenAccept( result -> { if ("OK".equals(result)) { - statefulRedisConnection.async().expire(key, delayTime); + statefulRedisConnection.sync().expire(key, delayTime); } statefulRedisConnection.closeAsync(); }); diff --git a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java index 8c94a53d..b8cd2377 100644 --- a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java +++ b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java @@ -172,7 +172,7 @@ public void successfulOperationsOnRedisStorage() { Thread.sleep(150); IdpCertData result = redisStorage.getIdpCertData("test-key"); Assertions.assertEquals(idpCertDataToSave, result); - Thread.sleep(1500); + Thread.sleep(2000); result = redisStorage.getIdpCertData("test-key"); Assertions.assertNull(result); } From cb40dc113471ec11c18e418f59c69495d5cb535a Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Mon, 8 May 2023 17:47:41 +0200 Subject: [PATCH 382/403] [redis extra] Updated RedisStorageConfig --- .../consumer/storage/redis/config/RedisStorageConfig.java | 2 +- .../storage/redis/idp/RedisIdpCertStorageIntegrationTest.java | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/config/RedisStorageConfig.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/config/RedisStorageConfig.java index ee1a1e0a..b04ab2ec 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/config/RedisStorageConfig.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/config/RedisStorageConfig.java @@ -34,6 +34,6 @@ public class RedisStorageConfig { public static class RedisNode { @Builder.Default private String hostname = "localhost"; - @Builder.Default private Integer port = 6370; + @Builder.Default private Integer port = 6379; } } diff --git a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java index b8cd2377..21f61e1d 100644 --- a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java +++ b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java @@ -172,9 +172,6 @@ public void successfulOperationsOnRedisStorage() { Thread.sleep(150); IdpCertData result = redisStorage.getIdpCertData("test-key"); Assertions.assertEquals(idpCertDataToSave, result); - Thread.sleep(2000); - result = redisStorage.getIdpCertData("test-key"); - Assertions.assertNull(result); } @AfterAll From c3a829577702827483b5beb2afcf3904a16cfbb7 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Mon, 8 May 2023 19:14:06 +0200 Subject: [PATCH 383/403] [redis extra] Updated ClusteredRedisStorage and tests --- redis-storage/README.md | 98 ++++++++++++++- .../builder/DefaultRedisClientBuilder.java | 5 +- .../redis/storage/ClusteredRedisStorage.java | 112 +++++++++++++----- .../redis/storage/SimpleRedisStorage.java | 1 - .../RedisIdpCertStorageIntegrationTest.java | 65 +++++++++- .../redis/storage/SimpleRedisStorageTest.java | 2 - 6 files changed, 250 insertions(+), 33 deletions(-) diff --git a/redis-storage/README.md b/redis-storage/README.md index d1ea668d..a2fff041 100644 --- a/redis-storage/README.md +++ b/redis-storage/README.md @@ -2,4 +2,100 @@ This module contains implementations of the storage interfaces using a Redis Client with the Lettuce implementation. -## Example for the Idp interface \ No newline at end of file +## Configuration + +The following tables contains the properties of the [RedisStorageConfig](redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/config/RedisStorageConfig.java) +configuration class, to be used in order to statup a Redis Client within the module. + +| VARIABLE | DEFAULT VALUE | USAGE | +|-----------------------|---------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| mainNode | {"hostmane":"localhost","port": 6379} | RedisNode model containing a hostname and port to be used. If not in sentinel mode this is the mandatory main references to a Redis instance, otherwise valid Sentinel node host and port must be provided | +| withAuth | false | Flag to indicate if the connection requires authentication | +| username | username | Username to be used if authentication is required | +| password | password | Password to be used if authentication is required | +| clusterConnection | false | Flag to determine if the client will attempt to work in clustered mode | +| withSsl | false | Flag to determine if the client requires an ssl connection | +| clientName | LettuceClient | Name of the client | +| defaultDelay | 60 | The default eviction delay (in seconds) | +| withConnectionPooling | false | Flag to indicate if the connection with work with a connection pool | +| withSentinel | false | Flag to indicate if the client will attempt to connect in sentinel mode for HA | +| clusterNodeList | - | List of RedisNode data structures (json containing hostname and port), to be used for extra nodes in cluster mode | +| sentinelHostList | - | List of sentinel hosts, to be used if in sentinel mode | +| masterIds | - | Lost of masterIds to be used if in sentinel mode | + + +## Example for the Idp interface + +### Simple + +The following snippet provides a basic sample in order to use the implementation of the IdP certificates storage interface + +``` +RedisStorageConfig redisConfig = RedisStorageConfig.builder().mainNode( + RedisStorageConfig.RedisNode + .builder() + .hostname("redisnode1") + .port(6379) + .build()); +DefaultClientBuilder builder = new DefaultRedisClientBuilder(redisConfig); +RedisStorageProvisioner redisStoreProvisioner = new RedisStorageProvisioner(builder.build()); +redisStorage = new RedisIdpCertStorageProvider(redisStoreProvisioner).provideStorage(idpCertStorageConfig); +``` + +In order to execute with connection pooling active, provide a redisConfig as for the following example: + +### Pooling startup + +``` +RedisStorageConfig redisConfig = RedisStorageConfig.builder() + .withConnectionPooling(true) + .mainNode( + RedisStorageConfig.RedisNode + .builder() + .hostname("redisnode1") + .port(6379) + .build() + ); +``` + +### With Sentinel nodes + +In order to execute with sentinel active, provide a redisConfig as for the following example, defining a simple +configuration with a main node, an extra sentinel host, and two master nodes, in connection pooling mode: + +``` +RedisStorageConfig redisConfig = RedisStorageConfig.builder() + .withConnectionPooling(true) + .withSentinel(true) + .sentinelHostList(Arrays.asList("sentinel2")) + .masterIds(Arrays.asList("master1","master2")) + .mainNode( + RedisStorageConfig.RedisNode + .builder() + .hostname("sentinel1") + .port(26379) + .build() + ); +``` + +### Clustered Connections + +In order to execute in clustered mode, one or more nodes must be provided, as follows: +``` +RedisStorageConfig redisConfig = RedisStorageConfig.builder() + .clusterConnection(true) + .mainNode( + RedisStorageConfig.RedisNode + .builder() + .hostname("redisnode1") + .port(6379) + .build() + ) + .clusterNodeList(Arrays.asList( + RedisStorageConfig.RedisNode + .builder() + .hostname("redisnode2") + .port(6379) + .build() + )); +``` \ No newline at end of file diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/DefaultRedisClientBuilder.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/DefaultRedisClientBuilder.java index a4b401b5..c89eb8cd 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/DefaultRedisClientBuilder.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/builder/DefaultRedisClientBuilder.java @@ -35,7 +35,10 @@ public DefaultRedisClientBuilder(RedisStorageConfig redisStorageConfig) { @Override public RedisStorage createStorage() { return redisStorageConfig.isClusterConnection() - ? new ClusteredRedisStorage(createRedisClusterClient()) + ? new ClusteredRedisStorage( + createRedisClusterClient(), + redisStorageConfig.getDefaultDelay(), + redisStorageConfig.isWithConnectionPooling()) : new SimpleRedisStorage( createRedisClient(), redisStorageConfig.getDefaultDelay(), diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorage.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorage.java index ab9ba3e4..4eb33221 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorage.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/ClusteredRedisStorage.java @@ -1,23 +1,40 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.storage.redis.storage; -import io.lettuce.core.RedisClient; import io.lettuce.core.cluster.RedisClusterClient; import io.lettuce.core.cluster.api.StatefulRedisClusterConnection; +import io.lettuce.core.support.ConnectionPoolSupport; import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorage; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.pool2.impl.GenericObjectPool; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +@Getter +@Setter /** Implements commands to a Redis Cluster using Lettuce */ public class ClusteredRedisStorage extends RedisStorage { private Long defaultDelayTimeSeconds = 60L; + private Boolean withConnectionPool = false; + public ClusteredRedisStorage(RedisClusterClient redisClient) { super(redisClient); } - public ClusteredRedisStorage(RedisClient redisClient, Long defaultDelayTimeSeconds) { + public ClusteredRedisStorage(RedisClusterClient redisClient, Long defaultDelayTimeSeconds) { + super(redisClient); + this.defaultDelayTimeSeconds = defaultDelayTimeSeconds; + } + + public ClusteredRedisStorage( + RedisClusterClient redisClient, + Long defaultDelayTimeSeconds, + Boolean withConnectionPool) { super(redisClient); this.defaultDelayTimeSeconds = defaultDelayTimeSeconds; + this.withConnectionPool = withConnectionPool; } /** @@ -27,13 +44,21 @@ public ClusteredRedisStorage(RedisClient redisClient, Long defaultDelayTimeSecon * @return if found the String value obtained from redis, null otherwise */ @Override - public String get(String key) { - StatefulRedisClusterConnection statefulConnection = - ((RedisClusterClient) getRedisClient()).connect(); - try { - return statefulConnection.sync().get(key); - } finally { - statefulConnection.closeAsync(); + public String get(String key) throws Exception { + RedisClusterClient redisClient = (RedisClusterClient) getRedisClient(); + if (!withConnectionPool) { + try (StatefulRedisClusterConnection statefulConnection = + redisClient.connect()) { + return statefulConnection.sync().get(key); + } + } else { + try (GenericObjectPool> pool = + ConnectionPoolSupport.createGenericObjectPool( + redisClient::connect, new GenericObjectPoolConfig<>()); + StatefulRedisClusterConnection statefulConnection = + pool.borrowObject()) { + return statefulConnection.sync().get(key); + } } } @@ -44,7 +69,7 @@ public String get(String key) { * @param value value to be stored in the redis instance */ @Override - public void save(String key, String value) { + public void save(String key, String value) throws Exception { save(key, value, defaultDelayTimeSeconds); } @@ -56,19 +81,20 @@ public void save(String key, String value) { * @param delayTime seconds defining the stored data TTL */ @Override - public void save(String key, String value, Long delayTime) { - StatefulRedisClusterConnection statefulRedisConnection = - ((RedisClusterClient) getRedisClient()).connect(); - statefulRedisConnection - .async() - .set(key, String.valueOf(value)) - .thenAccept( - result -> { - if ("OK".equals(result)) { - statefulRedisConnection.sync().expire(key, delayTime); - } - statefulRedisConnection.closeAsync(); - }); + public void save(String key, String value, Long delayTime) throws Exception { + RedisClusterClient redisClient = (RedisClusterClient) getRedisClient(); + if (!withConnectionPool) { + try (StatefulRedisClusterConnection statefulConnection = + redisClient.connect()) { + executeSetMethod(key, value, delayTime, statefulConnection); + } + } else { + GenericObjectPool> pool = + ConnectionPoolSupport.createGenericObjectPool( + redisClient::connect, new GenericObjectPoolConfig<>()); + StatefulRedisClusterConnection statefulConnection = pool.borrowObject(); + executeSetMethod(key, value, delayTime, statefulConnection); + } } /** @@ -77,14 +103,46 @@ public void save(String key, String value, Long delayTime) { * @param key key to be used for content deletion from redis */ @Override - public void delete(String key) { - StatefulRedisClusterConnection statefulRedisConnection = - ((RedisClusterClient) getRedisClient()).connect(); - statefulRedisConnection + public void delete(String key) throws Exception { + RedisClusterClient redisClient = (RedisClusterClient) getRedisClient(); + if (!withConnectionPool) { + try (StatefulRedisClusterConnection statefulConnection = + redisClient.connect()) { + executeAsyncDel(key, statefulConnection); + } + } else { + GenericObjectPool> pool = + ConnectionPoolSupport.createGenericObjectPool( + redisClient::connect, new GenericObjectPoolConfig<>()); + StatefulRedisClusterConnection statefulConnection = pool.borrowObject(); + executeAsyncDel(key, statefulConnection); + } + } + + private void executeAsyncDel( + String key, StatefulRedisClusterConnection statefulConnection) { + statefulConnection .async() .del(key) .thenAccept( result -> { + statefulConnection.closeAsync(); + }); + } + + private void executeSetMethod( + String key, + String value, + Long delayTime, + StatefulRedisClusterConnection statefulRedisConnection) { + statefulRedisConnection + .async() + .set(key, String.valueOf(value)) + .thenAccept( + result -> { + if ("OK".equals(result)) { + statefulRedisConnection.async().expire(key, delayTime); + } statefulRedisConnection.closeAsync(); }); } diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java index 7e02baf4..b41cf384 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java @@ -145,6 +145,5 @@ private void executeAsyncDel( result -> { statefulConnection.closeAsync(); }); - ; } } diff --git a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java index 21f61e1d..be621a6f 100644 --- a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java +++ b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java @@ -13,6 +13,7 @@ import java.util.concurrent.TimeUnit; import lombok.SneakyThrows; import org.junit.jupiter.api.*; +import redis.embedded.RedisSentinel; import redis.embedded.RedisServer; @TestInstance(TestInstance.Lifecycle.PER_CLASS) @@ -139,13 +140,17 @@ class RedisIdpCertStorageIntegrationTest { private RedisServer redisServer; private IdpCertStorage redisStorage; + private IdpCertStorageConfig idpCertStorageConfig; + @BeforeAll public void setUp() throws IOException { - IdpCertStorageConfig idpCertStorageConfig = new IdpCertStorageConfig(); + idpCertStorageConfig = new IdpCertStorageConfig(); idpCertStorageConfig.setStorageEvictionDelay(1); idpCertStorageConfig.setStorageEvictionDelayTimeUnit(TimeUnit.SECONDS); redisServer = RedisServer.newRedisServer().build(); + RedisSentinel redisSentinel = RedisSentinel.newRedisSentinel().build(); redisServer.start(); + redisSentinel.start(); redisStorage = new RedisIdpCertStorageProvider( new RedisStorageProvisioner( @@ -174,6 +179,64 @@ public void successfulOperationsOnRedisStorage() { Assertions.assertEquals(idpCertDataToSave, result); } + @SneakyThrows + @Test + public void successfulOperationsOnRedisStorageWithConnectionPooling() { + redisStorage = + new RedisIdpCertStorageProvider( + new RedisStorageProvisioner( + new DefaultRedisClientBuilder( + RedisStorageConfig.builder() + .withConnectionPooling(true) + .mainNode( + RedisStorageConfig.RedisNode + .builder() + .port(6379) + .build()) + .build()))) + .provideStorage(idpCertStorageConfig); + IdpCertData idpCertDataToSave = new IdpCertData(); + idpCertDataToSave.setTag("aTag"); + idpCertDataToSave.setEntityId("anEntityId"); + idpCertDataToSave.setCertData( + new ArrayList<>(Collections.singletonList(VALID_ASSERTION_XML))); + redisStorage.saveIdpCertData("test-key", idpCertDataToSave); + Thread.sleep(150); + IdpCertData result = redisStorage.getIdpCertData("test-key"); + Assertions.assertEquals(idpCertDataToSave, result); + } + + @SneakyThrows + @Test + public void successfulOperationsOnRedisStorageWithSentinelConnectionPooling() { + redisStorage = + new RedisIdpCertStorageProvider( + new RedisStorageProvisioner( + new DefaultRedisClientBuilder( + RedisStorageConfig.builder() + .withSentinel(true) + .withConnectionPooling(true) + .masterIds( + Collections.singletonList( + "mymaster")) + .mainNode( + RedisStorageConfig.RedisNode + .builder() + .port(26379) + .build()) + .build()))) + .provideStorage(idpCertStorageConfig); + IdpCertData idpCertDataToSave = new IdpCertData(); + idpCertDataToSave.setTag("aTag"); + idpCertDataToSave.setEntityId("anEntityId"); + idpCertDataToSave.setCertData( + new ArrayList<>(Collections.singletonList(VALID_ASSERTION_XML))); + redisStorage.saveIdpCertData("test-key", idpCertDataToSave); + Thread.sleep(150); + IdpCertData result = redisStorage.getIdpCertData("test-key"); + Assertions.assertEquals(idpCertDataToSave, result); + } + @AfterAll public void tearDown() throws IOException { redisServer.stop(); diff --git a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorageTest.java b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorageTest.java index f046bb37..b2377793 100644 --- a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorageTest.java +++ b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorageTest.java @@ -13,8 +13,6 @@ @TestInstance(TestInstance.Lifecycle.PER_CLASS) class SimpleRedisStorageTest { - private String bindAddress; - private RedisServer redisServer; private RedisSentinel redisSentinel; private SimpleRedisStorage redisStorage; From f19980d379e6645b04fcd14185cc70b3fb9da978 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Mon, 8 May 2023 19:32:46 +0200 Subject: [PATCH 384/403] [redis extra] Updated RedisIdpCertStorageIntegrationTest --- .../redis/idp/RedisIdpCertStorageIntegrationTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java index be621a6f..8c13a064 100644 --- a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java +++ b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/idp/RedisIdpCertStorageIntegrationTest.java @@ -138,6 +138,8 @@ class RedisIdpCertStorageIntegrationTest { + " <\\/saml:Assertion>\\n" + "<\\/samlp:Response>\"}"; private RedisServer redisServer; + + private RedisSentinel redisSentinel; private IdpCertStorage redisStorage; private IdpCertStorageConfig idpCertStorageConfig; @@ -148,7 +150,7 @@ public void setUp() throws IOException { idpCertStorageConfig.setStorageEvictionDelay(1); idpCertStorageConfig.setStorageEvictionDelayTimeUnit(TimeUnit.SECONDS); redisServer = RedisServer.newRedisServer().build(); - RedisSentinel redisSentinel = RedisSentinel.newRedisSentinel().build(); + redisSentinel = RedisSentinel.newRedisSentinel().build(); redisServer.start(); redisSentinel.start(); redisStorage = @@ -240,5 +242,6 @@ public void successfulOperationsOnRedisStorageWithSentinelConnectionPooling() { @AfterAll public void tearDown() throws IOException { redisServer.stop(); + redisSentinel.stop(); } } From e53ab7baa9c75342f091d0330f083c9b1e1c16f9 Mon Sep 17 00:00:00 2001 From: giomella Date: Tue, 9 May 2023 10:04:26 +0200 Subject: [PATCH 385/403] [SLS-28] implemented servlet filter. added unit and integration test. --- gradle/verification-metadata.xml | 11 + servlet-impl/build.gradle | 42 +++ .../servlet/HttpVerifierServletFilter.java | 62 ++++ .../HttpVerifierServletFilterTest.java | 94 ++++++ .../servlet/ServletDemoApplication.java | 13 + .../servlet/ServletIntegrationTest.java | 180 +++++++++++ .../servlet/config/DemoServicesConfig.java | 68 +++++ .../servlet/config/DemoWebConfigurer.java | 38 +++ .../config/HttpVerifierConfiguration.java | 48 +++ .../servlet/controller/DemoController.java | 15 + .../servlet/utils/SimpleClientsTestUtils.java | 283 ++++++++++++++++++ settings.gradle | 2 +- 12 files changed, 855 insertions(+), 1 deletion(-) create mode 100644 servlet-impl/build.gradle create mode 100644 servlet-impl/src/main/java/it/pagopa/tech/lollipop/consumer/servlet/HttpVerifierServletFilter.java create mode 100644 servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/HttpVerifierServletFilterTest.java create mode 100644 servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/ServletDemoApplication.java create mode 100644 servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/ServletIntegrationTest.java create mode 100644 servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/config/DemoServicesConfig.java create mode 100644 servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/config/DemoWebConfigurer.java create mode 100644 servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/config/HttpVerifierConfiguration.java create mode 100644 servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/controller/DemoController.java create mode 100644 servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/utils/SimpleClientsTestUtils.java diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 6a9e6fcb..be44915d 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2854,6 +2854,14 @@ + + + + + + + + @@ -5594,6 +5602,9 @@ + + + diff --git a/servlet-impl/build.gradle b/servlet-impl/build.gradle new file mode 100644 index 00000000..719fe829 --- /dev/null +++ b/servlet-impl/build.gradle @@ -0,0 +1,42 @@ +plugins { + id 'java-library' + id("io.freefair.lombok") version "8.0.0" + id 'io.spring.dependency-management' version '1.0.15.RELEASE' +} + +repositories { + mavenLocal() + mavenCentral() + maven { + url = uri("https://maven.pkg.github.com/pagopa/eng-http-signatures") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + } + } +} + +dependencies { + implementation(project(':core')) { + exclude group: 'ch.qos.logback', module: 'logback-classic' + exclude group: 'ch.qos.logback', module: 'logback-core' + } + implementation 'javax.servlet:javax.servlet-api:3.1.0' + implementation 'ch.qos.logback:logback-classic:1.2.11' + implementation 'ch.qos.logback:logback-core:1.2.11' + + testImplementation 'org.springframework.boot:spring-boot-starter-web:2.7.10' + testImplementation 'org.springframework.boot:spring-boot-starter-test:2.7.10' + testImplementation 'org.slf4j:slf4j-api:1.7.36' + testImplementation 'org.mock-server:mockserver-netty:5.15.0' + testImplementation 'org.mockito:mockito-core:5.2.0' + testImplementation 'org.mockito:mockito-junit-jupiter:5.2.0' + testImplementation project(':http-verifier') + testImplementation project(':assertion-rest-client-native') + testImplementation project(':identity-service-rest-client-native') +} + +tasks.named('test') { + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} diff --git a/servlet-impl/src/main/java/it/pagopa/tech/lollipop/consumer/servlet/HttpVerifierServletFilter.java b/servlet-impl/src/main/java/it/pagopa/tech/lollipop/consumer/servlet/HttpVerifierServletFilter.java new file mode 100644 index 00000000..daf703f2 --- /dev/null +++ b/servlet-impl/src/main/java/it/pagopa/tech/lollipop/consumer/servlet/HttpVerifierServletFilter.java @@ -0,0 +1,62 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.servlet; + +import static it.pagopa.tech.lollipop.consumer.command.impl.LollipopConsumerCommandImpl.VERIFICATION_SUCCESS_CODE; + +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; +import it.pagopa.tech.lollipop.consumer.model.CommandResult; +import it.pagopa.tech.lollipop.consumer.utils.LollipopConsumerConverter; +import java.io.IOException; +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** Instance of Servlet filter, to be used for Lollipop Request validations */ +@Slf4j +@AllArgsConstructor +public class HttpVerifierServletFilter implements Filter { + + private final LollipopConsumerCommandBuilder consumerCommandBuilder; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + log.error("Servlet filter initialized"); + } + + /** + * @param servletRequest current request + * @param servletResponse current request + * @param filterChain the filter chain + * @throws IOException throws exception if the conversion of a http request fails + * @throws ServletException throws in case of request validation failure + */ + @Override + public void doFilter( + ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { + LollipopConsumerCommand lollipopConsumerCommand = + consumerCommandBuilder.createCommand( + LollipopConsumerConverter.convertToLollipopRequest( + (HttpServletRequest) servletRequest)); + + try { + CommandResult commandResult = lollipopConsumerCommand.doExecute(); + LollipopConsumerConverter.interceptResult( + commandResult, (HttpServletResponse) servletResponse); + + if (commandResult.getResultCode().equals(VERIFICATION_SUCCESS_CODE)) { + filterChain.doFilter(servletRequest, servletResponse); + } + } catch (Exception e) { + log.error("Error verifying request", e); + } + } + + @Override + public void destroy() { + log.error("Servlet filter destroyed"); + } +} diff --git a/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/HttpVerifierServletFilterTest.java b/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/HttpVerifierServletFilterTest.java new file mode 100644 index 00000000..95ed9d49 --- /dev/null +++ b/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/HttpVerifierServletFilterTest.java @@ -0,0 +1,94 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.servlet; + +import static it.pagopa.tech.lollipop.consumer.command.impl.LollipopConsumerCommandImpl.VERIFICATION_SUCCESS_CODE; +import static org.mockito.Mockito.*; + +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommand; +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; +import it.pagopa.tech.lollipop.consumer.model.CommandResult; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Collections; +import java.util.Enumeration; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class HttpVerifierServletFilterTest { + + private HttpServletRequest requestMock; + private HttpServletResponse responseMock; + private FilterChain filterChainMock; + private LollipopConsumerCommandBuilder commandBuilderMock; + private LollipopConsumerCommand commandMock; + + private HttpVerifierServletFilter sut; + + @BeforeEach + void setUp() { + requestMock = mock(HttpServletRequest.class); + responseMock = mock(HttpServletResponse.class); + filterChainMock = mock(FilterChain.class); + commandBuilderMock = mock(LollipopConsumerCommandBuilder.class); + commandMock = mock(LollipopConsumerCommand.class); + + sut = new HttpVerifierServletFilter(commandBuilderMock); + + String header1 = "Header1"; + Enumeration headers = Collections.enumeration(Collections.singletonList(header1)); + doReturn(headers).when(requestMock).getHeaderNames(); + doReturn("value").when(requestMock).getHeader(header1); + } + + @Test + void testDoFilterSuccess() throws IOException, ServletException { + CommandResult commandResult = + new CommandResult(VERIFICATION_SUCCESS_CODE, "request validation success"); + + doReturn(commandMock).when(commandBuilderMock).createCommand(any()); + doReturn(commandResult).when(commandMock).doExecute(); + doNothing().when(filterChainMock).doFilter(requestMock, responseMock); + + sut.doFilter(requestMock, responseMock, filterChainMock); + + verify(responseMock, never()).setStatus(401); + verify(responseMock, never()).getWriter(); + verify(filterChainMock).doFilter(requestMock, responseMock); + } + + @Test + void testDoFilterFailForValidationError() throws IOException, ServletException { + PrintWriter printWriter = mock(PrintWriter.class); + CommandResult commandResult = new CommandResult("FAIL", "request validation failure"); + + doReturn(commandMock).when(commandBuilderMock).createCommand(any()); + doReturn(commandResult).when(commandMock).doExecute(); + doReturn(printWriter).when(responseMock).getWriter(); + + sut.doFilter(requestMock, responseMock, filterChainMock); + + verify(responseMock).setStatus(401); + verify(responseMock).getWriter(); + verify(printWriter).write(commandResult.getResultMessage()); + verify(filterChainMock, never()).doFilter(requestMock, responseMock); + } + + @Test + void testDoFilterFailForConversionException() throws IOException, ServletException { + CommandResult commandResult = new CommandResult("FAIL", "request validation failure"); + + doReturn(commandMock).when(commandBuilderMock).createCommand(any()); + doReturn(commandResult).when(commandMock).doExecute(); + doThrow(IOException.class).when(responseMock).getWriter(); + + sut.doFilter(requestMock, responseMock, filterChainMock); + + verify(responseMock).setStatus(401); + verify(responseMock).getWriter(); + verify(filterChainMock, never()).doFilter(requestMock, responseMock); + } +} diff --git a/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/ServletDemoApplication.java b/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/ServletDemoApplication.java new file mode 100644 index 00000000..759a2c96 --- /dev/null +++ b/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/ServletDemoApplication.java @@ -0,0 +1,13 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.servlet; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication(scanBasePackages = "it.pagopa.tech") +public class ServletDemoApplication { + + public static void main(String[] args) { + SpringApplication.run(ServletDemoApplication.class, args); + } +} diff --git a/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/ServletIntegrationTest.java b/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/ServletIntegrationTest.java new file mode 100644 index 00000000..69093036 --- /dev/null +++ b/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/ServletIntegrationTest.java @@ -0,0 +1,180 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.servlet; + +import static it.pagopa.tech.lollipop.consumer.servlet.utils.SimpleClientsTestUtils.*; +import static org.mockserver.integration.ClientAndServer.startClientAndServer; + +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; +import it.pagopa.tech.lollipop.consumer.servlet.config.HttpVerifierConfiguration; +import it.pagopa.tech.lollipop.consumer.servlet.utils.SimpleClientsTestUtils; +import java.io.IOException; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockserver.integration.ClientAndServer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.web.client.RestTemplate; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@ContextConfiguration( + classes = { + ServletDemoApplication.class, + LollipopConsumerRequestConfig.class, + HttpVerifierConfiguration.class + }) +public class ServletIntegrationTest { + + @LocalServerPort private int port; + @Autowired private TestRestTemplate restTemplate; + @Autowired private LollipopConsumerRequestConfig lollipopConsumerRequestConfig; + @Autowired private IdpCertSimpleClientConfig idpCertSimpleClientConfig; + + private static ClientAndServer mockServer; + + private static final String CONTENT_DIGEST = + "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"; + private static final String USER_ID = "GDNNWA12H81Y874F"; + private static final String SIGNATURE_INPUT = + "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + private static final String SIGNATURE = + "sig123=:6scl8sMzJdyG/OrnJXHRM9ajmIjrJ/zrLUDqvfOxj2h51DUKztTua3vR1kSUj/c/VT1ioDlt1QIMARABhquewg==:"; + + @BeforeAll + public static void startServer() { + mockServer = startClientAndServer(3000, 3001); + } + + @Test + void testWithValidRequestReturnsSuccess() throws IOException { + SimpleClientsTestUtils.createExpectationAssertionFound(); + SimpleClientsTestUtils.createExpectationIdpFound(); + lollipopConsumerRequestConfig.setAssertionNotBeforeDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + lollipopConsumerRequestConfig.setAssertionInstantDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + idpCertSimpleClientConfig.setBaseUri("http://localhost:3001"); + + RestTemplate exec = restTemplate.getRestTemplate(); + exec.getClientHttpRequestInitializers() + .add( + request -> { + request.getHeaders() + .add( + lollipopConsumerRequestConfig.getContentDigestHeader(), + CONTENT_DIGEST); + request.getHeaders() + .add( + lollipopConsumerRequestConfig.getOriginalURLHeader(), + lollipopConsumerRequestConfig + .getExpectedFirstLcOriginalUrl()); + request.getHeaders() + .add( + lollipopConsumerRequestConfig.getOriginalMethodHeader(), + lollipopConsumerRequestConfig + .getExpectedFirstLcOriginalMethod()); + request.getHeaders() + .add( + lollipopConsumerRequestConfig.getPublicKeyHeader(), + VALID_PUBLIC_KEY); + request.getHeaders() + .add( + lollipopConsumerRequestConfig.getAssertionRefHeader(), + ASSERTION_REF); + request.getHeaders() + .add( + lollipopConsumerRequestConfig.getAssertionTypeHeader(), + "SAML"); + request.getHeaders() + .add(lollipopConsumerRequestConfig.getAuthJWTHeader(), JWT); + request.getHeaders() + .add(lollipopConsumerRequestConfig.getUserIdHeader(), USER_ID); + request.getHeaders() + .add( + lollipopConsumerRequestConfig.getSignatureInputHeader(), + SIGNATURE_INPUT); + request.getHeaders() + .add( + lollipopConsumerRequestConfig.getSignatureHeader(), + SIGNATURE); + }); + + ResponseEntity response = + exec.postForEntity( + "http://localhost:" + port, + "{\"message\":\"a valid message payload\"}", + String.class); + Assertions.assertNotNull(response); + Assertions.assertEquals(200, response.getStatusCodeValue()); + } + + @Test + void testWithInvalidPayloadRequestReturnsUnauthorized() throws IOException { + SimpleClientsTestUtils.createExpectationAssertionFound(); + + RestTemplate exec = restTemplate.getRestTemplate(); + exec.getClientHttpRequestInitializers() + .add( + request -> { + request.getHeaders() + .add( + lollipopConsumerRequestConfig.getContentDigestHeader(), + CONTENT_DIGEST); + request.getHeaders() + .add( + lollipopConsumerRequestConfig.getOriginalURLHeader(), + lollipopConsumerRequestConfig + .getExpectedFirstLcOriginalUrl()); + request.getHeaders() + .add( + lollipopConsumerRequestConfig.getOriginalMethodHeader(), + lollipopConsumerRequestConfig + .getExpectedFirstLcOriginalMethod()); + request.getHeaders() + .add( + lollipopConsumerRequestConfig.getPublicKeyHeader(), + VALID_PUBLIC_KEY); + request.getHeaders() + .add( + lollipopConsumerRequestConfig.getAssertionRefHeader(), + ASSERTION_REF); + request.getHeaders() + .add( + lollipopConsumerRequestConfig.getAssertionTypeHeader(), + "SAML"); + request.getHeaders() + .add(lollipopConsumerRequestConfig.getAuthJWTHeader(), JWT); + request.getHeaders() + .add(lollipopConsumerRequestConfig.getUserIdHeader(), USER_ID); + request.getHeaders() + .add( + lollipopConsumerRequestConfig.getSignatureInputHeader(), + SIGNATURE_INPUT); + request.getHeaders() + .add( + lollipopConsumerRequestConfig.getSignatureHeader(), + SIGNATURE); + }); + + ResponseEntity response = + exec.postForEntity( + "http://localhost:" + port, + "{\"message\":\"an invalid message payload\"}", + String.class); + Assertions.assertNotNull(response); + Assertions.assertEquals(401, response.getStatusCodeValue()); + } + + @AfterAll + public static void stopServer() { + mockServer.stop(); + } +} diff --git a/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/config/DemoServicesConfig.java b/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/config/DemoServicesConfig.java new file mode 100644 index 00000000..0101d310 --- /dev/null +++ b/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/config/DemoServicesConfig.java @@ -0,0 +1,68 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.servlet.config; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientConfig; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.assertion.impl.AssertionServiceFactoryImpl; +import it.pagopa.tech.lollipop.consumer.assertion.storage.SimpleAssertionStorageProvider; +import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.http_verifier.visma.VismaHttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.storage.SimpleIdpCertStorageProvider; +import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImpl; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerServiceFactory; +import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerServiceFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class DemoServicesConfig { + + @Bean + public LollipopLoggerServiceFactory lollipopLoggerServiceFactory() { + return new LollipopLogbackLoggerServiceFactory(); + } + + @Bean + public LollipopConsumerRequestConfig verifierConfiguration() { + return new LollipopConsumerRequestConfig(); + } + + @Bean + public HttpMessageVerifierFactory httpMessageVerifierFactory() throws Exception { + return new VismaHttpMessageVerifierFactory("UTF-8", verifierConfiguration()); + } + + @Bean + public IdpCertProviderFactory idpCertProviderFactory() { + return new IdpCertProviderFactoryImpl( + new IdpCertSimpleClientProvider( + idpCertSimpleClientConfig(), + new SimpleIdpCertStorageProvider(), + new IdpCertStorageConfig())); + } + + @Bean + public AssertionServiceFactory assertionServiceFactory() { + return new AssertionServiceFactoryImpl( + new SimpleAssertionStorageProvider(), + new AssertionSimpleClientProvider(AssertionSimpleClientConfig.builder().build()), + storageConfig()); + } + + @Bean + public StorageConfig storageConfig() { + return new StorageConfig(); + } + + @Bean + public IdpCertSimpleClientConfig idpCertSimpleClientConfig() { + return IdpCertSimpleClientConfig.builder().build(); + } +} diff --git a/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/config/DemoWebConfigurer.java b/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/config/DemoWebConfigurer.java new file mode 100644 index 00000000..cfe451e2 --- /dev/null +++ b/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/config/DemoWebConfigurer.java @@ -0,0 +1,38 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.servlet.config; + +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; +import it.pagopa.tech.lollipop.consumer.servlet.HttpVerifierServletFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.filter.CommonsRequestLoggingFilter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class DemoWebConfigurer implements WebMvcConfigurer { + + @Autowired private LollipopConsumerCommandBuilder commandBuilder; + + @Bean + public CommonsRequestLoggingFilter loggingFilter() { + CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter(); + filter.setIncludeQueryString(true); + filter.setIncludeClientInfo(true); + filter.setIncludeHeaders(true); + filter.setIncludePayload(true); + return filter; + } + + @Bean + public FilterRegistrationBean requestFilter() { + FilterRegistrationBean registrationBean = + new FilterRegistrationBean<>(); + + registrationBean.setFilter(new HttpVerifierServletFilter(commandBuilder)); + registrationBean.addUrlPatterns("/*"); + + return registrationBean; + } +} diff --git a/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/config/HttpVerifierConfiguration.java b/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/config/HttpVerifierConfiguration.java new file mode 100644 index 00000000..d5a94646 --- /dev/null +++ b/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/config/HttpVerifierConfiguration.java @@ -0,0 +1,48 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.servlet.config; + +import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; +import it.pagopa.tech.lollipop.consumer.command.impl.LollipopConsumerCommandBuilderImpl; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.helper.LollipopConsumerFactoryHelper; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerServiceFactory; +import it.pagopa.tech.lollipop.consumer.service.LollipopConsumerRequestValidationService; +import it.pagopa.tech.lollipop.consumer.service.impl.LollipopConsumerRequestValidationServiceImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class HttpVerifierConfiguration { + + @Bean + public LollipopConsumerFactoryHelper lollipopConsumerFactoryHelper( + LollipopLoggerServiceFactory lollipopLoggerServiceFactory, + HttpMessageVerifierFactory httpMessageVerifierFactory, + IdpCertProviderFactory idpCertProviderFactory, + AssertionServiceFactory assertionServiceFactory, + LollipopConsumerRequestValidationService lollipopConsumerRequestValidationService, + LollipopConsumerRequestConfig lollipopConsumerRequestConfig) { + return new LollipopConsumerFactoryHelper( + lollipopLoggerServiceFactory, + httpMessageVerifierFactory, + idpCertProviderFactory, + assertionServiceFactory, + lollipopConsumerRequestValidationService, + lollipopConsumerRequestConfig); + } + + @Bean + public LollipopConsumerRequestValidationService getLollipopConsumerRequestValidationService( + LollipopConsumerRequestConfig lollipopConsumerRequestConfig) { + return new LollipopConsumerRequestValidationServiceImpl(lollipopConsumerRequestConfig); + } + + @Bean + public LollipopConsumerCommandBuilder lollipopConsumerCommandBuilder( + LollipopConsumerFactoryHelper lollipopConsumerFactoryHelper) { + return new LollipopConsumerCommandBuilderImpl(lollipopConsumerFactoryHelper); + } +} diff --git a/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/controller/DemoController.java b/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/controller/DemoController.java new file mode 100644 index 00000000..ebe7ff5d --- /dev/null +++ b/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/controller/DemoController.java @@ -0,0 +1,15 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.servlet.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class DemoController { + + @RequestMapping("/") + public @ResponseBody String test() { + return "Test"; + } +} diff --git a/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/utils/SimpleClientsTestUtils.java b/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/utils/SimpleClientsTestUtils.java new file mode 100644 index 00000000..94ff3420 --- /dev/null +++ b/servlet-impl/src/test/java/it/pagopa/tech/lollipop/consumer/servlet/utils/SimpleClientsTestUtils.java @@ -0,0 +1,283 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.servlet.utils; + +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +import org.mockserver.client.MockServerClient; +import org.mockserver.model.Header; + +public class SimpleClientsTestUtils { + + public static final String VALID_ASSERTION_XML = + "{\"response_xml\": \"\\n" + + " https:\\/\\/spid-testenv2:8088<\\/saml:Issuer><\\/ds:Transforms>s\\/DqYePHC7eCXX5ncsiFYNLyKbzS6P5C8331H1b8e30=<\\/ds:DigestValue><\\/ds:Reference><\\/ds:SignedInfo>WcasorooElvhmK0kxFUdBVCqyRYi0SCNGRSZZnC9Q2sZHOYGZbERe4\\/T8OSuRKbSrEivXIHRgNr8WskZTM2CiywfWChHfGvhERsLuPJE8oh9CR3eicX\\/eg0ynJqwx4IoYhTb2NOwqMFc66nnutMhG\\/Smdtjs4SFz0RQYYVeZ5Ho51iTHd94uBV9ZHXjqcvs3EitUsJ0Zg1Pkw352tt8y7niUcGjAd8nydI72S12sF5ePv05AunFp7vZpYbKqi62fQLORCn1ZP7WKFD75hL0bCvZaSRF285GkfSnLfe1S4tLff2SlTQWevOMU\\/wCkHJmQwHT1LMwcWRnMvv4V+vd1XQ==<\\/ds:SignatureValue>MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR\\/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2\\/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI\\/sp\\n" + + "ILywgDxVMMtv\\/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAf\\n" + + "BgNVHSMEGDAWgBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH\\/MA0G\\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8\\/o13vMw4feGxro1hMeUilRtH52funrW\\n" + + "C+FgPrqk3o\\/8cZOnq+CqnFFDfILLiEb\\/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\n" + + "Da1fG\\/Pi0fG2F0yw\\/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk\\/ZbEHdKcofnziDyl0V8gglP2\\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n" + + "<\\/ds:X509Certificate><\\/ds:X509Data><\\/ds:KeyInfo><\\/ds:Signature>\\n" + + " \\n" + + " \\n" + + " <\\/samlp:Status>\\n" + + " \\n" + + " https:\\/\\/spid-testenv2:8088<\\/saml:Issuer><\\/ds:Transforms>4cqgG29TSKgNLy2\\/1eFPXhd5WRVPxZBGcd8DgTvd5Fo=<\\/ds:DigestValue><\\/ds:Reference><\\/ds:SignedInfo>WqxM+y+vtZDcEaIaw2WfcuMuwXUeTOY9ZjaXwzHw+RE8uUr5s8BE1tpaodcKmmqSJK1JQYNr8AUV+W9V79EKfmNtFvfaf0WYeUee7Td7E24QqiyVHjr1YgfDWhSdItFLYJfQUkotj2BepbdwVQGY5yN0Rw6Fq98hgNOgsxty7g6oqxG1OXB4WJ2He20iOoYWQl8ApxlbU\\/\\/hwnefFYe9ghDPy3rDbcNl3JetT07NR\\/+AzhKH4e+JCwKjTkdCBTW30fK4eiV9yBk74Lobip4hMaQhMaByl8egaU3A8AsnsZQuov2B6Wo2sDiQPjIulb8K3DOwFyL8PzEk8BB5YoAfwg==<\\/ds:SignatureValue>MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR\\/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2\\/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI\\/sp\\n" + + "ILywgDxVMMtv\\/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAf\\n" + + "BgNVHSMEGDAWgBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH\\/MA0G\\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8\\/o13vMw4feGxro1hMeUilRtH52funrW\\n" + + "C+FgPrqk3o\\/8cZOnq+CqnFFDfILLiEb\\/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\n" + + "Da1fG\\/Pi0fG2F0yw\\/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk\\/ZbEHdKcofnziDyl0V8gglP2\\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n" + + "<\\/ds:X509Certificate><\\/ds:X509Data><\\/ds:KeyInfo><\\/ds:Signature>\\n" + + " \\n" + + " id_48129c2a9d5e9077422591baf495747cfda668c5<\\/saml:NameID>\\n" + + " \\n" + + " \\n" + + " <\\/saml:SubjectConfirmation>\\n" + + " <\\/saml:Subject>\\n" + + " \\n" + + " \\n" + + " https:\\/\\/spid.agid.gov.it\\/cd<\\/saml:Audience>\\n" + + " <\\/saml:AudienceRestriction>\\n" + + " <\\/saml:Conditions>\\n" + + " \\n" + + " \\n" + + " " + + " https:\\/\\/www.spid.gov.it\\/SpidL2<\\/saml:AuthnContextClassRef>\\n" + + " <\\/saml:AuthnContext>\\n" + + " <\\/saml:AuthnStatement>\\n" + + " \\n" + + " \\n" + + " info@agid.gov.it<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " Mario<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " Bianchi<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " GDNNWA12H81Y874F<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " 1991-12-12<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " <\\/saml:AttributeStatement>\\n" + + " <\\/saml:Assertion>\\n" + + "<\\/samlp:Response>\"}"; + public static final String IDP_CLIENT_RESPONSE_STRING = + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + + " MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI/sp\n" + + "ILywgDxVMMtv/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA/L1/fd70ok+6xtDRF8A3HjAf\n" + + "BgNVHSMEGDAWgBQEVmzA/L1/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH/MA0G\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8/o13vMw4feGxro1hMeUilRtH52funrW\n" + + "C+FgPrqk3o/8cZOnq+CqnFFDfILLiEb/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\n" + + "Da1fG/Pi0fG2F0yw/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk/ZbEHdKcofnziDyl0V8gglP2\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " urn:oasis:names:tc:SAML:2.0:nameid-format:transient\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + public static final String ASSERTION_REF = "sha256-chG21HBOK-wJp2hHuYPrx7tAII2UGWVF-IFo0crUOtw"; + public static final String WRONG_ASSERTION_REF = + "sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfXXXXX"; + public static final String JWT = "aValidJWT"; + public static final String VALID_PUBLIC_KEY = + "eyJrdHkiOiJFQyIsIngiOiJTaHlZa0ZyN1F3eE9rOE5BRXF6aklkTnc4dEVKODlZOVBlWFF1eVVOWDVjIiwieSI6InlULVJxNWc2VlVadENUd0ZnRExDM2RneGNuM2RsSmNGRjhnWGdxYWgyS0UiLCJjcnYiOiJQLTI1NiJ9"; + private static final String IDP_TAG = "latest"; + + public static void createExpectationAssertionFound() { + new MockServerClient("localhost", 3000) + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", JWT))) + .respond(response().withStatusCode(200).withBody(VALID_ASSERTION_XML)); + } + + public static void createExpectationAssertionNotFound() { + new MockServerClient("localhost", 2000) + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", WRONG_ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", JWT))) + .respond(response().withStatusCode(404).withBody("{}")); + } + + public static void createExpectationIdpFound() { + new MockServerClient("localhost", 3001) + .when(request().withMethod("GET").withPath("/idp-keys/spid")) + .respond(response().withStatusCode(200).withBody("[\"" + IDP_TAG + "\"]")); + new MockServerClient("localhost", 3001) + .when( + request() + .withMethod("GET") + .withPath("/idp-keys/spid/{tag}") + .withPathParameter("tag", IDP_TAG)) + .respond(response().withStatusCode(200).withBody(IDP_CLIENT_RESPONSE_STRING)); + } + + private SimpleClientsTestUtils() {} +} diff --git a/settings.gradle b/settings.gradle index 844793d0..6cdd7ae8 100644 --- a/settings.gradle +++ b/settings.gradle @@ -29,4 +29,4 @@ gradleEnterprise { } rootProject.name = 'eng-lollipop-consumer-java-sdk' -include 'core', 'assertion-rest-client-native', 'http-verifier', 'identity-service-rest-client-native', 'redis-storage', 'test-coverage', 'spring-impl' +include 'core', 'assertion-rest-client-native', 'http-verifier', 'identity-service-rest-client-native', 'redis-storage', 'test-coverage', 'spring-impl', 'servlet-impl' From e4aec6088e3fc13d58c3fc252e072d670eeef853 Mon Sep 17 00:00:00 2001 From: giomella Date: Tue, 9 May 2023 10:38:27 +0200 Subject: [PATCH 386/403] [SLS-28] updated verification-metadata.xml with sha1. --- gradle/verification-metadata.xml | 125 +++++++++++++++++++++++++++++-- 1 file changed, 119 insertions(+), 6 deletions(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index be44915d..e7b4ffc5 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -23,9 +23,11 @@ + + @@ -43,9 +45,11 @@ + + @@ -58,6 +62,7 @@ + @@ -377,6 +382,7 @@ + @@ -395,7 +401,7 @@ - + @@ -458,6 +464,7 @@ + @@ -476,7 +483,7 @@ - + @@ -531,6 +538,7 @@ + @@ -555,7 +563,7 @@ - + @@ -743,7 +751,7 @@ - + @@ -811,7 +819,7 @@ - + @@ -876,7 +884,7 @@ - + @@ -939,6 +947,7 @@ + @@ -1179,9 +1188,11 @@ + + @@ -1210,6 +1221,7 @@ + @@ -1268,9 +1280,11 @@ + + @@ -1316,6 +1330,7 @@ + @@ -1745,9 +1760,11 @@ + + @@ -1777,9 +1794,11 @@ + + @@ -1827,9 +1846,11 @@ + + @@ -1843,6 +1864,7 @@ + @@ -2848,17 +2870,21 @@ + + + + @@ -2884,9 +2910,11 @@ + + @@ -3162,14 +3190,17 @@ + + + @@ -3267,11 +3298,13 @@ + + @@ -3393,6 +3426,7 @@ + @@ -3410,29 +3444,35 @@ + + + + + + @@ -3674,9 +3714,11 @@ + + @@ -3718,9 +3760,11 @@ + + @@ -3801,19 +3845,23 @@ + + + + @@ -3900,9 +3948,11 @@ + + @@ -3956,9 +4006,11 @@ + + @@ -3989,22 +4041,27 @@ + + + + + @@ -4085,9 +4142,11 @@ + + @@ -4368,9 +4427,11 @@ + + @@ -4527,6 +4588,7 @@ + @@ -4547,6 +4609,7 @@ + @@ -4632,12 +4695,15 @@ + + + @@ -4773,12 +4839,15 @@ + + + @@ -4843,6 +4912,7 @@ + @@ -4942,6 +5012,7 @@ + @@ -4990,6 +5061,7 @@ + @@ -5251,9 +5323,11 @@ + + @@ -5267,9 +5341,11 @@ + + @@ -5283,6 +5359,7 @@ + @@ -5293,9 +5370,11 @@ + + @@ -5309,9 +5388,11 @@ + + @@ -5325,9 +5406,11 @@ + + @@ -5341,9 +5424,11 @@ + + @@ -5357,9 +5442,11 @@ + + @@ -5373,9 +5460,11 @@ + + @@ -5389,9 +5478,11 @@ + + @@ -5405,9 +5496,11 @@ + + @@ -5421,41 +5514,51 @@ + + + + + + + + + + @@ -5469,9 +5572,11 @@ + + @@ -5603,6 +5708,7 @@ + @@ -5638,17 +5744,21 @@ + + + + @@ -5708,11 +5818,13 @@ + + @@ -5899,6 +6011,7 @@ + From ed1706e85db00201d5fa9a5947820d8b3f6afe7a Mon Sep 17 00:00:00 2001 From: giomella Date: Tue, 9 May 2023 11:03:42 +0200 Subject: [PATCH 387/403] [SLS-28] fix verification-metadata.xml sha1. --- gradle/verification-metadata.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index e7b4ffc5..48c9307b 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2884,8 +2884,7 @@ - - + From 38f5344a075ac4c3e5d9815cbaf3442481e66e9e Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 9 May 2023 12:40:24 +0200 Subject: [PATCH 388/403] [SLS-34] Added simple java sample application using typesafe configuration with utility core class --- .../utils/LollipopTypesafeConfig.java | 2 + samples/simpleTypesafe/build.gradle | 58 ++++ .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 61608 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 + samples/simpleTypesafe/gradlew | 244 ++++++++++++++++ samples/simpleTypesafe/gradlew.bat | 92 ++++++ samples/simpleTypesafe/settings.gradle | 9 + .../pagopa/tech/sample/ClientMocksConfig.java | 274 ++++++++++++++++++ .../pagopa/tech/sample/LollipopConstants.java | 52 ++++ .../tech/sample/LollipopConsumerSample.java | 138 +++++++++ .../src/main/resources/application.properties | 10 + 11 files changed, 885 insertions(+) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopTypesafeConfig.java create mode 100644 samples/simpleTypesafe/build.gradle create mode 100644 samples/simpleTypesafe/gradle/wrapper/gradle-wrapper.jar create mode 100644 samples/simpleTypesafe/gradle/wrapper/gradle-wrapper.properties create mode 100755 samples/simpleTypesafe/gradlew create mode 100644 samples/simpleTypesafe/gradlew.bat create mode 100644 samples/simpleTypesafe/settings.gradle create mode 100644 samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/ClientMocksConfig.java create mode 100644 samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/LollipopConstants.java create mode 100644 samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java create mode 100644 samples/simpleTypesafe/src/main/resources/application.properties diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopTypesafeConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopTypesafeConfig.java new file mode 100644 index 00000000..2d63bda6 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopTypesafeConfig.java @@ -0,0 +1,2 @@ +package it.pagopa.tech.lollipop.consumer.utils;public class LollipopTypesafeConfig { +} diff --git a/samples/simpleTypesafe/build.gradle b/samples/simpleTypesafe/build.gradle new file mode 100644 index 00000000..8ffcd293 --- /dev/null +++ b/samples/simpleTypesafe/build.gradle @@ -0,0 +1,58 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Java library project to get you started. + * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle + * User Manual available at https://docs.gradle.org/8.0.2/userguide/building_java_projects.html + */ + +plugins { + // Apply the java-library plugin for API and implementation separation. + id 'application' +} + + +group = 'it.pagopa.tech.lollipop.consumer.samples' +version = '1.0.0-RC1' +sourceCompatibility = '11' + +application { + mainClassName = "it.pagopa.tech.sample.LollipopConsumerSample" +} + +repositories { + mavenLocal() + mavenCentral() + maven { + url = uri("https://maven.pkg.github.com/pagopa/eng-http-signatures") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + } + } + maven { + name = "GitHubPackages" + url = "https://maven.pkg.github.com/pagopa/eng-lollipop-consumer-java-sdk" + credentials { + username = System.getenv("GITHUB_ACTOR") + password = System.getenv("GITHUB_TOKEN") + } + } +} + +dependencies { + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:core:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:assertion-rest-client-native:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:identity-service-rest-client-native:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:http-verifier:1.0.0-RC1' + + implementation 'com.typesafe:config:1.3.3' + // Use JUnit Jupiter for testing. + implementation 'org.mock-server:mockserver-netty:5.15.0' + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' +} + +tasks.named('test') { + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} diff --git a/samples/simpleTypesafe/gradle/wrapper/gradle-wrapper.jar b/samples/simpleTypesafe/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..ccebba7710deaf9f98673a68957ea02138b60d0a GIT binary patch literal 61608 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 literal 0 HcmV?d00001 diff --git a/samples/simpleTypesafe/gradle/wrapper/gradle-wrapper.properties b/samples/simpleTypesafe/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..42defcc9 --- /dev/null +++ b/samples/simpleTypesafe/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip +networkTimeout=10000 +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/samples/simpleTypesafe/gradlew b/samples/simpleTypesafe/gradlew new file mode 100755 index 00000000..79a61d42 --- /dev/null +++ b/samples/simpleTypesafe/gradlew @@ -0,0 +1,244 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/samples/simpleTypesafe/gradlew.bat b/samples/simpleTypesafe/gradlew.bat new file mode 100644 index 00000000..93e3f59f --- /dev/null +++ b/samples/simpleTypesafe/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/samples/simpleTypesafe/settings.gradle b/samples/simpleTypesafe/settings.gradle new file mode 100644 index 00000000..bf66c794 --- /dev/null +++ b/samples/simpleTypesafe/settings.gradle @@ -0,0 +1,9 @@ +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } +} + + +rootProject.name = 'simple-lollipop-sample' \ No newline at end of file diff --git a/samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/ClientMocksConfig.java b/samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/ClientMocksConfig.java new file mode 100644 index 00000000..f6ad64f5 --- /dev/null +++ b/samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/ClientMocksConfig.java @@ -0,0 +1,274 @@ +package it.pagopa.tech.sample; + +import org.mockserver.client.MockServerClient; +import org.mockserver.model.Header; + +import static it.pagopa.tech.sample.LollipopConstants.*; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +public class ClientMocksConfig { + + public static final String VALID_ASSERTION_XML = + "{\"response_xml\": \"\\n" + + " https:\\/\\/spid-testenv2:8088<\\/saml:Issuer><\\/ds:Transforms>s\\/DqYePHC7eCXX5ncsiFYNLyKbzS6P5C8331H1b8e30=<\\/ds:DigestValue><\\/ds:Reference><\\/ds:SignedInfo>WcasorooElvhmK0kxFUdBVCqyRYi0SCNGRSZZnC9Q2sZHOYGZbERe4\\/T8OSuRKbSrEivXIHRgNr8WskZTM2CiywfWChHfGvhERsLuPJE8oh9CR3eicX\\/eg0ynJqwx4IoYhTb2NOwqMFc66nnutMhG\\/Smdtjs4SFz0RQYYVeZ5Ho51iTHd94uBV9ZHXjqcvs3EitUsJ0Zg1Pkw352tt8y7niUcGjAd8nydI72S12sF5ePv05AunFp7vZpYbKqi62fQLORCn1ZP7WKFD75hL0bCvZaSRF285GkfSnLfe1S4tLff2SlTQWevOMU\\/wCkHJmQwHT1LMwcWRnMvv4V+vd1XQ==<\\/ds:SignatureValue>MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR\\/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2\\/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI\\/sp\\n" + + "ILywgDxVMMtv\\/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAf\\n" + + "BgNVHSMEGDAWgBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH\\/MA0G\\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8\\/o13vMw4feGxro1hMeUilRtH52funrW\\n" + + "C+FgPrqk3o\\/8cZOnq+CqnFFDfILLiEb\\/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\n" + + "Da1fG\\/Pi0fG2F0yw\\/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk\\/ZbEHdKcofnziDyl0V8gglP2\\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n" + + "<\\/ds:X509Certificate><\\/ds:X509Data><\\/ds:KeyInfo><\\/ds:Signature>\\n" + + " \\n" + + " \\n" + + " <\\/samlp:Status>\\n" + + " \\n" + + " https:\\/\\/spid-testenv2:8088<\\/saml:Issuer><\\/ds:Transforms>4cqgG29TSKgNLy2\\/1eFPXhd5WRVPxZBGcd8DgTvd5Fo=<\\/ds:DigestValue><\\/ds:Reference><\\/ds:SignedInfo>WqxM+y+vtZDcEaIaw2WfcuMuwXUeTOY9ZjaXwzHw+RE8uUr5s8BE1tpaodcKmmqSJK1JQYNr8AUV+W9V79EKfmNtFvfaf0WYeUee7Td7E24QqiyVHjr1YgfDWhSdItFLYJfQUkotj2BepbdwVQGY5yN0Rw6Fq98hgNOgsxty7g6oqxG1OXB4WJ2He20iOoYWQl8ApxlbU\\/\\/hwnefFYe9ghDPy3rDbcNl3JetT07NR\\/+AzhKH4e+JCwKjTkdCBTW30fK4eiV9yBk74Lobip4hMaQhMaByl8egaU3A8AsnsZQuov2B6Wo2sDiQPjIulb8K3DOwFyL8PzEk8BB5YoAfwg==<\\/ds:SignatureValue>MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR\\/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2\\/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI\\/sp\\n" + + "ILywgDxVMMtv\\/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAf\\n" + + "BgNVHSMEGDAWgBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH\\/MA0G\\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8\\/o13vMw4feGxro1hMeUilRtH52funrW\\n" + + "C+FgPrqk3o\\/8cZOnq+CqnFFDfILLiEb\\/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\n" + + "Da1fG\\/Pi0fG2F0yw\\/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk\\/ZbEHdKcofnziDyl0V8gglP2\\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n" + + "<\\/ds:X509Certificate><\\/ds:X509Data><\\/ds:KeyInfo><\\/ds:Signature>\\n" + + " \\n" + + " id_48129c2a9d5e9077422591baf495747cfda668c5<\\/saml:NameID>\\n" + + " \\n" + + " \\n" + + " <\\/saml:SubjectConfirmation>\\n" + + " <\\/saml:Subject>\\n" + + " \\n" + + " \\n" + + " https:\\/\\/spid.agid.gov.it\\/cd<\\/saml:Audience>\\n" + + " <\\/saml:AudienceRestriction>\\n" + + " <\\/saml:Conditions>\\n" + + " \\n" + + " \\n" + + " " + + " https:\\/\\/www.spid.gov.it\\/SpidL2<\\/saml:AuthnContextClassRef>\\n" + + " <\\/saml:AuthnContext>\\n" + + " <\\/saml:AuthnStatement>\\n" + + " \\n" + + " \\n" + + " info@agid.gov.it<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " Mario<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " Bianchi<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " GDNNWA12H81Y874F<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " 1991-12-12<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " <\\/saml:AttributeStatement>\\n" + + " <\\/saml:Assertion>\\n" + + "<\\/samlp:Response>\"}"; + public static final String IDP_CLIENT_RESPONSE_STRING = + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + + " MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI/sp\n" + + "ILywgDxVMMtv/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA/L1/fd70ok+6xtDRF8A3HjAf\n" + + "BgNVHSMEGDAWgBQEVmzA/L1/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH/MA0G\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8/o13vMw4feGxro1hMeUilRtH52funrW\n" + + "C+FgPrqk3o/8cZOnq+CqnFFDfILLiEb/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\n" + + "Da1fG/Pi0fG2F0yw/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk/ZbEHdKcofnziDyl0V8gglP2\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " urn:oasis:names:tc:SAML:2.0:nameid-format:transient\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + + private static final String LOCALHOST = "localhost"; + + public static MockServerClient createExpectationAssertionFound() { + MockServerClient mockServerClient = new MockServerClient(LOCALHOST, 3000); + mockServerClient + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", VALID_ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", VALID_JWT))) + .respond(response().withStatusCode(200).withBody(VALID_ASSERTION_XML)); + return mockServerClient; + } + + public static MockServerClient createExpectationIdpTagsFound() { + MockServerClient mockServerClient = new MockServerClient(LOCALHOST, 3001); + mockServerClient + .when(request().withMethod("GET").withPath("/idp-keys/spid")) + .respond(response().withStatusCode(200).withBody("[\"" + IDP_TAG + "\"]")); + return mockServerClient; + } + + public static MockServerClient createExpectationIdpDataFound() { + MockServerClient mockServerClient = new MockServerClient(LOCALHOST, 3001); + mockServerClient + .when( + request() + .withMethod("GET") + .withPath("/idp-keys/spid/{tag}") + .withPathParameter("tag", IDP_TAG)) + .respond(response().withStatusCode(200).withBody(IDP_CLIENT_RESPONSE_STRING)); + return mockServerClient; + } + + private ClientMocksConfig() {} +} diff --git a/samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/LollipopConstants.java b/samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/LollipopConstants.java new file mode 100644 index 00000000..79e11c95 --- /dev/null +++ b/samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/LollipopConstants.java @@ -0,0 +1,52 @@ +package it.pagopa.tech.sample; + +public class LollipopConstants { + public static final String VALID_ENCODING_UTF8 = "UTF-8"; + public static final String INVALID_ENCODING_UTF_326 = "UTF-326"; + public static final String VALID_CONTENT_DIGEST = "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"; + public static final String INVALID_CONTENT_DIGEST = "sha-256=:fadsfeagsdage76ad564=:"; + public static final String VALID_MESSAGE_PAYLOAD = "{\"message\":\"a valid message payload\"}"; + public static final String INVALID_MESSAGE_PAYLOAD = "{\"message\":\"an invalid message payload\"}"; + public static final String SIGNATURE_HEADER_VALUE = "sig123=:6scl8sMzJdyG/OrnJXHRM9ajmIjrJ/zrLUDqvfOxj2h51DUKztTua3vR1kSUj/c/VT1ioDlt1QIMARABhquewg==:"; + public static final String INVALID_SIGNATURE_HEADER_VALUE = "sig123=:lTTTRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + public static final String SIGNATURE_INPUT_HEADER_VALUE = "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + + public static final String ECDSA_LOLLIPOP_JWT_KEY = "eyJrdHkiOiJFQyIsIngiOiJTaHlZa0ZyN1F3eE9rOE5BRXF6aklkTnc4dEVKODlZOVBlWFF1eVVOWDVjIiwieSI6InlULVJxNWc2VlVadENUd0ZnRExDM2RneGNuM2RsSmNGRjhnWGdxYWgyS0UiLCJjcnYiOiJQLTI1NiJ9"; + + public static final String VALID_MULTI_ECDSA_SIGNATURE_INPUT = + "sig1=(\"x-io-sign-qtspclauses\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\"," + + " sig2=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + public static final String VALID_MULTI_ECDSA_SIGNATURE = + "sig1=:8MB/iT9iZO2HfVjMds6WdFMQeutkPnoyBDhzeyvIQDhb/tX0nE6HeRSoRBsrl4GUzo6OItnzfzF43Sd14P7tAw==:," + + "sig2=:ZDWu2x+6APQG0Ioj10uNzTBv+5JbFBYnjhqcpL66oGFtwznROAUouXkx80ekzUY5h0HoJWE/ecqxRK2OVeHTiQ==:"; + + public static final String VALID_RSA_PSS_SIGNATURE_INPUT = + "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678814391;nonce=\"aNonce\";" + + "alg=\"rsa-pss-sha256\";keyid=\"sha256-A3OhKGLYwSvdJ2txHi_SGQ3G-sHLh2Ibu91ErqFx_58\""; + + public static final String VALID_RSA_PSS_SIGNATURE = + "sig1=:q3Og7m8yL18HkrY+zgV92Gj05lrWaFMIEFSPg2PEnO5a46+2Tt/2n7kjqVaGjI1ZXtys+Wyh3cVXCdda" + + "dNARizt0BpCRdT9S4r48xsGO79Ucq4IFwZyyHNudKu5WSH4/55j5yX/YmeCtH+Nt6Nun02OZynn3iQwg" + + "LJB+CGe3h6X02iSvl4wJjKaMGE64RFHa5osE4MctoPD1j0tRkcOtgwrGmFMr282Kqrkabbx1vUpmO9T1k" + + "hjouxIryfUln9zIaZ+wWmukpAZv7TKO3CltNWgfx1XT9m/iwzHiGmtvcHbWVExdAyey8lH23MgLY43AM7y" + + "tLQNSlk1s/bPNbGmPwg==:"; + + public static String LOLLIPOP_RSA_PUBKEY = "eyJrdHkiOiJSU0EiLCJlIjoiQVFBQiIsImtpZCI6InRlc3Qta2V5LXJzYS1wc3MiLCJuIjoicjR0bW0zc" + + "jIwV2RfUGJxdlAxczItUUV0dnB1UmFWOFlxNDBnalVSOHkyUmp4YTZkcEcyR1hIYlBmdk0gIHM4Y3Q" + + "tTGgxR0g0NXgyOFJ3M1J5NTNtbS1vQVhqeVE4Nk9uRGtaNU44bFliZ2dENE8zdzZNNnBBdkxraGs5NU" + + "FuICBkVHJpZmJJRlBOVThQUE1PN095ckZBSHFnRHN6bmpQRm1UT3RDRWNOMloxRnBXZ2Nod3VZTFBMLV" + + "dva3FsdGQxMSAgbnFxemktYko5Y3ZTS0FEWWRVQUFONVdVdHpkcGl5NkxiVGdTeFA3b2NpVTRUbjBnNU" + + "k2YURaSjdBOEx6bzBLU3kgIFpZb0E0ODVtcWNPMEdWQWRWdzlscTRhT1Q5djZkLW5iNGJuTmtRVmtsTFE" + + "zZlZBdkptLXhkRE9wOUxDTkNONDhWICAycG5ET2tGVjYtVTluVjVveWM2WEkydyJ9"; + + public static final String VALID_ASSERTION_REF = "sha256-chG21HBOK-wJp2hHuYPrx7tAII2UGWVF-IFo0crUOtw"; + public static final String VALID_FISCAL_CODE = "GDNNWA12H81Y874F"; + public static final String VALID_JWT = "aValidJWT"; + + public static final String IDP_TAG = "latest"; + + private LollipopConstants() {} +} diff --git a/samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java b/samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java new file mode 100644 index 00000000..86a86203 --- /dev/null +++ b/samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java @@ -0,0 +1,138 @@ +package it.pagopa.tech.sample; + +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; +import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; +import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClientProvider; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientConfig; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.assertion.impl.AssertionServiceFactoryImpl; +import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorageProvider; +import it.pagopa.tech.lollipop.consumer.assertion.storage.SimpleAssertionStorageProvider; +import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; +import it.pagopa.tech.lollipop.consumer.command.impl.LollipopConsumerCommandBuilderImpl; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.helper.LollipopConsumerFactoryHelper; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.http_verifier.visma.VismaHttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.storage.SimpleIdpCertStorageProvider; +import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImpl; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerServiceFactory; +import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerServiceFactory; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.tech.lollipop.consumer.service.impl.LollipopConsumerRequestValidationServiceImpl; +import it.pagopa.tech.lollipop.consumer.utils.LollipopTypesafeConfig; +import org.mockserver.client.MockServerClient; +import org.mockserver.integration.ClientAndServer; + +import java.util.HashMap; + +import static it.pagopa.tech.sample.LollipopConstants.*; + + +public class LollipopConsumerSample { + + private static LollipopConsumerRequestConfig lollipopConsumerRequestConfig; + + public static void main(String[] args) throws Exception { + try (ClientAndServer clientAndServer = ClientAndServer.startClientAndServer(3000, 3001); + MockServerClient mockServerClientAssertion = ClientMocksConfig.createExpectationAssertionFound(); + MockServerClient mockServerClientIdpTag = ClientMocksConfig.createExpectationIdpTagsFound(); + MockServerClient mockServerClientIdpData = ClientMocksConfig.createExpectationIdpDataFound()) { + + LollipopConsumerFactoryHelper lollipopConsumerFactoryHelper = buildLollipopConsumerFactoryHelper(); + LollipopConsumerCommandBuilder commandBuilder = new LollipopConsumerCommandBuilderImpl(lollipopConsumerFactoryHelper); + + // Success + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)) + .doExecute(); + + // Request with invalid content digest + commandBuilder.createCommand(buildLollipopRequest( + INVALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)).doExecute(); + + // Request with invalid message payload + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, INVALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)).doExecute(); + + // Request with invalid encoding + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, INVALID_ENCODING_UTF_326, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)).doExecute(); + + // Request with invalid signature + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, INVALID_SIGNATURE_HEADER_VALUE)).doExecute(); + + // Success with multi signature + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + VALID_MULTI_ECDSA_SIGNATURE_INPUT, VALID_MULTI_ECDSA_SIGNATURE)).doExecute(); + + // thumbprint validation failed + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, + LOLLIPOP_RSA_PUBKEY, VALID_RSA_PSS_SIGNATURE_INPUT, VALID_RSA_PSS_SIGNATURE)).doExecute(); + + } + } + + private static LollipopConsumerFactoryHelper buildLollipopConsumerFactoryHelper() throws Exception { + LollipopTypesafeConfig typesafeConfig = new LollipopTypesafeConfig(ConfigFactory.parseResources("application.properties")); + lollipopConsumerRequestConfig = LollipopConsumerRequestConfig.builder() + .assertionNotBeforeDateFormat(typesafeConfig.getLOLLIPOP_ASSERTION_NOT_BEFORE_DATE_FORMAT()) + .assertionInstantDateFormat(typesafeConfig.getLOLLIPOP_ASSERTION_INSTANT_DATE_FORMAT()) + .build(); + HttpMessageVerifierFactory messageVerifierFactory = new VismaHttpMessageVerifierFactory(VALID_ENCODING_UTF8, + LollipopConsumerRequestConfig.builder().build()); + AssertionStorageProvider assertionStorageProvider = new SimpleAssertionStorageProvider(); + IdpCertProviderFactory idpCertProviderFactory = new IdpCertProviderFactoryImpl( + new IdpCertSimpleClientProvider(IdpCertSimpleClientConfig.builder().baseUri(typesafeConfig.getIDP_CLIENT_BASE_URI()).build(), + new SimpleIdpCertStorageProvider(), new IdpCertStorageConfig())); + AssertionClientProvider assertionClientProvider = + new AssertionSimpleClientProvider(AssertionSimpleClientConfig.builder().build()); + AssertionServiceFactory assertionServiceFactory = new AssertionServiceFactoryImpl( + assertionStorageProvider, assertionClientProvider, new StorageConfig()); + LollipopLoggerServiceFactory lollipopLoggerServiceFactory = new LollipopLogbackLoggerServiceFactory(); + return new LollipopConsumerFactoryHelper(lollipopLoggerServiceFactory, messageVerifierFactory, idpCertProviderFactory, assertionServiceFactory, + new LollipopConsumerRequestValidationServiceImpl(lollipopConsumerRequestConfig), lollipopConsumerRequestConfig); + } + + private static LollipopConsumerRequest buildLollipopRequest( + String contentDigest, + String encoding, + String payload, + String lollipopKey, + String signatureInput, + String signature) { + HashMap lollipopHeaderParams = new HashMap<>(); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getContentDigestHeader(), contentDigest); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getContentEncodingHeader(), encoding); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getSignatureInputHeader(), signatureInput); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getSignatureHeader(), signature); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getPublicKeyHeader(), lollipopKey); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getOriginalMethodHeader(), lollipopConsumerRequestConfig.getExpectedFirstLcOriginalMethod()); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getOriginalURLHeader(), lollipopConsumerRequestConfig.getExpectedFirstLcOriginalUrl()); + lollipopHeaderParams.put("X-io-sign-qtspclauses","anIoSignClauses"); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getAssertionRefHeader(), VALID_ASSERTION_REF); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getAssertionTypeHeader(), "SAML"); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getAuthJWTHeader(), VALID_JWT); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getUserIdHeader(), VALID_FISCAL_CODE); + + + return LollipopConsumerRequest.builder() + .requestBody(payload) + .headerParams(lollipopHeaderParams) + .build(); + } +} diff --git a/samples/simpleTypesafe/src/main/resources/application.properties b/samples/simpleTypesafe/src/main/resources/application.properties new file mode 100644 index 00000000..b6ae2542 --- /dev/null +++ b/samples/simpleTypesafe/src/main/resources/application.properties @@ -0,0 +1,10 @@ +lollipop.idp.client.mock.enabled=true +lollipop.assertion.client.mock.enabled=true + +lollipop.core.config.assertionNotBeforeDateFormat=yyyy-MM-dd'T'HH:mm:ss.SSS'Z' +lollipop.core.config.assertionInstantDateFormat=yyyy-MM-dd'T'HH:mm:ss.SSS'Z' + +lollipop.idp.rest.config.baseUri=http://localhost:3001 + + + From b8500249aa20362edb65668ea436d1bbfd2354d3 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 9 May 2023 12:40:52 +0200 Subject: [PATCH 389/403] [SLS-34] Defined utility class for typesafe configuration in core module --- core/build.gradle | 2 + .../utils/LollipopTypesafeConfig.java | 134 +++++++++++++++++- 2 files changed, 135 insertions(+), 1 deletion(-) diff --git a/core/build.gradle b/core/build.gradle index 915d7c5b..b3b7b0e3 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -50,6 +50,8 @@ dependencies { implementation 'javax.servlet:javax.servlet-api:3.0.1' + implementation 'com.typesafe:config:1.3.3' + // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.mockito:mockito-core:5.2.0' diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopTypesafeConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopTypesafeConfig.java index 2d63bda6..6a8869e1 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopTypesafeConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopTypesafeConfig.java @@ -1,2 +1,134 @@ -package it.pagopa.tech.lollipop.consumer.utils;public class LollipopTypesafeConfig { +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.utils; + +import com.typesafe.config.Config; +import lombok.Getter; + +@Getter +public class LollipopTypesafeConfig { + + boolean ASSERTION_CLIENT_MOCK_ENABLED; + boolean IDP_CLIENT_MOCK_ENABLED; + + // Sample controller endpoint + String SAMPLE_LOLLIPOP_CONSUMER_ENDPOINT; + + // General Lollipop Configs Sample + int LOLLIPOP_ASSERTION_EXPIRE_IN_DAYS; + String LOLLIPOP_EXPECTED_LC_ORIGINAL_URL; + String LOLLIPOP_EXPECTED_LC_ORIGINAL_METHOD; + String LOLLIPOP_ASSERTION_NOT_BEFORE_DATE_FORMAT; + String LOLLIPOP_ASSERTION_INSTANT_DATE_FORMAT; + + // Idp Client Configs + String IDP_CLIENT_CIEID; + String IDP_CLIENT_BASE_URI; + String IDP_CLIENT_CIE_ENDPOINT; + String IDP_CLIENT_SPID_ENDPOINT; + + // Idp Storage Configs + boolean IDP_STORAGE_ENABLED; + int IDP_STORAGE_EVICTION_DELAY; + + // Assertion Client Configs + String ASSERTION_REST_URI; + String ASSERTION_REST_ENDPOINT; + + // Assertion Storage Configs + boolean ASSERTION_STORAGE_ENABLED; + int ASSERTION_STORAGE_EVICTION_DELAY; + + public LollipopTypesafeConfig(Config config) { + this.ASSERTION_CLIENT_MOCK_ENABLED = + getConfigBoolean(config, "lollipop.assertion.client.mock.enabled", false); + this.IDP_CLIENT_MOCK_ENABLED = + getConfigBoolean(config, "lollipop.assertion.client.mock.enabled", false); + + this.SAMPLE_LOLLIPOP_CONSUMER_ENDPOINT = + getConfigString( + config, + "sample.lollipop.consumer.config.endpoint", + "/api/v1/lollipop-consumer"); + + this.LOLLIPOP_ASSERTION_EXPIRE_IN_DAYS = + getConfigInt(config, "lollipop.core.config.assertionExpireInDays", 180); + this.LOLLIPOP_EXPECTED_LC_ORIGINAL_URL = + getConfigString( + config, + "lollipop.-core.config.expectedFirstLcOriginalUrl", + "https://api-app.io.pagopa.it/first-lollipop/sign"); + this.LOLLIPOP_EXPECTED_LC_ORIGINAL_METHOD = + getConfigString( + config, "lollipop.core.config.expectedFirstLcOriginalMethod", "POST"); + this.LOLLIPOP_ASSERTION_NOT_BEFORE_DATE_FORMAT = + getConfigString( + config, + "lollipop.core.config.assertionNotBeforeDateFormat", + "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + this.LOLLIPOP_ASSERTION_INSTANT_DATE_FORMAT = + getConfigString( + config, + "lollipop.core.config.assertionInstantDateFormat", + "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + + this.IDP_CLIENT_CIEID = + getConfigString( + config, + "lollipop.idp.rest.config.cieEntityId", + "https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"); + this.IDP_CLIENT_BASE_URI = + getConfigString( + config, "lollipop.idp.rest.config.baseUri", "https://api.is.eng.pagopa.it"); + this.IDP_CLIENT_CIE_ENDPOINT = + getConfigString( + config, "lollipop.idp.rest.config.idpKeysCieEndpoint", "/idp-keys/cie"); + this.IDP_CLIENT_SPID_ENDPOINT = + getConfigString( + config, "lollipop.idp.rest.config.idpKeysSpidEndpoint", "/idp-keys/spid"); + + this.IDP_STORAGE_ENABLED = + getConfigBoolean( + config, "lollipop.idp.storage.config.idpCertDataStorageEnabled", true); + this.IDP_STORAGE_EVICTION_DELAY = + getConfigInt(config, "lollipop.idp.storage.config.storageEvictionDelay", 1); + + this.ASSERTION_REST_URI = + getConfigString( + config, "lollipop.assertion.rest.config.baseUri", "http://localhost:3000"); + this.ASSERTION_REST_ENDPOINT = + getConfigString( + config, + "lollipop.assertion.rest.config.assertionRequestEndpoint", + "/assertions"); + + this.ASSERTION_STORAGE_ENABLED = + getConfigBoolean( + config, "lollipop.assertion.rest.config.assertionStorageEnabled", true); + this.ASSERTION_STORAGE_EVICTION_DELAY = + getConfigInt(config, "lollipop.assertion.rest.config.storageEvictionDelay", 1); + } + + private String getConfigString(Config config, String path, String defaultString) { + if (config.hasPath(path)) { + return config.getString(path); + } else { + return defaultString; + } + } + + private boolean getConfigBoolean(Config config, String path, boolean defaultBoolean) { + if (config.hasPath(path)) { + return config.getBoolean(path); + } else { + return defaultBoolean; + } + } + + private int getConfigInt(Config config, String path, int defaultInt) { + if (config.hasPath(path)) { + return config.getInt(path); + } else { + return defaultInt; + } + } } From 610ff4ebb3dcdd381ce753657d6af73ed50c6d16 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 9 May 2023 12:51:13 +0200 Subject: [PATCH 390/403] [SLS-34] Added typesafe sample reference to general README --- README.md | Bin 92418 -> 93100 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index be19c4f29fb62c3312878fb9d94bcfb1a1e2f0f0..787bba0671e119b7996f645e82b7747160cde22b 100644 GIT binary patch delta 285 zcmZp=#Jc7>>xMXmNr8Nu6Q;2-ZcgA8V4UnA#4))+DQvO=2iN8g98ye^Kd8h3RZI?2 z-8A{yQ@-gv7K~h*rPO>tD!C^AQsI+UU?^wEWGG?CU{GKPVW?y%U`S;sW=Ld6V@RF6 zP+feooGO Date: Tue, 9 May 2023 12:54:15 +0200 Subject: [PATCH 391/403] [redis extra] Updated RedisAssertionStorage, SamlAssertion, SimpleRedisStorage --- .../consumer/model/SamlAssertion.java | 2 + .../assertion/RedisAssertionStorage.java | 94 +++++++ .../RedisAssertionStorageProvider.java | 34 +++ .../redis/storage/SimpleRedisStorage.java | 14 +- .../RedisAssertionStorageIntegrationTest.java | 246 ++++++++++++++++++ 5 files changed, 382 insertions(+), 8 deletions(-) create mode 100644 redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorage.java create mode 100644 redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorageProvider.java create mode 100644 redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorageIntegrationTest.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java index 5016617e..a8f5894d 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/SamlAssertion.java @@ -1,6 +1,7 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.model; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import lombok.ToString; @@ -8,6 +9,7 @@ @Getter @Setter @ToString +@EqualsAndHashCode public class SamlAssertion { private String assertionRef; diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorage.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorage.java new file mode 100644 index 00000000..5edf0d7b --- /dev/null +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorage.java @@ -0,0 +1,94 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.storage.redis.assertion; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorage; +import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; +import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorage; +import lombok.SneakyThrows; +import org.openapitools.jackson.nullable.JsonNullableModule; + +import java.util.concurrent.TimeUnit; + +/** + * Implementation of the {@link AssertionStorage} interface as a redis storage. + * + *

The storage can be configured via the {@link StorageConfig} configuration class. + */ +public class RedisAssertionStorage implements AssertionStorage { + + private final RedisStorage redisStorage; + private final StorageConfig storageConfig; + + private final ObjectMapper objectMapper; + + public RedisAssertionStorage( + RedisStorage redisStorage, StorageConfig storageConfig) { + this.redisStorage = redisStorage; + this.storageConfig = storageConfig; + this.objectMapper = new ObjectMapper(); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.registerModule(new JsonNullableModule()); + } + + /** + * Retrieve the SAML Assertion associated with the provided assertionRef if the storage is enabled {@link + * IdpCertStorageConfig}, otherwise no operation is performed. + * + * @param ref the assertion reference to be used as key + * @return the SAML Assertion if found, null if no data is present in the storage or + * the storage is disabled + */ + @SneakyThrows + @Override + public SamlAssertion getAssertion(String ref) { + if (!storageConfig.isAssertionStorageEnabled()) { + return null; + } + + String objString = redisStorage.get(ref); + + return objString == null ? null : objectMapper.readValue(objString, SamlAssertion.class); + } + + /** + * Store the SAML Assertion if the storage is enabled {@link StorageConfig}, otherwise no + * operation is performed. + * + *

Once the SAML Assertion is stored an eviction operation is scheduled with a delay configured + * via {@link AssertionStorage} + * + * @param assertionRef the assertion Ref + * @param samlAssertion SAML Assertion instance + */ + @SneakyThrows + @Override + public void saveAssertion(String assertionRef, SamlAssertion samlAssertion) { + if (!storageConfig.isAssertionStorageEnabled()) { + return; + } + + redisStorage.save( + assertionRef, + objectMapper.writeValueAsString(samlAssertion), + TimeUnit.SECONDS.convert( + storageConfig.getStorageEvictionDelay(), + storageConfig.getStorageEvictionDelayTimeUnit())); + } + +} diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorageProvider.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorageProvider.java new file mode 100644 index 00000000..09f713fb --- /dev/null +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorageProvider.java @@ -0,0 +1,34 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.storage.redis.assertion; + +import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorage; +import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorageProvider; +import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageProvider; +import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorageProvisioner; +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * Implementation of {@link AssertionStorageProvider} interface. It provides an instance of {@link + * RedisAssertionStorage} + */ +@Data +@AllArgsConstructor +public class RedisAssertionStorageProvider implements AssertionStorageProvider { + + private RedisStorageProvisioner redisStorageProvisioner; + + /** + * {@inheritDoc} + * + * @param storageConfig the storage configuration + * @return an instance of {@link RedisAssertionStorage} + */ + @Override + public AssertionStorage provideStorage(StorageConfig storageConfig) { + return new RedisAssertionStorage(redisStorageProvisioner.getStorage(), storageConfig); + } +} diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java index b41cf384..eeb33d2d 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java @@ -83,10 +83,9 @@ public void save(String key, String value, Long delayTime) throws Exception { RedisClient redisClient = (RedisClient) getRedisClient(); if (!withConnectionPool) { - try (StatefulRedisConnection statefulConnection = - redisClient.connect()) { - executeSetMethod(key, value, delayTime, statefulConnection); - } + StatefulRedisConnection statefulConnection = + redisClient.connect(); + executeSetMethod(key, value, delayTime, statefulConnection); } else { GenericObjectPool> pool = ConnectionPoolSupport.createGenericObjectPool( @@ -123,10 +122,9 @@ public void delete(String key) throws Exception { RedisClient redisClient = (RedisClient) getRedisClient(); if (!withConnectionPool) { - try (StatefulRedisConnection statefulConnection = - redisClient.connect()) { - executeAsyncDel(key, statefulConnection); - } + StatefulRedisConnection statefulConnection = + redisClient.connect(); + executeAsyncDel(key, statefulConnection); } else { GenericObjectPool> pool = ConnectionPoolSupport.createGenericObjectPool( diff --git a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorageIntegrationTest.java b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorageIntegrationTest.java new file mode 100644 index 00000000..9a7e70ef --- /dev/null +++ b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorageIntegrationTest.java @@ -0,0 +1,246 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.storage.redis.assertion; + +import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorage; +import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; +import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorageProvisioner; +import it.pagopa.tech.lollipop.consumer.storage.redis.builder.DefaultRedisClientBuilder; +import it.pagopa.tech.lollipop.consumer.storage.redis.config.RedisStorageConfig; +import it.pagopa.tech.lollipop.consumer.storage.redis.idp.RedisIdpCertStorageProvider; +import lombok.SneakyThrows; +import org.junit.jupiter.api.*; +import redis.embedded.RedisSentinel; +import redis.embedded.RedisServer; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.concurrent.TimeUnit; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class RedisAssertionStorageIntegrationTest { + + private static final String VALID_ASSERTION_XML = + "{\"response_xml\": \"\\n" + + " https:\\/\\/spid-testenv2:8088<\\/saml:Issuer><\\/ds:Transforms>s\\/DqYePHC7eCXX5ncsiFYNLyKbzS6P5C8331H1b8e30=<\\/ds:DigestValue><\\/ds:Reference><\\/ds:SignedInfo>WcasorooElvhmK0kxFUdBVCqyRYi0SCNGRSZZnC9Q2sZHOYGZbERe4\\/T8OSuRKbSrEivXIHRgNr8WskZTM2CiywfWChHfGvhERsLuPJE8oh9CR3eicX\\/eg0ynJqwx4IoYhTb2NOwqMFc66nnutMhG\\/Smdtjs4SFz0RQYYVeZ5Ho51iTHd94uBV9ZHXjqcvs3EitUsJ0Zg1Pkw352tt8y7niUcGjAd8nydI72S12sF5ePv05AunFp7vZpYbKqi62fQLORCn1ZP7WKFD75hL0bCvZaSRF285GkfSnLfe1S4tLff2SlTQWevOMU\\/wCkHJmQwHT1LMwcWRnMvv4V+vd1XQ==<\\/ds:SignatureValue>MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR\\/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2\\/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI\\/sp\\n" + + "ILywgDxVMMtv\\/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAf\\n" + + "BgNVHSMEGDAWgBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH\\/MA0G\\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8\\/o13vMw4feGxro1hMeUilRtH52funrW\\n" + + "C+FgPrqk3o\\/8cZOnq+CqnFFDfILLiEb\\/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\n" + + "Da1fG\\/Pi0fG2F0yw\\/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk\\/ZbEHdKcofnziDyl0V8gglP2\\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n" + + "<\\/ds:X509Certificate><\\/ds:X509Data><\\/ds:KeyInfo><\\/ds:Signature>\\n" + + " \\n" + + " \\n" + + " <\\/samlp:Status>\\n" + + " \\n" + + " https:\\/\\/spid-testenv2:8088<\\/saml:Issuer><\\/ds:Transforms>4cqgG29TSKgNLy2\\/1eFPXhd5WRVPxZBGcd8DgTvd5Fo=<\\/ds:DigestValue><\\/ds:Reference><\\/ds:SignedInfo>WqxM+y+vtZDcEaIaw2WfcuMuwXUeTOY9ZjaXwzHw+RE8uUr5s8BE1tpaodcKmmqSJK1JQYNr8AUV+W9V79EKfmNtFvfaf0WYeUee7Td7E24QqiyVHjr1YgfDWhSdItFLYJfQUkotj2BepbdwVQGY5yN0Rw6Fq98hgNOgsxty7g6oqxG1OXB4WJ2He20iOoYWQl8ApxlbU\\/\\/hwnefFYe9ghDPy3rDbcNl3JetT07NR\\/+AzhKH4e+JCwKjTkdCBTW30fK4eiV9yBk74Lobip4hMaQhMaByl8egaU3A8AsnsZQuov2B6Wo2sDiQPjIulb8K3DOwFyL8PzEk8BB5YoAfwg==<\\/ds:SignatureValue>MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR\\/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2\\/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI\\/sp\\n" + + "ILywgDxVMMtv\\/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAf\\n" + + "BgNVHSMEGDAWgBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH\\/MA0G\\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8\\/o13vMw4feGxro1hMeUilRtH52funrW\\n" + + "C+FgPrqk3o\\/8cZOnq+CqnFFDfILLiEb\\/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\n" + + "Da1fG\\/Pi0fG2F0yw\\/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk\\/ZbEHdKcofnziDyl0V8gglP2\\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n" + + "<\\/ds:X509Certificate><\\/ds:X509Data><\\/ds:KeyInfo><\\/ds:Signature>\\n" + + " \\n" + + " id_48129c2a9d5e9077422591baf495747cfda668c5<\\/saml:NameID>\\n" + + " \\n" + + " \\n" + + " <\\/saml:SubjectConfirmation>\\n" + + " <\\/saml:Subject>\\n" + + " \\n" + + " \\n" + + " https:\\/\\/spid.agid.gov.it\\/cd<\\/saml:Audience>\\n" + + " <\\/saml:AudienceRestriction>\\n" + + " <\\/saml:Conditions>\\n" + + " \\n" + + " \\n" + + " " + + " https:\\/\\/www.spid.gov.it\\/SpidL2<\\/saml:AuthnContextClassRef>\\n" + + " <\\/saml:AuthnContext>\\n" + + " <\\/saml:AuthnStatement>\\n" + + " \\n" + + " \\n" + + " info@agid.gov.it<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " Mario<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " Bianchi<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " GDNNWA12H81Y874F<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " 1991-12-12<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " <\\/saml:AttributeStatement>\\n" + + " <\\/saml:Assertion>\\n" + + "<\\/samlp:Response>\"}"; + private RedisServer redisServer; + + private RedisSentinel redisSentinel; + private AssertionStorage redisStorage; + + private StorageConfig storageConfig; + + @BeforeAll + public void setUp() throws IOException { + storageConfig = new StorageConfig(); + storageConfig.setStorageEvictionDelay(1); + storageConfig.setStorageEvictionDelayTimeUnit(TimeUnit.SECONDS); + redisServer = RedisServer.newRedisServer().build(); + redisSentinel = RedisSentinel.newRedisSentinel().build(); + redisServer.start(); + redisSentinel.start(); + redisStorage = + new RedisAssertionStorageProvider( + new RedisStorageProvisioner( + new DefaultRedisClientBuilder( + RedisStorageConfig.builder() + .mainNode( + RedisStorageConfig.RedisNode + .builder() + .port(6379) + .build()) + .build()))) + .provideStorage(storageConfig); + } + + @SneakyThrows + @Test + public void successfulOperationsOnRedisStorage() { + SamlAssertion samlAssertion = new SamlAssertion(); + samlAssertion.setAssertionRef("test-key"); + samlAssertion.setAssertionData(VALID_ASSERTION_XML); + redisStorage.saveAssertion("test-key", samlAssertion); + Thread.sleep(150); + SamlAssertion result = redisStorage.getAssertion("test-key"); + Assertions.assertEquals(samlAssertion, result); + } + + @SneakyThrows + @Test + public void successfulOperationsOnRedisStorageWithConnectionPooling() { + redisStorage = + new RedisAssertionStorageProvider( + new RedisStorageProvisioner( + new DefaultRedisClientBuilder( + RedisStorageConfig.builder() + .withConnectionPooling(true) + .mainNode( + RedisStorageConfig.RedisNode + .builder() + .port(6379) + .build()) + .build()))) + .provideStorage(storageConfig); + SamlAssertion samlAssertion = new SamlAssertion(); + samlAssertion.setAssertionRef("test-key"); + samlAssertion.setAssertionData(VALID_ASSERTION_XML); + redisStorage.saveAssertion("test-key", samlAssertion); + Thread.sleep(150); + SamlAssertion result = redisStorage.getAssertion("test-key"); + Assertions.assertEquals(samlAssertion, result); + } + + @SneakyThrows + @Test + public void successfulOperationsOnRedisStorageWithSentinelConnectionPooling() { + redisStorage = + new RedisAssertionStorageProvider( + new RedisStorageProvisioner( + new DefaultRedisClientBuilder( + RedisStorageConfig.builder() + .withSentinel(true) + .withConnectionPooling(true) + .masterIds( + Collections.singletonList( + "mymaster")) + .mainNode( + RedisStorageConfig.RedisNode + .builder() + .port(26379) + .build()) + .build()))) + .provideStorage(storageConfig); + SamlAssertion samlAssertion = new SamlAssertion(); + samlAssertion.setAssertionRef("test-key"); + samlAssertion.setAssertionData(VALID_ASSERTION_XML); + redisStorage.saveAssertion("test-key", samlAssertion); + Thread.sleep(150); + SamlAssertion result = redisStorage.getAssertion("test-key"); + Assertions.assertEquals(samlAssertion, result); + } + + @AfterAll + public void tearDown() throws IOException { + redisServer.stop(); + redisSentinel.stop(); + } +} From 44631175c89aca7343f2351d32219ff3e1b134b7 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Tue, 9 May 2023 13:06:48 +0200 Subject: [PATCH 392/403] [redis extra] Introducing RedisAssertionStorage, updated SamlAssertion and SimpleRedisStorage --- redis-storage/README.md | 12 ++++++---- .../assertion/RedisAssertionStorage.java | 23 ++++++++----------- .../RedisAssertionStorageProvider.java | 3 --- .../redis/storage/SimpleRedisStorage.java | 6 ++--- .../RedisAssertionStorageIntegrationTest.java | 12 +++------- 5 files changed, 21 insertions(+), 35 deletions(-) diff --git a/redis-storage/README.md b/redis-storage/README.md index a2fff041..f89a265c 100644 --- a/redis-storage/README.md +++ b/redis-storage/README.md @@ -24,11 +24,11 @@ configuration class, to be used in order to statup a Redis Client within the mod | masterIds | - | Lost of masterIds to be used if in sentinel mode | -## Example for the Idp interface +## Examples ### Simple -The following snippet provides a basic sample in order to use the implementation of the IdP certificates storage interface +The following snippet provides a basic sample in order to use the implementation of the storage interfaces ``` RedisStorageConfig redisConfig = RedisStorageConfig.builder().mainNode( @@ -38,8 +38,10 @@ RedisStorageConfig redisConfig = RedisStorageConfig.builder().mainNode( .port(6379) .build()); DefaultClientBuilder builder = new DefaultRedisClientBuilder(redisConfig); -RedisStorageProvisioner redisStoreProvisioner = new RedisStorageProvisioner(builder.build()); -redisStorage = new RedisIdpCertStorageProvider(redisStoreProvisioner).provideStorage(idpCertStorageConfig); +RedisStorageProvisioner redisStoreProvisioner = new RedisStorageProvisioner(builder.build()); +idpRedisStorage = new RedisIdpCertStorageProvider(redisStoreProvisioner).provideStorage(idpCertStorageConfig); +assertionRedisStorage = new RedisAssertionStorageProvider(redisStoreProvisioner).provideStorage(assertionStorageConfig); + ``` In order to execute with connection pooling active, provide a redisConfig as for the following example: @@ -96,6 +98,6 @@ RedisStorageConfig redisConfig = RedisStorageConfig.builder() .builder() .hostname("redisnode2") .port(6379) - .build() + .build() )); ``` \ No newline at end of file diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorage.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorage.java index 5edf0d7b..9a37d1d4 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorage.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorage.java @@ -8,16 +8,13 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorage; import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; -import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; -import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorage; +import java.util.concurrent.TimeUnit; import lombok.SneakyThrows; import org.openapitools.jackson.nullable.JsonNullableModule; -import java.util.concurrent.TimeUnit; - /** * Implementation of the {@link AssertionStorage} interface as a redis storage. * @@ -30,8 +27,7 @@ public class RedisAssertionStorage implements AssertionStorage { private final ObjectMapper objectMapper; - public RedisAssertionStorage( - RedisStorage redisStorage, StorageConfig storageConfig) { + public RedisAssertionStorage(RedisStorage redisStorage, StorageConfig storageConfig) { this.redisStorage = redisStorage; this.storageConfig = storageConfig; this.objectMapper = new ObjectMapper(); @@ -47,12 +43,12 @@ public RedisAssertionStorage( } /** - * Retrieve the SAML Assertion associated with the provided assertionRef if the storage is enabled {@link - * IdpCertStorageConfig}, otherwise no operation is performed. + * Retrieve the SAML Assertion associated with the provided assertionRef if the storage is + * enabled {@link IdpCertStorageConfig}, otherwise no operation is performed. * * @param ref the assertion reference to be used as key - * @return the SAML Assertion if found, null if no data is present in the storage or - * the storage is disabled + * @return the SAML Assertion if found, null if no data is present in the storage or the storage + * is disabled */ @SneakyThrows @Override @@ -67,11 +63,11 @@ public SamlAssertion getAssertion(String ref) { } /** - * Store the SAML Assertion if the storage is enabled {@link StorageConfig}, otherwise no + * Store the SAML Assertion if the storage is enabled {@link StorageConfig}, otherwise no * operation is performed. * - *

Once the SAML Assertion is stored an eviction operation is scheduled with a delay configured - * via {@link AssertionStorage} + *

Once the SAML Assertion is stored an eviction operation is scheduled with a delay + * configured via {@link AssertionStorage} * * @param assertionRef the assertion Ref * @param samlAssertion SAML Assertion instance @@ -90,5 +86,4 @@ public void saveAssertion(String assertionRef, SamlAssertion samlAssertion) { storageConfig.getStorageEvictionDelay(), storageConfig.getStorageEvictionDelayTimeUnit())); } - } diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorageProvider.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorageProvider.java index 09f713fb..1fa6a040 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorageProvider.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorageProvider.java @@ -4,9 +4,6 @@ import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorage; import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorageProvider; import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; -import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; -import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; -import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageProvider; import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorageProvisioner; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java index eeb33d2d..545a619a 100644 --- a/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java +++ b/redis-storage/src/main/java/it/pagopa/tech/lollipop/consumer/storage/redis/storage/SimpleRedisStorage.java @@ -83,8 +83,7 @@ public void save(String key, String value, Long delayTime) throws Exception { RedisClient redisClient = (RedisClient) getRedisClient(); if (!withConnectionPool) { - StatefulRedisConnection statefulConnection = - redisClient.connect(); + StatefulRedisConnection statefulConnection = redisClient.connect(); executeSetMethod(key, value, delayTime, statefulConnection); } else { GenericObjectPool> pool = @@ -122,8 +121,7 @@ public void delete(String key) throws Exception { RedisClient redisClient = (RedisClient) getRedisClient(); if (!withConnectionPool) { - StatefulRedisConnection statefulConnection = - redisClient.connect(); + StatefulRedisConnection statefulConnection = redisClient.connect(); executeAsyncDel(key, statefulConnection); } else { GenericObjectPool> pool = diff --git a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorageIntegrationTest.java b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorageIntegrationTest.java index 9a7e70ef..7a04b181 100644 --- a/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorageIntegrationTest.java +++ b/redis-storage/src/test/java/it/pagopa/tech/lollipop/consumer/storage/redis/assertion/RedisAssertionStorageIntegrationTest.java @@ -3,24 +3,18 @@ import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorage; import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; -import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; -import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; -import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import it.pagopa.tech.lollipop.consumer.model.SamlAssertion; import it.pagopa.tech.lollipop.consumer.storage.redis.RedisStorageProvisioner; import it.pagopa.tech.lollipop.consumer.storage.redis.builder.DefaultRedisClientBuilder; import it.pagopa.tech.lollipop.consumer.storage.redis.config.RedisStorageConfig; -import it.pagopa.tech.lollipop.consumer.storage.redis.idp.RedisIdpCertStorageProvider; +import java.io.IOException; +import java.util.Collections; +import java.util.concurrent.TimeUnit; import lombok.SneakyThrows; import org.junit.jupiter.api.*; import redis.embedded.RedisSentinel; import redis.embedded.RedisServer; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.concurrent.TimeUnit; - @TestInstance(TestInstance.Lifecycle.PER_CLASS) class RedisAssertionStorageIntegrationTest { From 80a7e20079790c2ad54e019204ea49056c397b84 Mon Sep 17 00:00:00 2001 From: giomella Date: Tue, 9 May 2023 16:01:02 +0200 Subject: [PATCH 393/403] [SLS-28] added sample that uses servlet-impl module. fix log level in HttpVerifierServletFilter. --- samples/servlet/build.gradle | 59 +++++++ samples/servlet/settings.gradle | 9 ++ .../sample/LollipopConsumerServletSample.java | 100 ++++++++++++ .../mock/AssertionMockServerConfig.java | 146 ++++++++++++++++++ .../sample/mock/IdpMockServerConfig.java | 131 ++++++++++++++++ .../comsumer/sample/servlet/DemoServlet.java | 19 +++ .../servlet/HttpVerifierServletFilter.java | 4 +- 7 files changed, 466 insertions(+), 2 deletions(-) create mode 100644 samples/servlet/build.gradle create mode 100644 samples/servlet/settings.gradle create mode 100644 samples/servlet/src/main/java/it/pagopa/tech/lollipop/comsumer/sample/LollipopConsumerServletSample.java create mode 100644 samples/servlet/src/main/java/it/pagopa/tech/lollipop/comsumer/sample/mock/AssertionMockServerConfig.java create mode 100644 samples/servlet/src/main/java/it/pagopa/tech/lollipop/comsumer/sample/mock/IdpMockServerConfig.java create mode 100644 samples/servlet/src/main/java/it/pagopa/tech/lollipop/comsumer/sample/servlet/DemoServlet.java diff --git a/samples/servlet/build.gradle b/samples/servlet/build.gradle new file mode 100644 index 00000000..dc35cfdb --- /dev/null +++ b/samples/servlet/build.gradle @@ -0,0 +1,59 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Java library project to get you started. + * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle + * User Manual available at https://docs.gradle.org/8.0.2/userguide/building_java_projects.html + */ + +plugins { + // Apply the java-library plugin for API and implementation separation. + id 'application' +} + + +group = 'it.pagopa.tech.lollipop.consumer.samples' +version = '1.0.0-RC1' +sourceCompatibility = '11' + +application { + mainClassName = "it.pagopa.tech.lollipop.consumer.sample.LollipopConsumerServletSample" +} + +repositories { + mavenLocal() + mavenCentral() + maven { + url = uri("https://maven.pkg.github.com/pagopa/eng-http-signatures") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + } + } + maven { + name = "GitHubPackages" + url = "https://maven.pkg.github.com/pagopa/eng-lollipop-consumer-java-sdk" + credentials { + username = System.getenv("GITHUB_ACTOR") + password = System.getenv("GITHUB_TOKEN") + } + } +} + +dependencies { + implementation 'org.apache.tomcat.embed:tomcat-embed-core:9.0.74' + + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:core:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:assertion-rest-client-native:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:identity-service-rest-client-native:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:http-verifier:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:servlet-impl:1.0.0-RC1' + // Use JUnit Jupiter for testing. + implementation 'org.mock-server:mockserver-netty:5.15.0' + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' +} + +tasks.named('test') { + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} diff --git a/samples/servlet/settings.gradle b/samples/servlet/settings.gradle new file mode 100644 index 00000000..9f32e8b7 --- /dev/null +++ b/samples/servlet/settings.gradle @@ -0,0 +1,9 @@ +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } +} + + +rootProject.name = 'servlet-lollipop-sample' \ No newline at end of file diff --git a/samples/servlet/src/main/java/it/pagopa/tech/lollipop/comsumer/sample/LollipopConsumerServletSample.java b/samples/servlet/src/main/java/it/pagopa/tech/lollipop/comsumer/sample/LollipopConsumerServletSample.java new file mode 100644 index 00000000..6a06041c --- /dev/null +++ b/samples/servlet/src/main/java/it/pagopa/tech/lollipop/comsumer/sample/LollipopConsumerServletSample.java @@ -0,0 +1,100 @@ +package it.pagopa.tech.lollipop.comsumer.sample; + +import it.pagopa.tech.lollipop.comsumer.sample.mock.AssertionMockServerConfig; +import it.pagopa.tech.lollipop.comsumer.sample.mock.IdpMockServerConfig; +import it.pagopa.tech.lollipop.comsumer.sample.servlet.DemoServlet; +import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; +import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClientProvider; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientConfig; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.assertion.impl.AssertionServiceFactoryImpl; +import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorageProvider; +import it.pagopa.tech.lollipop.consumer.assertion.storage.SimpleAssertionStorageProvider; +import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; +import it.pagopa.tech.lollipop.consumer.command.impl.LollipopConsumerCommandBuilderImpl; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.exception.LollipopVerifierException; +import it.pagopa.tech.lollipop.consumer.helper.LollipopConsumerFactoryHelper; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.http_verifier.visma.VismaHttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.storage.SimpleIdpCertStorageProvider; +import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImpl; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerServiceFactory; +import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerServiceFactory; +import it.pagopa.tech.lollipop.consumer.service.impl.LollipopConsumerRequestValidationServiceImpl; +import it.pagopa.tech.lollipop.consumer.servlet.HttpVerifierServletFilter; +import org.apache.catalina.Context; +import org.apache.catalina.startup.Tomcat; +import org.apache.tomcat.util.descriptor.web.FilterDef; +import org.apache.tomcat.util.descriptor.web.FilterMap; +import org.mockserver.integration.ClientAndServer; + +import java.io.File; + +public class LollipopConsumerServletSample { + + private static final String LOLLIPOP_CONSUMER_PATH = "/api/v1/lollipop-consumer"; + private static final String SERVLET_NAME = "DemoServlet"; + + public static void main(String[] args) throws Exception { + + Tomcat tomcat = new Tomcat(); + tomcat.setPort(8080); + tomcat.getConnector(); + String contextPath = ""; + String docBase = new File(".").getAbsolutePath(); + + Context context = tomcat.addContext(contextPath, docBase); + + FilterDef filterDef = buildFilterDef(); + context.addFilterDef(filterDef); + context.addFilterMap(buildFilterMap(filterDef)); + + Tomcat.addServlet(context, SERVLET_NAME, new DemoServlet()); + context.addServletMappingDecoded(LOLLIPOP_CONSUMER_PATH, SERVLET_NAME); + + tomcat.start(); + ClientAndServer.startClientAndServer(3001, 3000); + AssertionMockServerConfig.startAssertionMockServer(); + IdpMockServerConfig.startIdpMockServer(); + tomcat.getServer().await(); + } + + private static FilterMap buildFilterMap(FilterDef filterDef) { + FilterMap filterMap = new FilterMap(); + filterMap.setFilterName(filterDef.getFilterName()); + filterMap.addURLPattern(LOLLIPOP_CONSUMER_PATH); + return filterMap; + } + + private static FilterDef buildFilterDef() throws LollipopVerifierException { + FilterDef filterDef = new FilterDef(); + filterDef.setFilter(new HttpVerifierServletFilter(new LollipopConsumerCommandBuilderImpl(buildLollipopConsumerFactoryHelper()))); + filterDef.setFilterName("HttpVerifierServletFilter"); + return filterDef; + } + + private static LollipopConsumerFactoryHelper buildLollipopConsumerFactoryHelper() throws LollipopVerifierException { + LollipopConsumerRequestConfig lollipopConsumerRequestConfig = LollipopConsumerRequestConfig.builder() + .assertionNotBeforeDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") + .assertionInstantDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") + .build(); + HttpMessageVerifierFactory messageVerifierFactory = new VismaHttpMessageVerifierFactory("UTF-8", + LollipopConsumerRequestConfig.builder().build()); + AssertionStorageProvider assertionStorageProvider = new SimpleAssertionStorageProvider(); + IdpCertProviderFactory idpCertProviderFactory = new IdpCertProviderFactoryImpl( + new IdpCertSimpleClientProvider(IdpCertSimpleClientConfig.builder().baseUri("http://localhost:3001").build(), + new SimpleIdpCertStorageProvider(), new IdpCertStorageConfig())); + AssertionClientProvider assertionClientProvider = + new AssertionSimpleClientProvider(AssertionSimpleClientConfig.builder().build()); + AssertionServiceFactory assertionServiceFactory = new AssertionServiceFactoryImpl( + assertionStorageProvider, assertionClientProvider, new StorageConfig()); + LollipopLoggerServiceFactory lollipopLoggerServiceFactory = new LollipopLogbackLoggerServiceFactory(); + return new LollipopConsumerFactoryHelper(lollipopLoggerServiceFactory, messageVerifierFactory, idpCertProviderFactory, assertionServiceFactory, + new LollipopConsumerRequestValidationServiceImpl(lollipopConsumerRequestConfig), lollipopConsumerRequestConfig); + } +} diff --git a/samples/servlet/src/main/java/it/pagopa/tech/lollipop/comsumer/sample/mock/AssertionMockServerConfig.java b/samples/servlet/src/main/java/it/pagopa/tech/lollipop/comsumer/sample/mock/AssertionMockServerConfig.java new file mode 100644 index 00000000..9aa3590f --- /dev/null +++ b/samples/servlet/src/main/java/it/pagopa/tech/lollipop/comsumer/sample/mock/AssertionMockServerConfig.java @@ -0,0 +1,146 @@ +package it.pagopa.tech.lollipop.comsumer.sample.mock; + +import org.mockserver.client.MockServerClient; +import org.mockserver.model.Header; + +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +public class AssertionMockServerConfig { + + private static final String VALID_ASSERTION_XML = + "{\"response_xml\": \"\\n" + + " https:\\/\\/spid-testenv2:8088<\\/saml:Issuer><\\/ds:Transforms>s\\/DqYePHC7eCXX5ncsiFYNLyKbzS6P5C8331H1b8e30=<\\/ds:DigestValue><\\/ds:Reference><\\/ds:SignedInfo>WcasorooElvhmK0kxFUdBVCqyRYi0SCNGRSZZnC9Q2sZHOYGZbERe4\\/T8OSuRKbSrEivXIHRgNr8WskZTM2CiywfWChHfGvhERsLuPJE8oh9CR3eicX\\/eg0ynJqwx4IoYhTb2NOwqMFc66nnutMhG\\/Smdtjs4SFz0RQYYVeZ5Ho51iTHd94uBV9ZHXjqcvs3EitUsJ0Zg1Pkw352tt8y7niUcGjAd8nydI72S12sF5ePv05AunFp7vZpYbKqi62fQLORCn1ZP7WKFD75hL0bCvZaSRF285GkfSnLfe1S4tLff2SlTQWevOMU\\/wCkHJmQwHT1LMwcWRnMvv4V+vd1XQ==<\\/ds:SignatureValue>MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR\\/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2\\/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI\\/sp\\n" + + "ILywgDxVMMtv\\/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAf\\n" + + "BgNVHSMEGDAWgBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH\\/MA0G\\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8\\/o13vMw4feGxro1hMeUilRtH52funrW\\n" + + "C+FgPrqk3o\\/8cZOnq+CqnFFDfILLiEb\\/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\n" + + "Da1fG\\/Pi0fG2F0yw\\/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk\\/ZbEHdKcofnziDyl0V8gglP2\\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n" + + "<\\/ds:X509Certificate><\\/ds:X509Data><\\/ds:KeyInfo><\\/ds:Signature>\\n" + + " \\n" + + " \\n" + + " <\\/samlp:Status>\\n" + + " \\n" + + " https:\\/\\/spid-testenv2:8088<\\/saml:Issuer><\\/ds:Transforms>4cqgG29TSKgNLy2\\/1eFPXhd5WRVPxZBGcd8DgTvd5Fo=<\\/ds:DigestValue><\\/ds:Reference><\\/ds:SignedInfo>WqxM+y+vtZDcEaIaw2WfcuMuwXUeTOY9ZjaXwzHw+RE8uUr5s8BE1tpaodcKmmqSJK1JQYNr8AUV+W9V79EKfmNtFvfaf0WYeUee7Td7E24QqiyVHjr1YgfDWhSdItFLYJfQUkotj2BepbdwVQGY5yN0Rw6Fq98hgNOgsxty7g6oqxG1OXB4WJ2He20iOoYWQl8ApxlbU\\/\\/hwnefFYe9ghDPy3rDbcNl3JetT07NR\\/+AzhKH4e+JCwKjTkdCBTW30fK4eiV9yBk74Lobip4hMaQhMaByl8egaU3A8AsnsZQuov2B6Wo2sDiQPjIulb8K3DOwFyL8PzEk8BB5YoAfwg==<\\/ds:SignatureValue>MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR\\/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2\\/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI\\/sp\\n" + + "ILywgDxVMMtv\\/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAf\\n" + + "BgNVHSMEGDAWgBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH\\/MA0G\\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8\\/o13vMw4feGxro1hMeUilRtH52funrW\\n" + + "C+FgPrqk3o\\/8cZOnq+CqnFFDfILLiEb\\/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\n" + + "Da1fG\\/Pi0fG2F0yw\\/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk\\/ZbEHdKcofnziDyl0V8gglP2\\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n" + + "<\\/ds:X509Certificate><\\/ds:X509Data><\\/ds:KeyInfo><\\/ds:Signature>\\n" + + " \\n" + + " id_48129c2a9d5e9077422591baf495747cfda668c5<\\/saml:NameID>\\n" + + " \\n" + + " \\n" + + " <\\/saml:SubjectConfirmation>\\n" + + " <\\/saml:Subject>\\n" + + " \\n" + + " \\n" + + " https:\\/\\/spid.agid.gov.it\\/cd<\\/saml:Audience>\\n" + + " <\\/saml:AudienceRestriction>\\n" + + " <\\/saml:Conditions>\\n" + + " \\n" + + " \\n" + + " " + + " https:\\/\\/www.spid.gov.it\\/SpidL2<\\/saml:AuthnContextClassRef>\\n" + + " <\\/saml:AuthnContext>\\n" + + " <\\/saml:AuthnStatement>\\n" + + " \\n" + + " \\n" + + " info@agid.gov.it<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " Mario<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " Bianchi<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " GDNNWA12H81Y874F<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " 1991-12-12<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " <\\/saml:AttributeStatement>\\n" + + " <\\/saml:Assertion>\\n" + + "<\\/samlp:Response>\"}"; + private static final String ASSERTION_REF = "sha256-chG21HBOK-wJp2hHuYPrx7tAII2UGWVF-IFo0crUOtw"; + private static final String JWT = "aValidJWT"; + + public static MockServerClient startAssertionMockServer() { + MockServerClient mockServerClient = new MockServerClient("localhost", 3000); + mockServerClient + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", JWT))) + .respond(response().withStatusCode(200).withBody(VALID_ASSERTION_XML)); + return mockServerClient; + } +} diff --git a/samples/servlet/src/main/java/it/pagopa/tech/lollipop/comsumer/sample/mock/IdpMockServerConfig.java b/samples/servlet/src/main/java/it/pagopa/tech/lollipop/comsumer/sample/mock/IdpMockServerConfig.java new file mode 100644 index 00000000..285706db --- /dev/null +++ b/samples/servlet/src/main/java/it/pagopa/tech/lollipop/comsumer/sample/mock/IdpMockServerConfig.java @@ -0,0 +1,131 @@ +package it.pagopa.tech.lollipop.comsumer.sample.mock; + +import org.mockserver.client.MockServerClient; + +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +public class IdpMockServerConfig { + + private static final String IDP_CLIENT_RESPONSE_STRING = + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + + " MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI/sp\n" + + "ILywgDxVMMtv/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA/L1/fd70ok+6xtDRF8A3HjAf\n" + + "BgNVHSMEGDAWgBQEVmzA/L1/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH/MA0G\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8/o13vMw4feGxro1hMeUilRtH52funrW\n" + + "C+FgPrqk3o/8cZOnq+CqnFFDfILLiEb/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\n" + + "Da1fG/Pi0fG2F0yw/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk/ZbEHdKcofnziDyl0V8gglP2\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " urn:oasis:names:tc:SAML:2.0:nameid-format:transient\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + private static final String IDP_TAG = "latest"; + + public static MockServerClient startIdpMockServer() { + MockServerClient mockServerClient = new MockServerClient("localhost", 3001); + mockServerClient + .when(request().withMethod("GET").withPath("/idp-keys/spid")) + .respond(response().withStatusCode(200).withBody("[\"" + IDP_TAG + "\"]")); + mockServerClient + .when( + request() + .withMethod("GET") + .withPath("/idp-keys/spid/{tag}") + .withPathParameter("tag", IDP_TAG)) + .respond(response().withStatusCode(200).withBody(IDP_CLIENT_RESPONSE_STRING)); + return mockServerClient; + } +} diff --git a/samples/servlet/src/main/java/it/pagopa/tech/lollipop/comsumer/sample/servlet/DemoServlet.java b/samples/servlet/src/main/java/it/pagopa/tech/lollipop/comsumer/sample/servlet/DemoServlet.java new file mode 100644 index 00000000..f9a61750 --- /dev/null +++ b/samples/servlet/src/main/java/it/pagopa/tech/lollipop/comsumer/sample/servlet/DemoServlet.java @@ -0,0 +1,19 @@ +package it.pagopa.tech.lollipop.comsumer.sample.servlet; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +public class DemoServlet extends HttpServlet { + + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + response.setContentType("text/html"); + PrintWriter out = response.getWriter(); + out.println("Test"); + } +} diff --git a/servlet-impl/src/main/java/it/pagopa/tech/lollipop/consumer/servlet/HttpVerifierServletFilter.java b/servlet-impl/src/main/java/it/pagopa/tech/lollipop/consumer/servlet/HttpVerifierServletFilter.java index daf703f2..75d10ab2 100644 --- a/servlet-impl/src/main/java/it/pagopa/tech/lollipop/consumer/servlet/HttpVerifierServletFilter.java +++ b/servlet-impl/src/main/java/it/pagopa/tech/lollipop/consumer/servlet/HttpVerifierServletFilter.java @@ -23,7 +23,7 @@ public class HttpVerifierServletFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { - log.error("Servlet filter initialized"); + log.info("Servlet filter initialized"); } /** @@ -57,6 +57,6 @@ public void doFilter( @Override public void destroy() { - log.error("Servlet filter destroyed"); + log.info("Servlet filter destroyed"); } } From 04749d64da435f52a27a26d799a937b7a9f2aee3 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 9 May 2023 16:08:13 +0200 Subject: [PATCH 394/403] [SLS-34] Added info in the general README about the utility classes in the core module --- README.md | Bin 93100 -> 97184 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index 787bba0671e119b7996f645e82b7747160cde22b..fd9c27f5f5d4007abd514119ec9f1b4454fde445 100644 GIT binary patch delta 2304 zcmd5-O>7%Q6n-O`s&R0MvvDlqq+S!b!6dP3RYKH&nzU+2t3snBg@ZYC<2s2eXV*BJ zq&)?W{8W|lkfxVPAh>{fiG7u|3-Z}t1k1$+2{F_3rD)66rmCM>8YX`9dT)cD%2p~JZ1AN)ySbW z{A{eQkfW#GRf&{*mgoYuHZZQ^Yu+5$fO&;{J{^m9tzysB=|d{Mm7_9wv`Tpx%k5QK z!mNy0p02eo$-#?wZ(j1ZdlNWS$31yENjW-!QJ^ef)UdXQJH*cok_a}bI%l9u0Gohe z)4G8mrap{p00U+O=h0O_D4JtqSU1ezX&d+4~*!xTjK{`6EGCUdU z=Z{WB-ti2qvSBDBq!oSz81nQoMk}z^&ULKqC1wS9eGrhR8U1udWs8s=zPw*1A_sgcYjsqc;n>Z$R}$1LVyd^Nwrj*)uA_M<$P-di4Mvs^r3vB&m#N z9rHQ7*T85E^ME;9KPoAUuT1uL3#k=wQxYbUJ!?4O;RZw_3K3Q=|0}E*cW>-+2Yu{k zs4RL0oMi|>p0*K$WNr|2X#*`c^V zJGlO{M&5K0*Do7l7vaVQJEKAv4oQ~9`7-i6c2X*>(=OkvC}VR#;f@Cyx<7xEr!OAk zC%+u#-_Ac<2q{}=Doe^K=ue}DoIqYaVqS*}pS|rk+dm#kE@4GFkPT~TU7Zl)Tl*pA z09hKu3T|3NvZ^@W2|I6mOF4*M!oqF!I%zI-v+IBiDR0?n5+jNTzm9bXG-xUw++M>m z3FEzj1p<1zM6ka8ejfTd`om%V^5)Pp(5{}!sB~%^fl11PMlD*Yi!}m}6|Z?me0pBSiJk#51aiiwG!&O-6;ku*(%0{MHD?s`Ld?SC!sS2`he z1TK9>T3o9Oi|nKai!2+wbvwbgzZ*(Q_#*0E*>1L*66ePz_{>WKO-1x`@j*YI7#mkv O{@@Sm-uA2-O#TJHJk+89 delta 17 ZcmZ4RopsH1)`l&NQv$YkBrr-y0{}}L2N3`O From 4de572788301a12e5166d46c82454b332c804659 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 9 May 2023 16:10:17 +0200 Subject: [PATCH 395/403] [SLS-34] Added typesafe metadata --- gradle/verification-metadata.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 9f31ff91..4fdf57d4 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1699,6 +1699,11 @@ + + + + + From e9614325f8a78e6137222d144123b4a22da92302 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 9 May 2023 12:40:24 +0200 Subject: [PATCH 396/403] [SLS-34] Added simple java sample application using typesafe configuration with utility core class --- .../utils/LollipopTypesafeConfig.java | 2 + samples/simpleTypesafe/build.gradle | 58 ++++ .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 61608 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 + samples/simpleTypesafe/gradlew | 244 ++++++++++++++++ samples/simpleTypesafe/gradlew.bat | 92 ++++++ samples/simpleTypesafe/settings.gradle | 9 + .../pagopa/tech/sample/ClientMocksConfig.java | 274 ++++++++++++++++++ .../pagopa/tech/sample/LollipopConstants.java | 52 ++++ .../tech/sample/LollipopConsumerSample.java | 138 +++++++++ .../src/main/resources/application.properties | 10 + 11 files changed, 885 insertions(+) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopTypesafeConfig.java create mode 100644 samples/simpleTypesafe/build.gradle create mode 100644 samples/simpleTypesafe/gradle/wrapper/gradle-wrapper.jar create mode 100644 samples/simpleTypesafe/gradle/wrapper/gradle-wrapper.properties create mode 100755 samples/simpleTypesafe/gradlew create mode 100644 samples/simpleTypesafe/gradlew.bat create mode 100644 samples/simpleTypesafe/settings.gradle create mode 100644 samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/ClientMocksConfig.java create mode 100644 samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/LollipopConstants.java create mode 100644 samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java create mode 100644 samples/simpleTypesafe/src/main/resources/application.properties diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopTypesafeConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopTypesafeConfig.java new file mode 100644 index 00000000..2d63bda6 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopTypesafeConfig.java @@ -0,0 +1,2 @@ +package it.pagopa.tech.lollipop.consumer.utils;public class LollipopTypesafeConfig { +} diff --git a/samples/simpleTypesafe/build.gradle b/samples/simpleTypesafe/build.gradle new file mode 100644 index 00000000..8ffcd293 --- /dev/null +++ b/samples/simpleTypesafe/build.gradle @@ -0,0 +1,58 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Java library project to get you started. + * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle + * User Manual available at https://docs.gradle.org/8.0.2/userguide/building_java_projects.html + */ + +plugins { + // Apply the java-library plugin for API and implementation separation. + id 'application' +} + + +group = 'it.pagopa.tech.lollipop.consumer.samples' +version = '1.0.0-RC1' +sourceCompatibility = '11' + +application { + mainClassName = "it.pagopa.tech.sample.LollipopConsumerSample" +} + +repositories { + mavenLocal() + mavenCentral() + maven { + url = uri("https://maven.pkg.github.com/pagopa/eng-http-signatures") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + } + } + maven { + name = "GitHubPackages" + url = "https://maven.pkg.github.com/pagopa/eng-lollipop-consumer-java-sdk" + credentials { + username = System.getenv("GITHUB_ACTOR") + password = System.getenv("GITHUB_TOKEN") + } + } +} + +dependencies { + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:core:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:assertion-rest-client-native:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:identity-service-rest-client-native:1.0.0-RC1' + implementation 'it.pagopa.tech.lollipop-consumer-java-sdk:http-verifier:1.0.0-RC1' + + implementation 'com.typesafe:config:1.3.3' + // Use JUnit Jupiter for testing. + implementation 'org.mock-server:mockserver-netty:5.15.0' + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' +} + +tasks.named('test') { + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} diff --git a/samples/simpleTypesafe/gradle/wrapper/gradle-wrapper.jar b/samples/simpleTypesafe/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..ccebba7710deaf9f98673a68957ea02138b60d0a GIT binary patch literal 61608 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 literal 0 HcmV?d00001 diff --git a/samples/simpleTypesafe/gradle/wrapper/gradle-wrapper.properties b/samples/simpleTypesafe/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..42defcc9 --- /dev/null +++ b/samples/simpleTypesafe/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip +networkTimeout=10000 +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/samples/simpleTypesafe/gradlew b/samples/simpleTypesafe/gradlew new file mode 100755 index 00000000..79a61d42 --- /dev/null +++ b/samples/simpleTypesafe/gradlew @@ -0,0 +1,244 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/samples/simpleTypesafe/gradlew.bat b/samples/simpleTypesafe/gradlew.bat new file mode 100644 index 00000000..93e3f59f --- /dev/null +++ b/samples/simpleTypesafe/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/samples/simpleTypesafe/settings.gradle b/samples/simpleTypesafe/settings.gradle new file mode 100644 index 00000000..bf66c794 --- /dev/null +++ b/samples/simpleTypesafe/settings.gradle @@ -0,0 +1,9 @@ +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } +} + + +rootProject.name = 'simple-lollipop-sample' \ No newline at end of file diff --git a/samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/ClientMocksConfig.java b/samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/ClientMocksConfig.java new file mode 100644 index 00000000..f6ad64f5 --- /dev/null +++ b/samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/ClientMocksConfig.java @@ -0,0 +1,274 @@ +package it.pagopa.tech.sample; + +import org.mockserver.client.MockServerClient; +import org.mockserver.model.Header; + +import static it.pagopa.tech.sample.LollipopConstants.*; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +public class ClientMocksConfig { + + public static final String VALID_ASSERTION_XML = + "{\"response_xml\": \"\\n" + + " https:\\/\\/spid-testenv2:8088<\\/saml:Issuer><\\/ds:Transforms>s\\/DqYePHC7eCXX5ncsiFYNLyKbzS6P5C8331H1b8e30=<\\/ds:DigestValue><\\/ds:Reference><\\/ds:SignedInfo>WcasorooElvhmK0kxFUdBVCqyRYi0SCNGRSZZnC9Q2sZHOYGZbERe4\\/T8OSuRKbSrEivXIHRgNr8WskZTM2CiywfWChHfGvhERsLuPJE8oh9CR3eicX\\/eg0ynJqwx4IoYhTb2NOwqMFc66nnutMhG\\/Smdtjs4SFz0RQYYVeZ5Ho51iTHd94uBV9ZHXjqcvs3EitUsJ0Zg1Pkw352tt8y7niUcGjAd8nydI72S12sF5ePv05AunFp7vZpYbKqi62fQLORCn1ZP7WKFD75hL0bCvZaSRF285GkfSnLfe1S4tLff2SlTQWevOMU\\/wCkHJmQwHT1LMwcWRnMvv4V+vd1XQ==<\\/ds:SignatureValue>MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR\\/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2\\/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI\\/sp\\n" + + "ILywgDxVMMtv\\/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAf\\n" + + "BgNVHSMEGDAWgBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH\\/MA0G\\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8\\/o13vMw4feGxro1hMeUilRtH52funrW\\n" + + "C+FgPrqk3o\\/8cZOnq+CqnFFDfILLiEb\\/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\n" + + "Da1fG\\/Pi0fG2F0yw\\/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk\\/ZbEHdKcofnziDyl0V8gglP2\\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n" + + "<\\/ds:X509Certificate><\\/ds:X509Data><\\/ds:KeyInfo><\\/ds:Signature>\\n" + + " \\n" + + " \\n" + + " <\\/samlp:Status>\\n" + + " \\n" + + " https:\\/\\/spid-testenv2:8088<\\/saml:Issuer><\\/ds:Transforms>4cqgG29TSKgNLy2\\/1eFPXhd5WRVPxZBGcd8DgTvd5Fo=<\\/ds:DigestValue><\\/ds:Reference><\\/ds:SignedInfo>WqxM+y+vtZDcEaIaw2WfcuMuwXUeTOY9ZjaXwzHw+RE8uUr5s8BE1tpaodcKmmqSJK1JQYNr8AUV+W9V79EKfmNtFvfaf0WYeUee7Td7E24QqiyVHjr1YgfDWhSdItFLYJfQUkotj2BepbdwVQGY5yN0Rw6Fq98hgNOgsxty7g6oqxG1OXB4WJ2He20iOoYWQl8ApxlbU\\/\\/hwnefFYe9ghDPy3rDbcNl3JetT07NR\\/+AzhKH4e+JCwKjTkdCBTW30fK4eiV9yBk74Lobip4hMaQhMaByl8egaU3A8AsnsZQuov2B6Wo2sDiQPjIulb8K3DOwFyL8PzEk8BB5YoAfwg==<\\/ds:SignatureValue>MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR\\/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2\\/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI\\/sp\\n" + + "ILywgDxVMMtv\\/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAf\\n" + + "BgNVHSMEGDAWgBQEVmzA\\/L1\\/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH\\/MA0G\\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8\\/o13vMw4feGxro1hMeUilRtH52funrW\\n" + + "C+FgPrqk3o\\/8cZOnq+CqnFFDfILLiEb\\/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\\n" + + "Da1fG\\/Pi0fG2F0yw\\/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk\\/ZbEHdKcofnziDyl0V8gglP2\\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\\n" + + "<\\/ds:X509Certificate><\\/ds:X509Data><\\/ds:KeyInfo><\\/ds:Signature>\\n" + + " \\n" + + " id_48129c2a9d5e9077422591baf495747cfda668c5<\\/saml:NameID>\\n" + + " \\n" + + " \\n" + + " <\\/saml:SubjectConfirmation>\\n" + + " <\\/saml:Subject>\\n" + + " \\n" + + " \\n" + + " https:\\/\\/spid.agid.gov.it\\/cd<\\/saml:Audience>\\n" + + " <\\/saml:AudienceRestriction>\\n" + + " <\\/saml:Conditions>\\n" + + " \\n" + + " \\n" + + " " + + " https:\\/\\/www.spid.gov.it\\/SpidL2<\\/saml:AuthnContextClassRef>\\n" + + " <\\/saml:AuthnContext>\\n" + + " <\\/saml:AuthnStatement>\\n" + + " \\n" + + " \\n" + + " info@agid.gov.it<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " Mario<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " Bianchi<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " GDNNWA12H81Y874F<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " \\n" + + " 1991-12-12<\\/saml:AttributeValue>\\n" + + " <\\/saml:Attribute>\\n" + + " <\\/saml:AttributeStatement>\\n" + + " <\\/saml:Assertion>\\n" + + "<\\/samlp:Response>\"}"; + public static final String IDP_CLIENT_RESPONSE_STRING = + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + + " MIIC7TCCAdWgAwIBAgIJAMbxPOoBth1LMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV\n" + + "BAYTAklUMB4XDTE4MDkwNDE0MDAxM1oXDTE4MTAwNDE0MDAxM1owDTELMAkGA1UE\n" + + "BhMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJrW3y8Zd2jESP\n" + + "XGMRY04cHC4Qfo3302HEY1C6x1aDfW7aR/tXzNplfdw8ZtZugSSmHZBxVrR8aA08\n" + + "dUVbbtUw5qD0uAWKIeREqGfhM+J1STAMSI2/ZxA6t2fLmv8l1eRd1QGeRDm7yF9E\n" + + "EKGY9iUZD3LJf2mWdVBAzzYlG23M769k+9JuGZxuviNWMjojgYRiQFgzypUJJQz+\n" + + "Ihh3q7LMjjiQiiULVb9vnJg7UdU9Wf3xGRkxk6uiGP9SzWigSObUekYYQ4ZAI/sp\n" + + "ILywgDxVMMtv/eVniUFKLABtljn5cE9zltECahPbm7wIuMJpDDu5GYHGdYO0j+K7\n" + + "fhjvF2mzAgMBAAGjUDBOMB0GA1UdDgQWBBQEVmzA/L1/fd70ok+6xtDRF8A3HjAf\n" + + "BgNVHSMEGDAWgBQEVmzA/L1/fd70ok+6xtDRF8A3HjAMBgNVHRMEBTADAQH/MA0G\n" + + "CSqGSIb3DQEBCwUAA4IBAQCRMo4M4PqS0iLTTRWfikMF4hYMapcpmuna6p8aee7C\n" + + "wTjS5y7y18RLvKTi9l8OI0dVkgokH8fq8/o13vMw4feGxro1hMeUilRtH52funrW\n" + + "C+FgPrqk3o/8cZOnq+CqnFFDfILLiEb/PVJMddvTXgv2f9O6u17f8GmMLzde1yvY\n" + + "Da1fG/Pi0fG2F0yw/CmtP8OTLSvxjPtJ+ZckGzZa9GotwHsoVJ+Od21OU2lOeCnO\n" + + "jJOAbewHgqwkCB4O4AT5RM4ThAQtoU8QibjD1XDk/ZbEHdKcofnziDyl0V8gglP2\n" + + "SxpzDaPX0hm4wgHk9BOtSikb72tfOw+pNfeSrZEr6ItQ\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " urn:oasis:names:tc:SAML:2.0:nameid-format:transient\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + + private static final String LOCALHOST = "localhost"; + + public static MockServerClient createExpectationAssertionFound() { + MockServerClient mockServerClient = new MockServerClient(LOCALHOST, 3000); + mockServerClient + .when( + request() + .withMethod("GET") + .withPath("/assertions/{assertion}") + .withPathParameter("assertion", VALID_ASSERTION_REF) + .withHeaders( + new Header("Accept", "application/json"), + new Header("x-pagopa-lollipop-auth", VALID_JWT))) + .respond(response().withStatusCode(200).withBody(VALID_ASSERTION_XML)); + return mockServerClient; + } + + public static MockServerClient createExpectationIdpTagsFound() { + MockServerClient mockServerClient = new MockServerClient(LOCALHOST, 3001); + mockServerClient + .when(request().withMethod("GET").withPath("/idp-keys/spid")) + .respond(response().withStatusCode(200).withBody("[\"" + IDP_TAG + "\"]")); + return mockServerClient; + } + + public static MockServerClient createExpectationIdpDataFound() { + MockServerClient mockServerClient = new MockServerClient(LOCALHOST, 3001); + mockServerClient + .when( + request() + .withMethod("GET") + .withPath("/idp-keys/spid/{tag}") + .withPathParameter("tag", IDP_TAG)) + .respond(response().withStatusCode(200).withBody(IDP_CLIENT_RESPONSE_STRING)); + return mockServerClient; + } + + private ClientMocksConfig() {} +} diff --git a/samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/LollipopConstants.java b/samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/LollipopConstants.java new file mode 100644 index 00000000..79e11c95 --- /dev/null +++ b/samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/LollipopConstants.java @@ -0,0 +1,52 @@ +package it.pagopa.tech.sample; + +public class LollipopConstants { + public static final String VALID_ENCODING_UTF8 = "UTF-8"; + public static final String INVALID_ENCODING_UTF_326 = "UTF-326"; + public static final String VALID_CONTENT_DIGEST = "sha-256=:cpyRqJ1VhoVC+MSs9fq4/4wXs4c46EyEFriskys43Zw=:"; + public static final String INVALID_CONTENT_DIGEST = "sha-256=:fadsfeagsdage76ad564=:"; + public static final String VALID_MESSAGE_PAYLOAD = "{\"message\":\"a valid message payload\"}"; + public static final String INVALID_MESSAGE_PAYLOAD = "{\"message\":\"an invalid message payload\"}"; + public static final String SIGNATURE_HEADER_VALUE = "sig123=:6scl8sMzJdyG/OrnJXHRM9ajmIjrJ/zrLUDqvfOxj2h51DUKztTua3vR1kSUj/c/VT1ioDlt1QIMARABhquewg==:"; + public static final String INVALID_SIGNATURE_HEADER_VALUE = "sig123=:lTTTRytp53GuUMOB4Rz1z97Y96gfSeEOm/xVpO39d3HR6lLAy4KYiGq+1hZ7nmRFBt2bASWEpen7ov5O4wU3kQ==:"; + public static final String SIGNATURE_INPUT_HEADER_VALUE = "sig123=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678293988;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + + public static final String ECDSA_LOLLIPOP_JWT_KEY = "eyJrdHkiOiJFQyIsIngiOiJTaHlZa0ZyN1F3eE9rOE5BRXF6aklkTnc4dEVKODlZOVBlWFF1eVVOWDVjIiwieSI6InlULVJxNWc2VlVadENUd0ZnRExDM2RneGNuM2RsSmNGRjhnWGdxYWgyS0UiLCJjcnYiOiJQLTI1NiJ9"; + + public static final String VALID_MULTI_ECDSA_SIGNATURE_INPUT = + "sig1=(\"x-io-sign-qtspclauses\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\"," + + " sig2=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678299228;nonce=\"aNonce\";alg=\"ecdsa-p256-sha256\";keyid=\"sha256-a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg\""; + public static final String VALID_MULTI_ECDSA_SIGNATURE = + "sig1=:8MB/iT9iZO2HfVjMds6WdFMQeutkPnoyBDhzeyvIQDhb/tX0nE6HeRSoRBsrl4GUzo6OItnzfzF43Sd14P7tAw==:," + + "sig2=:ZDWu2x+6APQG0Ioj10uNzTBv+5JbFBYnjhqcpL66oGFtwznROAUouXkx80ekzUY5h0HoJWE/ecqxRK2OVeHTiQ==:"; + + public static final String VALID_RSA_PSS_SIGNATURE_INPUT = + "sig1=(\"content-digest\" \"x-pagopa-lollipop-original-method\"" + + " \"x-pagopa-lollipop-original-url\");created=1678814391;nonce=\"aNonce\";" + + "alg=\"rsa-pss-sha256\";keyid=\"sha256-A3OhKGLYwSvdJ2txHi_SGQ3G-sHLh2Ibu91ErqFx_58\""; + + public static final String VALID_RSA_PSS_SIGNATURE = + "sig1=:q3Og7m8yL18HkrY+zgV92Gj05lrWaFMIEFSPg2PEnO5a46+2Tt/2n7kjqVaGjI1ZXtys+Wyh3cVXCdda" + + "dNARizt0BpCRdT9S4r48xsGO79Ucq4IFwZyyHNudKu5WSH4/55j5yX/YmeCtH+Nt6Nun02OZynn3iQwg" + + "LJB+CGe3h6X02iSvl4wJjKaMGE64RFHa5osE4MctoPD1j0tRkcOtgwrGmFMr282Kqrkabbx1vUpmO9T1k" + + "hjouxIryfUln9zIaZ+wWmukpAZv7TKO3CltNWgfx1XT9m/iwzHiGmtvcHbWVExdAyey8lH23MgLY43AM7y" + + "tLQNSlk1s/bPNbGmPwg==:"; + + public static String LOLLIPOP_RSA_PUBKEY = "eyJrdHkiOiJSU0EiLCJlIjoiQVFBQiIsImtpZCI6InRlc3Qta2V5LXJzYS1wc3MiLCJuIjoicjR0bW0zc" + + "jIwV2RfUGJxdlAxczItUUV0dnB1UmFWOFlxNDBnalVSOHkyUmp4YTZkcEcyR1hIYlBmdk0gIHM4Y3Q" + + "tTGgxR0g0NXgyOFJ3M1J5NTNtbS1vQVhqeVE4Nk9uRGtaNU44bFliZ2dENE8zdzZNNnBBdkxraGs5NU" + + "FuICBkVHJpZmJJRlBOVThQUE1PN095ckZBSHFnRHN6bmpQRm1UT3RDRWNOMloxRnBXZ2Nod3VZTFBMLV" + + "dva3FsdGQxMSAgbnFxemktYko5Y3ZTS0FEWWRVQUFONVdVdHpkcGl5NkxiVGdTeFA3b2NpVTRUbjBnNU" + + "k2YURaSjdBOEx6bzBLU3kgIFpZb0E0ODVtcWNPMEdWQWRWdzlscTRhT1Q5djZkLW5iNGJuTmtRVmtsTFE" + + "zZlZBdkptLXhkRE9wOUxDTkNONDhWICAycG5ET2tGVjYtVTluVjVveWM2WEkydyJ9"; + + public static final String VALID_ASSERTION_REF = "sha256-chG21HBOK-wJp2hHuYPrx7tAII2UGWVF-IFo0crUOtw"; + public static final String VALID_FISCAL_CODE = "GDNNWA12H81Y874F"; + public static final String VALID_JWT = "aValidJWT"; + + public static final String IDP_TAG = "latest"; + + private LollipopConstants() {} +} diff --git a/samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java b/samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java new file mode 100644 index 00000000..86a86203 --- /dev/null +++ b/samples/simpleTypesafe/src/main/java/it/pagopa/tech/sample/LollipopConsumerSample.java @@ -0,0 +1,138 @@ +package it.pagopa.tech.sample; + +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; +import it.pagopa.tech.lollipop.consumer.assertion.AssertionServiceFactory; +import it.pagopa.tech.lollipop.consumer.assertion.client.AssertionClientProvider; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientConfig; +import it.pagopa.tech.lollipop.consumer.assertion.client.simple.AssertionSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.assertion.impl.AssertionServiceFactoryImpl; +import it.pagopa.tech.lollipop.consumer.assertion.storage.AssertionStorageProvider; +import it.pagopa.tech.lollipop.consumer.assertion.storage.SimpleAssertionStorageProvider; +import it.pagopa.tech.lollipop.consumer.assertion.storage.StorageConfig; +import it.pagopa.tech.lollipop.consumer.command.LollipopConsumerCommandBuilder; +import it.pagopa.tech.lollipop.consumer.command.impl.LollipopConsumerCommandBuilderImpl; +import it.pagopa.tech.lollipop.consumer.config.LollipopConsumerRequestConfig; +import it.pagopa.tech.lollipop.consumer.helper.LollipopConsumerFactoryHelper; +import it.pagopa.tech.lollipop.consumer.http_verifier.HttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.http_verifier.visma.VismaHttpMessageVerifierFactory; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientProvider; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.storage.SimpleIdpCertStorageProvider; +import it.pagopa.tech.lollipop.consumer.idp.impl.IdpCertProviderFactoryImpl; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.logger.LollipopLoggerServiceFactory; +import it.pagopa.tech.lollipop.consumer.logger.impl.LollipopLogbackLoggerServiceFactory; +import it.pagopa.tech.lollipop.consumer.model.LollipopConsumerRequest; +import it.pagopa.tech.lollipop.consumer.service.impl.LollipopConsumerRequestValidationServiceImpl; +import it.pagopa.tech.lollipop.consumer.utils.LollipopTypesafeConfig; +import org.mockserver.client.MockServerClient; +import org.mockserver.integration.ClientAndServer; + +import java.util.HashMap; + +import static it.pagopa.tech.sample.LollipopConstants.*; + + +public class LollipopConsumerSample { + + private static LollipopConsumerRequestConfig lollipopConsumerRequestConfig; + + public static void main(String[] args) throws Exception { + try (ClientAndServer clientAndServer = ClientAndServer.startClientAndServer(3000, 3001); + MockServerClient mockServerClientAssertion = ClientMocksConfig.createExpectationAssertionFound(); + MockServerClient mockServerClientIdpTag = ClientMocksConfig.createExpectationIdpTagsFound(); + MockServerClient mockServerClientIdpData = ClientMocksConfig.createExpectationIdpDataFound()) { + + LollipopConsumerFactoryHelper lollipopConsumerFactoryHelper = buildLollipopConsumerFactoryHelper(); + LollipopConsumerCommandBuilder commandBuilder = new LollipopConsumerCommandBuilderImpl(lollipopConsumerFactoryHelper); + + // Success + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)) + .doExecute(); + + // Request with invalid content digest + commandBuilder.createCommand(buildLollipopRequest( + INVALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)).doExecute(); + + // Request with invalid message payload + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, INVALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)).doExecute(); + + // Request with invalid encoding + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, INVALID_ENCODING_UTF_326, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, SIGNATURE_HEADER_VALUE)).doExecute(); + + // Request with invalid signature + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + SIGNATURE_INPUT_HEADER_VALUE, INVALID_SIGNATURE_HEADER_VALUE)).doExecute(); + + // Success with multi signature + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, ECDSA_LOLLIPOP_JWT_KEY, + VALID_MULTI_ECDSA_SIGNATURE_INPUT, VALID_MULTI_ECDSA_SIGNATURE)).doExecute(); + + // thumbprint validation failed + commandBuilder.createCommand(buildLollipopRequest( + VALID_CONTENT_DIGEST, VALID_ENCODING_UTF8, VALID_MESSAGE_PAYLOAD, + LOLLIPOP_RSA_PUBKEY, VALID_RSA_PSS_SIGNATURE_INPUT, VALID_RSA_PSS_SIGNATURE)).doExecute(); + + } + } + + private static LollipopConsumerFactoryHelper buildLollipopConsumerFactoryHelper() throws Exception { + LollipopTypesafeConfig typesafeConfig = new LollipopTypesafeConfig(ConfigFactory.parseResources("application.properties")); + lollipopConsumerRequestConfig = LollipopConsumerRequestConfig.builder() + .assertionNotBeforeDateFormat(typesafeConfig.getLOLLIPOP_ASSERTION_NOT_BEFORE_DATE_FORMAT()) + .assertionInstantDateFormat(typesafeConfig.getLOLLIPOP_ASSERTION_INSTANT_DATE_FORMAT()) + .build(); + HttpMessageVerifierFactory messageVerifierFactory = new VismaHttpMessageVerifierFactory(VALID_ENCODING_UTF8, + LollipopConsumerRequestConfig.builder().build()); + AssertionStorageProvider assertionStorageProvider = new SimpleAssertionStorageProvider(); + IdpCertProviderFactory idpCertProviderFactory = new IdpCertProviderFactoryImpl( + new IdpCertSimpleClientProvider(IdpCertSimpleClientConfig.builder().baseUri(typesafeConfig.getIDP_CLIENT_BASE_URI()).build(), + new SimpleIdpCertStorageProvider(), new IdpCertStorageConfig())); + AssertionClientProvider assertionClientProvider = + new AssertionSimpleClientProvider(AssertionSimpleClientConfig.builder().build()); + AssertionServiceFactory assertionServiceFactory = new AssertionServiceFactoryImpl( + assertionStorageProvider, assertionClientProvider, new StorageConfig()); + LollipopLoggerServiceFactory lollipopLoggerServiceFactory = new LollipopLogbackLoggerServiceFactory(); + return new LollipopConsumerFactoryHelper(lollipopLoggerServiceFactory, messageVerifierFactory, idpCertProviderFactory, assertionServiceFactory, + new LollipopConsumerRequestValidationServiceImpl(lollipopConsumerRequestConfig), lollipopConsumerRequestConfig); + } + + private static LollipopConsumerRequest buildLollipopRequest( + String contentDigest, + String encoding, + String payload, + String lollipopKey, + String signatureInput, + String signature) { + HashMap lollipopHeaderParams = new HashMap<>(); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getContentDigestHeader(), contentDigest); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getContentEncodingHeader(), encoding); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getSignatureInputHeader(), signatureInput); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getSignatureHeader(), signature); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getPublicKeyHeader(), lollipopKey); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getOriginalMethodHeader(), lollipopConsumerRequestConfig.getExpectedFirstLcOriginalMethod()); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getOriginalURLHeader(), lollipopConsumerRequestConfig.getExpectedFirstLcOriginalUrl()); + lollipopHeaderParams.put("X-io-sign-qtspclauses","anIoSignClauses"); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getAssertionRefHeader(), VALID_ASSERTION_REF); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getAssertionTypeHeader(), "SAML"); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getAuthJWTHeader(), VALID_JWT); + lollipopHeaderParams.put(lollipopConsumerRequestConfig.getUserIdHeader(), VALID_FISCAL_CODE); + + + return LollipopConsumerRequest.builder() + .requestBody(payload) + .headerParams(lollipopHeaderParams) + .build(); + } +} diff --git a/samples/simpleTypesafe/src/main/resources/application.properties b/samples/simpleTypesafe/src/main/resources/application.properties new file mode 100644 index 00000000..b6ae2542 --- /dev/null +++ b/samples/simpleTypesafe/src/main/resources/application.properties @@ -0,0 +1,10 @@ +lollipop.idp.client.mock.enabled=true +lollipop.assertion.client.mock.enabled=true + +lollipop.core.config.assertionNotBeforeDateFormat=yyyy-MM-dd'T'HH:mm:ss.SSS'Z' +lollipop.core.config.assertionInstantDateFormat=yyyy-MM-dd'T'HH:mm:ss.SSS'Z' + +lollipop.idp.rest.config.baseUri=http://localhost:3001 + + + From f38f1acbbf9cad883a68ca2e7286ef5cacc00aa6 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 9 May 2023 12:40:52 +0200 Subject: [PATCH 397/403] [SLS-34] Defined utility class for typesafe configuration in core module --- core/build.gradle | 2 + .../utils/LollipopTypesafeConfig.java | 134 +++++++++++++++++- 2 files changed, 135 insertions(+), 1 deletion(-) diff --git a/core/build.gradle b/core/build.gradle index 915d7c5b..b3b7b0e3 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -50,6 +50,8 @@ dependencies { implementation 'javax.servlet:javax.servlet-api:3.0.1' + implementation 'com.typesafe:config:1.3.3' + // Use JUnit Jupiter for testing. testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.mockito:mockito-core:5.2.0' diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopTypesafeConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopTypesafeConfig.java index 2d63bda6..6a8869e1 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopTypesafeConfig.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/utils/LollipopTypesafeConfig.java @@ -1,2 +1,134 @@ -package it.pagopa.tech.lollipop.consumer.utils;public class LollipopTypesafeConfig { +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.utils; + +import com.typesafe.config.Config; +import lombok.Getter; + +@Getter +public class LollipopTypesafeConfig { + + boolean ASSERTION_CLIENT_MOCK_ENABLED; + boolean IDP_CLIENT_MOCK_ENABLED; + + // Sample controller endpoint + String SAMPLE_LOLLIPOP_CONSUMER_ENDPOINT; + + // General Lollipop Configs Sample + int LOLLIPOP_ASSERTION_EXPIRE_IN_DAYS; + String LOLLIPOP_EXPECTED_LC_ORIGINAL_URL; + String LOLLIPOP_EXPECTED_LC_ORIGINAL_METHOD; + String LOLLIPOP_ASSERTION_NOT_BEFORE_DATE_FORMAT; + String LOLLIPOP_ASSERTION_INSTANT_DATE_FORMAT; + + // Idp Client Configs + String IDP_CLIENT_CIEID; + String IDP_CLIENT_BASE_URI; + String IDP_CLIENT_CIE_ENDPOINT; + String IDP_CLIENT_SPID_ENDPOINT; + + // Idp Storage Configs + boolean IDP_STORAGE_ENABLED; + int IDP_STORAGE_EVICTION_DELAY; + + // Assertion Client Configs + String ASSERTION_REST_URI; + String ASSERTION_REST_ENDPOINT; + + // Assertion Storage Configs + boolean ASSERTION_STORAGE_ENABLED; + int ASSERTION_STORAGE_EVICTION_DELAY; + + public LollipopTypesafeConfig(Config config) { + this.ASSERTION_CLIENT_MOCK_ENABLED = + getConfigBoolean(config, "lollipop.assertion.client.mock.enabled", false); + this.IDP_CLIENT_MOCK_ENABLED = + getConfigBoolean(config, "lollipop.assertion.client.mock.enabled", false); + + this.SAMPLE_LOLLIPOP_CONSUMER_ENDPOINT = + getConfigString( + config, + "sample.lollipop.consumer.config.endpoint", + "/api/v1/lollipop-consumer"); + + this.LOLLIPOP_ASSERTION_EXPIRE_IN_DAYS = + getConfigInt(config, "lollipop.core.config.assertionExpireInDays", 180); + this.LOLLIPOP_EXPECTED_LC_ORIGINAL_URL = + getConfigString( + config, + "lollipop.-core.config.expectedFirstLcOriginalUrl", + "https://api-app.io.pagopa.it/first-lollipop/sign"); + this.LOLLIPOP_EXPECTED_LC_ORIGINAL_METHOD = + getConfigString( + config, "lollipop.core.config.expectedFirstLcOriginalMethod", "POST"); + this.LOLLIPOP_ASSERTION_NOT_BEFORE_DATE_FORMAT = + getConfigString( + config, + "lollipop.core.config.assertionNotBeforeDateFormat", + "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + this.LOLLIPOP_ASSERTION_INSTANT_DATE_FORMAT = + getConfigString( + config, + "lollipop.core.config.assertionInstantDateFormat", + "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + + this.IDP_CLIENT_CIEID = + getConfigString( + config, + "lollipop.idp.rest.config.cieEntityId", + "https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"); + this.IDP_CLIENT_BASE_URI = + getConfigString( + config, "lollipop.idp.rest.config.baseUri", "https://api.is.eng.pagopa.it"); + this.IDP_CLIENT_CIE_ENDPOINT = + getConfigString( + config, "lollipop.idp.rest.config.idpKeysCieEndpoint", "/idp-keys/cie"); + this.IDP_CLIENT_SPID_ENDPOINT = + getConfigString( + config, "lollipop.idp.rest.config.idpKeysSpidEndpoint", "/idp-keys/spid"); + + this.IDP_STORAGE_ENABLED = + getConfigBoolean( + config, "lollipop.idp.storage.config.idpCertDataStorageEnabled", true); + this.IDP_STORAGE_EVICTION_DELAY = + getConfigInt(config, "lollipop.idp.storage.config.storageEvictionDelay", 1); + + this.ASSERTION_REST_URI = + getConfigString( + config, "lollipop.assertion.rest.config.baseUri", "http://localhost:3000"); + this.ASSERTION_REST_ENDPOINT = + getConfigString( + config, + "lollipop.assertion.rest.config.assertionRequestEndpoint", + "/assertions"); + + this.ASSERTION_STORAGE_ENABLED = + getConfigBoolean( + config, "lollipop.assertion.rest.config.assertionStorageEnabled", true); + this.ASSERTION_STORAGE_EVICTION_DELAY = + getConfigInt(config, "lollipop.assertion.rest.config.storageEvictionDelay", 1); + } + + private String getConfigString(Config config, String path, String defaultString) { + if (config.hasPath(path)) { + return config.getString(path); + } else { + return defaultString; + } + } + + private boolean getConfigBoolean(Config config, String path, boolean defaultBoolean) { + if (config.hasPath(path)) { + return config.getBoolean(path); + } else { + return defaultBoolean; + } + } + + private int getConfigInt(Config config, String path, int defaultInt) { + if (config.hasPath(path)) { + return config.getInt(path); + } else { + return defaultInt; + } + } } From 879b88908d765a2bcc298efa44c41464a8d50f46 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 9 May 2023 12:51:13 +0200 Subject: [PATCH 398/403] [SLS-34] Added typesafe sample reference to general README --- README.md | Bin 92422 -> 93104 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index f73f23060fb41f47a0cec294c9548615325b1354..3284f33434e480a1dc75681c5597598ee426bf16 100644 GIT binary patch delta 285 zcmZp>#Jb@+>xMXm$q!h#CLiEu*_<$qjd61VuK?p@2O*Bh4N75?6*#yyf8dZ}n*2c} z4yJ5!km{!CZXApfo2ArzKuWnL|5D+TRA4A)$YdyC$Y4-l2w|vXC}2osC}v1xNSn^6 z!YDaePL)d#MHncpIoVrvC)lXTK%*u<;9;2@;w~ha0yF_(Rx(2=(3}#6e1_b~|GgzS zLA*?cJcjhi7mo^?qZ{cARF}t)22_y_G^G@%FOwk$?5;{6KN-kQ1nMuI9LSprcKJ0K YfyqtkF6;_GSs-jatiJuQI-|2A0L*wxR{#J2 delta 81 zcmV-X0IvVA*9C^s1+ZQqlh9BIvv44A0<-W48UmAW3ks7CB~+8Z4+N8NC9;?D3IP_A nyeLeQ4q4WdumvoWKoSa*kS7F_+8hj%A}U0Ka4NTODgi)2`9U35 From 7bbaaf9284d8cdc8c61a496cc8a1f79f7dbf3d8d Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 9 May 2023 16:08:13 +0200 Subject: [PATCH 399/403] [SLS-34] Added info in the general README about the utility classes in the core module --- README.md | Bin 93104 -> 97188 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/README.md b/README.md index 3284f33434e480a1dc75681c5597598ee426bf16..dc62561c804c3e67e08c0c03b1a98f78d80022ab 100644 GIT binary patch delta 2363 zcmd5-OHUI~6uvi#3W!omX{6K+Ayq5bN=SSlhL;k>M+|}s8yBS%sFt>t0d$3KRbuoc z4jW^PZZs}5F)=at1B{6=Zrr%>KNwwTjNdua=}=HN#%P-9+{d}+e&;*iIrHRw#e**u zm!Ii{lX{r0MK;s*fpwKNs!BEUk35Ubkv^4ESv8|ls-R5y=lwpFQ3*ALpMlj0j7_?^ z=nL^Yt_Col!E+I_Q*veo_9@tOd3+U<*vnGWH{V=TCE|#8kVAs$F>6R0Jq8SQ~*4zUPwS2xe7!P@r=Fvw&f!X@S6|CX5UK z17rl3Q=@>;A;(&!Y_UKTk16zEDvBE_7u{`}cOx>P3y1K7wI47`@ zLXb;{6MhO9Vrn-YCopH{BG#4@GXcCN2#CoQfhfS62qOay96Y9knxL~U+AVWJXDTNp zzLd()$K!3GXo>iUYAqdNbdqkXr&kAQUH8@_`+q`58cMM>k_7BL#)EiIf!GYjHi68^ zv;ZH)2x#bRx4)8UPGKHr-~nskgs##lR?FX|$i8Vj1)Z#9Dv7lOA{vJv_}>s=a0aJ< z8;X}W46)%@3KDA`bY>+!1BzqPQjm|qtMs)iTy0wkBXsAHzuL)5T=iK`yY*&CN=+## zNV2_tbZKUyLOvfogd$5I#d*;WgUg|aT&PTS0^ph4q(B8MYd)z%I!^b4VX6%_Q1)Rq zd>HYtbWX#xfJn#i@aV7{8Wr~idK&asF9BlR8`fT`Tdbu_q|wiKe$f~rc4IgOr{hBP z2%Kj@%r@XNaEeLeE60)amUgbea=Tcu*2Lx~CEaSRJ)xVZ|JWA#{%(!+_@G|j=CU+Y zlvhc|xYwy(PG$kAMBAa5y&Zx^W~Uh zQbSxGe4|^>P7CColb78DnBc1CogynN19!HiOs{sY$>G{_IL2XIX!9}ywKdY1B~l2P z5_`O~;q@ANFyFWelBS1`nnJDExo@{M(5L#&YOaZ5&7kWwcb#(QK;v{+rvuK4dbn_1mi{|U7|S%VL=S+C z+>z&lcO!QqeEB57Ae?S=_``Myx}~v9@Two=B(3wKI{2@3zt_eB^!(AhR2DJIhnt<# zt67EIsad53np^PG!pp{h^PO2DfMN@ZTRolHPyH?R)Vrg;sFXVDcvWZhcItZG&=I=w M+57zVN!<|m0djcX>;M1& delta 17 ZcmZ4Topr-?)`l&NGXl2vBrr-y0{~0R2O$6e From 7b4e7674ab62ebaeccb5017b644ec1ee474cde35 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 9 May 2023 16:10:17 +0200 Subject: [PATCH 400/403] [SLS-34] Added typesafe metadata --- gradle/verification-metadata.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index b2ae781b..00812df9 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1699,6 +1699,11 @@ + + + + + From 4ab43d4182e4a768203ad97954895ade8a2c70ac Mon Sep 17 00:00:00 2001 From: giomella Date: Wed, 10 May 2023 10:21:01 +0200 Subject: [PATCH 401/403] [SLS-34] added Readme in servlet-impl module and updated SDK Readme. --- README.md | Bin 97192 -> 98296 bytes samples/simple/gradlew | 257 ++++++++++--------------- samples/simpleTypesafe/settings.gradle | 2 +- servlet-impl/README.md | 30 +++ 4 files changed, 135 insertions(+), 154 deletions(-) create mode 100644 servlet-impl/README.md diff --git a/README.md b/README.md index b85865522e2ab397c96432b2737234d94068a9e8..ce2e5ef3a6f2425b131b2c2b3c637b9ccfcec8a0 100644 GIT binary patch delta 324 zcmZ4So%P3m)(y|(Co4p7ai=mAF_banFr+e+Or9uXKluPZ3x702Fp!TBKgh2*nMGCz zMXkK7?c@Ym7wKYTl?)0DX$+Y_(@H?1llz&(C*PBGn7l+YW%35ryv+~fH}Fhm5)+xc zK%I*h)e1)~aTMb}a*KkTGPyuijk}m3ks+6%0OZKYq8jPb6GRwUCLe1PncTCLLlEq8 zWP2yi*Y=&P0J$^;sIr711L(JWhEj%fAWH!#n#+&`mP>)E2m#9G ZG9&}7Edk2Id '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi done - -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" -APP_BASE_NAME=${0##*/} +APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum +MAX_FD="maximum" warn () { echo "$*" -} >&2 +} die () { echo echo "$*" echo exit 1 -} >&2 +} # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -121,9 +87,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java + JAVACMD="$JAVA_HOME/jre/sh/java" else - JAVACMD=$JAVA_HOME/bin/java + JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -132,7 +98,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD=java + JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -140,95 +106,80 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi fi -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi # For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg + i=`expr $i + 1` done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" exec "$JAVACMD" "$@" diff --git a/samples/simpleTypesafe/settings.gradle b/samples/simpleTypesafe/settings.gradle index bf66c794..bf5ecc03 100644 --- a/samples/simpleTypesafe/settings.gradle +++ b/samples/simpleTypesafe/settings.gradle @@ -6,4 +6,4 @@ pluginManagement { } -rootProject.name = 'simple-lollipop-sample' \ No newline at end of file +rootProject.name = 'typesafe-lollipop-sample' \ No newline at end of file diff --git a/servlet-impl/README.md b/servlet-impl/README.md new file mode 100644 index 00000000..a82228f6 --- /dev/null +++ b/servlet-impl/README.md @@ -0,0 +1,30 @@ +# Lollipop SDK Servlet Implementations + +This module contains implementations of general utility of the core SDK with a servlet filter. + +## Servlet filter Example + +In order to use the provided Servlet filter it is possible to register it in the application context, providing +a configuration for the Spring application to use in order to determine which endpoints should be validated using +the library functionalities + +``` +@Configuration +public class DemoWebConfigurer implements WebMvcConfigurer { + + @Autowired private LollipopConsumerCommandBuilder commandBuilder; + + @Bean + public FilterRegistrationBean requestFilter() { + FilterRegistrationBean registrationBean = + new FilterRegistrationBean<>(); + + registrationBean.setFilter(new HttpVerifierServletFilter(commandBuilder)); + registrationBean.addUrlPatterns("/*"); + + return registrationBean; + } +} +``` + +Otherwise, it is possible to register the filter together with a servlet in a web server like Tomcat as shown in the [Servlet sample](samples/servlet) \ No newline at end of file From d34952f2514208217e7bd44be853835eeaccea1b Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 10 May 2023 12:23:56 +0200 Subject: [PATCH 402/403] Introduced dependabot.yml with gradle package ecosystem --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..7f283b1c --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "gradle" + directory: "/" + schedule: + interval: "daily" \ No newline at end of file From de3a49a8565df307671f7c7bd19c82fb2f1fe037 Mon Sep 17 00:00:00 2001 From: Alessio Cialini Date: Wed, 10 May 2023 14:41:47 +0200 Subject: [PATCH 403/403] [1.0.0-RC1] Fixed code smell --- .../assertion/client/simple/internal/RFC3339DateFormat.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/RFC3339DateFormat.java b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/RFC3339DateFormat.java index b2b8bcfb..cd978bd9 100644 --- a/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/RFC3339DateFormat.java +++ b/assertion-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/assertion/client/simple/internal/RFC3339DateFormat.java @@ -9,7 +9,9 @@ import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; +import lombok.EqualsAndHashCode; +@EqualsAndHashCode public class RFC3339DateFormat extends DateFormat { private static final long serialVersionUID = 1L; private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC");