/* * 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.auth.modules.eidas.config; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineConfigurationException; import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.FileUtils; import at.gv.egovernment.moa.util.MiscUtil; import eu.eidas.samlengineconfig.BinaryParameter; import eu.eidas.samlengineconfig.EngineInstance; import eu.eidas.samlengineconfig.InstanceConfiguration; import eu.eidas.samlengineconfig.PropsParameter; import eu.eidas.samlengineconfig.SamlEngineConfiguration; /** * @author tlenz * */ public class MOAeIDASSAMLEngineConfigurationImpl extends SamlEngineConfiguration { private static final String KEYSTORE_PATH="keyStorePath"; private static final String METADATA_KEYSTORE_PATH="metadata.keyStorePath"; private static final String ENCRYPTION_ACTIVATION="encryptionActivation"; public static final String[] BINARY_PARAMETERS={KEYSTORE_PATH, ENCRYPTION_ACTIVATION,METADATA_KEYSTORE_PATH}; public List getInstances(){ return super.getInstances(); } @Override public void setInstances(List engineInstances) { super.setInstances(engineInstances); } public Map getInstanceMap() { Map result = new HashMap(); for(EngineInstance instance:getInstances()) { result.put(instance.getName(), instance); } return result; } //initialize public void initialize() throws ConfigurationException { //create an eIDAS SAML-engine instance EngineInstance engineInst = new EngineInstance(); engineInst.setName(Constants.eIDAS_SAML_ENGINE_NAME); List engineConfigs = new ArrayList(); //add configurations //add basic eIDAS SAML-engine configuration MOAeIDASSAMLInstanceConfigurationImpl samlBaseConfig = new MOAeIDASSAMLInstanceConfigurationImpl(); samlBaseConfig.setName(Constants.eIDAS_SAML_ENGINE_NAME_ID_BASICCONFIG); samlBaseConfig.addParameter(buildPropsParameter(Constants.CONIG_PROPS_EIDAS_SAMLENGINE_BASIC_CONFIGFILE)); engineConfigs.add(samlBaseConfig); //add signing eIDAS SAML-engine configuration MOAeIDASSAMLInstanceConfigurationImpl samlSignConfig = new MOAeIDASSAMLInstanceConfigurationImpl(); samlSignConfig.setName(Constants.eIDAS_SAML_ENGINE_NAME_ID_SIGNATURECONFIG); samlSignConfig.addParameter(Constants.eIDAS_SAML_ENGINE_NAME_ID_CLASS, Constants.SAML_SIGNING_IMPLENTATION); //TODO: load signing keys directly from MOA-ID configuration in finale version samlSignConfig.addParameter(loadConfigurationFromExternalFile(Constants.CONIG_PROPS_EIDAS_SAMLENGINE_SIGN_CONFIGFILE)); engineConfigs.add(samlSignConfig); //add encryption eIDAS SAML-engine configuration MOAeIDASSAMLInstanceConfigurationImpl samlEncConfig = new MOAeIDASSAMLInstanceConfigurationImpl(); samlEncConfig.setName(Constants.eIDAS_SAML_ENGINE_NAME_ID_ENCRYPTIONCONFIG); samlEncConfig.addParameter(Constants.eIDAS_SAML_ENGINE_NAME_ID_CLASS, Constants.SAML_ENCRYPTION_IMPLENTATION); //TODO: load encryption keys directly from MOA-ID configuration in finale version samlEncConfig.addParameter(loadConfigurationFromExternalFile(Constants.CONIG_PROPS_EIDAS_SAMLENGINE_ENC_CONFIGFILE)); engineConfigs.add(samlEncConfig); engineInst.setConfigurations(engineConfigs); super.addInstance(engineInst); } /** * Load an external eIDAS SAML-engine configuration file, which is referenced from MOA-ID configuration * * @param key Configuration key, which is used in property based MOA-ID configuration file * @return eIDAS SAML-engine configuration Properties * @throws ConfigurationException */ private Properties loadConfigurationFromExternalFile(String key) throws ConfigurationException { String configFile = AuthConfigurationProviderFactory.getInstance().getBasicMOAIDConfiguration(key); if (MiscUtil.isEmpty(configFile)) { Logger.warn("No eIDAS SAML-engine configuration key: " + key + " found in MOA-ID properties configuration file."); //throw new EIDASEngineConfigurationException("No eIDAS SAML-engine configuration property.", null); return null; } Properties inputProps = loadPropsFromXml(configFile); return inputProps; //return buildPropsParameter(inputProps, configFile); } private PropsParameter buildPropsParameter(String configKey) throws ConfigurationException { Properties inputProps = loadConfigurationFromExternalFile(configKey); String configFile = AuthConfigurationProviderFactory.getInstance().getBasicMOAIDConfiguration(configKey); PropsParameter outputProps = new PropsParameter(); outputProps.setFileName(configFile); //original eIDAS SAML-engine use this identifier outputProps.setName("fileConfiguration"); outputProps.setValue(inputProps); //post-process special parameters for(String key:BINARY_PARAMETERS) { Object keystorePath = inputProps.get(key); if (keystorePath != null) { if (keystorePath instanceof String && isBinaryParameter((String)keystorePath) ) { BinaryParameter bp = new BinaryParameter(); bp.setValue(loadBinaryFile(keystorePath.toString())); bp.setName(key); bp.setUrl(keystorePath.toString()); inputProps.put(key, bp); } else { Logger.warn("eIDAS SAML-engine keyStore parameter has an unsuspected type. +" + "(Type: " + keystorePath.toString() + ")"); } } } return outputProps; } private boolean isBinaryParameter(String parameter) { if (MiscUtil.isNotEmpty(parameter)) { String absoluteConfigFile; try { absoluteConfigFile = FileUtils.makeAbsoluteURL( parameter, AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir()); File file = new File(new URL(absoluteConfigFile).toURI()); return file.exists(); } catch (ConfigurationException | MalformedURLException | URISyntaxException e) { Logger.warn("Binary eIDAS SAML-engine configuration parameter: " + parameter + " is not loadable."); } } return false; } private byte[] loadBinaryFile(String fileName) throws EIDASEngineConfigurationException{ InputStream is = null; byte data[]=null; try { String absoluteConfigFile = FileUtils.makeAbsoluteURL( fileName, AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir()); File file = new File(new URL(absoluteConfigFile).toURI()); is = new FileInputStream(file); data=new byte[is.available()]; is.read(data); } catch (ConfigurationException | URISyntaxException | IOException e) { throw new EIDASEngineConfigurationException("eIDAS SAML-engine configuration FAILED", null, e); } finally { if (is != null) try { is.close(); } catch (IOException e) { Logger.warn("eIDAS SAML-engine configuration is not closeable.", e); } } return data; } private Properties loadPropsFromXml(String configFile) throws EIDASEngineConfigurationException { Properties props = new Properties(); InputStream is = null; try { String absoluteConfigFile = FileUtils.makeAbsoluteURL( configFile, AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir()); Logger.debug("Load eIDAS configuration from file:" + absoluteConfigFile); File file = new File(new URL(absoluteConfigFile).toURI()); is = new FileInputStream(file); props.loadFromXML(is); } catch (ConfigurationException | URISyntaxException | IOException e) { throw new EIDASEngineConfigurationException("eIDAS SAML-engine configuration FAILED", null, e); } finally { if (is != null) try { is.close(); } catch (IOException e) { Logger.warn("eIDAS SAML-engine configuration is not closeable.", e); } } return props; } }