Java tutorial
/******************************************************************************* * Copyright 2014 Federal Chancellery Austria * MOA-ID has been developed in a cooperation between BRZ, the Federal * Chancellery Austria - ICT staff unit, and Graz University of Technology. * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * http://www.osor.eu/eupl/ * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. *******************************************************************************/ package at.gv.egovernment.moa.id.configuration.config; import iaik.x509.X509Certificate; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.util.Properties; import java.util.Timer; import java.util.jar.Attributes; import java.util.jar.Manifest; import javax.servlet.http.HttpServletRequest; import org.apache.commons.httpclient.MOAHttpClient; import org.apache.log4j.Logger; import org.opensaml.DefaultBootstrap; import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; import org.opensaml.xml.parse.BasicParserPool; import org.opensaml.xml.security.x509.BasicX509Credential; import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils; import at.gv.egovernment.moa.id.commons.db.dao.config.ChainingModeType; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; import at.gv.egovernment.moa.id.commons.ex.MOAHttpProtocolSocketFactoryException; import at.gv.egovernment.moa.id.commons.utils.MOAHttpProtocolSocketFactory; import at.gv.egovernment.moa.id.configuration.Constants; import at.gv.egovernment.moa.id.configuration.auth.pvp2.MetaDataVerificationFilter; import at.gv.egovernment.moa.id.configuration.exception.ConfigurationException; import at.gv.egovernment.moa.id.configuration.utils.UserRequestCleaner; import at.gv.egovernment.moa.util.FileUtils; import at.gv.egovernment.moa.util.MiscUtil; public class ConfigurationProvider { public static final String HTMLTEMPLATE_DIR = "/htmlTemplates"; public static final String HTMLTEMPLATE_FILE = "/loginFormFull.html"; private static final Logger log = Logger.getLogger(ConfigurationProvider.class); private static final String SYSTEM_PROP_CONFIG = "moa.id.webconfig"; private static ConfigurationProvider instance; private Properties props; private String configFileName; private String configRootDir; private HTTPMetadataProvider idpMetadataProvider = null; private KeyStore keyStore = null; private String publicURLPreFix = null; private boolean pvp2logininitialzied = false; public static ConfigurationProvider getInstance() throws ConfigurationException { if (instance == null) { instance = new ConfigurationProvider(); instance.inizialize(); } return instance; } private void inizialize() throws ConfigurationException { configFileName = System.getProperty(SYSTEM_PROP_CONFIG); if (configFileName == null) { throw new ConfigurationException("config.05"); } // determine the directory of the root config file configRootDir = new File(configFileName).getParent(); log.info("Loading MOA-ID-AUTH configuration " + configFileName); //Initial Hibernate Framework log.trace("Initializing Hibernate framework."); //Load MOAID-2.0 properties file File propertiesFile = new File(configFileName); FileInputStream fis; props = new Properties(); try { fis = new FileInputStream(propertiesFile); props.load(fis); fis.close(); // initialize hibernate synchronized (ConfigurationProvider.class) { //Initial config Database ConfigurationDBUtils.initHibernate(props); } log.trace("Hibernate initialization finished."); DefaultBootstrap.bootstrap(); log.info("OPENSAML initialized"); UserRequestCleaner.start(); log.info("MOA-ID-Configuration initialization completed"); } catch (FileNotFoundException e) { throw new ConfigurationException("config.01", new Object[] { configFileName }, e); } catch (IOException e) { throw new ConfigurationException("config.02", new Object[] { configFileName }, e); } catch (MOADatabaseException e) { throw new ConfigurationException("config.03", e); } catch (org.opensaml.xml.ConfigurationException e) { throw new ConfigurationException("config.04", e); } } public String getPublicUrlPreFix(HttpServletRequest request) { publicURLPreFix = props.getProperty("general.publicURLContext"); if (MiscUtil.isEmpty(publicURLPreFix) && request != null) { String url = request.getRequestURL().toString(); String contextpath = request.getContextPath(); int index = url.indexOf(contextpath); publicURLPreFix = url.substring(0, index + contextpath.length() + 1); } return publicURLPreFix; } public int getUserRequestCleanUpDelay() { String delay = props.getProperty("general.userrequests.cleanup.delay"); return Integer.getInteger(delay, 12); } // public String getContactMailAddress() { // return props.getProperty("general.contact.mail"); // } public String getSSOLogOutURL() { return props.getProperty("general.login.pvp2.idp.sso.logout.url"); } public KeyStore getPVP2KeyStore() throws ConfigurationException, IOException, NoSuchAlgorithmException, CertificateException, KeyStoreException { if (keyStore == null) { String keystoretype = getPVP2MetadataKeystoreType(); if (MiscUtil.isEmpty(keystoretype)) { log.debug("No KeyStoreType defined. Using default KeyStoreType."); keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); } else { log.debug("Using " + keystoretype + " KeyStoreType."); keyStore = KeyStore.getInstance(keystoretype); } String fileURL = getPVP2MetadataKeystoreURL(); log.debug("Load KeyStore from URL " + fileURL); if (MiscUtil.isEmpty(fileURL)) { log.info("Metadata KeyStoreURL is empty"); throw new ConfigurationException("Metadata KeyStoreURL is empty"); } URL keystoreURL = new URL((FileUtils.makeAbsoluteURL(fileURL, getConfigRootDir()))); InputStream inputStream = keystoreURL.openStream(); keyStore.load(inputStream, getPVP2MetadataKeystorePassword().toCharArray()); inputStream.close(); } return keyStore; } public String getConfigFile() { return configFileName; } public String getConfigRootDir() { return configRootDir; } public String getMOAIDInstanceURL() { return props.getProperty("general.moaid.instance.url"); } public boolean isLoginDeaktivated() { String result = props.getProperty("general.login.deaktivate", "false"); return Boolean.parseBoolean(result); } public boolean isOATargetVerificationDeaktivated() { String result = props.getProperty("general.OATargetVerification.deaktivate", "false"); return Boolean.parseBoolean(result); } //PVP2 Login configuration public void initializePVP2Login() throws ConfigurationException { if (!pvp2logininitialzied) initalPVP2Login(); } public boolean isPVP2LoginActive() { return Boolean.parseBoolean(props.getProperty("general.login.pvp2.isactive", "false")); } public boolean isPVP2LoginBusinessService() { String result = props.getProperty("general.login.pvp2.isbusinessservice", "false"); return Boolean.parseBoolean(result); } public String getPVP2LoginTarget() { return props.getProperty("general.login.pvp2.target"); } public String getPVP2LoginIdenificationValue() { return props.getProperty("general.login.pvp2.identificationvalue"); } public String getPVP2MetadataEntitiesName() { return props.getProperty("general.login.pvp2.metadata.entities.name"); } public String getPVP2MetadataKeystoreURL() { return props.getProperty("general.login.pvp2.keystore.url"); } public String getPVP2MetadataKeystorePassword() { return props.getProperty("general.login.pvp2.keystore.password"); } public String getPVP2MetadataKeystoreType() { return props.getProperty("general.login.pvp2.keystore.type"); } public String getPVP2KeystoreMetadataKeyAlias() { return props.getProperty("general.login.pvp2.keystore.metadata.key.alias"); } public String getPVP2KeystoreMetadataKeyPassword() { return props.getProperty("general.login.pvp2.keystore.metadata.key.password"); } public String getPVP2KeystoreAuthRequestKeyAlias() { return props.getProperty("general.login.pvp2.keystore.authrequest.key.alias"); } public String getPVP2KeystoreAuthRequestKeyPassword() { return props.getProperty("general.login.pvp2.keystore.authrequest.key.password"); } public String getPVP2KeystoreAuthRequestEncryptionKeyAlias() { return props.getProperty("general.login.pvp2.keystore.authrequest.encryption.key.alias"); } public String getPVP2KeystoreAuthRequestEncryptionKeyPassword() { return props.getProperty("general.login.pvp2.keystore.authrequest.encryption.key.password"); } public String getPVP2IDPMetadataURL() { return props.getProperty("general.login.pvp2.idp.metadata.url"); } public String getPVP2IDPMetadataCertificate() { return props.getProperty("general.login.pvp2.idp.metadata.certificate"); } public String getPVP2IDPMetadataEntityName() { return props.getProperty("general.login.pvp2.idp.metadata.entityID"); } public HTTPMetadataProvider getMetaDataProvier() { return idpMetadataProvider; } //SMTP Server public String getSMTPMailHost() { return props.getProperty("general.mail.host"); } public String getSMTPMailPort() { return props.getProperty("general.mail.host.port"); } public String getSMTPMailUsername() { return props.getProperty("general.mail.host.username"); } public String getSMTPMailPassword() { return props.getProperty("general.mail.host.password"); } //Mail Configuration public String getMailFromName() { return props.getProperty("general.mail.from.name"); } public String getMailFromAddress() { return props.getProperty("general.mail.from.address"); } public String getMailUserAcountVerificationSubject() { return props.getProperty("general.mail.useraccountrequest.verification.subject"); } public String getMailUserAcountVerificationTemplate() throws ConfigurationException { String url = props.getProperty("general.mail.useraccountrequest.verification.template"); if (MiscUtil.isNotEmpty(url)) { return url; } else { log.warn("MailUserAcountVerificationTemplate is empty"); throw new ConfigurationException("MailUserAcountVerificationTemplate is empty"); } } public String getMailUserAcountActivationSubject() { return props.getProperty("general.mail.useraccountrequest.isactive.subject"); } public String getMailUserAcountActivationTemplate() throws ConfigurationException { String url = props.getProperty("general.mail.useraccountrequest.isactive.template"); if (MiscUtil.isNotEmpty(url)) { return url; } else { log.warn("MailUserAcountActivationTemplate is empty"); throw new ConfigurationException("MailUserAcountActivationTemplate is empty"); } } public String getMailOAActivationSubject() { return props.getProperty("general.mail.createOArequest.isactive.subject"); } public String getDefaultLanguage() { try { return props.getProperty("general.defaultlanguage", "de").toLowerCase(); } catch (Exception ex) { return "de"; } } public String getMailOAActivationTemplate() throws ConfigurationException { String url = props.getProperty("general.mail.createOArequest.isactive.template"); if (MiscUtil.isNotEmpty(url)) { return url; } else { log.warn("MailOAActivationTemplate is empty"); throw new ConfigurationException("MailOAActivationTemplate is empty"); } } public String getMailUserAcountRevocationTemplate() throws ConfigurationException { String url = props.getProperty("general.mail.useraccountrequest.rejected.template"); if (MiscUtil.isNotEmpty(url)) { return url; } else { log.warn("MailUserAcountVerificationTemplate is empty"); throw new ConfigurationException("MailUserAcountRevocationTemplate is empty"); } } public String getMailAdminSubject() { return props.getProperty("general.mail.admin.subject"); } public String getMailAdminTemplate() throws ConfigurationException { String url = props.getProperty("general.mail.admin.adresses.template"); if (MiscUtil.isNotEmpty(url)) { return url; } else { log.warn("MailUserAcountVerificationTemplate is empty"); throw new ConfigurationException("MailAdminTemplate is empty"); } } public String getMailAdminAddress() { return props.getProperty("general.mail.admin.adress"); } public String getConfigToolVersion() { return parseVersionFromManifest(); } public String getCertStoreDirectory() throws ConfigurationException { String dir = props.getProperty("general.ssl.certstore"); if (MiscUtil.isNotEmpty(dir)) return FileUtils.makeAbsoluteURL(dir, configRootDir); else throw new ConfigurationException("No SSLCertStore configured use default JAVA TrustStore."); } public String getTrustStoreDirectory() throws ConfigurationException { String dir = props.getProperty("general.ssl.truststore"); if (MiscUtil.isNotEmpty(dir)) return FileUtils.makeAbsoluteURL(dir, configRootDir); else throw new ConfigurationException("No SSLTrustStore configured use default JAVA TrustStore."); } public String getConfigurationEncryptionKey() { return props.getProperty("general.moaconfig.key"); } private void initalPVP2Login() throws ConfigurationException { try { String metadataCert = getPVP2IDPMetadataCertificate(); if (MiscUtil.isEmpty(metadataCert)) { log.info("NO IDP Certificate to verify IDP Metadata"); throw new ConfigurationException("NO IDP Certificate to verify IDP Metadata"); } URL keystoreURL = new URL((FileUtils.makeAbsoluteURL(metadataCert, getConfigRootDir()))); InputStream certstream = keystoreURL.openStream(); X509Certificate cert = new X509Certificate(certstream); BasicX509Credential idpCredential = new BasicX509Credential(); idpCredential.setEntityCertificate(cert); log.debug("IDP Certificate loading finished"); String metadataurl = getPVP2IDPMetadataURL(); if (MiscUtil.isEmpty(metadataurl)) { log.info("NO IDP Metadata URL."); throw new ConfigurationException("NO IDP Metadata URL."); } MOAHttpClient httpClient = new MOAHttpClient(); if (metadataurl.startsWith("https:")) { try { MOAHttpProtocolSocketFactory protoSocketFactory = new MOAHttpProtocolSocketFactory( "MOAMetaDataProvider", ConfigurationProvider.getInstance().getCertStoreDirectory(), ConfigurationProvider.getInstance().getTrustStoreDirectory(), null, ChainingModeType.PKIX, true); httpClient.setCustomSSLTrustStore(metadataurl, protoSocketFactory); } catch (MOAHttpProtocolSocketFactoryException e) { log.warn("MOA SSL-TrustStore can not initialized. Use default Java TrustStore."); } } idpMetadataProvider = new HTTPMetadataProvider(new Timer(), httpClient, metadataurl); idpMetadataProvider.setRequireValidMetadata(true); idpMetadataProvider.setParserPool(new BasicParserPool()); idpMetadataProvider.setMetadataFilter(new MetaDataVerificationFilter(idpCredential)); idpMetadataProvider.setMaxRefreshDelay(1000 * 3600 * 12); //refresh Metadata every 12h idpMetadataProvider.initialize(); pvp2logininitialzied = true; } catch (Exception e) { log.warn("PVP2 authentification can not be initialized."); throw new ConfigurationException("PVP2 authentification can not be initialized.", e); } } private String parseVersionFromManifest() { try { Class clazz = ConfigurationProvider.class; String className = clazz.getSimpleName() + ".class"; String classPath = clazz.getResource(className).toString(); if (classPath.startsWith("jar")) { log.info("MOA-ID-Configuration Version can NOT parsed from Manifest. Set blank Version"); return Constants.DEFAULT_VERSION; } String manifestPath = classPath.substring(0, classPath.lastIndexOf("WEB-INF/classes/") + "WEB-INF/classes/".length()) + "../../META-INF/MANIFEST.MF"; Manifest manifest = new Manifest(new URL(manifestPath).openStream()); ; Attributes attributes = manifest.getMainAttributes(); String version = attributes.getValue("version"); if (MiscUtil.isNotEmpty(version)) return version; else { log.info("MOA-ID-Configuration Version not found in Manifest. Set blank Version"); return Constants.DEFAULT_VERSION; } } catch (Throwable e) { log.info("MOA-ID Version can NOT parsed from Manifest. Set blank Version"); return Constants.DEFAULT_VERSION; } } }