From 31bc1246bb56fcd8807678e3f7516023bdfaed44 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Fri, 20 Jul 2018 10:56:04 +0200 Subject: add SZR client add different logging backends define errorcodes and error messages update to eIDAS Ref. impl 2.1 --- .../tasks/CreateIdentityLinkTask.java | 391 ++++++++++++++++----- 1 file changed, 304 insertions(+), 87 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java index dfd945c9..b31b6a21 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java @@ -3,41 +3,80 @@ package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.tasks; import java.io.InputStream; +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.util.Base64Utils; +import org.w3._2000._09.xmldsig.KeyValueType; +import org.w3._2000._09.xmldsig.RSAKeyValueType; import org.w3c.dom.Element; import org.w3c.dom.Node; -import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; -import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants; -import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; -import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; -import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; -import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.eIDASAttributeException; -import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; -import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser; -import at.gv.egovernment.moa.id.commons.api.data.IIdentityLink; -import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; -import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; -import at.gv.egovernment.moa.id.process.api.ExecutionContext; -import at.gv.egovernment.moa.id.util.IdentityLinkReSigner; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.DOMUtils; -import at.gv.egovernment.moa.util.XPathUtils; -import eu.eidas.auth.commons.attribute.ImmutableAttributeMap; - -/** +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +import at.gv.e_government.reference.namespace.persondata._20020228.PersonNameType; +import at.gv.e_government.reference.namespace.persondata._20020228.PhysicalPersonType; +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.data.PVPAttributeDefinitions; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink; +import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.core.impl.data.Trible; +import at.gv.egiz.eaaf.core.impl.idp.auth.builder.BPKBuilder; +import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper; +import at.gv.egiz.eaaf.core.impl.idp.auth.data.SimpleIdentityLinkAssertionParser; +import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; +import at.gv.egiz.eaaf.core.impl.utils.DOMUtils; +import at.gv.egiz.eaaf.core.impl.utils.XPathUtils; +import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.Constants; +import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.exception.SZRCommunicationException; +import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.exception.eIDASAttributeException; +import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.szr.SZRClient; +import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.utils.eIDASResponseUtils; +import eu.eidas.auth.commons.attribute.AttributeDefinition; +import eu.eidas.auth.commons.attribute.AttributeValue; +import eu.eidas.auth.commons.light.ILightResponse; +import eu.eidas.auth.commons.protocol.eidas.impl.PostalAddress; +import szrservices.IdentityLinkType; +import szrservices.PersonInfoType; +import szrservices.TravelDocumentType; + +/** * @author tlenz - * + * */ @Component("CreateIdentityLinkTask") public class CreateIdentityLinkTask extends AbstractAuthServletTask { - + private static final Logger log = LoggerFactory.getLogger(CreateIdentityLinkTask.class); + + //@Autowired private eIDASAttributeRegistry attrRegistry; + @Autowired private IConfiguration basicConfig; + @Autowired private SZRClient szrClient; + + /* (non-Javadoc) * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @@ -46,115 +85,293 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask { HttpServletRequest request, HttpServletResponse response) throws TaskExecutionException { try{ - defaultTaskInitialization(request, executionContext); - - //get eIDAS attributes from MOA-Session - ImmutableAttributeMap eIDASAttributes = moasession.getGenericDataFromSession( - AuthenticationSessionStorageConstants.eIDAS_ATTRIBUTELIST, - ImmutableAttributeMap.class); - - IIdentityLink identityLink = null; - + AuthProcessDataWrapper authProcessData = pendingReq.getSessionData(AuthProcessDataWrapper.class); + ILightResponse eIDASResponse = authProcessData.getGenericDataFromSession( + Constants.DATA_FULL_EIDAS_RESPONSE, ILightResponse.class); + Map simpleAttrMap = converteIDASAttrToSimpleMap(eIDASResponse.getAttributes().getAttributeMap()); + + IIdentityLink identityLink = null; + String bPK = null; + + //extract attributes + Object eIdentifierObj = simpleAttrMap.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER); + Object familyNameObj = simpleAttrMap.get(Constants.eIDAS_ATTR_CURRENTFAMILYNAME); + Object givenNameObj = simpleAttrMap.get(Constants.eIDAS_ATTR_CURRENTGIVENNAME); + Object dateOfBirthObj = simpleAttrMap.get(Constants.eIDAS_ATTR_DATEOFBIRTH); + + //check if availabe + if (eIdentifierObj == null || !(eIdentifierObj instanceof String)) + throw new eIDASAttributeException(Constants.eIDAS_ATTR_PERSONALIDENTIFIER); + + if (familyNameObj == null || !(familyNameObj instanceof String)) + throw new eIDASAttributeException(Constants.eIDAS_ATTR_CURRENTFAMILYNAME); + + if (givenNameObj == null || !(givenNameObj instanceof String)) + throw new eIDASAttributeException(Constants.eIDAS_ATTR_CURRENTGIVENNAME); + + if (dateOfBirthObj == null || !(dateOfBirthObj instanceof DateTime)) + throw new eIDASAttributeException(Constants.eIDAS_ATTR_DATEOFBIRTH); + //connect SZR-Gateway - //TODO: implement SZR-Gateway communication!!!! - if(true) { - + if(basicConfig.getBasicMOAIDConfigurationBoolean( + Constants.CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_USEDUMMY, false)) { + log.warn("SZR-Dummy IS ACTIVE! IdentityLink is NOT VALID!!!!"); // create fake IdL // - fetch IdL template from resources InputStream s = CreateIdentityLinkTask.class.getResourceAsStream("/resources/xmldata/fakeIdL_IdL_template.xml"); Element idlTemplate = DOMUtils.parseXmlValidating(s); - identityLink = new IdentityLinkAssertionParser(idlTemplate).parseIdentityLink(); + identityLink = new SimpleIdentityLinkAssertionParser(idlTemplate).parseIdentityLink(); // replace data Element idlassertion = identityLink.getSamlAssertion(); // - set fake baseID; - Node prIdentification = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH); - - - Object eIdentifier = eIDASAttributes.getFirstValue( - SAMLEngineUtils.getMapOfAllAvailableAttributes().get( - Constants.eIDAS_ATTR_PERSONALIDENTIFIER)); - if (eIdentifier == null || !(eIdentifier instanceof String)) - throw new eIDASAttributeException(Constants.eIDAS_ATTR_PERSONALIDENTIFIER); - prIdentification.getFirstChild().setNodeValue((String) eIdentifier); + Node prIdentification = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH); + prIdentification.getFirstChild().setNodeValue((String) eIdentifierObj); //build personal identifier which looks like a baseID // String fakeBaseID = new BPKBuilder().buildBPK(eIdentifier, "baseID"); // Logger.info("Map eIDAS eIdentifier:" + eIdentifier + " to fake baseID:" + fakeBaseID); // prIdentification.getFirstChild().setNodeValue(fakeBaseID); - + // - set last name - Node prFamilyName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH); - Object familyName = eIDASAttributes.getFirstValue( - SAMLEngineUtils.getMapOfAllAvailableAttributes().get( - Constants.eIDAS_ATTR_CURRENTFAMILYNAME)); - if (familyName == null || !(familyName instanceof String)) - throw new eIDASAttributeException(Constants.eIDAS_ATTR_CURRENTFAMILYNAME); - prFamilyName.getFirstChild().setNodeValue((String) familyName); + Node prFamilyName = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH); + prFamilyName.getFirstChild().setNodeValue((String) familyNameObj); // - set first name - Node prGivenName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH); - Object givenName = eIDASAttributes.getFirstValue( - SAMLEngineUtils.getMapOfAllAvailableAttributes().get( - Constants.eIDAS_ATTR_CURRENTGIVENNAME)); - if (givenName == null || !(givenName instanceof String)) - throw new eIDASAttributeException(Constants.eIDAS_ATTR_CURRENTGIVENNAME); - prGivenName.getFirstChild().setNodeValue((String) givenName); + Node prGivenName = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH); + prGivenName.getFirstChild().setNodeValue((String) givenNameObj); // - set date of birth - Node prDateOfBirth = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_DATE_OF_BIRTH_XPATH); - Object dateOfBirth = eIDASAttributes.getFirstValue( - SAMLEngineUtils.getMapOfAllAvailableAttributes().get( - Constants.eIDAS_ATTR_DATEOFBIRTH)); - if (dateOfBirth == null || !(dateOfBirth instanceof DateTime)) - throw new eIDASAttributeException(Constants.eIDAS_ATTR_DATEOFBIRTH); - - String formatedDateOfBirth = new SimpleDateFormat("yyyy-MM-dd").format(((DateTime)dateOfBirth).toDate()); + Node prDateOfBirth = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_DATE_OF_BIRTH_XPATH); + String formatedDateOfBirth = new SimpleDateFormat("yyyy-MM-dd").format(((DateTime)dateOfBirthObj).toDate()); prDateOfBirth.getFirstChild().setNodeValue(formatedDateOfBirth); - identityLink = new IdentityLinkAssertionParser(idlassertion).parseIdentityLink(); + identityLink = new SimpleIdentityLinkAssertionParser(idlassertion).parseIdentityLink(); - //resign IDL - IdentityLinkReSigner identitylinkresigner = IdentityLinkReSigner.getInstance(); - Element resignedilAssertion = identitylinkresigner.resignIdentityLink(identityLink.getSamlAssertion(), authConfig.getStorkFakeIdLResigningKey()); - identityLink = new IdentityLinkAssertionParser(resignedilAssertion).parseIdentityLink(); - + Pair bPKCalc = new BPKBuilder().generateAreaSpecificPersonIdentifier( + identityLink.getIdentificationValue(), + identityLink.getIdentificationType(), + pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()); + bPK = bPKCalc.getFirst(); + + } else { //contact SZR Gateway - Logger.debug("Starting connecting SZR Gateway"); + log.debug("Starting connecting SZR Gateway"); + PersonInfoType personInfo = new PersonInfoType(); + PersonNameType personName = new PersonNameType(); + PhysicalPersonType naturalPerson = new PhysicalPersonType(); + TravelDocumentType eDocument = new TravelDocumentType(); + + naturalPerson.setName(personName ); + personInfo.setPerson(naturalPerson ); + personInfo.setTravelDocument(eDocument ); + + //parse some eID attributes + String dateOfBirth = new SimpleDateFormat("yyyy-MM-dd").format(((DateTime)dateOfBirthObj).toDate()); + Trible eIdentifier = + eIDASResponseUtils.parseEidasPersonalIdentifier((String)eIdentifierObj); + String uniqueId = (String)eIdentifierObj; + String citizenCountry = eIdentifier.getFirst(); + + //person information + personName.setFamilyName((String)familyNameObj); + personName.setGivenName((String)givenNameObj); + naturalPerson.setDateOfBirth(dateOfBirth); + eDocument.setIssuingCountry(citizenCountry); + eDocument.setDocumentNumber(uniqueId); + + //eID document information + eDocument.setDocumentType(basicConfig.getBasicConfiguration( + Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_EDOCUMENTTYPE, + Constants.SZR_CONSTANTS_DEFAULT_DOCUMENT_TYPE)); + + //TODO: that should be removed + eDocument.setIssueDate(basicConfig.getBasicConfiguration( + Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_ISSUING_DATE, + Constants.SZR_CONSTANTS_DEFAULT_ISSUING_DATE)); + eDocument.setIssuingAuthority(basicConfig.getBasicConfiguration( + Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_ISSUING_AUTHORITY, + Constants.SZR_CONSTANTS_DEFAULT_ISSUING_AUTHORITY)); + + //TODO: keys are not available in eIDAS + List keyValue = dummyCodeForKeys(); + + /*TODO: + * Validate if IDL signature is valid after using this method + * MAYBE we had to switch to 'getIdentityLinkInRawMode' method! + */ + IdentityLinkType result = szrClient.getIdentityLink( + personInfo, + keyValue, + basicConfig.getBasicMOAIDConfigurationBoolean( + Constants.CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_INSERTERNB, + true) + ); + + Element idlFromSZR = (Element)result.getAssertion(); + identityLink = new SimpleIdentityLinkAssertionParser(idlFromSZR).parseIdentityLink(); + + + //get bPK from SZR + bPK = szrClient.getBPK( + personInfo, + pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier(), + basicConfig.getBasicConfiguration( + Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_VKZ, + "no VKZ defined")); + + } + + if (identityLink == null) { + log.error("ERnB did not return an identity link."); + throw new SZRCommunicationException("ernb.00", null); + + } - //TODO:!!!!!! + if (bPK == null) { + log.error("ERnB did not return a bPK for target: " + pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()); + throw new SZRCommunicationException("ernb.01", null); } - Logger.debug("SZR communication was successfull"); + log.debug("ERnB communication was successfull"); + + revisionsLogger.logEvent(pendingReq, -1); + authProcessData.setForeigner(true); + authProcessData.setIdentityLink(identityLink); + authProcessData.setGenericDataToSession( + PVPAttributeDefinitions.EID_ISSUING_NATION_NAME, + eIDASResponseUtils.parseEidasPersonalIdentifier((String) simpleAttrMap.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER)).getFirst()); + + //set bPK and bPKType into auth session + authProcessData.setGenericDataToSession( + PVPAttributeDefinitions.BPK_NAME, + extendBPKbyPrefix( + bPK, + pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()) + ); + authProcessData.setGenericDataToSession( + PVPAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME, + pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()); - if (identityLink == null) { - Logger.error("SZR Gateway did not return an identity link."); - throw new MOAIDException("stork.10", null); - } - revisionsLogger.logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_PEPS_IDL_RECEIVED); - moasession.setForeigner(true); - moasession.setIdentityLink(identityLink); - moasession.setBkuURL("Not applicable (eIDASAuthentication)"); - //store MOA-session to database + //store pending-request requestStoreage.storePendingRequest(pendingReq); - + } catch (eIDASAttributeException e) { throw new TaskExecutionException(pendingReq, "Minimum required eIDAS attributeset not found.", e); - } catch (MOAIDException | MOADatabaseException e) { + } catch (EAAFException e) { throw new TaskExecutionException(pendingReq, "IdentityLink generation for foreign person FAILED.", e); } catch (Exception e) { - Logger.error("IdentityLink generation for foreign person FAILED.", e); + log.error("IdentityLink generation for foreign person FAILED.", e); throw new TaskExecutionException(pendingReq, "IdentityLink generation for foreign person FAILED.", e); } } + private List dummyCodeForKeys() { + if (basicConfig.getBasicMOAIDConfigurationBoolean( + Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_KEYS_USEDUMMY, + false)) { + List keyvalueList = new ArrayList(); + try { + PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Constants.SZR_CONSTANTS_DEFAULT_PUBL_KEY); + KeyFactory kf = KeyFactory.getInstance("RSA"); + + PublicKey pb = kf.generatePublic(spec); + + RSAPublicKey rsapb = (RSAPublicKey)pb; + BigInteger modulus = rsapb.getModulus(); + BigInteger exponent = rsapb.getPublicExponent(); + + // set key values + RSAKeyValueType rsa = new RSAKeyValueType(); + rsa.setExponent(new String(Base64Utils.encode(exponent.toByteArray()))); + rsa.setModulus(new String(Base64Utils.encode(modulus.toByteArray()))); + + KeyValueType key = new KeyValueType(); + key.setRSAKeyValue(rsa); + + keyvalueList.add(key); + + return keyvalueList; + } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { + log.error("TestCode has an internal ERROR", e); + + } + + } + + return null; + + } + + private String extendBPKbyPrefix(String bpk, String type) { + String bPKType = null; + + if (type.startsWith(EAAFConstants.URN_PREFIX_WBPK)) + bPKType = type.substring((EAAFConstants.URN_PREFIX_WBPK).length()); + + else if (type.startsWith(EAAFConstants.URN_PREFIX_CDID)) + bPKType = type.substring((EAAFConstants.URN_PREFIX_CDID).length()); + + else if (type.startsWith(EAAFConstants.URN_PREFIX_EIDAS)) + bPKType = type.substring((EAAFConstants.URN_PREFIX_EIDAS).length()); + + + if (bPKType != null ) { + log.trace("Authenticate user with bPK/wbPK " + bpk + " and Type=" + bPKType); + return bPKType + ":" + bpk; + + } else { + log.warn("Service Provider Target with: " + type + " is NOT supported. Set bPK as it is ..."); + return bpk; + + } + + } + + //TODO: update for complexe attributes + private Map converteIDASAttrToSimpleMap( + ImmutableMap, ImmutableSet>> attributeMap) { + Map result = new HashMap(); + + for (AttributeDefinition el : attributeMap.keySet()) { + + final Class parameterizedType = el.getParameterizedType(); + if ((DateTime.class).equals(parameterizedType)) { + DateTime attribute = eIDASResponseUtils.translateDateAttribute(el, attributeMap.get(el).asList()); + if (attribute != null) + result.put(el.getFriendlyName(), attribute); + else + log.info("Ignore empty 'DateTime' attribute"); + + } else if ((PostalAddress.class).equals(parameterizedType)) { + PostalAddress addressAttribute = eIDASResponseUtils.translateAddressAttribute(el, attributeMap.get(el).asList()); + if (addressAttribute != null) + result.put(el.getFriendlyName(), addressAttribute); + else + log.info("Ignore empty 'PostalAddress' attribute"); + + } else { + List natPersonIdObj = eIDASResponseUtils.translateStringListAttribute(el, attributeMap.get(el).asList()); + String stringAttr = natPersonIdObj.get(0); + if (StringUtils.isNotEmpty(stringAttr)) + result.put(el.getFriendlyName(), stringAttr); + else + log.info("Ignore empty 'String' attribute"); + + } + } + + return result; + } + + } -- cgit v1.2.3