package at.gv.egovernment.moa.id.protocols.pvp2x.metadata; import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Timer; import javax.xml.namespace.QName; import org.apache.commons.httpclient.HttpClient; import org.opensaml.saml2.metadata.EntitiesDescriptor; import org.opensaml.saml2.metadata.EntityDescriptor; import org.opensaml.saml2.metadata.RoleDescriptor; import org.opensaml.saml2.metadata.provider.ChainingMetadataProvider; import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; import org.opensaml.saml2.metadata.provider.MetadataFilter; import org.opensaml.saml2.metadata.provider.MetadataProvider; import org.opensaml.saml2.metadata.provider.MetadataProviderException; import org.opensaml.xml.XMLObject; import org.opensaml.xml.parse.BasicParserPool; import at.gv.egovernment.moa.id.commons.db.ConfigurationDBRead; import at.gv.egovernment.moa.id.commons.db.dao.config.OAPVP2; import at.gv.egovernment.moa.id.commons.db.dao.config.OnlineApplication; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.MetadataSignatureFilter; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; public class MOAMetadataProvider implements MetadataProvider { private static MOAMetadataProvider instance = null; private static Object mutex = new Object(); private static Date timestamp = null; public static MOAMetadataProvider getInstance() { if (instance == null) { synchronized (mutex) { if (instance == null) { instance = new MOAMetadataProvider(); } } } return instance; } public static Date getTimeStamp() { return timestamp; } public static void reInitialize() { synchronized (mutex) { /**add new Metadataprovider or remove Metadataprovider which are not in use any more.**/ if (instance != null) instance.addAndRemoveMetadataProvider(); else Logger.info("MOAMetadataProvider is not loaded."); } } public static void destroy() { if (instance != null) { instance.internalDestroy(); } else { Logger.info("MOAMetadataProvider is not loaded. Accordingly it can not be destroyed"); } } MetadataProvider internalProvider; private void addAndRemoveMetadataProvider() { if (internalProvider != null && internalProvider instanceof ChainingMetadataProvider) { Logger.info("Relaod MOAMetaDataProvider."); /*OpenSAML ChainingMetadataProvider can not remove a MetadataProvider (UnsupportedOperationException) *The ChainingMetadataProvider use internal a unmodifiableList to hold all registrated MetadataProviders.*/ Map providersinuse = new HashMap(); Map loadedproviders = new HashMap(); ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider; //make a Map of all actually loaded HTTPMetadataProvider List providers = chainProvider.getProviders(); for (MetadataProvider provider : providers) { if (provider instanceof HTTPMetadataProvider) { HTTPMetadataProvider httpprovider = (HTTPMetadataProvider) provider; loadedproviders.put(httpprovider.getMetadataURI(), httpprovider); } } //load all PVP2 OAs form ConfigurationDatabase and //compare actually loaded Providers with configured PVP2 OAs List oaList = ConfigurationDBRead .getAllActiveOnlineApplications(); //set Timestamp timestamp = new Date(); Iterator oaIt = oaList.iterator(); while (oaIt.hasNext()) { try { OnlineApplication oa = oaIt.next(); OAPVP2 pvp2Config = oa.getAuthComponentOA().getOAPVP2(); if (pvp2Config != null && MiscUtil.isNotEmpty(pvp2Config.getMetadataURL())) { String metadataurl = pvp2Config.getMetadataURL(); if (loadedproviders.containsKey(metadataurl)) { //PVP2 OA is actually loaded, to nothing providersinuse.put(metadataurl, loadedproviders.get(metadataurl)); loadedproviders.remove(metadataurl); } else if ( MiscUtil.isNotEmpty(metadataurl) && !providersinuse.containsKey(metadataurl) ) { //PVP2 OA is new, add it to MOAMetadataProvider Logger.info("Loading metadata for: " + oa.getFriendlyName()); HTTPMetadataProvider httpProvider = createNewHTTPMetaDataProvider( pvp2Config.getMetadataURL(), pvp2Config.getCertificate(), oa.getFriendlyName()); if (httpProvider != null) providersinuse.put(metadataurl, httpProvider); } } } catch (Throwable e) { Logger.error( "Failed to add Metadata (unhandled reason: " + e.getMessage(), e); } } //remove all actually loaded MetadataProviders with are not in ConfigurationDB any more Collection notusedproviders = loadedproviders.values(); for (HTTPMetadataProvider provider : notusedproviders) { String metadataurl = provider.getMetadataURI(); try { provider.destroy(); /*OpenSAML ChainingMetadataProvider can not remove a MetadataProvider (UnsupportedOperationException) *The ChainingMetadataProvider use internal a unmodifiableList to hold all registrated MetadataProviders.*/ //chainProvider.removeMetadataProvider(provider); Logger.info("Remove not used MetadataProvider with MetadataURL " + metadataurl); } catch (Throwable e) { Logger.error("HTTPMetadataProvider with URL " + metadataurl + " can not be removed from the list of actually loaded Providers.", e); } } try { chainProvider.setProviders(new ArrayList(providersinuse.values())); } catch (MetadataProviderException e) { Logger.warn("ReInitalize MOAMetaDataProvider is not possible! MOA-ID Instance has to be restarted manualy", e); } } else { Logger.warn("ReInitalize MOAMetaDataProvider is not possible! MOA-ID Instance has to be restarted manualy"); } } public void internalDestroy() { if (internalProvider != null && internalProvider instanceof ChainingMetadataProvider) { Logger.info("Destrorying MOAMetaDataProvider."); ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider; List providers = chainProvider.getProviders(); for (MetadataProvider provider : providers) { if (provider instanceof HTTPMetadataProvider) { HTTPMetadataProvider httpprovider = (HTTPMetadataProvider) provider; Logger.debug("Destroy HTTPMetadataProvider +" + httpprovider.getMetadataURI()); httpprovider.destroy(); } else { Logger.warn("MetadataProvider can not be destroyed."); } } instance = null; } else { Logger.warn("ReInitalize MOAMetaDataProvider is not possible! MOA-ID Instance has to be restarted manualy"); } } private MOAMetadataProvider() { ChainingMetadataProvider chainProvider = new ChainingMetadataProvider(); Logger.info("Loading metadata"); Map providersinuse = new HashMap(); List oaList = ConfigurationDBRead .getAllActiveOnlineApplications(); Iterator oaIt = oaList.iterator(); while (oaIt.hasNext()) { try { OnlineApplication oa = oaIt.next(); Logger.info("Loading metadata for: " + oa.getFriendlyName()); OAPVP2 pvp2Config = oa.getAuthComponentOA().getOAPVP2(); if (pvp2Config != null && MiscUtil.isNotEmpty(pvp2Config.getMetadataURL())) { String metadataURL = pvp2Config.getMetadataURL(); if (!providersinuse.containsKey(metadataURL)) { HTTPMetadataProvider httpProvider = createNewHTTPMetaDataProvider( metadataURL, pvp2Config.getCertificate(), oa.getFriendlyName()); if (httpProvider != null) providersinuse.put(metadataURL, httpProvider); } else { Logger.info(metadataURL + " are already added."); } } else { Logger.info(oa.getFriendlyName() + " is not a PVP2 Application skipping"); } } catch (Throwable e) { Logger.error( "Failed to add Metadata (unhandled reason: " + e.getMessage(), e); } } try { chainProvider.setProviders(new ArrayList(providersinuse.values())); } catch (MetadataProviderException e) { Logger.error( "Failed to add Metadata (unhandled reason: " + e.getMessage(), e); } internalProvider = chainProvider; timestamp = new Date(); } private HTTPMetadataProvider createNewHTTPMetaDataProvider(String metadataURL, byte[] certificate, String oaName) { try { HTTPMetadataProvider httpProvider = new HTTPMetadataProvider(new Timer(), new HttpClient(), metadataURL); httpProvider.setParserPool(new BasicParserPool()); httpProvider.setRequireValidMetadata(true); httpProvider.setMinRefreshDelay(1000*60*15); //15 minutes httpProvider.setMaxRefreshDelay(1000*60*60*24); //24 hours //httpProvider.setRefreshDelayFactor(0.1F); // TODO: use proper SSL checking MetadataFilter filter = new MetadataSignatureFilter( metadataURL, certificate); httpProvider.setMetadataFilter(filter); httpProvider.initialize(); return httpProvider; } catch (MetadataProviderException e) { Logger.error( "Failed to add Metadata file for " + oaName + "[ " + e.getMessage() + " ]", e); } catch (CertificateException e) { Logger.error( "Failed to add Metadata file for " + oaName + "[ " + e.getMessage() + " ]", e); } return null; } public boolean requireValidMetadata() { return internalProvider.requireValidMetadata(); } public void setRequireValidMetadata(boolean requireValidMetadata) { internalProvider.setRequireValidMetadata(requireValidMetadata); } public MetadataFilter getMetadataFilter() { return internalProvider.getMetadataFilter(); } public void setMetadataFilter(MetadataFilter newFilter) throws MetadataProviderException { internalProvider.setMetadataFilter(newFilter); } public XMLObject getMetadata() throws MetadataProviderException { return internalProvider.getMetadata(); } public EntitiesDescriptor getEntitiesDescriptor(String name) throws MetadataProviderException { return internalProvider.getEntitiesDescriptor(name); } public EntityDescriptor getEntityDescriptor(String entityID) throws MetadataProviderException { return internalProvider.getEntityDescriptor(entityID); } public List getRole(String entityID, QName roleName) throws MetadataProviderException { return internalProvider.getRole(entityID, roleName); } public RoleDescriptor getRole(String entityID, QName roleName, String supportedProtocol) throws MetadataProviderException { return internalProvider.getRole(entityID, roleName, supportedProtocol); } }