package at.gv.egiz.eaaf.modules.pvp2.test.metadata; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Collection; import java.util.List; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactoryConfigurationError; import org.apache.commons.lang3.RandomStringUtils; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; import org.opensaml.core.xml.io.MarshallingException; import org.opensaml.core.xml.io.UnmarshallingException; import org.opensaml.core.xml.util.XMLObjectSupport; import org.opensaml.saml.common.xml.SAMLConstants; import org.opensaml.saml.saml2.core.Attribute; import org.opensaml.saml.saml2.core.NameIDType; import org.opensaml.saml.saml2.metadata.ContactPerson; import org.opensaml.saml.saml2.metadata.EntityDescriptor; import org.opensaml.saml.saml2.metadata.Organization; import org.opensaml.saml.saml2.metadata.RequestedAttribute; import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator; import org.opensaml.security.SecurityException; import org.opensaml.security.credential.Credential; import org.opensaml.security.x509.BasicX509Credential; import org.opensaml.xmlsec.signature.support.SignatureException; import org.opensaml.xmlsec.signature.support.SignatureValidator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; import at.gv.egiz.eaaf.modules.pvp2.api.utils.IPvp2CredentialProvider; import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder; import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; import net.shibboleth.utilities.java.support.xml.XMLParserException; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml", "/spring/test_eaaf_core_spring_config.beans.xml", "/spring/eaaf_utils.beans.xml" }) @TestPropertySource(locations = { "/config/config_1.props" }) @DirtiesContext(classMode = ClassMode.BEFORE_CLASS) public class MetadataBuilderTest { @Autowired private PvpMetadataBuilder metadataBuilder; @Autowired private DummyCredentialProvider credentialProvider; private static CertificateFactory fact; /** * JUnit class initializer. * * @throws Exception In case of an OpenSAML3 initialization error */ @BeforeClass public static void classInitializer() throws Exception { EaafOpenSaml3xInitializer.eaafInitialize(); fact = CertificateFactory.getInstance("X.509"); } @Test public void buildIdpMetadata() throws CredentialsNotAvailableException, EaafException, SecurityException, TransformerFactoryConfigurationError, MarshallingException, TransformerException, ParserConfigurationException, IOException, SignatureException, XMLParserException, UnmarshallingException, CertificateException { final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(credentialProvider, false, true); //generate metadata final String metadata = metadataBuilder.buildPvpMetadata(config); //validate final EntityDescriptor entity = validateMetadata(metadata); Assert.assertNotNull("IDPSSODescr. is null", entity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS)); Assert.assertNull("IDPSSODescr. is null", entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS)); } @Test public void buildSpMetadata() throws CredentialsNotAvailableException, EaafException, SecurityException, TransformerFactoryConfigurationError, MarshallingException, TransformerException, ParserConfigurationException, IOException, SignatureException, XMLParserException, UnmarshallingException, CertificateException { final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(credentialProvider, true, false); //generate metadata final String metadata = metadataBuilder.buildPvpMetadata(config); //validate final EntityDescriptor entity = validateMetadata(metadata); Assert.assertNull("IDPSSODescr. is null", entity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS)); Assert.assertNotNull("IDPSSODescr. is null", entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS)); } @Test public void buildSpAndIdpMetadata() throws CredentialsNotAvailableException, EaafException, SecurityException, TransformerFactoryConfigurationError, MarshallingException, TransformerException, ParserConfigurationException, IOException, SignatureException, XMLParserException, UnmarshallingException, CertificateException { final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(credentialProvider, true, true); //generate metadata final String metadata = metadataBuilder.buildPvpMetadata(config); //validate final EntityDescriptor entity = validateMetadata(metadata); Assert.assertNotNull("IDPSSODescr. is null", entity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS)); Assert.assertNotNull("IDPSSODescr. is null", entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS)); } private EntityDescriptor validateMetadata(String metadata) throws UnsupportedEncodingException, XMLParserException, UnmarshallingException, SignatureException, CertificateException { Assert.assertNotNull("Metadata is null", metadata); Assert.assertFalse("Metadata is empty", metadata.isEmpty()); final EntityDescriptor entity = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream( XMLObjectProviderRegistrySupport.getParserPool(), new ByteArrayInputStream(metadata.getBytes("UTF-8"))); Assert.assertNotNull("Unmarshalling failed", entity); Assert.assertNotNull("EntityId is null", entity.getEntityID()); Assert.assertNotNull("Signature is null", entity.getSignature()); final SAMLSignatureProfileValidator sigValidator = new SAMLSignatureProfileValidator(); sigValidator.validate(entity.getSignature()); final Credential cred = new BasicX509Credential((X509Certificate) fact.generateCertificate( MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt"))); SignatureValidator.validate(entity.getSignature(), cred); return entity; } /** * Dummy Metadata builder configuration. * * @param credentialProvider Credentialprovider * @param buildSpInfos Sp metadata flag * @param buildIdpInfos IDP metadata flag * @return */ public static IPvpMetadataBuilderConfiguration idpMetadataConfig( IPvp2CredentialProvider credentialProvider, boolean buildSpInfos, boolean buildIdpInfos) { return new IPvpMetadataBuilderConfiguration() { @Override public boolean wantAuthnRequestSigned() { return true; } @Override public boolean wantAssertionSigned() { return true; } @Override public String getSpSloSoapBindingUrl() { return RandomStringUtils.randomAlphabetic(10); } @Override public String getSpSloRedirectBindingUrl() { return RandomStringUtils.randomAlphabetic(10); } @Override public String getSpSloPostBindingUrl() { return RandomStringUtils.randomAlphabetic(10); } @Override public Collection getSpRequiredAttributes() { return null; } @Override public String getSpNameForLogging() { return RandomStringUtils.randomAlphabetic(10); } @Override public String getSpAssertionConsumerServiceRedirectBindingUrl() { return RandomStringUtils.randomAlphabetic(10); } @Override public String getSpAssertionConsumerServicePostBindingUrl() { return RandomStringUtils.randomAlphabetic(10); } @Override public List getSpAllowedNameIdTypes() { return Arrays.asList(NameIDType.PERSISTENT); } @Override public Credential getRequestorResponseSigningCredentials() throws CredentialsNotAvailableException { return credentialProvider.getMessageSigningCredential(); } @Override public Organization getOrgansiationInformation() { return null; } @Override public int getMetadataValidUntil() { return 10; } @Override public EaafX509Credential getMetadataSigningCredentials() throws CredentialsNotAvailableException { return credentialProvider.getMetaDataSigningCredential(); } @Override public String getIdpWebSsoRedirectBindingUrl() { return RandomStringUtils.randomAlphabetic(10); } @Override public String getIdpWebSsoPostBindingUrl() { return RandomStringUtils.randomAlphabetic(10); } @Override public String getIdpSloRedirectBindingUrl() { return RandomStringUtils.randomAlphabetic(10); } @Override public String getIdpSloPostBindingUrl() { return RandomStringUtils.randomAlphabetic(10); } @Override public List getIdpPossibleNameIdTypes() { return Arrays.asList(NameIDType.PERSISTENT); } @Override public List getIdpPossibleAttributes() { return null; } @Override public String getEntityID() { return RandomStringUtils.randomAlphabetic(10); } @Override public String getEntityFriendlyName() { return RandomStringUtils.randomAlphabetic(10); } @Override public Credential getEncryptionCredentials() throws CredentialsNotAvailableException { return credentialProvider.getMessageSigningCredential(); } @Override public List getContactPersonInformation() { return null; } @Override public boolean buildSpSsoDescriptor() { return buildSpInfos; } @Override public boolean buildIdpSsoDescriptor() { return buildIdpInfos; } @Override public boolean buildEntitiesDescriptorAsRootElement() { return false; } }; } }