diff --git a/token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlDecrypterFactoryTest.java b/token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlDecrypterFactoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..60d558fc863fb2f1905f7b3131e750429f847518 --- /dev/null +++ b/token-checker-server/src/test/java/de/ozgcloud/token/saml/SamlDecrypterFactoryTest.java @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * 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.token.saml; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPrivateKey; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Spy; +import org.opensaml.saml.saml2.encryption.Decrypter; +import org.opensaml.security.credential.CredentialSupport; +import org.opensaml.security.x509.BasicX509Credential; +import org.opensaml.xmlsec.encryption.support.ChainingEncryptedKeyResolver; +import org.opensaml.xmlsec.keyinfo.impl.CollectionKeyInfoCredentialResolver; + +import de.ozgcloud.token.TokenValidationProperties.TokenValidationProperty; +import de.ozgcloud.token.saml.SamlDecrypterFactory.DecrypterBuilder; + +class SamlDecrypterFactoryTest { + + @Spy + @InjectMocks + private SamlDecrypterFactory factory; + + @Mock + private TokenValidationProperty tokenValidationProperty; + + @Nested + class TestBuildDecrypter { + + @Mock + private CollectionKeyInfoCredentialResolver keyInfoCredentialResolver; + @Mock + private ChainingEncryptedKeyResolver encryptedKeyResolver; + @Mock + private DecrypterBuilder decrypterBuilder; + @Mock + private Decrypter decrypter; + + private MockedStatic<DecrypterBuilder> decrypterBuilderMock; + + @BeforeEach + void init() { + doReturn(keyInfoCredentialResolver).when(factory).buildKeyInfoCredentialResolver(any()); + doReturn(encryptedKeyResolver).when(factory).buildEncryptedKeyResolver(); + decrypterBuilderMock = mockStatic(DecrypterBuilder.class); + decrypterBuilderMock.when(DecrypterBuilder::builder).thenReturn(decrypterBuilder); + when(decrypterBuilder.keyEncryptionKeyResolver(any())).thenReturn(decrypterBuilder); + when(decrypterBuilder.encryptedKeyElementsResolver(any())).thenReturn(decrypterBuilder); + when(decrypterBuilder.build()).thenReturn(decrypter); + } + + @AfterEach + void close() { + decrypterBuilderMock.close(); + } + + @Test + void shouldCallBuildKeyInfoCredentialResolver() { + buildDecrypter(); + + verify(factory).buildKeyInfoCredentialResolver(tokenValidationProperty); + } + + @Test + void shouldSetKeyEncryptionKeyResolver() { + buildDecrypter(); + + verify(decrypterBuilder).keyEncryptionKeyResolver(keyInfoCredentialResolver); + } + + @Test + void shouldCallBuildEncryptedKeyResolver() { + buildDecrypter(); + + verify(factory).buildEncryptedKeyResolver(); + } + + @Test + void shouldSetEncryptedKeyElementsResolver() { + buildDecrypter(); + + verify(decrypterBuilder).encryptedKeyElementsResolver(encryptedKeyResolver); + } + + @Test + void shouldCallBuild() { + buildDecrypter(); + + verify(decrypterBuilder).build(); + } + + @Test + void shouldReturnResult() { + var result = buildDecrypter(); + + assertThat(result).isSameAs(decrypter); + } + + private Decrypter buildDecrypter() { + return factory.buildDecrypter(tokenValidationProperty); + } + } + + @Nested + class TestBuildKeyInfoCredentialResolver { + + @Mock + private X509Certificate certificate; + @Mock + private RSAPrivateKey privateKey; + @Mock + private BasicX509Credential credential; + + private MockedStatic<CredentialSupport> credentialSupportMock; + + @BeforeEach + void init() { + doReturn(certificate).when(factory).getCertificate(any()); + doReturn(privateKey).when(factory).getPrivateKey(any()); + credentialSupportMock = mockStatic(CredentialSupport.class); + credentialSupportMock.when(() -> CredentialSupport.getSimpleCredential(any(X509Certificate.class), any())).thenReturn(credential); + } + + @AfterEach + void close() { + credentialSupportMock.close(); + } + + @Test + void shouldCallGetCertificate() { + buildKeyInfoCredentialResolver(); + + verify(factory).getCertificate(tokenValidationProperty); + } + + @Test + void shouldCallGetPrivateKey() { + buildKeyInfoCredentialResolver(); + + verify(factory).getPrivateKey(tokenValidationProperty); + } + + @Test + void shouldCallGetSimpleCredential() { + buildKeyInfoCredentialResolver(); + + credentialSupportMock.verify(() -> CredentialSupport.getSimpleCredential(certificate, privateKey)); + } + + @Test + void shouldReturnResult() { + var result = buildKeyInfoCredentialResolver(); + + assertThat(result.getCollection()).contains(credential); + } + + private CollectionKeyInfoCredentialResolver buildKeyInfoCredentialResolver() { + return factory.buildKeyInfoCredentialResolver(tokenValidationProperty); + } + } +} \ No newline at end of file