Skip to content
Snippets Groups Projects
Select Git revision
  • 6283a591f1e406ef901de7efbd111e6b1955afe5
  • master default protected
  • add-frequency-to-form
  • dev protected
  • ckan-2.11.0
  • add-package-custom-fields
  • fix-adding-datasets-for-users-and-editors
  • add-auth-subroute
  • 71-migrate-custom-fields-to-ckanext-scheming
  • add-author-maintainer-information
  • fix-inline-flex-btns
  • fix-known-spatial-uri-validation
  • py3
  • 47-aktuelle-resource-einer-collection-wird-nicht-mehr-gefunden
  • 10-eingabe-der-dct-accrualperiodicity-in-weboberflache
  • v1.3
  • 2.5.3
  • 2.5.2
  • 2.5.1
  • 2.5.0
  • 2.4.7
  • 2.4.6
  • 2.4.5
  • 2.4.4
  • 2.4.3
  • 2.4.2
  • 2.4.1
  • 2.4.0
  • 2.3.1
  • 2.3.0
  • 2.2.0
  • 2.1.0
  • 2.0.0
  • 1.4.3
  • 1.4.2
  • 1.4.1
36 results

plugin.py

Blame
  • TokenCheckConfiguration.java 7.93 KiB
    /*
     * Copyright (c) 2024.
     * Lizenziert unter der EUPL, Version 1.2 oder - sobald
     * diese von der Europäischen Kommission genehmigt wurden -
     * Folgeversionen der EUPL ("Lizenz");
     * Sie dürfen dieses Werk ausschließlich gemäß
     * dieser Lizenz nutzen.
     * Eine Kopie der Lizenz finden Sie hier:
     *
     * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
     *
     * Sofern nicht durch anwendbare Rechtsvorschriften
     * gefordert oder in schriftlicher Form vereinbart, wird
     * die unter der Lizenz verbreitete Software "so wie sie
     * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
     * ausdrücklich oder stillschweigend - verbreitet.
     * Die sprachspezifischen Genehmigungen und Beschränkungen
     * unter der Lizenz sind dem Lizenztext zu entnehmen.
     */
    
    package de.ozgcloud.token;
    
    import static de.ozgcloud.token.saml.SamlTokenUtils.*;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    import jakarta.annotation.PostConstruct;
    
    import org.opensaml.core.config.ConfigurationService;
    import org.opensaml.core.config.InitializationException;
    import org.opensaml.core.config.InitializationService;
    import org.opensaml.core.criterion.EntityIdCriterion;
    import org.opensaml.core.xml.XMLObject;
    import org.opensaml.core.xml.config.XMLObjectProviderRegistry;
    import org.opensaml.saml.criterion.ProtocolCriterion;
    import org.opensaml.saml.metadata.criteria.role.impl.EvaluableProtocolRoleDescriptorCriterion;
    import org.opensaml.saml.saml2.encryption.Decrypter;
    import org.opensaml.saml.saml2.encryption.EncryptedElementTypeEncryptedKeyResolver;
    import org.opensaml.security.credential.Credential;
    import org.opensaml.security.credential.CredentialResolver;
    import org.opensaml.security.credential.CredentialSupport;
    import org.opensaml.security.credential.UsageType;
    import org.opensaml.security.credential.criteria.impl.EvaluableEntityIDCredentialCriterion;
    import org.opensaml.security.credential.criteria.impl.EvaluableUsageCredentialCriterion;
    import org.opensaml.security.credential.impl.CollectionCredentialResolver;
    import org.opensaml.security.criteria.UsageCriterion;
    import org.opensaml.security.x509.BasicX509Credential;
    import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap;
    import org.opensaml.xmlsec.encryption.support.ChainingEncryptedKeyResolver;
    import org.opensaml.xmlsec.encryption.support.EncryptedKeyResolver;
    import org.opensaml.xmlsec.encryption.support.InlineEncryptedKeyResolver;
    import org.opensaml.xmlsec.encryption.support.SimpleRetrievalMethodEncryptedKeyResolver;
    import org.opensaml.xmlsec.keyinfo.impl.CollectionKeyInfoCredentialResolver;
    import org.opensaml.xmlsec.signature.support.SignatureTrustEngine;
    import org.opensaml.xmlsec.signature.support.impl.ExplicitKeySignatureTrustEngine;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.io.Resource;
    import org.springframework.security.saml2.Saml2Exception;
    import org.springframework.security.saml2.core.Saml2X509Credential;
    import org.springframework.stereotype.Component;
    
    import de.ozgcloud.common.errorhandling.TechnicalException;
    import de.ozgcloud.token.saml.ConfigurationEntity;
    import de.ozgcloud.token.saml.SamlSetting;
    import de.ozgcloud.token.saml.SamlSettingsRegistry;
    import de.ozgcloud.token.saml.SamlTokenUtils;
    import lombok.RequiredArgsConstructor;
    import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
    import net.shibboleth.utilities.java.support.xml.ParserPool;
    import net.shibboleth.utilities.java.support.xml.XMLParserException;
    
    @Component
    @Configuration
    @RequiredArgsConstructor
    public class TokenCheckConfiguration {
    	private XMLObjectProviderRegistry registry;
    	private final TokenCheckProperties tokenCheckerProperties;
    	private final ParserPool parserPool;
    	private final SamlSettingsRegistry samlSettingsRegistry;
    
    	private static final EncryptedKeyResolver encryptedKeyResolver = new ChainingEncryptedKeyResolver(
    			Arrays.asList(new InlineEncryptedKeyResolver(), new EncryptedElementTypeEncryptedKeyResolver(),
    					new SimpleRetrievalMethodEncryptedKeyResolver()));
    
    	@PostConstruct
    	public void initOpenSAML() {
    		try {
    			registry = new XMLObjectProviderRegistry();
    			ConfigurationService.register(XMLObjectProviderRegistry.class, registry);
    
    			registry.setParserPool(parserPool);
    			InitializationService.initialize();
    
    			tokenCheckerProperties.getEntities().forEach(this::initSamlSetting);
    		} catch (InitializationException e) {
    			throw new TechnicalException("Initialization failed", e);
    		}
    	}
    
    	private void initSamlSetting(final ConfigurationEntity entity) {
    		var trustEngine = initTrustEngine(entity.getMetadata(), entity.getIdpEntityId());
    		var verificationCriteria = getVerificationCriteria(entity.getIdpEntityId());
    		var decrypter = initDecrypter(entity);
    
    		var samlSetting = SamlSetting.builder()
    				.trustEngine(trustEngine)
    				.criteriaSet(verificationCriteria)
    				.decrypter(decrypter)
    				.mappings(entity.getMappings())
    				.idIsPostfachId(entity.getUseIdAsPostfachId())
    				.build();
    
    		samlSettingsRegistry.addSetting(entity.getIdpEntityId(), samlSetting);
    	}
    
    	private SignatureTrustEngine initTrustEngine(Resource metadata, String idpEntityId) {
    		Set<Credential> credentials = new HashSet<>();
    		Collection<Saml2X509Credential> keys = getCertificatesFromMetadata(metadata);
    
    		for (Saml2X509Credential key : keys) {
    			var cred = new BasicX509Credential(key.getCertificate());
    			cred.setUsageType(UsageType.SIGNING);
    			cred.setEntityId(idpEntityId);
    			credentials.add(cred);
    		}
    
    		CredentialResolver credentialsResolver = new CollectionCredentialResolver(credentials);
    		return new ExplicitKeySignatureTrustEngine(credentialsResolver,
    				DefaultSecurityConfigurationBootstrap.buildBasicInlineKeyInfoCredentialResolver());
    	}
    
    	private CriteriaSet getVerificationCriteria(String idpEntityId) {
    		var criteria = new CriteriaSet();
    		criteria.add(new EvaluableEntityIDCredentialCriterion(new EntityIdCriterion(idpEntityId)));
    		criteria.add(new EvaluableProtocolRoleDescriptorCriterion(new ProtocolCriterion("urn:oasis:names:tc:SAML:2.0:protocol")));
    		criteria.add(new EvaluableUsageCredentialCriterion(new UsageCriterion(UsageType.SIGNING)));
    		return criteria;
    	}
    
    	private List<Saml2X509Credential> getCertificatesFromMetadata(Resource metadataResource) {
    		try (var metadata = metadataResource.getInputStream()) {
    			var xmlObject = xmlObject(metadata);
    			var descriptorOptional = findEntityDescriptor(xmlObject);
    			if (descriptorOptional.isPresent()) {
    				return SamlTokenUtils.getVerificationCertificates(descriptorOptional.get());
    			}
    		} catch (IOException e) {
    			throw new Saml2Exception("Error reading idp metadata.", e);
    		} catch (XMLParserException e) {
    			throw new Saml2Exception("Error initializing parser pool.", e);
    		}
    
    		throw new Saml2Exception("No IDPSSO Descriptors found");
    	}
    
    	private XMLObject xmlObject(InputStream inputStream) throws XMLParserException {
    		var document = parserPool.parse(inputStream);
    		var element = document.getDocumentElement();
    		var unmarshaller = registry.getUnmarshallerFactory().getUnmarshaller(element);
    		if (unmarshaller == null) {
    			throw new Saml2Exception("Unsupported element of type " + element.getTagName());
    		}
    		try {
    			return unmarshaller.unmarshall(element);
    		} catch (Exception ex) {
    			throw new Saml2Exception(ex);
    		}
    	}
    
    	private Decrypter initDecrypter(ConfigurationEntity entity) {
    		var credentials = new ArrayList<Credential>();
    		var decryptionX509Credential = SamlTokenUtils.getDecryptionCredential(entity.getKey(), entity.getCertificate());
    
    		var cred = CredentialSupport.getSimpleCredential(decryptionX509Credential.getCertificate(), decryptionX509Credential.getPrivateKey());
    		credentials.add(cred);
    
    		var resolver = new CollectionKeyInfoCredentialResolver(credentials);
    		var setupDecrypter = new Decrypter(null, resolver, encryptedKeyResolver);
    		setupDecrypter.setRootInNewDocument(true);
    
    		return setupDecrypter;
    	}
    }