From 691356756910253d77fbcdd3d58ce3051776cc5f Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Mon, 27 Feb 2023 14:42:29 +0100 Subject: fix(ernp): set full person info in case of MDS update ERnP does not support partial personData updates. Therefore, we have to copy the latest ERnP result to all information during an update request. --- .../auth/eidas/v2/clients/ernp/ErnpRestClient.java | 85 ++++++++++++++------- .../eidas/v2/test/clients/ErnpRestClientTest.java | 87 ++++++++++++++++++++++ .../data/ernp/6_kitt_search_latest_resp.json | 63 ++++++++++++++++ .../resources/data/ernp/6_kitt_update_resp.json | 60 +++++++++++++++ 4 files changed, 270 insertions(+), 25 deletions(-) create mode 100644 modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/6_kitt_search_latest_resp.json create mode 100644 modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/6_kitt_update_resp.json diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java index a2f87b25..10aa020d 100644 --- a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java +++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java @@ -45,7 +45,6 @@ import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ErnpPersonRegisterResult; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData; -import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData.SimpleEidasDataBuilder; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.api.DefaultApi; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.invoker.ApiClient; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Aendern; @@ -59,6 +58,7 @@ import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PersonAen import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PersonAnlegen; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PersonSuchen; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Personendaten; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Personendaten.GeburtsbundeslandEnum; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PersonendatenErgebnis; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.SuchEidas; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Suchdaten; @@ -266,9 +266,9 @@ public class ErnpRestClient implements IErnpClient { // select elements that have to be updated final Collection eidasDocumentToAdd = selectEidasDocumentsToAdd(ernpPersonToKitt, eidData); - final SimpleEidasData mdsToUpdate = selectMdsInformationToUpdate(ernpPersonToKitt, eidData); + final boolean mdsValidInErnp = isMdsInErnpValid(ernpPersonToKitt, eidData); - if (eidasDocumentToAdd.isEmpty() && mdsToUpdate == null) { + if (eidasDocumentToAdd.isEmpty() && mdsValidInErnp) { log.info("Find no eIDAS document or MDS for update during: {}. Nothing todo on ERnP side", PROCESS_KITT_GENERAL); return new ErnpRegisterResult(Arrays.asList(new ErnpPersonRegisterResult(registerResult, false))); @@ -278,8 +278,7 @@ public class ErnpRestClient implements IErnpClient { PROCESS_KITT_GENERAL); // update entry based on selected update info's and results from search response - return updatePersonInErnp(ernpPersonToKitt, eidasDocumentToAdd, mdsToUpdate, eidData - .getCitizenCountryCode()); + return updatePersonInErnp(ernpPersonToKitt, eidasDocumentToAdd, mdsValidInErnp, eidData); } @@ -540,7 +539,7 @@ public class ErnpRestClient implements IErnpClient { } private ErnpRegisterResult updatePersonInErnp(Person ernpPersonToKitt, - Collection eidasDocumentToAdd, SimpleEidasData mdsToUpdate, String citizenCountryCode) + Collection eidasDocumentToAdd, boolean mdsValidInErnp, SimpleEidasData eidData) throws ServiceFault { // build generic request metadata final GenericRequestParams generic = buildGenericRequestParameters(); @@ -562,9 +561,9 @@ public class ErnpRestClient implements IErnpClient { } // update MDS if required - if (mdsToUpdate != null) { + if (!mdsValidInErnp) { log.debug("Find MDS to update. Injection update entries into ERnP request ... "); - ernpReq.setAendern(generateMdsChangeRequest(ernpPersonToKitt, mdsToUpdate)); + ernpReq.setAendern(generateMdsChangeRequest(ernpPersonToKitt, eidData)); } @@ -575,7 +574,7 @@ public class ErnpRestClient implements IErnpClient { log.trace("Receive response from ERnP for '{}' operation", PROCESS_KITT_IDENITIES_UPDATE); return new ErnpRegisterResult(Collections.singletonList( - mapErnpResponseToRegisterResult(ernpResp.getPerson(), citizenCountryCode))); + mapErnpResponseToRegisterResult(ernpResp.getPerson(), eidData.getCitizenCountryCode()))); } @@ -711,32 +710,68 @@ public class ErnpRestClient implements IErnpClient { return el; } - private SimpleEidasData selectMdsInformationToUpdate(Person ernpPersonToKitt, SimpleEidasData eidData) { + private boolean isMdsInErnpValid(Person ernpPersonToKitt, SimpleEidasData eidData) { final PersonendatenErgebnis person = ernpPersonToKitt.getPersonendaten(); - final SimpleEidasDataBuilder builder = SimpleEidasData.builder() - .givenName(eidData.getGivenName()) - .familyName(eidData.getFamilyName()) - .dateOfBirth(eidData.getDateOfBirth()); - - final boolean findMatch = person.getVorname().equals(eidData.getGivenName()) - && person.getFamilienname().equals(eidData.getFamilyName()) - && getTextualBirthday(person.getGeburtsdatum()).equals(eidData.getDateOfBirth()); - return findMatch ? null : builder.build(); + return person.getVorname().equalsIgnoreCase(eidData.getGivenName()) + && person.getFamilienname().equalsIgnoreCase(eidData.getFamilyName()) + && getTextualBirthday(person.getGeburtsdatum()).equalsIgnoreCase(eidData.getDateOfBirth()); } - private Aendern generateMdsChangeRequest(Person ernpPersonToKitt, SimpleEidasData mdsToUpdate) { + private Aendern generateMdsChangeRequest(Person ernpPersonToKitt, SimpleEidasData eidData) { + final PersonendatenErgebnis input = ernpPersonToKitt.getPersonendaten(); + + // copy full Person result because ERnP does not support delta updates + final Personendaten person = makeCopyOfPerson(input); + + // change MDS to eIDAS information in required + if (!input.getFamilienname().equalsIgnoreCase(eidData.getFamilyName())) { + person.setFamilienname(eidData.getFamilyName()); + + } + + if (!input.getVorname().equalsIgnoreCase(eidData.getGivenName())) { + person.setVorname(eidData.getGivenName()); + + } + + if (!getTextualBirthday(input.getGeburtsdatum()).equalsIgnoreCase(eidData.getDateOfBirth())) { + person.setGeburtsdatum(buildErnpBirthday(eidData.getDateOfBirth())); + + } + final Aendern el = new Aendern(); - final Personendaten person = new Personendaten(); - person.setEntityId(ernpPersonToKitt.getPersonendaten().getEntityId()); el.setPersonendaten(person); - person.setFamilienname(mdsToUpdate.getFamilyName()); - person.setVorname(mdsToUpdate.getGivenName()); - person.setGeburtsdatum(buildErnpBirthday(mdsToUpdate.getDateOfBirth())); return el; } + private Personendaten makeCopyOfPerson(PersonendatenErgebnis input) { + + final Personendaten person = new Personendaten(); + person.setEntityId(input.getEntityId()); + person.setFamilienname(input.getFamilienname()); + person.setGeburtsdatum(input.getGeburtsdatum()); + person.setGeburtsort(input.getGeburtsort()); + person.setGeburtsstaat(input.getGeburtsstaat()); + person.setNameVorEhe(input.getNameVorEhe()); + person.setVorname(input.getVorname()); + + if (input.getGeburtsbundesland() != null) { + person.setGeburtsbundesland( + GeburtsbundeslandEnum.fromValue(input.getGeburtsbundesland().getValue())); + + } + + if (input.getGeschlecht() != null) { + person.setGeschlecht( + Personendaten.GeschlechtEnum.fromValue(input.getGeschlecht().getValue())); + + } + return person; + + } + /** * Map an AT specific Date String 'yyyy-MM-dd' to ERnP birthday representation. * diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/ErnpRestClientTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/ErnpRestClientTest.java index 8057eafe..7b2e2b61 100644 --- a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/ErnpRestClientTest.java +++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/ErnpRestClientTest.java @@ -1056,6 +1056,93 @@ public class ErnpRestClientTest { } + @Test + @SneakyThrows + public void differendMdsButOnlyUppercase() { + final String cc = "DE"; + final String personalIdentifierFirst = "Y8ADWaeh0h"; + final SimpleEidasData eidasDataFirst = SimpleEidasData.builder() + .citizenCountryCode(cc) + .familyName("CTKKrtUe") + .givenName("DUEYZUFg") + .dateOfBirth("1995-05-05") + .personalIdentifier(cc + "/AT/" + personalIdentifierFirst) + .pseudonym(personalIdentifierFirst) + .placeOfBirth("hrFevCfP") + .birthName("sNUEAhEr") + .build(); + + // set ERnP response + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(IOUtils.toString( + ErnpRestClientTest.class.getResourceAsStream("/data/ernp/6_kitt_search_latest_resp.json"), + "UTF-8")) + .setHeader("Content-Type", "application/json;charset=utf-8")); + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(IOUtils.toString( + ErnpRestClientTest.class.getResourceAsStream("/data/ernp/6_kitt_update_resp.json"), + "UTF-8")) + .setHeader("Content-Type", "application/json;charset=utf-8")); + + RegisterResult ernpResult = RegisterResult.builder() + .familyName("CtKKrtUe") + .givenName("dUeYzUFg") + .dateOfBirth("1985-05-05") + .bpk("+OQnljn0Son1W2rkM73nP/VMsvc=") + .pseudonym(Arrays.asList("Y8ADWaeh0h")) + .birthName("sNUEAhEr") + .placeOfBirth("hrFevCfP") + .build(); + + // execute operation + ErnpRegisterResult resp = client.update(ernpResult, eidasDataFirst); + + // validate request + // check get-latest-version request + final RecordedRequest request = mockWebServer.takeRequest(); + String reqBody = request.getBody().readUtf8(); + assertFalse("no request body", reqBody.isEmpty()); + JsonNode reqJson = mapper.readTree(reqBody); + checkSearchOptions(reqJson, "KITT get-latest-version"); + JsonNode person = getJsonObject(reqJson, "suchdaten"); + checkJsonElement(person, "familienname", ernpResult.getFamilyName()); + checkJsonElement(person, "vorname", ernpResult.getGivenName()); + checkJsonElement(person, "bpkZp", ernpResult.getBpk()); + checkPersonDateOfBirth(person, ernpResult.getDateOfBirth()); + + // check update request + final RecordedRequest requestKitt = mockWebServer.takeRequest(); + String reqBodyKitt = requestKitt.getBody().readUtf8(); + assertFalse("no request body", reqBodyKitt.isEmpty()); + JsonNode reqJsonKitt = mapper.readTree(reqBodyKitt); + checkJsonElement(reqJsonKitt, "begruendung", "KITT update dataset"); + checkJsonElement(reqJsonKitt, "entityId", "1933000000000475"); + checkJsonElement(reqJsonKitt, "version", "2022-03-03T10:07:28.885Z"); + JsonNode personChange = getJsonObject(reqJsonKitt, "aendern"); + JsonNode personKitt = getJsonObject(personChange, "personendaten"); + checkJsonElement(personKitt, "familienname", "CtKKrtUe"); + checkJsonElement(personKitt, "vorname", "dUeYzUFg"); + checkPersonDateOfBirth(personKitt, eidasDataFirst.getDateOfBirth()); + + checkJsonElement(personKitt, "geburtsbundesland", "Burgenland"); + + assertFalse("find 'aendern' element", reqJsonKitt.has("anlegen")); + assertFalse("find 'aendern' element", personChange.has("eidas")); + + // validate state + assertNotNull("no ERnP response", resp); + assertEquals("wrong resp size", 1, resp.getPersonResult().size()); + RegisterResult persInfo = resp.getPersonResult().get(0); + assertEquals("wrong familyname", "CtKKrtUe", persInfo.getFamilyName()); + assertEquals("wrong givenName", "dUeYzUFg", persInfo.getGivenName()); + assertEquals("wrong dateOfBirth", eidasDataFirst.getDateOfBirth(), persInfo.getDateOfBirth()); + assertEquals("wrong bpk", ernpResult.getBpk(), persInfo.getBpk()); + assertEquals("wrong pseudonym", ernpResult.getPseudonym().get(0), persInfo.getPseudonym().get(0)); + assertEquals("wrong placeOfBirth", "hrFevCfP", persInfo.getPlaceOfBirth()); + assertEquals("wrong birthName", "sNUEAhEr", persInfo.getBirthName()); + + } + @Test @SneakyThrows public void updateUpdateRequiredEidasDocs() { diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/6_kitt_search_latest_resp.json b/modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/6_kitt_search_latest_resp.json new file mode 100644 index 00000000..bb2efcb1 --- /dev/null +++ b/modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/6_kitt_search_latest_resp.json @@ -0,0 +1,63 @@ +{ + "person": [ + { + "type": "Person", + "eidas": [ + { + "ablaufDatum": "9999-12-31T00:00:00.000+01:00", + "art": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", + "ausstellDatum": "9999-12-31T00:00:00.000+01:00", + "entityId": "1933000000000486", + "gueltigAb": "2022-03-03T11:07:28.885+01:00", + "staatscode2": "DE", + "wert": "Y8ADWaeh0h" + }, + { + "ablaufDatum": "9999-12-31T00:00:00.000+01:00", + "art": "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", + "ausstellDatum": "9999-12-31T00:00:00.000+01:00", + "entityId": "1933000000000488", + "gueltigAb": "2022-03-03T11:07:28.885+01:00", + "staatscode2": "DE", + "wert": "hrFevCfP" + }, + { + "ablaufDatum": "9999-12-31T00:00:00.000+01:00", + "art": "http://eidas.europa.eu/attributes/naturalperson/BirthName", + "ausstellDatum": "9999-12-31T00:00:00.000+01:00", + "entityId": "1933000000000490", + "gueltigAb": "2022-03-03T11:07:28.885+01:00", + "staatscode2": "DE", + "wert": "sNUEAhEr" + } + ], + "entityId": "1933000000000475", + "gueltigAb": "2022-03-03T11:07:28.885+01:00", + "letzteOperation": { + "begruendung": "Add new person", + "durchgefuehrtVon": { + "behoerdenkennzeichen": "380630", + "benutzer": "eidtapp@bmi.gv.at" + }, + "vorgang": "PersonAnlegen", + "zeitpunkt": "2022-03-03T11:07:28.885+01:00" + }, + "personendaten": { + "basiszahl": "000482591530", + "bpkZp": "+OQnljn0Son1W2rkM73nP/VMsvc=", + "entityId": "1933000000000475", + "familienname": "CtKKrtUe", + "geburtsdatum": { + "jahr": 1985, + "monat": 5, + "tag": 5 + }, + "geprueft": false, + "gueltigAb": "2022-03-03T11:07:28.885+01:00", + "vorname": "dUeYzUFg", + "geburtsbundesland" : "Burgenland" + }, + "version": "2022-03-03T11:07:28.885+01:00" + } + ] +} diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/6_kitt_update_resp.json b/modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/6_kitt_update_resp.json new file mode 100644 index 00000000..8ef1b59d --- /dev/null +++ b/modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/6_kitt_update_resp.json @@ -0,0 +1,60 @@ +{ + "person": { + "type": "Person", + "eidas": [ + { + "ablaufDatum": "9999-12-31T00:00:00.000+01:00", + "art": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", + "ausstellDatum": "9999-12-31T00:00:00.000+01:00", + "entityId": "1933000000000486", + "gueltigAb": "2022-03-03T11:07:28.885+01:00", + "staatscode2": "DE", + "wert": "Y8ADWaeh0h" + }, + { + "ablaufDatum": "9999-12-31T00:00:00.000+01:00", + "art": "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", + "ausstellDatum": "9999-12-31T00:00:00.000+01:00", + "entityId": "1933000000000488", + "gueltigAb": "2022-03-03T11:07:28.885+01:00", + "staatscode2": "DE", + "wert": "hrFevCfP" + }, + { + "ablaufDatum": "9999-12-31T00:00:00.000+01:00", + "art": "http://eidas.europa.eu/attributes/naturalperson/BirthName", + "ausstellDatum": "9999-12-31T00:00:00.000+01:00", + "entityId": "1933000000000490", + "gueltigAb": "2022-03-03T11:07:28.885+01:00", + "staatscode2": "DE", + "wert": "sNUEAhEr" + } + ], + "entityId": "1933000000000475", + "gueltigAb": "2022-03-03T11:07:29.751+01:00", + "letzteOperation": { + "begruendung": "KITT update dataset", + "durchgefuehrtVon": { + "behoerdenkennzeichen": "380630", + "benutzer": "eidtapp@bmi.gv.at" + }, + "vorgang": "PersonAendern", + "zeitpunkt": "2022-03-03T11:07:29.751+01:00" + }, + "personendaten": { + "basiszahl": "000482591530", + "bpkZp": "+OQnljn0Son1W2rkM73nP/VMsvc=", + "entityId": "1933000000000475", + "familienname": "CtKKrtUe", + "geburtsdatum": { + "jahr": 1995, + "monat": 5, + "tag": 5 + }, + "geprueft": false, + "gueltigAb": "2022-03-03T11:07:29.751+01:00", + "vorname": "dUeYzUFg" + }, + "version": "2022-03-03T11:07:29.751+01:00" + } +} -- cgit v1.2.3