Skip to content
Snippets Groups Projects
Commit 3a4e0312 authored by OZGCloud's avatar OZGCloud
Browse files

OZG-7092 [test] add tests

parent 1acdbafc
No related branches found
No related tags found
1 merge request!1OZG-7092 Anpassung TokenChecker
...@@ -81,8 +81,8 @@ class SamlTrustEngineFactory { ...@@ -81,8 +81,8 @@ class SamlTrustEngineFactory {
return new CollectionCredentialResolver(credentials); return new CollectionCredentialResolver(credentials);
} }
Stream<Saml2X509Credential> getCertificatesFromMetadata(Resource metadataResource) { Stream<Saml2X509Credential> getCertificatesFromMetadata(Resource metadata) {
try (var metadataInputStream = metadataResource.getInputStream()) { try (var metadataInputStream = metadata.getInputStream()) {
return findEntityDescriptor(getXmlObject(metadataInputStream)) return findEntityDescriptor(getXmlObject(metadataInputStream))
.map(this::getVerificationCertificates) .map(this::getVerificationCertificates)
.orElseThrow(() -> new TechnicalException("No IDPSSO Descriptors found")); .orElseThrow(() -> new TechnicalException("No IDPSSO Descriptors found"));
......
...@@ -24,29 +24,56 @@ ...@@ -24,29 +24,56 @@
package de.ozgcloud.token.saml; package de.ozgcloud.token.saml;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*; import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
import java.io.InputStream;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.mockito.InjectMocks; import org.mockito.InjectMocks;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Spy; import org.mockito.Spy;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.config.XMLObjectProviderRegistry; import org.opensaml.core.xml.config.XMLObjectProviderRegistry;
import org.opensaml.core.xml.io.Unmarshaller;
import org.opensaml.core.xml.io.UnmarshallerFactory;
import org.opensaml.saml.common.xml.SAMLConstants;
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.UsageType;
import org.opensaml.security.credential.impl.CollectionCredentialResolver; import org.opensaml.security.credential.impl.CollectionCredentialResolver;
import org.opensaml.security.x509.BasicX509Credential;
import org.opensaml.security.x509.X509Credential;
import org.opensaml.xmlsec.keyinfo.KeyInfoSupport;
import org.opensaml.xmlsec.signature.KeyInfo;
import org.opensaml.xmlsec.signature.support.impl.ExplicitKeySignatureTrustEngine; import org.opensaml.xmlsec.signature.support.impl.ExplicitKeySignatureTrustEngine;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.security.saml2.core.Saml2X509Credential; import org.springframework.security.saml2.core.Saml2X509Credential;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import de.ozgcloud.common.errorhandling.TechnicalException; import de.ozgcloud.common.errorhandling.TechnicalException;
import de.ozgcloud.token.TokenValidationProperties.TokenValidationProperty; import de.ozgcloud.token.TokenValidationProperties.TokenValidationProperty;
import lombok.SneakyThrows;
import net.shibboleth.utilities.java.support.xml.ParserPool; import net.shibboleth.utilities.java.support.xml.ParserPool;
class SamlTrustEngineFactoryTest { class SamlTrustEngineFactoryTest {
private static final String IDP_ENTITY_ID = UUID.randomUUID().toString();
@Spy @Spy
@InjectMocks @InjectMocks
private SamlTrustEngineFactory factory; private SamlTrustEngineFactory factory;
...@@ -101,36 +128,521 @@ class SamlTrustEngineFactoryTest { ...@@ -101,36 +128,521 @@ class SamlTrustEngineFactoryTest {
@Mock @Mock
private Resource metadata; private Resource metadata;
@Nested
class TestBuildSuccessfully {
@Mock
private X509Credential x509Credential;
@BeforeEach @BeforeEach
void init() { void init() {
when(tokenValidationProperty.getMetadata()).thenReturn(metadata); when(tokenValidationProperty.getMetadata()).thenReturn(metadata);
when(tokenValidationProperty.getIdpEntityId()).thenReturn(IDP_ENTITY_ID);
doReturn(Stream.of(credential)).when(factory).getCertificatesFromMetadata(any());
doReturn(x509Credential).when(factory).buildBasicX509Credential(any(), any());
} }
@Test @Test
void shouldCallGetCertificatesFromMetadata() { void shouldCallGetCertificatesFromMetadata() {
when(factory.getCertificatesFromMetadata(any())).thenReturn(Stream.of(credential)); buildCredentialResolver();
factory.buildCredentialResolver(tokenValidationProperty);
verify(factory).getCertificatesFromMetadata(metadata); verify(factory).getCertificatesFromMetadata(metadata);
} }
@Test @Test
void shouldThrowExceptionWhenNoCertificates() { void shouldCallBuildBasicX509Credential() {
when(factory.getCertificatesFromMetadata(any())).thenReturn(Stream.empty()); buildCredentialResolver();
assertThatThrownBy(() -> factory.buildCredentialResolver(tokenValidationProperty)).isInstanceOf(TechnicalException.class) verify(factory).buildBasicX509Credential(credential, IDP_ENTITY_ID);
.hasMessage("Metadata response is missing verification certificates, necessary for verifying SAML assertions");
} }
@Test @Test
void shouldBuildCredentialResolver() { void shouldBuildCredentialResolver() {
when(factory.getCertificatesFromMetadata(any())).thenReturn(Stream.of("key")); var result = buildCredentialResolver();
doReturn(new CollectionCredentialResolver(null)).when(factory).buildCredentialResolver(any());
assertThat(result.getCollection()).containsExactly(x509Credential);
}
}
@Nested
class TestThrowException {
@Test
void shouldThrowExceptionWhenNoCertificates() {
doReturn(Stream.empty()).when(factory).getCertificatesFromMetadata(any());
assertThrows(TechnicalException.class, TestBuildCredentialResolver.this::buildCredentialResolver);
}
}
private CollectionCredentialResolver buildCredentialResolver() {
return factory.buildCredentialResolver(tokenValidationProperty);
}
}
@Nested
class TestGetCertificatesFromMetadata {
@Mock
private Resource metadata;
@Mock
private InputStream inputStream;
@Mock
private XMLObject xmlObject;
@Mock
private Saml2X509Credential credential;
@Mock
private EntityDescriptor entityDescriptor;
@BeforeEach
@SneakyThrows
void init() {
when(metadata.getInputStream()).thenReturn(inputStream);
doReturn(xmlObject).when(factory).getXmlObject(any());
}
@Nested
class TestSuccessfully {
@BeforeEach
void init() {
doReturn(Optional.of(entityDescriptor)).when(factory).findEntityDescriptor(any());
doReturn(Stream.of(credential)).when(factory).getVerificationCertificates(any());
}
@Test
void shouldCallGetXmlObject() {
getCertificatesFromMetadata();
verify(factory).getXmlObject(inputStream);
}
@Test
void shouldCallFindEntityDescriptor() {
getCertificatesFromMetadata();
verify(factory).findEntityDescriptor(xmlObject);
}
@Test
void shouldGetVerificationCertificates() {
getCertificatesFromMetadata();
verify(factory).getVerificationCertificates(entityDescriptor);
}
@Test
void shouldReturnResult() {
var result = getCertificatesFromMetadata();
assertThat(result).containsExactly(credential);
}
}
@Nested
class TestWithException {
@Test
void shouldThrowException() {
doReturn(Optional.empty()).when(factory).findEntityDescriptor(any());
assertThrows(TechnicalException.class, TestGetCertificatesFromMetadata.this::getCertificatesFromMetadata);
}
}
private List<Saml2X509Credential> getCertificatesFromMetadata() {
return factory.getCertificatesFromMetadata(metadata).toList();
}
}
@Nested
class TestGetXmlObject {
@Mock
private InputStream inputStream;
@Mock
private Unmarshaller unmarshaller;
@Mock
private XMLObject xmlObject;
@Mock
private Document document;
@Mock
private Element element;
@BeforeEach
@SneakyThrows
void init() {
when(parserPool.parse(any(InputStream.class))).thenReturn(document);
when(document.getDocumentElement()).thenReturn(element);
doReturn(unmarshaller).when(factory).getUnmarshaller(any());
when(unmarshaller.unmarshall(element)).thenReturn(xmlObject);
}
@Test
@SneakyThrows
void shouldCallParse() {
getXmlObject();
verify(parserPool).parse(inputStream);
}
@Test
void shouldCallGetUnmarshaller() {
getXmlObject();
verify(factory).getUnmarshaller(element);
}
@Test
@SneakyThrows
void shouldCallUnmarshall() {
getXmlObject();
verify(unmarshaller).unmarshall(element);
}
@Test
void shouldReturnResult() {
var result = getXmlObject();
assertThat(result).isEqualTo(xmlObject);
}
private XMLObject getXmlObject() {
return factory.getXmlObject(inputStream);
}
}
@Nested
class TestGetUnmarshaller {
@Mock
private Element element;
@Mock
private UnmarshallerFactory unmarshallerFactory;
@Mock
private Unmarshaller unmarshaller;
@BeforeEach
void init() {
when(registry.getUnmarshallerFactory()).thenReturn(unmarshallerFactory);
}
@Nested
class TestSuccessfully {
@BeforeEach
void init() {
when(unmarshallerFactory.getUnmarshaller(any(Element.class))).thenReturn(unmarshaller);
}
@Test
void shouldCallGetUnmarshallerFactory() {
getUnmarshaller();
verify(registry).getUnmarshallerFactory();
}
@Test
void shouldCallGetUnmarshaller() {
getUnmarshaller();
verify(unmarshallerFactory).getUnmarshaller(element);
}
@Test
void shouldReturnResult() {
var result = getUnmarshaller();
assertThat(result).isEqualTo(unmarshaller);
}
}
@Nested
class TestNoUnmarshaller {
@Test
void shouldThrowException() {
assertThrows(TechnicalException.class, TestGetUnmarshaller.this::getUnmarshaller);
}
}
private Unmarshaller getUnmarshaller() {
return factory.getUnmarshaller(element);
}
}
@Nested
class TestFindEntityDescriptor {
@Mock
private XMLObject xmlObject;
@Mock
private EntityDescriptor entityDescriptor;
@Mock
private IDPSSODescriptor descriptor;
@BeforeEach
void init() {
when(factory.extractEntityDescriptor(any())).thenReturn(Optional.of(entityDescriptor));
}
@Test
void shouldCallExtractEntityDescriptor() {
findEntityDescriptor();
verify(factory).extractEntityDescriptor(xmlObject);
}
@Test
void shouldFilterDescriptor() {
when(entityDescriptor.getIDPSSODescriptor(anyString())).thenReturn(descriptor);
findEntityDescriptor();
verify(entityDescriptor).getIDPSSODescriptor(SAMLConstants.SAML20P_NS);
}
@Test
void shouldReturnResult() {
when(entityDescriptor.getIDPSSODescriptor(anyString())).thenReturn(descriptor);
var result = findEntityDescriptor();
assertThat(result).contains(entityDescriptor);
}
private Optional<EntityDescriptor> findEntityDescriptor() {
return factory.findEntityDescriptor(xmlObject);
}
}
@Nested
class TestExtractEntityDescriptor {
@Mock
private XMLObject xmlObject;
@Test
void shouldReturnEmpty() {
var result = factory.extractEntityDescriptor(xmlObject);
assertThat(result).isEmpty();
}
@Nested
class TestEntityDescriptor {
@Mock
private EntityDescriptor entityDescriptor;
@Test
void shouldReturnEntityDescriptor() {
var result = factory.extractEntityDescriptor(entityDescriptor);
assertThat(result).contains(entityDescriptor);
}
}
@Nested
class TestEntitiesDescriptor {
@Mock
private EntitiesDescriptor entitiesDescriptor;
@Mock
private EntityDescriptor entityDescriptor;
var result = factory.buildCredentialResolver(tokenValidationProperty); @BeforeEach
void init() {
when(entitiesDescriptor.getEntityDescriptors()).thenReturn(List.of(entityDescriptor));
}
@Test
void shouldReturnEntityDescriptor() {
var result = factory.extractEntityDescriptor(entitiesDescriptor);
assertThat(result).contains(entityDescriptor);
}
}
}
@Nested
class TestGetVerificationCertificates {
@Mock
private EntityDescriptor descriptor;
@Nested
class TestSuccessfully {
@Mock
private IDPSSODescriptor idpSsoDescriptor;
@Mock
private KeyDescriptor keyDescriptor;
@Mock
private X509Certificate certificate;
@BeforeEach
void init() {
when(descriptor.getIDPSSODescriptor(anyString())).thenReturn(idpSsoDescriptor);
when(idpSsoDescriptor.getKeyDescriptors()).thenReturn(List.of(keyDescriptor));
doReturn(true).when(factory).isSignatureKey(any());
doReturn(Stream.of(certificate)).when(factory).getCertificates(any());
}
@Test
void shouldCallGetKeyDescriptors() {
getVerificationCertificates();
verify(idpSsoDescriptor).getKeyDescriptors();
}
@Test
void shouldCallIsSignatureKey() {
getVerificationCertificates();
verify(factory).isSignatureKey(keyDescriptor);
}
@Test
void shouldCallGetCertificates() {
getVerificationCertificates();
verify(factory).getCertificates(keyDescriptor);
}
@Test
void shouldCallVerification() {
try (var credentialMock = mockStatic(Saml2X509Credential.class)) {
getVerificationCertificates();
credentialMock.verify(() -> Saml2X509Credential.verification(certificate));
}
}
}
@Nested
class TestWithException {
@Test
void shouldThrowException() {
assertThrows(TechnicalException.class, TestGetVerificationCertificates.this::getVerificationCertificates);
}
}
private List<Saml2X509Credential> getVerificationCertificates() {
return factory.getVerificationCertificates(descriptor).toList();
}
}
@Nested
class TestIsSignatureKey {
@Mock
private KeyDescriptor keyDescriptor;
@Test
void shouldReturnTrue() {
when(keyDescriptor.getUse()).thenReturn(UsageType.SIGNING);
var result = isSignatureKey();
assertThat(result).isTrue();
}
@DisplayName("should return false")
@ParameterizedTest(name = "when keyDescriptor use is {0}")
@EnumSource(value = UsageType.class, names = { "SIGNING" }, mode = EnumSource.Mode.EXCLUDE)
void shouldReturnFalse(UsageType use) {
when(keyDescriptor.getUse()).thenReturn(use);
var result = isSignatureKey();
assertThat(result).isFalse();
}
private boolean isSignatureKey() {
return factory.isSignatureKey(keyDescriptor);
}
}
@Nested
class TestGetCertificates {
@Mock
private KeyDescriptor keyDescriptor;
@Mock
private KeyInfo keyInfo;
@Mock
private X509Certificate certificate;
@BeforeEach
void init() {
when(keyDescriptor.getKeyInfo()).thenReturn(keyInfo);
}
@Test
void shouldCallGetCertificates() {
try (var keyInfoSupportMock = mockStatic(KeyInfoSupport.class)) {
getCertificates();
keyInfoSupportMock.verify(() -> KeyInfoSupport.getCertificates(keyInfo));
}
}
@Test
void shouldReturnResult() {
try (var keyInfoSupportMock = mockStatic(KeyInfoSupport.class)) {
keyInfoSupportMock.when(() -> KeyInfoSupport.getCertificates(any(KeyInfo.class))).thenReturn(List.of(certificate));
var result = getCertificates();
assertThat(result).containsExactly(certificate);
}
}
private List<X509Certificate> getCertificates() {
return factory.getCertificates(keyDescriptor).toList();
}
}
@Nested
class TestBuildBasicX509Credential {
@Mock
private Saml2X509Credential samlKey;
@Mock
private X509Certificate certificate;
@BeforeEach
void init() {
when(samlKey.getCertificate()).thenReturn(certificate);
}
@Test
void shouldSetEntityCertificate() {
var result = buildBasicX509Credential();
assertThat(result.getEntityCertificate()).isEqualTo(certificate);
}
@Test
void shouldSetUsageType() {
var result = buildBasicX509Credential();
assertThat(result.getUsageType()).isEqualTo(UsageType.SIGNING);
}
@Test
void shouldSetEntityId() {
var result = buildBasicX509Credential();
assertThat(result.getEntityId()).isEqualTo(IDP_ENTITY_ID);
}
assertThat(result).isNotNull(); private BasicX509Credential buildBasicX509Credential() {
return (BasicX509Credential) factory.buildBasicX509Credential(samlKey, IDP_ENTITY_ID);
} }
} }
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment