/* * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * * 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.egiz.eaaf.modules.pvp2.impl.utils; import java.io.IOException; import java.io.InputStream; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.PrivateKey; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.RSAPrivateKey; import javax.annotation.PostConstruct; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.impl.utils.KeyStoreUtils; import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.EaafKeyStoreX509CredentialAdapter; import org.apache.commons.lang3.StringUtils; import org.opensaml.security.credential.Credential; import org.opensaml.security.credential.UsageType; import org.opensaml.xmlsec.signature.Signature; import org.opensaml.xmlsec.signature.support.SignatureConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; public abstract class AbstractCredentialProvider { @Autowired protected ResourceLoader resourceLoader; @Autowired protected IConfiguration basicConfig; private static final Logger log = LoggerFactory.getLogger(AbstractCredentialProvider.class); private KeyStore keyStore = null; /** * Get a friendlyName for this keyStore implementation This friendlyName is used * for logging. * * @return keyStore friendlyName */ public abstract String getFriendlyName(); /** * Get KeyStore. * * @return URL to the keyStore * @throws EaafException In case of an invalid filepath */ public abstract String getKeyStoreFilePath() throws EaafException; /** * Get keyStore password. * * @return Password of the keyStore */ public abstract String getKeyStorePassword(); /** * Get alias of key for metadata signing. * * @return key alias */ public abstract String getMetadataKeyAlias(); /** * Get password of key for metadata signing. * * @return key password */ public abstract String getMetadataKeyPassword(); /** * Get alias of key for request/response signing. * * @return key alias */ public abstract String getSignatureKeyAlias(); /** * Get password of key for request/response signing. * * @return key password */ public abstract String getSignatureKeyPassword(); /** * Get alias of key for IDP response encryption. * * @return key alias */ public abstract String getEncryptionKeyAlias(); /** * Get password of key for IDP response encryption. * * @return key password */ public abstract String getEncryptionKeyPassword(); /** * Get Credentials to sign metadata. * * @return Credentials * @throws CredentialsNotAvailableException In case of a credential error */ public EaafX509Credential getIdpMetaDataSigningCredential() throws CredentialsNotAvailableException { try { final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter(keyStore, getMetadataKeyAlias(), getMetadataKeyPassword().toCharArray(), getFriendlyName()); credentials.setUsageType(UsageType.SIGNING); credentials.setSignatureAlgorithmForSigning(Saml2Utils.getSignatureAlgorithm( credentials, basicConfig.getBasicConfiguration( PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG, PvpConstants.DEFAULT_SIGNING_METHODE_RSA), basicConfig.getBasicConfiguration( PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG, PvpConstants.DEFAULT_SIGNING_METHODE_EC))); return credentials; } catch (final SamlSigningException e) { throw new CredentialsNotAvailableException("internal.pvp.01", new Object[] { getFriendlyName(), getMetadataKeyAlias() }, e); } } /** * Get Credentials to sign Assertion. * * @return Credentials * @throws CredentialsNotAvailableException In case of a credential error */ public EaafX509Credential getIdpAssertionSigningCredential() throws CredentialsNotAvailableException { try { final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter(keyStore, getSignatureKeyAlias(), getSignatureKeyPassword().toCharArray(), getFriendlyName()); credentials.setUsageType(UsageType.SIGNING); credentials.setSignatureAlgorithmForSigning(Saml2Utils.getSignatureAlgorithm( credentials, basicConfig.getBasicConfiguration( PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG, PvpConstants.DEFAULT_SIGNING_METHODE_RSA), basicConfig.getBasicConfiguration( PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG, PvpConstants.DEFAULT_SIGNING_METHODE_EC))); return credentials; } catch (final Exception e) { throw new CredentialsNotAvailableException("internal.pvp.01", new Object[] { getFriendlyName(), getSignatureKeyAlias() }, e); } } /** * Get Credentials to encrypt assertion. * * @return Credentials * @throws CredentialsNotAvailableException In case of a credential error */ public EaafX509Credential getIdpAssertionEncryptionCredential() throws CredentialsNotAvailableException { // if no encryption key is configured return null if (StringUtils.isEmpty(getEncryptionKeyAlias())) { return null; } final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter(keyStore, getEncryptionKeyAlias(), getEncryptionKeyPassword().toCharArray(), getFriendlyName()); credentials.setUsageType(UsageType.ENCRYPTION); return credentials; } /** * Get an XML signature object. * * @param credentials Credentials for signing * @return OpenSAML Signature object */ @Deprecated public static Signature getIdpSignature(final Credential credentials) { final PrivateKey privatekey = credentials.getPrivateKey(); final Signature signer = Saml2Utils.createSamlObject(Signature.class); if (privatekey instanceof RSAPrivateKey) { signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256); } else if (privatekey instanceof ECPrivateKey) { signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256); } else { log.warn("Could NOT evaluate the Private-Key type from " + credentials.getEntityId() + " credential."); } signer.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); signer.setSigningCredential(credentials); return signer; } @Lazy @PostConstruct private void initialize() throws Exception { try { final Resource ressource = resourceLoader.getResource(getKeyStoreFilePath()); final InputStream is = ressource.getInputStream(); keyStore = KeyStoreUtils.loadKeyStore(is, getKeyStorePassword()); if (keyStore == null) { throw new EaafConfigurationException("module.00", new Object[] { getFriendlyName(), "KeyStore initialization failed. Maybe wrong password" }); } } catch (IOException | KeyStoreException | EaafException e) { log.error("Can not initialize KeyStore for eIDAS authentication client.", e); throw e; } } }