diff --git a/pom.xml b/pom.xml index ea8fad71a8e2961058187e3b2ce4f3ceb8b7813e..b117118defc51f43f953bb980c8f1d750d951ad8 100644 --- a/pom.xml +++ b/pom.xml @@ -1,316 +1,360 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- + ~ Copyright (c) 2024. + ~ Lizenziert unter der EUPL, Version 1.2 oder - sobald + ~ diese von der Europäischen Kommission genehmigt wurden - + ~ Folgeversionen der EUPL ("Lizenz"); + ~ Sie dürfen dieses Werk ausschließlich gemäß + ~ dieser Lizenz nutzen. + ~ Eine Kopie der Lizenz finden Sie hier: + ~ + ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + ~ + ~ Sofern nicht durch anwendbare Rechtsvorschriften + ~ gefordert oder in schriftlicher Form vereinbart, wird + ~ die unter der Lizenz verbreitete Software "so wie sie + ~ ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + ~ ausdrücklich oder stillschweigend - verbreitet. + ~ Die sprachspezifischen Genehmigungen und Beschränkungen + ~ unter der Lizenz sind dem Lizenztext zu entnehmen. + --> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> - Copyright (C) 2022-2023 Das Land Schleswig-Holstein vertreten durch den - Ministerpräsidenten des Landes Schleswig-Holstein - Staatskanzlei - Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + <parent> + <groupId>de.ozgcloud.common</groupId> + <artifactId>ozgcloud-common-parent</artifactId> + <version>3.0.1</version> + <relativePath/> + </parent> - Lizenziert unter der EUPL, Version 1.2 oder - sobald - diese von der Europäischen Kommission genehmigt wurden - - Folgeversionen der EUPL ("Lizenz"); - Sie dürfen dieses Werk ausschließlich gemäß - dieser Lizenz nutzen. - Eine Kopie der Lizenz finden Sie hier: + <groupId>de.ozgcloud.nachrichten</groupId> + <artifactId>nachrichten-manager</artifactId> + <version>2.4.0-SNAPSHOT</version> + <name>OZG-Cloud Nachrichten Manager</name> - https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + <properties> + <java.version>17</java.version> + <!-- TODO version management --> + <shedlock.version>4.25.0</shedlock.version> + <logcaptor.version>2.7.10</logcaptor.version> + <ozgcloud.license.version>1.3.0</ozgcloud.license.version> + <jaxb-maven-plugin.version>3.0.1</jaxb-maven-plugin.version> + <ozg-info-manager-interface.version>0.10.0-22.8503e49-20240124.071709-1</ozg-info-manager-interface.version> + <bayernid-proxy-interface.version>0.1.0-SNAPSHOT</bayernid-proxy-interface.version> + <opensaml.version>4.3.0</opensaml.version> + </properties> - Sofern nicht durch anwendbare Rechtsvorschriften - gefordert oder in schriftlicher Form vereinbart, wird - die unter der Lizenz verbreitete Software "so wie sie - ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - - ausdrücklich oder stillschweigend - verbreitet. - Die sprachspezifischen Genehmigungen und Beschränkungen - unter der Lizenz sind dem Lizenztext zu entnehmen. + <repositories> + <repository> + <id>shibboleth-releases</id> + <name>Shibboleth Releases Repository</name> + <url>https://build.shibboleth.net/maven/releases/</url> + <releases> + <enabled>true</enabled> + <checksumPolicy>warn</checksumPolicy> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </repository> + <repository> + <id>shibboleth-thirdparty</id> + <name>Shibboleth Thirdparty Repository</name> + <url>https://build.shibboleth.net/maven/thirdparty/</url> + <releases> + <enabled>true</enabled> + <checksumPolicy>fail</checksumPolicy> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </repository> + </repositories> ---> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> + <dependencies> + <dependency> + <groupId>de.ozgcloud.vorgang</groupId> + <artifactId>vorgang-manager-base</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>de.ozgcloud.vorgang</groupId> + <artifactId>vorgang-manager-interface</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>de.ozgcloud.command</groupId> + <artifactId>command-manager</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>de.ozgcloud.vorgang</groupId> + <artifactId>vorgang-manager-utils</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>de.ozgcloud.nachrichten</groupId> + <artifactId>bayernid-proxy-interface</artifactId> + <version>${bayernid-proxy-interface.version}</version> + </dependency> - <parent> - <groupId>de.ozgcloud.common</groupId> - <artifactId>ozgcloud-common-parent</artifactId> - <version>3.0.1</version> - <relativePath/> - </parent> + <dependency> + <groupId>com.mgmtp.bup.ozg</groupId> + <artifactId>ozg-info-manager-interface</artifactId> + <version>${ozg-info-manager-interface.version}</version> + </dependency> - <groupId>de.ozgcloud.nachrichten</groupId> - <artifactId>nachrichten-manager</artifactId> - <version>2.4.0-SNAPSHOT</version> - <name>OZG-Cloud Nachrichten Manager</name> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-mail</artifactId> + </dependency> - <properties> - <java.version>17</java.version> - <!-- TODO version management --> - <shedlock.version>4.25.0</shedlock.version> - <logcaptor.version>2.7.10</logcaptor.version> - <ozgcloud.license.version>1.3.0</ozgcloud.license.version> - <jaxb-maven-plugin.version>3.0.1</jaxb-maven-plugin.version> - <ozg-info-manager-interface.version>0.10.0-22.8503e49-20240124.071709-1</ozg-info-manager-interface.version> - <bayernid-proxy-interface.version>0.1.0-SNAPSHOT</bayernid-proxy-interface.version> - </properties> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-json</artifactId> + <scope>compile</scope> + </dependency> - <dependencies> - <dependency> - <groupId>de.ozgcloud.vorgang</groupId> - <artifactId>vorgang-manager-base</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>de.ozgcloud.vorgang</groupId> - <artifactId>vorgang-manager-interface</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>de.ozgcloud.command</groupId> - <artifactId>command-manager</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>de.ozgcloud.vorgang</groupId> - <artifactId>vorgang-manager-utils</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>de.ozgcloud.nachrichten</groupId> - <artifactId>bayernid-proxy-interface</artifactId> - <version>${bayernid-proxy-interface.version}</version> - </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-web</artifactId> + </dependency> - <dependency> - <groupId>com.mgmtp.bup.ozg</groupId> - <artifactId>ozg-info-manager-interface</artifactId> - <version>${ozg-info-manager-interface.version}</version> - </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-validation</artifactId> + </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-mail</artifactId> - </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web-services</artifactId> + </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-json</artifactId> - <scope>compile</scope> - </dependency> + <dependency> + <groupId>org.glassfish.jaxb</groupId> + <artifactId>jaxb-runtime</artifactId> + </dependency> - <dependency> - <groupId>org.springframework</groupId> - <artifactId>spring-web</artifactId> - </dependency> + <dependency> + <groupId>net.javacrumbs.shedlock</groupId> + <artifactId>shedlock-spring</artifactId> + <version>${shedlock.version}</version> + </dependency> + <dependency> + <groupId>net.javacrumbs.shedlock</groupId> + <artifactId>shedlock-provider-mongo</artifactId> + <version>${shedlock.version}</version> + </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-validation</artifactId> - </dependency> + <dependency> + <groupId>org.mapstruct</groupId> + <artifactId>mapstruct</artifactId> + </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-web-services</artifactId> - </dependency> + <!-- open saml2 --> + <dependency> + <groupId>org.opensaml</groupId> + <artifactId>opensaml-core</artifactId> + <version>${opensaml.version}</version> + </dependency> + <dependency> + <groupId>org.opensaml</groupId> + <artifactId>opensaml-saml-api</artifactId> + <version>${opensaml.version}</version> + </dependency> + <dependency> + <groupId>org.opensaml</groupId> + <artifactId>opensaml-saml-impl</artifactId> + <version>${opensaml.version}</version> + </dependency> + <dependency> + <groupId>org.springframework.security</groupId> + <artifactId>spring-security-saml2-service-provider</artifactId> + </dependency> - <dependency> - <groupId>org.glassfish.jaxb</groupId> - <artifactId>jaxb-runtime</artifactId> - </dependency> + <!-- grpc --> + <dependency> + <groupId>net.devh</groupId> + <artifactId>grpc-server-spring-boot-starter</artifactId> + </dependency> + <dependency> + <groupId>net.devh</groupId> + <artifactId>grpc-client-spring-boot-starter</artifactId> + </dependency> - <dependency> - <groupId>net.javacrumbs.shedlock</groupId> - <artifactId>shedlock-spring</artifactId> - <version>${shedlock.version}</version> - </dependency> - <dependency> - <groupId>net.javacrumbs.shedlock</groupId> - <artifactId>shedlock-provider-mongo</artifactId> - <version>${shedlock.version}</version> - </dependency> + <!-- commons --> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents.client5</groupId> + <artifactId>httpclient5</artifactId> + </dependency> + <dependency> + <groupId>commons-beanutils</groupId> + <artifactId>commons-beanutils</artifactId> + </dependency> - <dependency> - <groupId>org.mapstruct</groupId> - <artifactId>mapstruct</artifactId> - </dependency> + <!-- DEV --> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-devtools</artifactId> + <scope>runtime</scope> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <optional>true</optional> + <scope>provided</scope> + </dependency> - <!-- grpc --> - <dependency> - <groupId>net.devh</groupId> - <artifactId>grpc-server-spring-boot-starter</artifactId> - </dependency> - <dependency> - <groupId>net.devh</groupId> - <artifactId>grpc-client-spring-boot-starter</artifactId> - </dependency> + <!-- TEST --> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-configuration-processor</artifactId> + <optional>true</optional> + </dependency> + <dependency> + <groupId>io.github.hakky54</groupId> + <artifactId>logcaptor</artifactId> + <version>${logcaptor.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>de.ozgcloud.vorgang</groupId> + <artifactId>vorgang-manager-base</artifactId> + <version>${project.version}</version> + <type>test-jar</type> + <scope>test</scope> + </dependency> + </dependencies> - <!-- commons --> - <dependency> - <groupId>org.apache.commons</groupId> - <artifactId>commons-lang3</artifactId> - </dependency> - <dependency> - <groupId>org.apache.httpcomponents.client5</groupId> - <artifactId>httpclient5</artifactId> - </dependency> - <dependency> - <groupId>commons-beanutils</groupId> - <artifactId>commons-beanutils</artifactId> - </dependency> + <build> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <configuration> + <skip>true</skip> + </configuration> + </plugin> - <!-- DEV --> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-devtools</artifactId> - <scope>runtime</scope> - <optional>true</optional> - </dependency> - <dependency> - <groupId>org.projectlombok</groupId> - <artifactId>lombok</artifactId> - <optional>true</optional> - <scope>provided</scope> - </dependency> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>test-jar</goal> + </goals> + </execution> + </executions> + </plugin> - <!-- TEST --> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-test</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-configuration-processor</artifactId> - <optional>true</optional> - </dependency> - <dependency> - <groupId>io.github.hakky54</groupId> - <artifactId>logcaptor</artifactId> - <version>${logcaptor.version}</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>de.ozgcloud.vorgang</groupId> - <artifactId>vorgang-manager-base</artifactId> - <version>${project.version}</version> - <type>test-jar</type> - <scope>test</scope> - </dependency> - </dependencies> + <plugin> + <groupId>org.jvnet.jaxb</groupId> + <artifactId>jaxb-maven-plugin</artifactId> + <version>${jaxb-maven-plugin.version}</version> + <configuration> + <schemas> + <schema> + <fileset> + <directory>${basedir}/src/main/resources/bayernid</directory> + <includes> + <include>*.wsdl</include> + </includes> + </fileset> + </schema> + <schema> + <fileset> + <directory>${basedir}/src/main/resources/bayernid</directory> + <includes> + <include>*.xsd</include> + </includes> + </fileset> + </schema> + </schemas> + <episode>false</episode> + </configuration> + <executions> + <execution> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> + </plugin> - <build> - <plugins> - <plugin> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-maven-plugin</artifactId> - <configuration> - <skip>true</skip> - </configuration> - </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-jar-plugin</artifactId> - <executions> - <execution> - <goals> - <goal>test-jar</goal> - </goals> - </execution> - </executions> - </plugin> + <plugin> + <groupId>org.sonarsource.scanner.maven</groupId> + <artifactId>sonar-maven-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + </plugin> - <plugin> - <groupId>org.jvnet.jaxb</groupId> - <artifactId>jaxb-maven-plugin</artifactId> - <version>${jaxb-maven-plugin.version}</version> - <configuration> - <schemas> - <schema> - <fileset> - <directory>${basedir}/src/main/resources/bayernid</directory> - <includes> - <include>*.wsdl</include> - </includes> - </fileset> - </schema> - <schema> - <fileset> - <directory>${basedir}/src/main/resources/bayernid</directory> - <includes> - <include>*.xsd</include> - </includes> - </fileset> - </schema> - </schemas> - <episode>false</episode> - </configuration> - <executions> - <execution> - <goals> - <goal>generate</goal> - </goals> - </execution> - </executions> - </plugin> - - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - </plugin> + <plugin> + <groupId>com.mycila</groupId> + <artifactId>license-maven-plugin</artifactId> + <configuration> + <mapping> + <config>SCRIPT_STYLE</config> + </mapping> + <licenseSets> + <licenseSet> + <header>license/eupl_v1_2_de/header.txt</header> + <excludes> + <exclude>**/README</exclude> + <exclude>src/test/resources/**</exclude> + <exclude>src/main/resources/**</exclude> + </excludes> + </licenseSet> + </licenseSets> + </configuration> + <dependencies> + <dependency> + <groupId>de.ozgcloud.common</groupId> + <artifactId>ozgcloud-common-license</artifactId> + <version>${ozgcloud.license.version}</version> + </dependency> + </dependencies> + </plugin> + </plugins> + </build> - <plugin> - <groupId>org.sonarsource.scanner.maven</groupId> - <artifactId>sonar-maven-plugin</artifactId> - </plugin> - <plugin> - <groupId>org.jacoco</groupId> - <artifactId>jacoco-maven-plugin</artifactId> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-failsafe-plugin</artifactId> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-surefire-plugin</artifactId> - </plugin> - - <plugin> - <groupId>com.mycila</groupId> - <artifactId>license-maven-plugin</artifactId> - <configuration> - <mapping> - <config>SCRIPT_STYLE</config> - </mapping> - <licenseSets> - <licenseSet> - <header>license/eupl_v1_2_de/header.txt</header> - <excludes> - <exclude>**/README</exclude> - <exclude>src/test/resources/**</exclude> - <exclude>src/main/resources/**</exclude> - </excludes> - </licenseSet> - </licenseSets> - </configuration> - <dependencies> - <dependency> - <groupId>de.ozgcloud.common</groupId> - <artifactId>ozgcloud-common-license</artifactId> - <version>${ozgcloud.license.version}</version> - </dependency> - </dependencies> - </plugin> - </plugins> - </build> - - <distributionManagement> - <repository> - <id>ozg-nexus</id> - <name>ozg-releases</name> - <url>https://nexus.ozg-sh.de/repository/ozg-releases/</url> - </repository> - <snapshotRepository> - <id>ozg-snapshots-nexus</id> - <name>ozg-snapshots</name> - <url>https://nexus.ozg-sh.de/repository/ozg-snapshots/</url> - </snapshotRepository> - </distributionManagement> + <distributionManagement> + <repository> + <id>ozg-nexus</id> + <name>ozg-releases</name> + <url>https://nexus.ozg-sh.de/repository/ozg-releases/</url> + </repository> + <snapshotRepository> + <id>ozg-snapshots-nexus</id> + <name>ozg-snapshots</name> + <url>https://nexus.ozg-sh.de/repository/ozg-snapshots/</url> + </snapshotRepository> + </distributionManagement> </project> diff --git a/src/main/java/de/ozgcloud/nachrichten/antragsraum/AntragsraumGrpcService.java b/src/main/java/de/ozgcloud/nachrichten/antragsraum/AntragsraumGrpcService.java index 9e786b8c2a9320bbb3e80d99eba3d0d3d52df3e4..dccea1f32c20d3196e5921f628c8a392483edfc7 100644 --- a/src/main/java/de/ozgcloud/nachrichten/antragsraum/AntragsraumGrpcService.java +++ b/src/main/java/de/ozgcloud/nachrichten/antragsraum/AntragsraumGrpcService.java @@ -24,15 +24,15 @@ import de.ozgcloud.nachrichten.postfach.PersistPostfachNachrichtService; import de.ozgcloud.nachrichten.postfach.antragraum.*; import de.ozgcloud.vorgang.grpc.command.GrpcCommand; import io.grpc.stub.StreamObserver; -import org.springframework.beans.factory.annotation.Autowired; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.NotImplementedException; import org.springframework.stereotype.Service; @Service +@RequiredArgsConstructor public class AntragsraumGrpcService extends AntragraumServiceGrpc.AntragraumServiceImplBase { - @Autowired - private PersistPostfachNachrichtService postfachNachrichtService; - @Autowired - private NachrichtMapper mapper; + private final PersistPostfachNachrichtService postfachNachrichtService; + private final NachrichtMapper mapper; @Override public void findRueckfragen(GrpcFindRueckfragenRequest request, StreamObserver<GrpcFindRueckfragenResponse> streamObserver) { @@ -59,8 +59,7 @@ public class AntragsraumGrpcService extends AntragraumServiceGrpc.AntragraumServ public void sendRueckfrageAnswer(GrpcSendRueckfrageAnswerRequest request, StreamObserver<GrpcCommand> streamObserver) { verifyToken(request.getSamlToken()); - streamObserver.onNext(null); - streamObserver.onCompleted(); + throw new NotImplementedException("sendRueckfrageAnswer not implemented yet"); } void verifyToken(String token) { diff --git a/src/main/java/de/ozgcloud/nachrichten/antragsraum/BayernIdSamlConfiguration.java b/src/main/java/de/ozgcloud/nachrichten/antragsraum/BayernIdSamlConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..728c4bbc23878e8f7824de5c6b756f38b0336293 --- /dev/null +++ b/src/main/java/de/ozgcloud/nachrichten/antragsraum/BayernIdSamlConfiguration.java @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2024. + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ + +package de.ozgcloud.nachrichten.antragsraum; + +import jakarta.annotation.PostConstruct; +import lombok.extern.log4j.Log4j2; +import net.shibboleth.utilities.java.support.resolver.CriteriaSet; +import net.shibboleth.utilities.java.support.xml.BasicParserPool; +import net.shibboleth.utilities.java.support.xml.ParserPool; +import org.opensaml.core.config.ConfigurationService; +import org.opensaml.core.config.InitializationService; +import org.opensaml.core.criterion.EntityIdCriterion; +import org.opensaml.core.xml.XMLObject; +import org.opensaml.core.xml.config.XMLObjectProviderRegistry; +import org.opensaml.core.xml.io.Unmarshaller; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.criterion.ProtocolCriterion; +import org.opensaml.saml.metadata.criteria.role.impl.EvaluableProtocolRoleDescriptorCriterion; +import org.opensaml.saml.saml2.metadata.EntitiesDescriptor; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.IDPSSODescriptor; +import org.opensaml.saml.saml2.metadata.KeyDescriptor; +import org.opensaml.security.credential.Credential; +import org.opensaml.security.credential.CredentialResolver; +import org.opensaml.security.credential.UsageType; +import org.opensaml.security.credential.criteria.impl.EvaluableEntityIDCredentialCriterion; +import org.opensaml.security.credential.criteria.impl.EvaluableUsageCredentialCriterion; +import org.opensaml.security.credential.impl.CollectionCredentialResolver; +import org.opensaml.security.criteria.UsageCriterion; +import org.opensaml.security.x509.BasicX509Credential; +import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap; +import org.opensaml.xmlsec.keyinfo.KeyInfoSupport; +import org.opensaml.xmlsec.signature.support.SignatureTrustEngine; +import org.opensaml.xmlsec.signature.support.impl.ExplicitKeySignatureTrustEngine; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.Resource; +import org.springframework.security.converter.RsaKeyConverters; +import org.springframework.security.saml2.Saml2Exception; +import org.springframework.security.saml2.core.Saml2X509Credential; +import org.springframework.util.Assert; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.io.IOException; +import java.io.InputStream; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPrivateKey; +import java.util.*; + +@Configuration +@Log4j2 +public class BayernIdSamlConfiguration { + @Value("${ozgcloud.bayernid.saml.entity-id}") + private String entityId; + @Value("${ozgcloud.bayernid.saml.metadata-uri}") + private Resource metadataUri; + @Value("${ozgcloud.bayernid.saml.signing.private-key-location}") + private Resource signingPrivateKey; + @Value("${ozgcloud.bayernid.saml.signing.certificate-location}") + private Resource signingCertificate; + @Value("${ozgcloud.bayernid.saml.decryption.private-key-location}") + private Resource decryptionPrivateKey; + @Value("${ozgcloud.bayernid.saml.decryption.certificate-location}") + private Resource decryptionCertificate; + private XMLObjectProviderRegistry registry; + + @PostConstruct + void initOpenSAML() { + try { + registry = new XMLObjectProviderRegistry(); + ConfigurationService.register(XMLObjectProviderRegistry.class, registry); + + registry.setParserPool(getParserPool()); + InitializationService.initialize(); + } catch (Exception e) { + throw new RuntimeException("Initialization failed"); + } + } + + @Bean + Saml2Decrypter decrypter() { + return new Saml2Decrypter(asDecryptionCredential()); + } + + @Bean + Saml2Parser parser() { + try { + return new Saml2Parser(getParserPool()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Bean + Saml2Verifier verifier() { + return new Saml2Verifier(parser(), trustEngine(), verificationCriteria()); + } + + SignatureTrustEngine trustEngine() { + Set<Credential> credentials = new HashSet<>(); + Collection<Saml2X509Credential> keys = getCertificatesFromMetadata(); + + for (Saml2X509Credential key : keys) { + BasicX509Credential cred = new BasicX509Credential(key.getCertificate()); + cred.setUsageType(UsageType.SIGNING); + cred.setEntityId(entityId); + credentials.add(cred); + } + + CredentialResolver credentialsResolver = new CollectionCredentialResolver(credentials); + return new ExplicitKeySignatureTrustEngine(credentialsResolver, DefaultSecurityConfigurationBootstrap.buildBasicInlineKeyInfoCredentialResolver()); + } + + CriteriaSet verificationCriteria() { + CriteriaSet criteria = new CriteriaSet(); + criteria.add(new EvaluableEntityIDCredentialCriterion(new EntityIdCriterion(entityId))); + criteria.add(new EvaluableProtocolRoleDescriptorCriterion(new ProtocolCriterion("urn:oasis:names:tc:SAML:2.0:protocol"))); + criteria.add(new EvaluableUsageCredentialCriterion(new UsageCriterion(UsageType.SIGNING))); + return criteria; + } + + private Saml2X509Credential asDecryptionCredential() { + RSAPrivateKey privateKey = readPrivateKey(decryptionPrivateKey); + X509Certificate certificate = readCertificateFromResource(decryptionCertificate); + return new Saml2X509Credential(privateKey, certificate, Saml2X509Credential.Saml2X509CredentialType.DECRYPTION); + } + + private RSAPrivateKey readPrivateKey(Resource location) { + Assert.state(location != null, "No private key location specified"); + Assert.state(location.exists(), () -> "Private key location '" + location + "' does not exist"); + + try (InputStream inputStream = location.getInputStream()) { + return RsaKeyConverters.pkcs8().convert(inputStream); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } + + private X509Certificate readCertificateFromResource(Resource location) { + Assert.state(location != null, "No certificate location specified"); + Assert.state(location.exists(), () -> "Certificate location '" + location + "' does not exist"); + + try (InputStream inputStream = location.getInputStream()) { + + return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(inputStream); + } catch (IOException | CertificateException e) { + throw new IllegalArgumentException(e); + } + } + + List<Saml2X509Credential> getCertificatesFromMetadata() { + try (InputStream metadata = metadataUri.getInputStream()) { + XMLObject xmlObject = xmlObject(metadata); + if (xmlObject instanceof EntitiesDescriptor descriptors) { + for (EntityDescriptor descriptor : descriptors.getEntityDescriptors()) { + if (descriptor.getIDPSSODescriptor(SAMLConstants.SAML20P_NS) != null) { + return getVerificationCertificates(descriptor); + } + } + } + } catch (IOException e) { + LOG.error("Error reading idp metadata. ", e); + throw new Saml2Exception("Error reading medatadata.", e); + } + + throw new Saml2Exception("No IDPSSO Descriptors found"); + } + + private XMLObject xmlObject(InputStream inputStream) { + Document document = document(inputStream); + Element element = document.getDocumentElement(); + Unmarshaller unmarshaller = this.registry.getUnmarshallerFactory().getUnmarshaller(element); + if (unmarshaller == null) { + throw new Saml2Exception("Unsupported element of type " + element.getTagName()); + } + try { + return unmarshaller.unmarshall(element); + } catch (Exception ex) { + throw new Saml2Exception(ex); + } + } + + private Document document(InputStream inputStream) { + try { + return getParserPool().parse(inputStream); + } catch (Exception ex) { + throw new Saml2Exception(ex); + } + } + + static ParserPool getParserPool() throws Exception { + BasicParserPool parserPool = new BasicParserPool(); + parserPool.setMaxPoolSize(100); + parserPool.setCoalescing(true); + parserPool.setIgnoreComments(true); + parserPool.setIgnoreElementContentWhitespace(true); + parserPool.setNamespaceAware(true); + parserPool.setExpandEntityReferences(false); + parserPool.setXincludeAware(false); + + final Map<String, Boolean> features = createFeatureMap(); + + parserPool.setBuilderFeatures(features); + + parserPool.setBuilderAttributes(new HashMap<>()); + + parserPool.initialize(); + + return parserPool; + } + + private static Map<String, Boolean> createFeatureMap() { + final Map<String, Boolean> features = new HashMap<>(); + features.put("http://xml.org/sax/features/external-general-entities", Boolean.FALSE); + features.put("http://xml.org/sax/features/external-parameter-entities", Boolean.FALSE); + features.put("http://apache.org/xml/features/disallow-doctype-decl", Boolean.TRUE); + features.put("http://apache.org/xml/features/validation/schema/normalized-value", Boolean.FALSE); + features.put("http://javax.xml.XMLConstants/feature/secure-processing", Boolean.TRUE); + return features; + } + + List<Saml2X509Credential> getVerificationCertificates(EntityDescriptor descriptor) { + IDPSSODescriptor idpssoDescriptor = descriptor.getIDPSSODescriptor(SAMLConstants.SAML20P_NS); + if (idpssoDescriptor == null) { + throw new Saml2Exception("Metadata response is missing the necessary IDPSSODescriptor element"); + } + List<Saml2X509Credential> verification = new ArrayList<>(); + for (KeyDescriptor keyDescriptor : idpssoDescriptor.getKeyDescriptors()) { + if (keyDescriptor.getUse().equals(UsageType.SIGNING)) { + List<X509Certificate> certificates = certificates(keyDescriptor); + for (X509Certificate certificate : certificates) { + verification.add(Saml2X509Credential.verification(certificate)); + } + } + } + if (verification.isEmpty()) { + throw new Saml2Exception( + "Metadata response is missing verification certificates, necessary for verifying SAML assertions"); + } + + return verification; + } + + private List<X509Certificate> certificates(KeyDescriptor keyDescriptor) { + try { + return KeyInfoSupport.getCertificates(keyDescriptor.getKeyInfo()); + } catch (CertificateException ex) { + throw new Saml2Exception(ex); + } + } +} diff --git a/src/main/java/de/ozgcloud/nachrichten/antragsraum/NachrichtMapper.java b/src/main/java/de/ozgcloud/nachrichten/antragsraum/NachrichtMapper.java index 226c906b3e9c84b32aa13bfc7a3227b5d4a28b15..c7411a3898ce03c3679f00ce2dafea8800520e51 100644 --- a/src/main/java/de/ozgcloud/nachrichten/antragsraum/NachrichtMapper.java +++ b/src/main/java/de/ozgcloud/nachrichten/antragsraum/NachrichtMapper.java @@ -22,13 +22,35 @@ package de.ozgcloud.nachrichten.antragsraum; import de.ozgcloud.nachrichten.postfach.PostfachNachricht; import de.ozgcloud.nachrichten.postfach.antragraum.GrpcRueckfrage; +import org.apache.commons.collections.MapUtils; import org.mapstruct.Mapper; +import java.util.Collections; import java.util.Map; @Mapper public interface NachrichtMapper { - GrpcRueckfrage toGrpc(PostfachNachricht postfachNachricht); + String DEFAULT_STATUS = "NEU"; - GrpcRueckfrage toGrpc(Map<String, Object> itemMap); + default GrpcRueckfrage toGrpc(PostfachNachricht postfachNachricht) { + return GrpcRueckfrage.newBuilder() + .setText(postfachNachricht.getMailBody()) + .setSendAt(postfachNachricht.getSentAt().toString()) + .setVorgangName(postfachNachricht.getSubject()) + .setVorgangId(postfachNachricht.getVorgangId()) + .setStatus(DEFAULT_STATUS) + .addAllAnswerAttachmentFileId(postfachNachricht.getAttachments()) + .build(); + } + + @SuppressWarnings("unchecked") + default GrpcRueckfrage toGrpc(Map<String, Object> itemMap) { + var rueckfrageBuilder = GrpcRueckfrage.newBuilder() + .setId(MapUtils.getString(itemMap, PostfachNachricht.FIELD_ID)) + .setVorgangId(MapUtils.getString(itemMap, PostfachNachricht.FIELD_VORGANG_ID)) + .setVorgangName(MapUtils.getString(itemMap, PostfachNachricht.FIELD_SUBJECT)) + .addAllAnswerAttachmentFileId((Iterable<String>) itemMap.getOrDefault(PostfachNachricht.FIELD_ATTACHMENTS, Collections.emptyList())); + + return rueckfrageBuilder.build(); + } } diff --git a/src/main/java/de/ozgcloud/nachrichten/antragsraum/Saml2Decrypter.java b/src/main/java/de/ozgcloud/nachrichten/antragsraum/Saml2Decrypter.java new file mode 100644 index 0000000000000000000000000000000000000000..4b96afe825179720ddbac9415ff38c5c89d52721 --- /dev/null +++ b/src/main/java/de/ozgcloud/nachrichten/antragsraum/Saml2Decrypter.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2024. + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ + +package de.ozgcloud.nachrichten.antragsraum; + +import org.opensaml.core.xml.XMLObject; +import org.opensaml.core.xml.schema.XSString; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.AttributeStatement; +import org.opensaml.saml.saml2.core.EncryptedAssertion; +import org.opensaml.saml.saml2.core.Response; +import org.opensaml.saml.saml2.encryption.Decrypter; +import org.opensaml.saml.saml2.encryption.EncryptedElementTypeEncryptedKeyResolver; +import org.opensaml.security.credential.Credential; +import org.opensaml.security.credential.CredentialSupport; +import org.opensaml.xmlsec.encryption.support.ChainingEncryptedKeyResolver; +import org.opensaml.xmlsec.encryption.support.EncryptedKeyResolver; +import org.opensaml.xmlsec.encryption.support.InlineEncryptedKeyResolver; +import org.opensaml.xmlsec.encryption.support.SimpleRetrievalMethodEncryptedKeyResolver; +import org.opensaml.xmlsec.keyinfo.KeyInfoCredentialResolver; +import org.opensaml.xmlsec.keyinfo.impl.CollectionKeyInfoCredentialResolver; +import org.springframework.security.saml2.Saml2Exception; +import org.springframework.security.saml2.core.Saml2X509Credential; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +class Saml2Decrypter { + private final Decrypter decrypter; + private static final EncryptedKeyResolver encryptedKeyResolver = new ChainingEncryptedKeyResolver( + Arrays.asList(new InlineEncryptedKeyResolver(), new EncryptedElementTypeEncryptedKeyResolver(), + new SimpleRetrievalMethodEncryptedKeyResolver())); + + public Saml2Decrypter(Saml2X509Credential decryptionX509Credential) { + Collection<Credential> credentials = new ArrayList<>(); + + Credential cred = CredentialSupport.getSimpleCredential(decryptionX509Credential.getCertificate(), decryptionX509Credential.getPrivateKey()); + credentials.add(cred); + + KeyInfoCredentialResolver resolver = new CollectionKeyInfoCredentialResolver(credentials); + Decrypter decrypter = new Decrypter(null, resolver, encryptedKeyResolver); + decrypter.setRootInNewDocument(true); + + this.decrypter = decrypter; + } + + void decryptResponseElements(Response response) { + for (EncryptedAssertion encryptedAssertion : response.getEncryptedAssertions()) { + try { + Assertion assertion = decrypter.decrypt(encryptedAssertion); + response.getAssertions().add(assertion); + } catch (Exception ex) { + throw new Saml2Exception(ex); + } + } + } + + String decryptPostfachId(Response response) { + decryptResponseElements(response); + + var samlAssertion = response.getAssertions().get(0); + var statements = (AttributeStatement) samlAssertion.getStatements().get(1); + var attributes = statements.getAttributes(); + var postfachIdOptional = attributes.stream().filter(attribute -> "legacyPostkorbHandle".equals(attribute.getFriendlyName())).findFirst(); + + return postfachIdOptional.map(postfachIdAttribute -> { + List<XMLObject> values = postfachIdAttribute.getAttributeValues(); + return ((XSString) values.get(0)).getValue(); + }).orElseThrow(); + + } +} diff --git a/src/main/java/de/ozgcloud/nachrichten/antragsraum/Saml2Parser.java b/src/main/java/de/ozgcloud/nachrichten/antragsraum/Saml2Parser.java new file mode 100644 index 0000000000000000000000000000000000000000..872ebf753a2d34a74de1f95edeb93f4f53bfe755 --- /dev/null +++ b/src/main/java/de/ozgcloud/nachrichten/antragsraum/Saml2Parser.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024. + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ + +package de.ozgcloud.nachrichten.antragsraum; + +import net.shibboleth.utilities.java.support.xml.ParserPool; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.saml.saml2.core.Response; +import org.opensaml.saml.saml2.core.impl.ResponseUnmarshaller; +import org.springframework.security.saml2.Saml2Exception; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; + +class Saml2Parser { + private final ParserPool parserPool; + private ResponseUnmarshaller unmarshaller; + + Saml2Parser(ParserPool parserPool) { + this.parserPool = parserPool; + init(); + } + + void init() { + try { + unmarshaller = (ResponseUnmarshaller) XMLObjectProviderRegistrySupport.getUnmarshallerFactory().getUnmarshaller(Response.DEFAULT_ELEMENT_NAME); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + Response parse(String request) throws Saml2Exception { + try { + Document document = parserPool.parse(new ByteArrayInputStream(request.getBytes(StandardCharsets.UTF_8))); + Element element = document.getDocumentElement(); + return (Response) unmarshaller.unmarshall(element); + } catch (Exception e) { + throw new Saml2Exception("Failed to deserialize LogoutRequest", e); + } + } +} diff --git a/src/main/java/de/ozgcloud/nachrichten/antragsraum/Saml2Verifier.java b/src/main/java/de/ozgcloud/nachrichten/antragsraum/Saml2Verifier.java new file mode 100644 index 0000000000000000000000000000000000000000..5ec95ae2580be0107ed1abb4fc71dc35dabb7a6b --- /dev/null +++ b/src/main/java/de/ozgcloud/nachrichten/antragsraum/Saml2Verifier.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2024. + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ + +package de.ozgcloud.nachrichten.antragsraum; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import net.shibboleth.utilities.java.support.resolver.CriteriaSet; +import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator; +import org.opensaml.xmlsec.signature.Signature; +import org.opensaml.xmlsec.signature.support.SignatureTrustEngine; +import org.springframework.security.saml2.core.Saml2Error; +import org.springframework.security.saml2.core.Saml2ErrorCodes; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +@Log4j2 +@RequiredArgsConstructor +class Saml2Verifier { + public static final String INVALID_SIGNATURE = "Invalid signature for object [%s]: "; + public static final String SIGNATURE_MISSING = "Signature missing"; + private final Saml2Parser parser; + private final SignatureTrustEngine trustEngine; + private final CriteriaSet verificationCriteria; + + + List<Saml2Error> verify(String samlToken) { + var response = parser.parse(samlToken); + + List<Saml2Error> errors = new ArrayList<>(); + Signature signature = response.getSignature(); + SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator(); + if (Objects.nonNull(signature)) { + try { + profileValidator.validate(signature); + } catch (Exception ex) { + LOG.error("Error validating SAML Token: ", ex); + errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE, INVALID_SIGNATURE.formatted(response.getID()))); + } + + try { + if (!trustEngine.validate(signature, verificationCriteria)) { + errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE, INVALID_SIGNATURE.formatted(response.getID()))); + } + } catch (Exception ex) { + LOG.error("Error validating SAML Token: ", ex); + errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE, INVALID_SIGNATURE.formatted(response.getID()))); + } + } else { + errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE, SIGNATURE_MISSING)); + } + + return errors; + } +} diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8c90a64fc001ba9fdf129f03b842dc747592f18c --- /dev/null +++ b/src/main/resources/application.yaml @@ -0,0 +1,8 @@ +ozgcloud: + bayernid: + saml: + entity-id: https://antragsraum.ozgcloud.de/ + metadata-uri: "classpath:/bayernid/metadata/bayernid-idp-infra.xml" + decryption: + private-key-location: "classpath:/bayernid/bayernid-test-enc.key" + certificate-location: "classpath:/bayernid/bayernid-test-enc.crt" \ No newline at end of file diff --git a/src/main/resources/bayernid/bayernid-test-enc.crt b/src/main/resources/bayernid/bayernid-test-enc.crt new file mode 100644 index 0000000000000000000000000000000000000000..fe04bc8d5ad148f0e84ca1c98160c111f3aeba5d --- /dev/null +++ b/src/main/resources/bayernid/bayernid-test-enc.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDsTCCApmgAwIBAgIUdw/27be5+2vj+MhGtoJjDsMsdDEwDQYJKoZIhvcNAQEL +BQAwaDELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJheWVybjERMA8GA1UEBwwITXVl +bmNoZW4xDzANBgNVBAoMBm1nbSB0cDEkMCIGCSqGSIb3DQEJARYVamVucy5yZWVz +ZUBtZ20tdHAuY29tMB4XDTI0MDExNjEyMjI0OVoXDTI1MDExNTEyMjI0OVowaDEL +MAkGA1UEBhMCREUxDzANBgNVBAgMBkJheWVybjERMA8GA1UEBwwITXVlbmNoZW4x +DzANBgNVBAoMBm1nbSB0cDEkMCIGCSqGSIb3DQEJARYVamVucy5yZWVzZUBtZ20t +dHAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/HBBWBDSrEgd +wXkSy15V00EaVTyLgc4vh/JcDiGIYZSqmcMwBd+B1u36xbdBf/duEtCUymMNP48O +MjgFZtR6xn0meuR4NR6Ykn9mYGdU/GhldGuGv9XLAEAkVuTlo0H1QYyBS/6JwKQo +SsHDkJ3YwDwKcyOt7QtpSadRZjQEN3gDvWoRYjgXTxj2I1ovllmi0zOHsFi5PBIu +iPWUdJvBrHxpD/XVS9R/qzJpHPu3bjQ6UVRmhiZCUF7H5F/PQNwk+qXvjV0ooBeS +WWO5hywhk4OP4QEgbYMOSo20YukYX8TJEsum1pwIcQrw7kW4GyKaAycyRsa1fbM3 +tEkj+TiBKwIDAQABo1MwUTAdBgNVHQ4EFgQUfDL/6R33SJodsONCvxKy96AtU18w +HwYDVR0jBBgwFoAUfDL/6R33SJodsONCvxKy96AtU18wDwYDVR0TAQH/BAUwAwEB +/zANBgkqhkiG9w0BAQsFAAOCAQEA+PCnvSwKU+bArTCIg5lfrwONbzKkjvPUymDN +YX3oj1wVEN75hNf0RD7Rr0//ZYT3Rt0G193gjDcH1gbGIYhMLeGGkxEous2l3O+p +RIQRR+hprjr6HzF8IphaJy1RbDwyGsXyLcyOylPL4cX9IjUdhklHiLZusBq95LSy +w7hsCOAL2+vn816O7yv+28EWXXbnP2XEUjW36nxcZvR6oTJUplXyHRuuJJTsOxGR +NuXA3UVgNbkdm1HnoSGpnsGdUKsUFoEmEJkcSdQRwxeH21WzYGOZmKMcvx2gObaS +P8tafWh5z4Jx+Z7z5WP72Jt44/lnVjaV8aGo0KHXwgqQOtYftQ== +-----END CERTIFICATE----- diff --git a/src/main/resources/bayernid/bayernid-test-enc.key b/src/main/resources/bayernid/bayernid-test-enc.key new file mode 100644 index 0000000000000000000000000000000000000000..8d1c8b69c3fce7bea45c73efd06983e3c419a92f --- /dev/null +++ b/src/main/resources/bayernid/bayernid-test-enc.key @@ -0,0 +1 @@ + diff --git a/src/main/resources/bayernid/metadata/bayernid-idp-infra.xml b/src/main/resources/bayernid/metadata/bayernid-idp-infra.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec1ed7ca7099b8be7a8cff7448a740f0b9404c34 --- /dev/null +++ b/src/main/resources/bayernid/metadata/bayernid-idp-infra.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?><md:EntitiesDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"> + <md:EntityDescriptor entityID="https://infra-pre-id.bayernportal.de/idp"> + <md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> + <md:KeyDescriptor use="signing"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIFbzCCA1egAwIBAgIJAPdFXXarkBN2MA0GCSqGSIb3DQEBCwUAME4xCzAJBgNV + BAYTAkRFMQ8wDQYDVQQIDAZCYXllcm4xETAPBgNVBAcMCE11ZW5jaGVuMQ0wCwYD + VQQKDARBS0RCMQwwCgYDVQQLDANJRE0wHhcNMjAxMDI3MTMxODQxWhcNMjUxMDI2 + MTMxODQxWjBOMQswCQYDVQQGEwJERTEPMA0GA1UECAwGQmF5ZXJuMREwDwYDVQQH + DAhNdWVuY2hlbjENMAsGA1UECgwEQUtEQjEMMAoGA1UECwwDSURNMIICIjANBgkq + hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzDtWAEdC3J9FD+ti1exRhN1lzNgKWqO2 + gQNdJvlt7KGHA2VGGO7tqRogTuoqi/ydtiHJ8+lhp4kcWqyfv7i9HXOncvcsRRmR + dZjUY2Iui6ozJqD5LVm/vP5YfdP7vQPdbqyyfpoJhf3mbMEtdNDdGRnGIPUfDn+C + Fbo37f9tPwMgf3jgh4gxaujtLIhhr9gevVTEeZAFu9EvzLNd3kEtRb7MuXqIOdu1 + rW8HlGYFwwVLqEyBn8XG0QAIfhMmGjFMG7z+Kco2quwOmmZVzWQfeH/3AlN2KbcP + t7j+pl+6Bew2AAivP7O+95YKORqQjTu3rPWMF4txPId37MSjoytwBRyd5EACTvhQ + BOGrDFKQUOx6fTtRc8+7XGVz8MdQaZQWQXXh1ByU783twNdnRSrSVIyLdjiy1uCb + jvsSAtbzGBygPIvDo3skCNLNFXsChtHIfFFDK20KPGb0ghEDf2q3hDbFG3ZDGGyn + ZmJcZKuZhJqodJ/++sAXADyTJNAPVYDjKCF4ypELp2Eu/p1gaQPJEb74L/ZFZVOE + JFyXIiaqB9J+fcn/biqHHOmcCi8n9aIiNt1fatr1Z4lQRWoGtKaGU0+bzUSH4Bgs + 2EG4u1CI2MKDWqK2aEsHrtu8tbS9LrUmDVKtaEUOeul8xWVa036vp/YUIdiJNZSx + ZG4iTmSOATECAwEAAaNQME4wHQYDVR0OBBYEFFYeltslkaolOmcINXQeSe7nURwp + MB8GA1UdIwQYMBaAFFYeltslkaolOmcINXQeSe7nURwpMAwGA1UdEwQFMAMBAf8w + DQYJKoZIhvcNAQELBQADggIBAKqAlXoO41SAiycYUOrR90pfwTCysmbtHF5RWSCM + jF2aCG8URJ7bXwC0lBH8E5zCetFZwdqZziQtxzRkIOfhS5uWbH0RDhwuxZG+5RTP + yaHPAZI6e5xHDu8vHl/VbC3lnL/6K8l+Purr/yo8qkJqrPgThZRL9jBQyYRhDSsJ + UyIw5zcKKUQC/JWtMQAQcopbjekCs6xDT1HqIN90Sc/gOfYjNo0dGMNmro9mxcw8 + 2Iow18KNVdtEexfD+/6x4NPD61pzuQEe09TR+Cv3XyzBoGQ/2arijcPnGvth79ff + VFtRSf3fSs7wEKV9g3mEWXFDtPBhDj6K0kKU/kJfEZixkXl92MY+bmugrtTIrazj + tfrgMglIAHu9XCYWd/gef0J+PNfHsxgbTEr3XSC+5/xoFKPQSw3PgV8lkUDq4mJU + Ky/q4YmA37XQxourFR5pWvF03YACdtq6zPjtVeI7Cvkte6k0YW5S3cx9RmPv6YZh + laZ5ERpWNiv6IjokLsvNeemf2PApjO7Q2EDBIoHBYH31wwJSsyRDrSVmbaqLFI15 + fLXeh2A4YbaBDZdGvDiLOAk+dG1wdZ2aGw/uNBzMtc8VeKqI1HPcqIluBA3uUPpy + LLA+9hDPf6Pp4j0gkXxBikz+/h22bFxE1HmDiOSkEn+2NmOHuEFeA+D8jsCAL5VJ + 3emK</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat> + <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://infra-pre-id.bayernportal.de/idp/profile/SAML2/POST/SSO"/> + <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://infra-pre-id.bayernportal.de/idp/profile/SAML2/Redirect/SSO"/> + </md:IDPSSODescriptor> + </md:EntityDescriptor> +</md:EntitiesDescriptor> \ No newline at end of file diff --git a/src/main/resources/bayernid/metadata/bayernid-idp.xml b/src/main/resources/bayernid/metadata/bayernid-idp.xml new file mode 100644 index 0000000000000000000000000000000000000000..ebcc84c287b6dc26ed23c56a7ab359fc109f942e --- /dev/null +++ b/src/main/resources/bayernid/metadata/bayernid-idp.xml @@ -0,0 +1,47 @@ +<md:EntitiesDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"> + <md:EntityDescriptor entityID="https://id.bayernportal.de/idp"> + <md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> + <md:KeyDescriptor use="signing"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIFbzCCA1egAwIBAgIJAIpEXcxsS1nEMA0GCSqGSIb3DQEBCwUAME4xCzAJBgNV + BAYTAkRFMQ8wDQYDVQQIDAZCYXllcm4xETAPBgNVBAcMCE11ZW5jaGVuMQ0wCwYD + VQQKDARBS0RCMQwwCgYDVQQLDANJRE0wHhcNMjAxMDI3MTMxNzE3WhcNMjUxMDI2 + MTMxNzE3WjBOMQswCQYDVQQGEwJERTEPMA0GA1UECAwGQmF5ZXJuMREwDwYDVQQH + DAhNdWVuY2hlbjENMAsGA1UECgwEQUtEQjEMMAoGA1UECwwDSURNMIICIjANBgkq + hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4MvmcEZhH4gcNhLLsEBhbB24fbU7ex1K + ZROJr4s8OMqAHryfenCFxxVKPI8Vm2+qg6SY+D+MbKHc3lITYecq0EAQQoV1M1bc + D31qVRtxTVb1Q9qGTv2V72LZB12qCCcgyWT4LOKTnGYUv5dIyj6EkEgVn8+Ia5Ow + Q5KeoCsh9yVo5PJBJXkerQEA/M4/LkT/obeaK+3+8eRGFmoGLb+bFM40ths9St2j + eeYT3UWl9NTY66mq4YVDZcaimUCMJQ4X9SjQ8HZeLgRzLx5X/6PwAJysyKVseN4j + SV+4sm/HnMrPcQLLLQCD0ltdp1jk5zvoZ6C8cZ8FJ7kCJ+Kvz1zEmH32Pw0bxPwB + QsKabyRxg5ESTIWwE2lWOnuooqSWk8lZIaGf8Sn8JFjRaVqVKN6JRFxgryurreJL + 9igN1e5cOdKYwXLfuqygcdVW40wYTjsL1MxKVf9Pb8J4EuOC95Hb85X6VckwRCx8 + Yroyr/UeDM8SKgsBJuSqTuFCo6oTf3zjDaD+BBzdVqBmQELfY81laG3at1A3vz0M + E9UkY5kv9/LH161YIDELgir63fBNsQSXPir5awP8xihgUlmCIfOXiMU+m9vp60KL + 8LzA2AODo2H5AY7BMxAlM+LF+KvPqUBxdq2QyTnhQFaeiP9l7Lk1xagnloiR6rW/ + GP+hsBAVO5UCAwEAAaNQME4wHQYDVR0OBBYEFAS91fX286nxHd+4kJSFE4clWiuC + MB8GA1UdIwQYMBaAFAS91fX286nxHd+4kJSFE4clWiuCMAwGA1UdEwQFMAMBAf8w + DQYJKoZIhvcNAQELBQADggIBAMt8FUGWNqtKAuVAklNojt9JXk476XvZNXn4lTjx + IaIyQLd+SpJ4vKPDAb78mKF4PtTdG2pqDIarvuxyLvG4Ut8Cd/NHTI9j9V7Yuw9g + MKPKzXfI9Zb4pOIantmEspRr/BApLPJzZMHI8KmeQ3V0Ip3i8QHMuHfkFuTN9hdS + mKTqoWZTo6dLawOkOpgjKh5RQjqjbXWUovMWQc/tffzUved0LePbPllJgSjUZRxm + +723ToZ1frFCYpFj1xJiOuqr+GJdtWz0DFRt+nXxRfznYtXd1YRC5BzpVwNtH8GL + OZfyH1HZtn1x5hcQOnRHwgcx37lJRW8yprAMiqLHtNYNlY/SD1KNMmqT07pkBwMq + Cgvic7T2yj9Jg38s6XjiwWiFRMNhC2+z9G1uf63tfXLi3J8HS8YyTSjEK+9aXMEj + 57HWHBsLAiAzO+RyrVdTEnp0f5qbUeu0d4DKvHocOWkxu0jp220ZlCHPm6f/nWM/ + Eo5TGT0htLo0vidoj36PmCu2KOJ+AhdEml81/M5ENg8ofhhkidiQo2he7eGjLyn4 + 4DPvSAiK/S1rvQmF65j/6mg0guFbGLpmLFQJXPztok2xTA+Vwvd/T5FxMNkKR9mh + P9E8rUGOu4hGB4KSHD8mo8nYyp1cCke72e7dMobhLGsCqxEnIeO+NTBzSbd/gqGm 2fd0 + </ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat> + <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" + Location="https://id.bayernportal.de/idp/profile/SAML2/POST/SSO"/> + <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" + Location="https://id.bayernportal.de/idp/profile/SAML2/Redirect/SSO"/> + </md:IDPSSODescriptor> + </md:EntityDescriptor> +</md:EntitiesDescriptor> \ No newline at end of file diff --git a/src/test/java/de/ozgcloud/nachrichten/antragsraum/AntragsraumGrpcServiceTest.java b/src/test/java/de/ozgcloud/nachrichten/antragsraum/AntragsraumGrpcServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..27e3f85376469e9657409e9fc6beaa2197d336e8 --- /dev/null +++ b/src/test/java/de/ozgcloud/nachrichten/antragsraum/AntragsraumGrpcServiceTest.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024. + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ + +package de.ozgcloud.nachrichten.antragsraum; + +import org.junit.jupiter.api.BeforeEach; + +class AntragsraumGrpcServiceTest { + + @BeforeEach + void setUp() { + } +} \ No newline at end of file diff --git a/src/test/java/de/ozgcloud/nachrichten/antragsraum/BayernIdSamlConfigurationITCase.java b/src/test/java/de/ozgcloud/nachrichten/antragsraum/BayernIdSamlConfigurationITCase.java new file mode 100644 index 0000000000000000000000000000000000000000..f2ab9263006f84fd72767dad5f8ce4e59cf4be3d --- /dev/null +++ b/src/test/java/de/ozgcloud/nachrichten/antragsraum/BayernIdSamlConfigurationITCase.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024. + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ + +package de.ozgcloud.nachrichten.antragsraum; + +import de.ozgcloud.common.test.ITCase; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.*; + +@ITCase +@SpringBootTest(classes = {BayernIdSamlConfiguration.class}) +class BayernIdSamlConfigurationITCase { + @Autowired + private BayernIdSamlConfiguration bayernIdSamlConfiguration; + + @Test + void shouldCreateTrustEngine() { + assertThat(bayernIdSamlConfiguration.trustEngine()).isNotNull(); + } + + @Test + void shouldCreateVerificationCriteria() { + assertThat(bayernIdSamlConfiguration.verificationCriteria()).isNotNull(); + } + + @Test + void shouldLoadVerificationCert() throws Exception { + assertThat(bayernIdSamlConfiguration.getCertificatesFromMetadata()).isNotNull(); + } +} \ No newline at end of file diff --git a/src/test/java/de/ozgcloud/nachrichten/antragsraum/NachrichtMapperTest.java b/src/test/java/de/ozgcloud/nachrichten/antragsraum/NachrichtMapperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..bd8f93a8ec4d8bbc55a77f1fd05c165de5747237 --- /dev/null +++ b/src/test/java/de/ozgcloud/nachrichten/antragsraum/NachrichtMapperTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2024. + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ + +package de.ozgcloud.nachrichten.antragsraum; + +import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory; +import de.ozgcloud.nachrichten.postfach.antragraum.GrpcRueckfrage; +import de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory; +import org.junit.jupiter.api.Test; +import org.mapstruct.factory.Mappers; + +import static org.assertj.core.api.Assertions.*; + +class NachrichtMapperTest { + + NachrichtMapper mapper = Mappers.getMapper(NachrichtMapper.class); + + @Test + void shouldMapVorgangId() { + var result = map(); + + assertThat(result.getVorgangId()).isEqualTo(MessageTestFactory.VORGANG_ID); + } + + @Test + void shouldMapVorgangName() { + var result = map(); + + assertThat(result.getVorgangName()).isEqualTo(MessageTestFactory.SUBJECT); + } + + @Test + void shouldMapStatus() { + var result = map(); + + assertThat(result.getStatus()).isEqualTo(NachrichtMapper.DEFAULT_STATUS); + } + + @Test + void shouldMapSendAt() { + var result = map(); + + assertThat(result.getSendAt()).isEqualTo(PostfachNachrichtTestFactory.SENT_AT.toString()); + } + + @Test + void shouldMapText() { + var result = map(); + + assertThat(result.getText()).isEqualTo(PostfachNachrichtTestFactory.MAIL_BODY); + } + + @Test + void shouldMapAttachments() { + var result = map(); + + assertThat(result.getAnswerAttachmentFileIdCount()).isEqualTo(1); + assertThat(result.getAnswerAttachmentFileId(0)).isEqualTo(PostfachNachrichtTestFactory.ATTACHMENTS.get(0)); + } + + private GrpcRueckfrage map() { + return mapper.toGrpc(PostfachNachrichtTestFactory.create()); + } +} \ No newline at end of file diff --git a/src/test/java/de/ozgcloud/nachrichten/antragsraum/Saml2DecrypterITCase.java b/src/test/java/de/ozgcloud/nachrichten/antragsraum/Saml2DecrypterITCase.java new file mode 100644 index 0000000000000000000000000000000000000000..b6a66c491c69c97d010117b7d994fbf5bea9d59b --- /dev/null +++ b/src/test/java/de/ozgcloud/nachrichten/antragsraum/Saml2DecrypterITCase.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2024. + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ + +package de.ozgcloud.nachrichten.antragsraum; + +import de.ozgcloud.common.test.ITCase; +import de.ozgcloud.common.test.TestUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.opensaml.saml.saml2.core.Attribute; +import org.opensaml.saml.saml2.core.AttributeStatement; +import org.opensaml.saml.saml2.core.Response; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.*; + +@ITCase +@SpringBootTest(classes = {BayernIdSamlConfiguration.class}) +public class Saml2DecrypterITCase { + private Response samlResponse; + + @Autowired + private Saml2Parser parser; + + @Autowired + private Saml2Decrypter decrypter; + + @BeforeEach + void setup() { + var samlResponseString = TestUtils.loadTextFile("SamlResponse.xml"); + samlResponse = parser.parse(samlResponseString); + } + + @Test + void shouldDecrypt() { + assertThat(samlResponse.getAssertions()).isEmpty(); + + decrypter.decryptResponseElements(samlResponse); + + assertThat(samlResponse.getAssertions()).isNotEmpty(); + } + + @Test + void shouldHaveSubject() { + decrypter.decryptResponseElements(samlResponse); + var samlAssertion = samlResponse.getAssertions().get(0); + + assertThat(samlAssertion.getSubject()).isNotNull(); + } + + @Test + void shouldHaveAuthnStatements() { + decrypter.decryptResponseElements(samlResponse); + var samlAssertion = samlResponse.getAssertions().get(0); + var authnStatements = samlAssertion.getAuthnStatements(); + + assertThat(authnStatements).isNotNull(); + } + + @Test + void shouldHaveStatements() { + decrypter.decryptResponseElements(samlResponse); + var samlAssertion = samlResponse.getAssertions().get(0); + var statements = samlAssertion.getStatements(); + + assertThat(statements).isNotNull(); + } + + @Test + void shouldHaveAttributes() { + decrypter.decryptResponseElements(samlResponse); + var samlAssertion = samlResponse.getAssertions().get(0); + var statements = (AttributeStatement) samlAssertion.getStatements().get(1); + var attributes = statements.getAttributes(); + assertThat(attributes).hasSize(7); + } + + @Test + void shouldHavePostfachId() { + decrypter.decryptResponseElements(samlResponse); + var samlAssertion = samlResponse.getAssertions().get(0); + var statements = (AttributeStatement) samlAssertion.getStatements().get(1); + var attributes = statements.getAttributes(); + var postfachIdOptional = attributes.stream().filter(attribute -> "legacyPostkorbHandle".equals(attribute.getFriendlyName())).findFirst(); + assertThat(postfachIdOptional).map(Attribute::getAttributeValues).isNotNull(); + } + + @Test + void shouldGetPostfachId() { + var postfachId = decrypter.decryptPostfachId(samlResponse); + + assertThat(postfachId).isEqualTo("28721c6f-b78f-4d5c-a048-19fd2fc429d2"); + } +} \ No newline at end of file diff --git a/src/test/java/de/ozgcloud/nachrichten/antragsraum/Saml2ParserTest.java b/src/test/java/de/ozgcloud/nachrichten/antragsraum/Saml2ParserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4b2240c3b4cc1d09b52dd25de8a0c1cf9e31ec39 --- /dev/null +++ b/src/test/java/de/ozgcloud/nachrichten/antragsraum/Saml2ParserTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024. + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ + +package de.ozgcloud.nachrichten.antragsraum; + +import de.ozgcloud.common.test.TestUtils; +import org.junit.jupiter.api.Test; +import org.opensaml.saml.saml2.core.Response; + +import static org.assertj.core.api.Assertions.*; + +class Saml2ParserTest { + @Test + void shouldInit() throws Exception { + Saml2Parser parser = new Saml2Parser(BayernIdSamlConfiguration.getParserPool()); + assertThat(parser).isNotNull(); + } + + @Test + void shouldParseSamlToken() throws Exception { + var response = getResponse(); + assertThat(response).isNotNull(); + } + + @Test + void shouldHaveAssertions() throws Exception { + var response = getResponse(); + assertThat(response.getAssertions()).isNotNull(); + } + + @Test + void shouldHaveEncryptedAssertions() throws Exception { + var response = getResponse(); + assertThat(response.getEncryptedAssertions()).isNotNull(); + } + + @Test + void shouldHaveIssuer() throws Exception { + var response = getResponse(); + assertThat(response.getIssuer().getValue()).isEqualTo("https://infra-pre-id.bayernportal.de/idp"); + } + + private static Response getResponse() throws Exception { + var token = TestUtils.loadTextFile("SamlResponse.xml"); + Saml2Parser parser = new Saml2Parser(BayernIdSamlConfiguration.getParserPool()); + + return parser.parse(token); + } + +} \ No newline at end of file diff --git a/src/test/java/de/ozgcloud/nachrichten/antragsraum/Saml2VerifierITCase.java b/src/test/java/de/ozgcloud/nachrichten/antragsraum/Saml2VerifierITCase.java new file mode 100644 index 0000000000000000000000000000000000000000..cccbd0ff647eec7ee88ec0e462af5b1199428bb6 --- /dev/null +++ b/src/test/java/de/ozgcloud/nachrichten/antragsraum/Saml2VerifierITCase.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024. + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ + +package de.ozgcloud.nachrichten.antragsraum; + +import de.ozgcloud.common.test.ITCase; +import de.ozgcloud.common.test.TestUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.assertj.core.api.Assertions.*; + +@ITCase +@SpringBootTest(classes = {BayernIdSamlConfiguration.class}) +public class Saml2VerifierITCase { + private String samlResponse; + + @Autowired + private Saml2Verifier verifier; + + @BeforeEach + void setup() { + samlResponse = TestUtils.loadTextFile("SamlResponse.xml"); + } + + @Test + void shouldGetVerificationError() { + var res = verifier.verify(samlResponse); + + assertThat(res).isNotEmpty(); + } +} \ No newline at end of file diff --git a/src/test/resources/SamlResponse.xml b/src/test/resources/SamlResponse.xml new file mode 100644 index 0000000000000000000000000000000000000000..d28738585aa627bc0bd4e6b7288ff3346ea4029e --- /dev/null +++ b/src/test/resources/SamlResponse.xml @@ -0,0 +1,128 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Copyright (c) 2024. + ~ Lizenziert unter der EUPL, Version 1.2 oder - sobald + ~ diese von der Europäischen Kommission genehmigt wurden - + ~ Folgeversionen der EUPL ("Lizenz"); + ~ Sie dürfen dieses Werk ausschließlich gemäß + ~ dieser Lizenz nutzen. + ~ Eine Kopie der Lizenz finden Sie hier: + ~ + ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + ~ + ~ Sofern nicht durch anwendbare Rechtsvorschriften + ~ gefordert oder in schriftlicher Form vereinbart, wird + ~ die unter der Lizenz verbreitete Software "so wie sie + ~ ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + ~ ausdrücklich oder stillschweigend - verbreitet. + ~ Die sprachspezifischen Genehmigungen und Beschränkungen + ~ unter der Lizenz sind dem Lizenztext zu entnehmen. + --> + +<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" + Destination="https://deep-touching-condor.ngrok-free.app/login/saml2/sso/bayernid" + ID="_d75103771f4e3869ca4bf743efb51320" InResponseTo="ARQf371368-b6eb-4708-b90d-e8a9c5fc0ffd" + IssueInstant="2024-02-07T10:27:18.456Z" Version="2.0"> + <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://infra-pre-id.bayernportal.de/idp + </saml2:Issuer> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> + <ds:Reference URI="#_d75103771f4e3869ca4bf743efb51320"> + <ds:Transforms> + <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </ds:Transforms> + <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <ds:DigestValue>y8O2/uKwgap3hb7Ym/sn+v0e3l+w0Z+wIFe11xXkSHU=</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue> + G4fZCUS7Z+7PwDF7J+ZwXssM+iHBgxt34Uf4U3PWrbaYROrCZFD3hlVwCj35Z7RlQkDBi4q1m9RW6XGGVx2vpUDjT9dTkfbF7tB9PXa6l4mq3RyxuRELMwRpcbnamfe02qwtp0N7n9+gdjTVPb2xTMhp7FVG3OZ46OKwwJIm6jNLE+zVbKkNmxnv8XqGK+FgDS82CCG6Zi8nIZZkR80vHuRnSwrpStiInWSURoIYvG8nQfJ6u6IxbtMkDPtLrQHP6th9NMEyODe4RrjNwH8ERkbBl+rvtz406y3hngOW4uxNSTdQGOWj68t7LSn78S+Zc+5g/8up8gRIY6FWB5QxTl+GINIskcoWEfpyQcY932Jh9jGKFRBj2bcP0xALOeP+LTAz1O3hY0EZD0HpjILNhjp4/4Ki6SSeoVrp4UdEZGPpfFAMXdA9unjQGf5DqT3los5mH+KgkpAQoIU0725tIJuGojigXDIKgbNftB1oXjepcqcWvdnbRZlE9Kk4iU2YcVKGxHtEGi03+Qr2M37SqnooXw94Q0LxOQHU0jaOuw+nA8JbcvbpmHVbh7Qyg6OfrI/g+1pwhaQWrL6zEDDlgF3Fj6QxZGhMviCf43WJd8nPPwLIp0dFxXmbX5yBnpAPC4txJkf4idH8gze054O0Zf9G35vFH8oxELrA+d3qbPY= + </ds:SignatureValue> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>MIIFbzCCA1egAwIBAgIJAPdFXXarkBN2MA0GCSqGSIb3DQEBCwUAME4xCzAJBgNVBAYTAkRFMQ8w + DQYDVQQIDAZCYXllcm4xETAPBgNVBAcMCE11ZW5jaGVuMQ0wCwYDVQQKDARBS0RCMQwwCgYDVQQL + DANJRE0wHhcNMjAxMDI3MTMxODQxWhcNMjUxMDI2MTMxODQxWjBOMQswCQYDVQQGEwJERTEPMA0G + A1UECAwGQmF5ZXJuMREwDwYDVQQHDAhNdWVuY2hlbjENMAsGA1UECgwEQUtEQjEMMAoGA1UECwwD + SURNMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzDtWAEdC3J9FD+ti1exRhN1lzNgK + WqO2gQNdJvlt7KGHA2VGGO7tqRogTuoqi/ydtiHJ8+lhp4kcWqyfv7i9HXOncvcsRRmRdZjUY2Iu + i6ozJqD5LVm/vP5YfdP7vQPdbqyyfpoJhf3mbMEtdNDdGRnGIPUfDn+CFbo37f9tPwMgf3jgh4gx + aujtLIhhr9gevVTEeZAFu9EvzLNd3kEtRb7MuXqIOdu1rW8HlGYFwwVLqEyBn8XG0QAIfhMmGjFM + G7z+Kco2quwOmmZVzWQfeH/3AlN2KbcPt7j+pl+6Bew2AAivP7O+95YKORqQjTu3rPWMF4txPId3 + 7MSjoytwBRyd5EACTvhQBOGrDFKQUOx6fTtRc8+7XGVz8MdQaZQWQXXh1ByU783twNdnRSrSVIyL + djiy1uCbjvsSAtbzGBygPIvDo3skCNLNFXsChtHIfFFDK20KPGb0ghEDf2q3hDbFG3ZDGGynZmJc + ZKuZhJqodJ/++sAXADyTJNAPVYDjKCF4ypELp2Eu/p1gaQPJEb74L/ZFZVOEJFyXIiaqB9J+fcn/ + biqHHOmcCi8n9aIiNt1fatr1Z4lQRWoGtKaGU0+bzUSH4Bgs2EG4u1CI2MKDWqK2aEsHrtu8tbS9 + LrUmDVKtaEUOeul8xWVa036vp/YUIdiJNZSxZG4iTmSOATECAwEAAaNQME4wHQYDVR0OBBYEFFYe + ltslkaolOmcINXQeSe7nURwpMB8GA1UdIwQYMBaAFFYeltslkaolOmcINXQeSe7nURwpMAwGA1Ud + EwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAKqAlXoO41SAiycYUOrR90pfwTCysmbtHF5RWSCM + jF2aCG8URJ7bXwC0lBH8E5zCetFZwdqZziQtxzRkIOfhS5uWbH0RDhwuxZG+5RTPyaHPAZI6e5xH + Du8vHl/VbC3lnL/6K8l+Purr/yo8qkJqrPgThZRL9jBQyYRhDSsJUyIw5zcKKUQC/JWtMQAQcopb + jekCs6xDT1HqIN90Sc/gOfYjNo0dGMNmro9mxcw82Iow18KNVdtEexfD+/6x4NPD61pzuQEe09TR + +Cv3XyzBoGQ/2arijcPnGvth79ffVFtRSf3fSs7wEKV9g3mEWXFDtPBhDj6K0kKU/kJfEZixkXl9 + 2MY+bmugrtTIrazjtfrgMglIAHu9XCYWd/gef0J+PNfHsxgbTEr3XSC+5/xoFKPQSw3PgV8lkUDq + 4mJUKy/q4YmA37XQxourFR5pWvF03YACdtq6zPjtVeI7Cvkte6k0YW5S3cx9RmPv6YZhlaZ5ERpW + Niv6IjokLsvNeemf2PApjO7Q2EDBIoHBYH31wwJSsyRDrSVmbaqLFI15fLXeh2A4YbaBDZdGvDiL + OAk+dG1wdZ2aGw/uNBzMtc8VeKqI1HPcqIluBA3uUPpyLLA+9hDPf6Pp4j0gkXxBikz+/h22bFxE + 1HmDiOSkEn+2NmOHuEFeA+D8jsCAL5VJ3emK + </ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </ds:Signature> + <saml2p:Status xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"> + <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> + </saml2p:Status> + <saml2:EncryptedAssertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"> + <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="_baed1174200b81b1bff3856cb4e6365c" + Type="http://www.w3.org/2001/04/xmlenc#Element"> + <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" + xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"/> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <xenc:EncryptedKey Id="_5a164760d15a61d269e1f7fdd9872a10" Recipient="https://antragsraum.ozgcloud.de/" + xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> + <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" + xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> + <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" + xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/> + </xenc:EncryptionMethod> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate> + MIIDsTCCApmgAwIBAgIUdw/27be5+2vj+MhGtoJjDsMsdDEwDQYJKoZIhvcNAQELBQAwaDELMAkG + A1UEBhMCREUxDzANBgNVBAgMBkJheWVybjERMA8GA1UEBwwITXVlbmNoZW4xDzANBgNVBAoMBm1n + bSB0cDEkMCIGCSqGSIb3DQEJARYVamVucy5yZWVzZUBtZ20tdHAuY29tMB4XDTI0MDExNjEyMjI0 + OVoXDTI1MDExNTEyMjI0OVowaDELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJheWVybjERMA8GA1UE + BwwITXVlbmNoZW4xDzANBgNVBAoMBm1nbSB0cDEkMCIGCSqGSIb3DQEJARYVamVucy5yZWVzZUBt + Z20tdHAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/HBBWBDSrEgdwXkSy15V + 00EaVTyLgc4vh/JcDiGIYZSqmcMwBd+B1u36xbdBf/duEtCUymMNP48OMjgFZtR6xn0meuR4NR6Y + kn9mYGdU/GhldGuGv9XLAEAkVuTlo0H1QYyBS/6JwKQoSsHDkJ3YwDwKcyOt7QtpSadRZjQEN3gD + vWoRYjgXTxj2I1ovllmi0zOHsFi5PBIuiPWUdJvBrHxpD/XVS9R/qzJpHPu3bjQ6UVRmhiZCUF7H + 5F/PQNwk+qXvjV0ooBeSWWO5hywhk4OP4QEgbYMOSo20YukYX8TJEsum1pwIcQrw7kW4GyKaAycy + Rsa1fbM3tEkj+TiBKwIDAQABo1MwUTAdBgNVHQ4EFgQUfDL/6R33SJodsONCvxKy96AtU18wHwYD + VR0jBBgwFoAUfDL/6R33SJodsONCvxKy96AtU18wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B + AQsFAAOCAQEA+PCnvSwKU+bArTCIg5lfrwONbzKkjvPUymDNYX3oj1wVEN75hNf0RD7Rr0//ZYT3 + Rt0G193gjDcH1gbGIYhMLeGGkxEous2l3O+pRIQRR+hprjr6HzF8IphaJy1RbDwyGsXyLcyOylPL + 4cX9IjUdhklHiLZusBq95LSyw7hsCOAL2+vn816O7yv+28EWXXbnP2XEUjW36nxcZvR6oTJUplXy + HRuuJJTsOxGRNuXA3UVgNbkdm1HnoSGpnsGdUKsUFoEmEJkcSdQRwxeH21WzYGOZmKMcvx2gObaS + P8tafWh5z4Jx+Z7z5WP72Jt44/lnVjaV8aGo0KHXwgqQOtYftQ== + </ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> + <xenc:CipherValue> + ffr9pG/yL4QGQ4o1z/t6HH5XRG8pMHHjzlVTq6uC4eRpVvaNMz8XpUXqNAFGiB0Xbpkm++qOhGsOuz5Wffq5Qo78fMBfU95L1Lk9cVH1pUFfYyz5GV1LqlhStAZrCGHUdv5d0O7JLKgbi45JxxTc7ErAwPlOMqKLs95ZJuhl8Fp9XcYrdzW9IjuwmkB/HyPyjBWV066gaCMLImeBdCzBZc0pxuvH9jq8eX7h1B1eCd5F1LIoj35YDeU3PA/P/E6tLBxdGLFws+nYqNU3B5R2FPPoW+LP9zM7Q+SR20ti1Uh6TEMha05sJjWXFJU78PpJAtEl978ifqqO/23lYXYCrA== + </xenc:CipherValue> + </xenc:CipherData> + </xenc:EncryptedKey> + </ds:KeyInfo> + <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> + <xenc:CipherValue> + YvHcO5br8vWMo/vreVcU8MQylgUmU6vxmvEoUJ07+8kSV0prHD46TtuXHXsLnsYKQMs+SM6bnTWMooNxIy8b0/BvIG4lg/l3m+SwoP56+lOMx26mTEwz9dJT+4BTFH25i3GbWQd86AbD4wT2X9juExE1t6uq1bhACqgeA1erhy/fjTS+1fKKbOTdC0DF35idejruc/YFyV/BNRMHncfj5BnFQFUmXT0b2Fg+WyUAIzflqwXmUhdzmQNl2uqZDL2Vaw4vQp1a9S0ePD3t+QCSGtCYcmqvg+FhooS1KfhqITNinzi07KaQNW6sY0uXpnq3/BGWxXrU58rmU24AQ5ozAgwPfpmOnZhyUURSikvKmvcpD8DPy8jMOxi+rd/tYlxokjPjFSV8ixh0fGZl+7mDAt/YvxBOSSln3nUEMVoKMNgUT3ax6cyUTBXOxt1EMLYuAcHRIBpF2R9MYasmaaR1RntlkKPiomaPdGqIgh1HtkmuwkS6npAH68d0ObD/SpRqu+vPuu++RxHPlbIjShbJWYUJIqPJlhtG7/p9VkC3514t/H1cgxALKstC95OXNH8S6b4m+atl1Wf4PELfHD7lT/QgYHwZk2/xhoWduKc18nauB4kc3v3FZ8nIO3iCgBkXT8qq+/1wJgOnVqAEFWs8w8AC99gHoTgm04q+JUw9XramIXEOdJ10/2Y8HW97XCt53KG+kbaJZe7DISx+2eh79ed3BxEzwgqcXlsrIVcezXWJAl2myFxUggn3c/N1ckgOWFwENOSDFXS6WAtSo/8dlXYvgZTYyKVvVO7l5oq5al2ESrFkHqB3WKu0q9LaWEKw7jMy6FnOawSOjJ2t5o43hfqs9+Wg3J7bgM8YjDuuNZIJ55SO7NIdeeFOkkgGMgcmF0svsxGKbHhdkvqa0t0BLtase7dNIgfWY5laXU7xBn+HEhrz9ZR1xnk8gK28KZwR1wO72rpcV9igsbek5cxEJ/hAk9NSHw7VXAgXZJ6VKZapJfoOqanE50FfK8z0TaoKBUbc1kfOAFnB0n9nUKpUXyyqfiu12w4n3lAs3tBB2S4w3UW5Mef1ZGdF8dqs/T0GUs819vrwYENVUM8u1usP44MnMdTw2i3eo6/VYrCOo1tsa31t46BbLEnercEdGDgpOOBjuda+C3G4NtlDEFzM8rN2FspLS5wphCvKiTB867Q9nrsXOQdDTiwXs2wOpVq1utASdV82Yam1ucVVfriDWlLlhFsFpZnUmwG4zwCPqah2t8inSwx9jramTbJnXpihRw75mFGFC5QAalnV/EAtZ58ecIz4PVTRq4zP7OKtwnN+qIOMm//8AOl6e5H/At7qWB5/dVjw8BUdIxaUF+e33NdQG6x8IEbMhlGFTGCjv5E0h27D/AbqCBU6PKrkGZowZHtKNtz7nITysa0hpyefM0rQkFHwf4NmR8uSHZ9YoT8VLStTtrF6daHSYlUT45EDXkiSA7NCAX8BIDbZNGxPGNCWR3reZxtQoJ89YPPdQngyqMn7sB1T4sP+euWpnAOOF5VDA2xyM2WtPzuKDZFD0XH5r3AqKf2jl+E1/jSBlhW1Y677WVLTLJm7+lMYYLK6YVaSsKQp10lOdhcNSoNF2iWUwmdCTfkrYIqM6Dz6FiYSrg1TTlOJb7Mg/z54eO6utHzIRFepBTL+pu9qP38Y21NtpUWu//jh0vpniXu1rzGQvuiuoNGIiqYA/dL39cpLB5JIwEVWNsnlHvzRcYQnqg2mhdkFMNZPhZwb3f+BV3GNA/dTziazHEgUN5G0esGl85PlZM7oLrPkXe1mYKh3pVRVHx9bScTQ/KR/Dll0NI1d5ul2SZa80Pmj29voelfMUa5Ml5q4zHzXK6N1E70ujMzWWJB025gLIb3e7aE9eN/5SJegL2ctob8uNQCTSouel6ko+Ykw/pstPL8IYWgsAwrckmzNJHasZi9MB9re639Zf+bDvflpigNboH6Jgzs7us5C2dozH1s5IzGP4XzgeALu8XP/T2coQxhj9xfaAJFrtqWRse9MM9gKIWCBEIzzIPeMa0+S7QAKAd7XRS/oZSDeqUFK2jRkrpbEnUxRErfX6lmHWlaY4CU8XKbSYU13LkuJcyzCm9EN/BU7f5cOwaVwSLMfOQeOx0GwJ5KRF4F30pVQIKfQmXt627TEmrutHr2mIgBLcte+S052JdumcRFMnlNLlmpl/rnOrU0bBeNDtXHQuYCWwfgiyZ47J2OZ+R68v0lA8mSdHFtJ81mbGnYQZn6PnZ/gbKz8uTu5WZE6CQ+n8IY6uvd8B0EYOjaoJK/FTQRjnYe6cBWTQFfmFzH441Ao3vcfKh6co4d5Ec1L9PXQWXidhCv4aJw1G06zgOTIcLCqvE3rbBpYOFUOmKlQbBmaIiKWqG+Xqk34jbQgzfHmcFO96sqh6B64/OzjPdjQupzCTM9hBNwSUABWoOAb9Yn0wtCUU5tRMTXf2DessFKbm5Jygvbh7KrBIQX3SGLQ1sHY+MYVbDpRTyi6/cATCCSWcekyT08mEh52KDKbrTR4CFdu2B7wsIqKxoiW4XiHOOc7DGtgVaCXgoce0nd9YXrtXbIjriMddx7wo/A5xvQbTOyaBuL/j3893Ny6eU10c18p8tZCzdBO1VOWH+R+8TkdvhkA995xzrdvjw7RoSdO7eqdyiOqkHBJGAp+OVSMWf0+/kHKRQf3LTT+CcwYN+7mx+Qz6Uw6Squ6/9JsxsEfIQ3VRsa84hUjcmmKf4QTpzy54RIteqPZc0kNQPobpKmvyWUUjldV0jgYi98XfErrdLQF3gyU/TG0kOsEPjuskIHoLEEka+nGXOjbtxj7HZe7onJ54kIluMkHeKfLWOMoZ2Qx9tqYMoGtbvLf6RrKh7METcaenirAS0waZfYWbIKS/XQQnlG0kWmK2VbUtKpKwAkjlEFEkYo8NtYRTqB1gYp7iyOhOcYT8Hdd6y+276P+sF+FuuXBAd1WJ8GWosOGcBOSMlvbxOyuaa58K10CUcBu3UNYMXfbifsNunrPPaJClyHK279gtweail/SVEc9XoyUh2uP/sL2eU3edeOBnscRj+0TXCkr+8auzW2BlMHrzDniQBXnFQelm94yDB4Ue3BfqKlkPmfC9QO+X/Jsjl6RtIQ6kqvwz9ZQ9uzFi4ZS5xd0I/IBp621GEXFkqIZhx13ohoiGa1KlhXS1AkDSRptzy7DlkW/ZDR3rh4WKGYsIF7/09WGtSPzicF8E3Mc9BS1OBksTuDuC1ayo6o0qxgEED0s3tNKE4GMQ5Kr9glfvoTbkMtgJst2R+Tq0/HozNCp5Dr4cqTcOZwOTtyPtZbdmzmdfT66mkdC4P1e8JPGugtHv+5HC8u0PSyBQGEewIo7g417mxC/5mf84Cp+1a/TLTe5mb4xqycaUexYM8+jLy4YdStpvR0NuTcx3ZzTwsi357S3NfACfLnU2BnD5WyvID9Y3uNd7Mawa4b+631WfuMdFWBOa3qQYifzdnzo98CpkpatCn5HSse87LqTxZ8Cm8ziu42g/uKcHuvGJXDzcFSD4wk0qclvpcdrSfhRZfU9H/YFK4JuW6q9aAvL24DgdD9mBDI2Gz94xFwu7u9iMivTQXEC5vgHD2lvdH9XtnpHxElqTBN4whFTujk9ZhjcEY50ntoaplQOs0N3S9XhQhLMjNz+g6CvY77jTq+3pdoGffuoecbD/hOWZqebdqaC5Oa7ytnH/YY2J6L3tCTaFloqNOetWvre3uaz5aNh4i6F4f4Z4CkTWGksHPcKdukMQDMNb0gm+JiWt9Wa2bHhQ1KmK+XQHZEIEM6GAhzIDCk0kMeKiyyE3zOwIJomqjHZVb5O4GmpJ1oONZzBSyvdBusaRYl1r8MT5BWgh0f8l34wc5pMxmvZUT11hZPDzawPfKLYCqHDAPvAEOR7JDkOBb3X8ILMRUIGslzzu17y0gP9qiOOuwadoyTcTHxvPJaEc6lQYn3j9E44C3TxDGpNOHl9rgT0EkRT4o2QNLNXXAoKPl2lFw/8goob9s73dMqtzeRwVVJdoC9kGv7TBzDJcs6yIXMM9EvExeuotANi99JdL4xLUZiRrtcv3+fJnIsJPdgczGYV/9ScODFIsa8N3fNFiIOe9b+5gPDwutGVYoSf2Fs+mzsbrxLv7/D+7vRAQxlya9WCvWtw8YjkTaBTEX+y8FUOHtHDBczu4XXEHaznZ1chnV/Pb5FkX78BiEO86ai1dB6v5+F2J/MLdEWhqEvEW8QYAPB6AYwfdEeVZX5igCF17mqbCqS/sg3z/hdW0iLSnjVeYqHXwTHbuFWM/c0MLCddnqvO49vZacWzXHk86wRyghbQTJUx3HUa/mJDGACZysvHLGzv2qjmlsKviokYLWA/Wsg2G1UV3eAmVq7VXt9s3v8nFvTRyqeWeHIkBpw45NFOR/H1sUjWAklBWOdiT/db0y6SOCvaTxVWqnk/6nL+/7vhhF3Zp9HrImt8+lk2vpeAS12YD8mHS/LJPWY+nLBWu1t0yI4aca70gJsBGJI5NvZbDGGe6f5SGfxbVHCr5NS/cBOUMOo+Oh87/IYv2XGZPwvD+7S9b84VnZVXdj9lQh0Et+v+zbaRkB4lquJMoGnF5UwcLtV0/RQybThfIpOYjNMs1LuW/6jPS6PCKlxeUGNwDvlKDCQlDhZkAQ1PPVPMlhA7QlMceaSYXnRLzI+IHJBQb6freSwWF6zBHYFI9H39CxxUUjIiR5sv5ViOi8tO5RgHtF3bsj3i8yQS43SdFTe0C4cxIuBuQMuSz7laE8/gZl3yGo7Wjgy/3RknSjla2sUt0d6PLQ2QQndxcWHKCNt19i6sYTttLqrywCHrjSyYwEBlWEC2nioEDONieaFc3iticbgSD/a5xzW9aefnQVFZWCRWkP0wVtBkf/tGtHl9PXau4+TV66rTq5X9aY3jEeU83OCnsuY5zBHFm3S5blMlvA+ebCcEWhyHDVwLfI7FAQ7fmcz3xO9cQf0waI6CK70yV+poRFAKDiCD1HELm6ij1KR/y2uWPF3LZ5P3pMGTr2W5hnC7Kvh+yqGvaID2L1athALmORgJHv1CDQzx0AzxfGMvUkgtQq8bCdjf0XvX1H4SKiPylc/2AwFM1PwS8eR429YnIMwJ6yyAQ68u5VyEGaFMdyrXX3I/vYStWcuUBrsN4oheWxIcNVKO1fFC0f6O0N5bRf8Kjyz9siRZK3z+vsU/zD1l6ShheQdoDeiXQKYgv91C7X3dJEx7fo60lRHVurySIUq1J5omLBMSl8b8F7Eqw1jTmZlVvSHcgzulhNYbv88MA1reVj6RQOfRA8LfaNID/RA89xAPYuEadd92uAjbQqExObqj5ELcNmhqOX/JrB+hn2aef3pWzSJmy98C9FdJuvF2l2XnZ5sDS25I9hnuCRAHeyHoAk4/VfjqEIjTN8BG1b0sTjSwJFBlHJCwBsKaaJviwXl5qynN1Z2f0IjoZ4gzwl9QDtcZDqYxk+qxbWDFqc9Nz/dhFLjGYTpX8VNEedNaa4/c/wTOpq7KioMEzASNlfwoIk9Ha6Xpph4PDoumFoeE6ONFEHNK3LgPDzEDfjj8HykTkq/VZIA7uN4BaaGFAi5Ah66FuVFFT7Mp9vUMvCfSH/Wdx/AYijS5WNBULlDpLJeLQ79oJfZ1ItrBOfD7oBSt5hIK7qoVM2aCMXwdOVSE6M34SJfgMPC9MCfcJudvQjDvYX31ZA42ZGGDgD4Iab75KMOXMdOR4aqlxCTb6FoLqqahzFTh6bMWtHEdqCz4uTVeHcH/FGUC/2j1BQE5FEKg3EIKl0uja5ztpSZa+3e59cmOHAPcyhlYE9ov+tU6GVzThHqBGs9Wd4zw6oNMvBt+YbbepNJotoU7YtuST1Z5mZIjpJaD+kDHqmmLyDYxlpWaHJFsPETkRsGj1Ko6lzgz1NYVMuejwOw2EwUtWQ+YKy7c3Y54dVk0hWD8oRaqOo8HNQ9YKURUjeIXXZ8OGst6WE5KtvoV/ga8VZQ8gE8SRc/XEWdXGrdDKc8tMxnVN03pSJQGIYquLQGU7QwUUftlJ6MYA8jgQFpGcW0FVBmsxl03zyxSL+FemGrtEoVwAOlfAiLaHuLV2QZ84j+dJAoWjdOFIF+uXwOzyeQNMPTwFg+ivSAkE9D23HFQJOnC34NYENFHBLCZfK+oICubzmXnFKHbLJrlNvlvbCONp+LiFK2iXMda3p8oGojI5o/92vlxF4mn5ZH4JZ8jRX6Xalj18Cw6H6j8UzO6w4cI5OV0RvFEKOwKmGvN/W7OvdHPMBMmg1oxFhAX6p8KdyULTdU+1C4JkX7mBND+Y5mjLv4/M3GIzyEcwyL6sxVTz0aqkKSCltyedUU/g9JmiuEp11d2Pk0skRo1o/gqPdJ5lbVG/fJXGcvxG6sIhAGcCOLIjHG873yWf2rJY7RRWk0W8lX5IjgvmDIWY9Tf8W8dNUWoRTbJ8IzAqL9YtYyOKDt4W8fdXKSRP+cljxQhmHmXTzyJ9mQkGpy0TWsf7VE96ki5aAhbRikjQ5mYN6xLyiLC1YKz8c/tZOb0bPH897bhFgjRHOtfzRbRm9p/Sqk4AMsStChqcVkZDM2bz3WOjNpBLI0/K8OCd+PDT+xg9ehjzBcM2WNjspKmch9rK6T58YRulEmbQbc9QT1+A2lPTnb2aXccptRrP+CwkQ2bsT/OMbUnE3NHvw0/G5Z3pSU0Qy6L10+lJ8SXzFGf4XTPoLuK+fNKj05IWFxJiHINtjo3WbwLdKZp8Kd97X+TW+z7XpP2qKqaRMfeYwzoc56y7w1NnOGzH48qicaC+DXipszT5mYmW6e1bxjwqNpo+E1JmXZQR/LeFi84XEGUYNxaaAciQfRX/6jO4b81TmdvWjyADWHwMonDXXHjO4YoSbh1M6pRKR2Psuw066/O/WvJh+WrIhlsJC6D9W2HtDK8gIU2F8SrpXOxd3hlntVFYsMo37s6kPAtFm2hu+eWN+NtX9/EO8psgAdiXvMNczCSFxV9cdEEXfDHHbQBmH/g+XilwtXYcjoZas9LqLS4xBSU4vLMnCqrtQ0qauh2g52wDFz6mAj7Z6OydXcVDwjK4QD2P2zfAYsfOqIhhg7xEzDJoumTy+eRbkGbFHraOet+LF5N8lKKplstYqiVamzJ56geEsZ6QP1NYv/KXdKk+OjtRC/KdoOZjrBXsoR8/CS8Az6JV/DyGqbTkwlo9gA5hnKaVKtRy9q7uNASl9asjj82WN/0VYIhMfLoR1CbW+vUrOSbAh/ilqbcq3HJ8c5+E2HuhKIbYRJRMQrfJrxKk7xKTRAgeSbA5dRzQACm31Ch2FSvoS5KnIpYXyqm4828lGGNApJiZ1aU0Q2mLUI/ZHAHrzMacshZtckhWG9n9MKIcDc8ld0gl7Tl5QFMOswgHvWyzuEqgTnuBxJqfhTprv6tbLJ4xcpNz2/v4fHE743YuVN5/lJG0SEfwUUq53MtXUqII9PRcjnTAN4TT3Y+cz6QWaW/l/tW0uSvniLha36gw3WlfA5qWdBuwE2uR0XMyYXE5d7WEkHUnAYzzJsRqrvhkqNwQO0V1jF14ApnUltMxqK3pbyWO3tw1o5+PIjcvKFeOFYCUucRa2lS0h4peA8FdiOcMkUabgHdtsAJuUrlxa+Vi39Y6PVg24XRyupLFIy80QmIF5H4GUY/aW5Ig687karDPyHVnr9M6PEJ3q3acV4yKwZSMBvlxqlvUFYgLm8NELucYtQvyI7CYRDl6LvSpdro+FK9IJSaOLXFghk90IlcJz4Ic74UY8a8+l+8tQKEjhVzFeYbLvrHGTv5A0OAs43fxIxAe5q/iqRFZUAXE+h0PUfky5af3xo/7zZXGhnzfz1Um8L58WUa5hTavUhbD0+zRqiajkJ7nyqIKj5b6nRTzHwG+lr7bxs5P5SPYycAoDdEqjT3TUqY3dz2tONxBh1lU7WX3BTxfO/WSqi0Zz+sEAOrvGu8io4SmIM4/Ka5RTXQscbG1I04g28x0fTm6KSXDFhAcNsNw0Mw8o2u5Lxa42szqPdapNqo6lrOP2N6RQ0pzOUJ6d/f/4Yqt1/r6XtoTqCPE70IwyZvaAWjqTX1XoLmvQ4uajXSpxDA84kZ1fFNd96Y892wh4ygX6RMg6vUd67kkRKcrmAckL8UmAklWAJryol61L8fPBt8o32hDuVCE2itZBjVn/4vEZVMARe0U7X/NOb6NDdrbP8TCM4g4+XeV7Jej+MnqvdA0c19fSUqxU1fhrSQL4cuNcdPKbdPSyPzptcmrxngxL9Yotv6/Ah2c4kL8dt1m7uQE8cdunn3qMB176itdJQu6lEF3p/gg/kuBO70VtY6gVISN1cNPnv8EiKYKzLhCf89np5f/fCDWOhciRKDwWRzULf3jZvHDJ8cd25p5JA3UppQIqy/8C9g6UrJwmYWZ8f8z0+sGCY25gGwsQs5UREaq9GQKE//vFneh09XAVdDhzDkqspkWjL6RmLDWdIpttc0N5NTdX2DdqR9JVikvEkg9OBHpYxkxYr0RQMp5bphj0ee6KsYcbZ4x06gbJFeGSgKZjuR4EpDJ8yPJXFFxldxmUtsrCMr/z9NA9olxU7+l4OD+dXd0AEAfMtpIK+g98cuLM0HNfslZ5/YgWBxFF2zmKJFunA9bb/agMyUR9AGAVr/HER9lxJEwdbwKtHQy9vwiMF8G+452JLK/t0/j0mvspENFA9z2ZJPL9jFbSRuF34ppQ3mV/E14IZeGP29NIv2uOHOxL1uzKwNydi1YbLIJRDE25zm0Zh/ulUBJWEnMqUfmzDqo1V8qy4VxfXeym4xccedSOiEyyLna/lP08giG6hUmQLxnvzrMHK2AEe+ggm3RGoS8Rown66LX+See1iohZqnbqxISRf6rNBpM45XPvxph3Q3pKcjDvoeq9eaUFSA92VfxpnVBO/tXtiQGBLYuBSZpqxTWd6G4RP/PFdrmUOhVkRsUXBufoj2MKSgNx6Ab+KMUg5qY52yrkYGKt8O6CubJt0/GJnIlCRODd3ZdcuCNaVWx2PN5+LK6Jy4jEFKtw/f+Ub+piXcpBL02TiO1SCI7qU0MznFxbs5CYrYOo5uQe/CaxWIN8Pq57WuPJ4UT+FHcRW6eiVYxa5hQTAf/ai3XsH5xP2LT/CWdWB175xA8uN8iZ6ai3yJysIENsHcRD6bpGEZ6gc+IIFu+JEhm4zMxIhu9CqjscKnyUIIzasUxdo2Ioa6hZaq4exO0dC/5gQbL4vR23nf5/PfxEzggWNQyDhM+UupTXtBIO2yqV6/wotUPibw5rOcqU+Amua0hAt+7RVXHwvfnFVfCo8E6mdD8wv8xSK2i1mElL9KiW/eVZWBRNE8gSBYQ8DpaNF193CPDyWKxPHz3Hg/aehKa5P4GPE7ugkqhjsYVMUo9Pvq7wXrjAs6U8EKDEh9zsRfFyg91RJaRSqSMNaUbuTkqKYq7KalV3WErKQRL6SxCZa3xGwJ8H5t5bYU+J3lCbtQjtDZ8O66PwKPPvyx1zuiiMjQcwv+JNGNIlFraoEgz5MlGkrBEgIRGXZDuS6ZVAa8L8lqE+/en4pHcj6HNlKtriDeosSDduttT+zi45k4bkgXWgO0a8d7gdqZ3UJR29T2KFIOSrm2Eqat9SF4S8lc33+LUUePfo82x/nQilk3+Eu+HhupyjfM5PGq1dglQ4wG/lJYazW0LlJ774pf/fwHYuPGjVC0CgsOjDzN8o2F6koQV+o90KCDPNkmqpGuAx8+43UGbtxxZGt0OpiFwi3tp8JyYExjdfni19OpI6SI48mM4pZCQXpkhvbZnbvD9hHigF+ERZJfzZZRGExPctz5QL8eQNAFI/KuL4DC23teZmSi1RNxU26PZTrfmtXwgciXXMyvm8j2ACq5n3+x4PyKdvh+SAVEvOQpc1SO7JDZf4+1L+fmB31RWMENRock5xOJ6H2UdMncn+nU9plECElvoLRnImET+mfWHT1fAfrR6iA1Yks9UXu3F2KHIc/wAeChopbz8RCkHQGxOQEVSbujBdd/Hjod1X8g4kF4MsefT+gd4n0UGoUgd30zeGmabC7h7W29PhizM8IZvfZbzVFdLPLU5X8s+wmdN65Woyld4B+BVEQ+w1GA4J4K6WVcSki7AeL4Gv6v3DXYBgdHl5aHXI1epDe0MxtdxvyPhHxoO3pHodmCkdJ1udrGu1167EDHXzknCB5r5U9cxI/UFt54Xxr5LPwrfONSxhMj3DqfGLSQQfxf2cSWWFig3jGf2mOfQ+XzH62mfn3Dv0KSS2M12rilop/c5iFK5ApaiFse2g== + </xenc:CipherValue> + </xenc:CipherData> + </xenc:EncryptedData> + </saml2:EncryptedAssertion> +</saml2p:Response> diff --git a/src/test/resources/application.yaml b/src/test/resources/application.yaml new file mode 100644 index 0000000000000000000000000000000000000000..329aba1ddb082512852ba36fed08134247826cb9 --- /dev/null +++ b/src/test/resources/application.yaml @@ -0,0 +1,11 @@ +ozgcloud: + bayernid: + saml: + entity-id: https://antragsraum.ozgcloud.de/ + metadata-uri: "classpath:/bayernid/metadata/bayernid-idp-infra.xml" + decryption: + private-key-location: "classpath:/bayernid/bayernid-test-enc.key" + certificate-location: "classpath:/bayernid/bayernid-test-enc.crt" +logging: + level: + "org.opensaml.xmlsec.signature": debug \ No newline at end of file