diff options
author | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2020-02-05 11:03:59 +0100 |
---|---|---|
committer | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2020-02-05 11:03:59 +0100 |
commit | fc8aab29eb278a1489a75847efa38ea72b941c79 (patch) | |
tree | 50a8d9c939ce24c7bb068007467737354bae50a6 /eaaf_modules/eaaf_module_pvp2_core/src | |
parent | 5a1eca23a9b35541b7b1955b83b47e0af983d5dd (diff) | |
download | EAAF-Components-fc8aab29eb278a1489a75847efa38ea72b941c79.tar.gz EAAF-Components-fc8aab29eb278a1489a75847efa38ea72b941c79.tar.bz2 EAAF-Components-fc8aab29eb278a1489a75847efa38ea72b941c79.zip |
Extract interface from AbstractCredentialProvider.java
Add new interface IPvpAddableChainingMetadataProvider.java and implement it in AbstractChainingMetadataProvider.java
Fix possible nullPointer in Saml2Utils.java
Diffstat (limited to 'eaaf_modules/eaaf_module_pvp2_core/src')
6 files changed, 214 insertions, 70 deletions
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpAddableChainingMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpAddableChainingMetadataProvider.java new file mode 100644 index 00000000..8e5eb715 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpAddableChainingMetadataProvider.java @@ -0,0 +1,22 @@ +package at.gv.egiz.eaaf.modules.pvp2.api.metadata; + +import javax.annotation.Nonnull; + +import at.gv.egiz.eaaf.core.api.IGarbageCollectorProcessing; + +import org.opensaml.saml.metadata.resolver.MetadataResolver; + +public interface IPvpAddableChainingMetadataProvider { + + /** + * Manually add a metadata resolver into a chaining metadata provider. + * <br> + * <b>If the chaining metadata provider also implements + * {@link IGarbageCollectorProcessing} manually added provider + * can be removed by garbage-collector process. This behavior + * depends on chaining metadata-provider implementation. </b> + * + * @param resolver Metadata provider that should be added + */ + void addMetadataResolverIntoChain(@Nonnull MetadataResolver resolver); +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataConfigurationFactory.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataConfigurationFactory.java index 0cf7e293..fb1352ce 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataConfigurationFactory.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataConfigurationFactory.java @@ -19,11 +19,11 @@ package at.gv.egiz.eaaf.modules.pvp2.api.metadata; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.utils.IPvp2CredentialProvider; public interface IPvpMetadataConfigurationFactory { IPvpMetadataBuilderConfiguration generateMetadataBuilderConfiguration(String authUrl, - AbstractCredentialProvider pvpIdpCredentials); + IPvp2CredentialProvider pvpIdpCredentials); } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/utils/IPvp2CredentialProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/utils/IPvp2CredentialProvider.java new file mode 100644 index 00000000..a564efb2 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/utils/IPvp2CredentialProvider.java @@ -0,0 +1,55 @@ +package at.gv.egiz.eaaf.modules.pvp2.api.utils; + +import java.security.cert.X509Certificate; +import java.util.List; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; + +public interface IPvp2CredentialProvider { + + /** + * Get Credentials to sign metadata. + * + * @return Credentials + * @throws CredentialsNotAvailableException In case of a credential error + */ + @Nonnull + EaafX509Credential getMetaDataSigningCredential() throws CredentialsNotAvailableException; + + /** + * Get Credentials to sign SAML2 messages, like AuthnRequest, Response, + * Assertions as some examples. + * + * @return Credentials + * @throws CredentialsNotAvailableException In case of a credential error + */ + @Nonnull + EaafX509Credential getMessageSigningCredential() throws CredentialsNotAvailableException; + + /** + * Get Credentials to encrypt messages, like Assertion as example. + * + * @return Credentials + * @throws CredentialsNotAvailableException In case of a credential error + */ + @Nullable + EaafX509Credential getMessageEncryptionCredential() + throws CredentialsNotAvailableException; + + /** + * Get a List of trusted {@link X509Certificate} that are available in this + * KeyStore. + * + * @return List of trusted {@link X509Certificate}, or an emptry {@link List} if + * no certificates are available + * @throws CredentialsNotAvailableException In case of a KeyStore error + */ + @Nonnull + List<X509Certificate> getTrustedCertificates() + throws CredentialsNotAvailableException; + +}
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java index 8a20b932..80511f64 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java @@ -36,6 +36,7 @@ import at.gv.egiz.components.spring.api.IDestroyableObject; import at.gv.egiz.eaaf.core.api.IGarbageCollectorProcessing; import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpAddableChainingMetadataProvider; import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; import org.apache.commons.lang3.StringUtils; @@ -56,7 +57,7 @@ import net.shibboleth.utilities.java.support.resolver.ResolverException; @Slf4j public abstract class AbstractChainingMetadataProvider implements IGarbageCollectorProcessing, - IRefreshableMetadataProvider, + IRefreshableMetadataProvider, IPvpAddableChainingMetadataProvider, IDestroyableObject, IPvp2MetadataProvider, ClearableMetadataResolver { @Nonnull @@ -157,21 +158,6 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec } - /** - * Close metadata provider and remove all loaded metadata. - * - */ - public void internalDestroy() { - log.info("Destroying chained metadata resolvers ..."); - - for (final MetadataResolver resolver : internalResolvers) { - destroyMetadataResolver(resolver); - } - - internalResolvers.clear(); - - } - @Override public final MetadataFilter getMetadataFilter() { log.warn("{} does NOT support {}", AbstractChainingMetadataProvider.class.getName(), @@ -194,7 +180,7 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec * getEntityDescriptor( java.lang.String) */ @Override - public EntityDescriptor getEntityDescriptor(final String entityID) + public final EntityDescriptor getEntityDescriptor(final String entityID) throws ResolverException { EntityDescriptor entityDesc = null; try { @@ -212,6 +198,7 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec "Can not find PVP metadata for entityID: " + entityID + " Start refreshing process ..."); if (refreshMetadataProvider(entityID)) { return resolveEntityDescripor(entityID); + } } @@ -221,22 +208,21 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec @Override @Nullable - public final EntityDescriptor resolveSingle(@Nullable final CriteriaSet criteria) throws ResolverException { - for (final MetadataResolver resolver : internalResolvers) { - try { - final EntityDescriptor descriptors = resolver.resolveSingle(criteria); - if (descriptors != null) { - return descriptors; - } - - } catch (final ResolverException e) { - continue; + public final EntityDescriptor resolveSingle(@Nullable final CriteriaSet criteria) + throws ResolverException { + EntityDescriptor result = internalResolveSingle(criteria); + if (result == null && criteria != null) { + final EntityIdCriterion entityIdCriteria = criteria.get(EntityIdCriterion.class); + if (entityIdCriteria != null + && refreshMetadataProvider(entityIdCriteria.getEntityId())) { + log.debug("Can not find PVP metadata for entityID: {}. Metadata refreshing was done ... ", + entityIdCriteria.getEntityId()); + result = internalResolveSingle(criteria); } - } - return null; + return result; } @@ -244,21 +230,18 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec @Nonnull public final Iterable<EntityDescriptor> resolve(@Nullable final CriteriaSet criteria) throws ResolverException { - for (final MetadataResolver resolver : internalResolvers) { - try { - final Iterable<EntityDescriptor> descriptors = resolver.resolve(criteria); - if (descriptors != null && descriptors.iterator().hasNext()) { - return descriptors; - - } - - } catch (final ResolverException e) { - continue; - + Iterable<EntityDescriptor> result = internalResolve(criteria); + if (criteria != null) { + final EntityIdCriterion entityIdCriteria = criteria.get(EntityIdCriterion.class); + if (!result.iterator().hasNext() && entityIdCriteria != null + && refreshMetadataProvider(entityIdCriteria.getEntityId())) { + log.debug("Can not find PVP metadata for entityID: {}. Metadata refreshing was done ... ", + entityIdCriteria.getEntityId()); + result = internalResolve(criteria); } } - return Collections.emptyList(); + return result; } @Override @@ -295,7 +278,7 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec @Override @Nullable - public DateTime getLastUpdate() { + public final DateTime getLastUpdate() { DateTime ret = null; for (final MetadataResolver resolver : internalResolvers) { if (resolver instanceof RefreshableMetadataResolver) { @@ -325,6 +308,42 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec return ret; } + @Override + public final DateTime getLastSuccessfulRefresh() { + return this.lastRefeshTimestamp; + + } + + @Override + public final Boolean wasLastRefreshSuccess() { + return this.lastRefeshSuccessful; + + } + + @Override + public final boolean isRequireValidMetadata() { + log.warn("Attempt to access unsupported requireValidMetadata property on ChainingMetadataResolver"); + return false; + } + + @Override + public final void setRequireValidMetadata(final boolean requireValidMetadata) { + throw new UnsupportedOperationException( + "Setting requireValidMetadata is not supported on chaining resolver"); + } + + @Override + public final String getId() { + return getMetadataProviderId(); + + } + + @Override + public final void addMetadataResolverIntoChain(MetadataResolver resolver) { + internalResolvers.add(resolver); + + } + /** * Get the URL to metadata for a specific entityID. * @@ -465,34 +484,58 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec } } - @Override - public DateTime getLastSuccessfulRefresh() { - return this.lastRefeshTimestamp; + /** + * Close metadata provider and remove all loaded metadata. + * + */ + private void internalDestroy() { + log.info("Destroying chained metadata resolvers ..."); - } + for (final MetadataResolver resolver : internalResolvers) { + destroyMetadataResolver(resolver); + } - @Override - public Boolean wasLastRefreshSuccess() { - return this.lastRefeshSuccessful; + internalResolvers.clear(); } - @Override - public boolean isRequireValidMetadata() { - log.warn("Attempt to access unsupported requireValidMetadata property on ChainingMetadataResolver"); - return false; - } + private EntityDescriptor internalResolveSingle(@Nullable final CriteriaSet criteria) + throws ResolverException { + for (final MetadataResolver resolver : internalResolvers) { + try { + final EntityDescriptor descriptors = resolver.resolveSingle(criteria); + if (descriptors != null) { + return descriptors; + } + + } catch (final ResolverException e) { + continue; + + } + } + + return null; - @Override - public void setRequireValidMetadata(final boolean requireValidMetadata) { - throw new UnsupportedOperationException( - "Setting requireValidMetadata is not supported on chaining resolver"); } - @Override - public String getId() { - return getMetadataProviderId(); + @Nonnull + private Iterable<EntityDescriptor> internalResolve(@Nullable final CriteriaSet criteria) + throws ResolverException { + for (final MetadataResolver resolver : internalResolvers) { + try { + final Iterable<EntityDescriptor> descriptors = resolver.resolve(criteria); + if (descriptors != null && descriptors.iterator().hasNext()) { + return descriptors; + + } + } catch (final ResolverException e) { + continue; + + } + } + + return Collections.emptyList(); } } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java index 13124114..6959b6bd 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java @@ -39,6 +39,7 @@ 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.api.utils.IPvp2CredentialProvider; 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; @@ -53,7 +54,7 @@ import org.springframework.core.io.ResourceLoader; import lombok.extern.slf4j.Slf4j; @Slf4j -public abstract class AbstractCredentialProvider { +public abstract class AbstractCredentialProvider implements IPvp2CredentialProvider { private static final String TRUSTED_CERTIFICATES_OPERATION = "Trusted Certificate Entries"; @@ -136,10 +137,11 @@ public abstract class AbstractCredentialProvider { * @return Credentials * @throws CredentialsNotAvailableException In case of a credential error */ + @Override public EaafX509Credential getMetaDataSigningCredential() throws CredentialsNotAvailableException { try { final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter(keyStore, - getMetadataKeyAlias(), getMetadataKeyPassword().toCharArray(), getFriendlyName()); + getMetadataKeyAlias(), getPassCharArrayOrNull(getMetadataKeyPassword()), getFriendlyName()); credentials.setUsageType(UsageType.SIGNING); credentials.setSignatureAlgorithmForSigning(selectSigningAlgorithm(credentials)); credentials.setKeyEncryptionAlgorithmForDataEncryption(selectKeyEncryptionAlgorithm(credentials)); @@ -152,6 +154,8 @@ public abstract class AbstractCredentialProvider { } } + + /** * Get Credentials to sign SAML2 messages, like AuthnRequest, Response, * Assertions as some examples. @@ -159,10 +163,11 @@ public abstract class AbstractCredentialProvider { * @return Credentials * @throws CredentialsNotAvailableException In case of a credential error */ + @Override public EaafX509Credential getMessageSigningCredential() throws CredentialsNotAvailableException { try { final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter(keyStore, - getSignatureKeyAlias(), getSignatureKeyPassword().toCharArray(), getFriendlyName()); + getSignatureKeyAlias(), getPassCharArrayOrNull(getSignatureKeyPassword()), getFriendlyName()); credentials.setUsageType(UsageType.SIGNING); credentials.setSignatureAlgorithmForSigning(selectSigningAlgorithm(credentials)); credentials.setKeyEncryptionAlgorithmForDataEncryption(selectKeyEncryptionAlgorithm(credentials)); @@ -181,6 +186,7 @@ public abstract class AbstractCredentialProvider { * @return Credentials * @throws CredentialsNotAvailableException In case of a credential error */ + @Override public EaafX509Credential getMessageEncryptionCredential() throws CredentialsNotAvailableException { // if no encryption key is configured return null @@ -190,7 +196,7 @@ public abstract class AbstractCredentialProvider { try { final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter(keyStore, - getEncryptionKeyAlias(), getEncryptionKeyPassword().toCharArray(), getFriendlyName()); + getEncryptionKeyAlias(), getPassCharArrayOrNull(getEncryptionKeyPassword()), getFriendlyName()); credentials.setUsageType(UsageType.ENCRYPTION); credentials.setSignatureAlgorithmForSigning(selectSigningAlgorithm(credentials)); credentials.setKeyEncryptionAlgorithmForDataEncryption(selectKeyEncryptionAlgorithm(credentials)); @@ -212,6 +218,7 @@ public abstract class AbstractCredentialProvider { * no certificates are available * @throws CredentialsNotAvailableException In case of a KeyStore error */ + @Override @Nonnull public List<X509Certificate> getTrustedCertificates() throws CredentialsNotAvailableException { @@ -288,4 +295,14 @@ public abstract class AbstractCredentialProvider { PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_EC)); } + private char[] getPassCharArrayOrNull(String metadataKeyPassword) { + char[] keyPassChar = null; + if (metadataKeyPassword != null) { + keyPassChar = metadataKeyPassword.toCharArray(); + + } + + return keyPassChar; + } + } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java index 14e6a78a..a3154b0d 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java @@ -22,9 +22,11 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.utils; import java.io.IOException; import java.io.InputStream; import java.security.PrivateKey; +import java.security.PublicKey; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; import java.util.List; import javax.annotation.Nonnull; @@ -229,17 +231,22 @@ public class Saml2Utils { public static String getKeyOperationAlgorithmFromCredential(X509Credential credentials, String rsaSigAlgorithm, String ecSigAlgorithm) throws SamlSigningException { final PrivateKey privatekey = credentials.getPrivateKey(); - if (privatekey instanceof RSAPrivateKey) { + final PublicKey publickey = credentials.getPublicKey(); + if (privatekey instanceof RSAPrivateKey + || publickey instanceof RSAPublicKey) { return rsaSigAlgorithm; - } else if (privatekey instanceof ECPrivateKey) { + } else if (privatekey instanceof ECPrivateKey + || publickey instanceof ECPublicKey) { return ecSigAlgorithm; } else { log.warn("Could NOT evaluate the Private-Key type from " + credentials.getEntityId() + " credential."); throw new SamlSigningException("internal.pvp.97", - new Object[] { credentials.getEntityId(), privatekey.getClass().getName() }); + new Object[] { credentials.getEntityId(), + privatekey != null ? privatekey.getClass().getName() : publickey.getClass().getName() + }); } } |