Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Det første afsnit beskriver de den arkitekturmæssige begrundelser motivation for indførelse indførelsen af NSP Audit API.

Dernæst vises hvordan NSP Audit API rent praktisk indføres i en NSP komponent med konkrete eksempler på anvendelse.  Denne sektion er især relevant for udviklere, der skal bruge NSP Audit API i forbindelse med en konkret opgave.

Efterfølgende Tilsidst vises "effekten" af anvendelse af NSP Audit API - hvilke informationer logges, og hvor stammer de fra.   Her gives også input til, hvilket niveau af dokumentation den enkelte NSP komponent skal levere i f.eks. driftsmanualen.

Arkitekturoverblik og motivation for NSP Audit API

Dette giver et overblik over, hvilke oplysninger, som anvender/udvikler selv er ansvarlig for at skaffe, og hvilke der bliver logget af NSP Audit API automatisk.

Til sidst inkluderes en "dokumentationsskabelon", der kan anvendes som input til de konkrete driftsmanualer for de NSP komponenter, der anvender NSP Audit API.

Arkitekturoverblik og motivation for NSP Audit API

Auditlogning er en capability, som Auditlogning er en capability, som er nødvendig for mange af NSP'ens komponenter: Af juridiske hensyn er det nødvendigt at kunne følge op på hvem, der har gjort hvad og hvornår henover NSP'ens service portefølje.

...

Kravene til indholdet af auditloggen er sammenfaldende henover NSP'ens services i forhold til information om hvornår og hvem, der har lavet foretaget en handling, som er auditloggetskal auditlogges.

Hvad, der skal auditlogges, er i høj grad op til den enkelte NSP komponent og de forretningsmæssige og juridiske krav, der omgiver denne.

Ensartetheden i forhold til granularitet og format for audit informationer vil lette letter det efterfølgende arbejde med disse - både i forhold til opfølgning og anvendelse og i forhold til den generelle håndtering og opbevaring.

NSP Audit API er derfor født ud af ønsket om:

  1. At gøre det let for NSP komponenter at auditlogge
  2. At sørge for at informationsniveauet i auditloggen er ensartet henover de forskellige komponenter
  3. At sørge for at strukturen i auditloggen er ensartet henover de forskellige komponenter

...

Gliffy Diagram
size600
displayNameNSP Audit API overview
nameNSP Audit API overview
pagePin3

Anvendelse af NSP Audit API i NSP komponenter

For at anvende NSP Audit API i en konkret NSP komponent i udviklingsmæssig sammenhæng, så er der et par tekniske øvelser, der skal være på plads. Da hovedparten af NSP'ens komponenter er bygget op på samme måde, så vil denne vejledning umiddelbart kunne anvendes i langt de fleste tilfælde. Antagelsen i denne vejledning er derfor at:

  • Komponenten anvender Maven til styring af tredjeparts dependencies
  • Komponenten afvikles på Wildfly (evt via et af NSP'ens Docker images)

...

Dernæst vises det med et praktisk eksempel hentet fra Dokumentdelingsservicen, hvordan NSP Audit API kan anvendes i koden applikationskode til at implementere relevant auditlogning.

Maven dependency

Langt de fleste NSP komponenter anvender Maven til at holde styr på afhængigheder til tredjeparts biblioteker.

NSP Audit API adskiller sig ikke fra andre tredjeparts biblioteker i den forstand og kræver således blot, at følgende tilføjes til rækken af dependencies (NB! tjek versionsnummer i forhold til den gældende version) i konfigurationsfilen (pom.xml):

...

Provided scope i Maven benyttes til at udtrykke en afhængighed til et tredjeparts bibliotek, som ikke skal inkluderes i modulet selvlibrary uden dette inkluderes i det færdigbyggede modul (jar/war), men som i stedet antages at blive stillet til rådighed (provided) af de omgivelser, som modulet afvikles i.

Afviklingsomgivelserne for en NSP komponent er Wildfly (evt via et af NSP'ens Docker images). I det følgende afsnit vises, hvordan man sørger for, at Wildfly rent faktisk stiller NSP Audit API til rådighed for den anvendende komponent og derved opfylder kontrakten, som blev udtrykt i Maven konfigurationsfilen.

Wildfly dependency

I forgående afsnit blev det fremhævet, at det ikke er en NSP komponents ansvar selv at inkludere NSP Audit API i dens færdigbyggede modul.

I stedet udtrykker komponenten, at den regner med, at de omgivelser, hvori den efterfølgende afvikles, stiller NSP Audit API til rådighed for denpå afviklingstidspunktet.

Afviklingsomgivelsern Afviklingsomgivelserne for en standard NSP komponent er Wildfly (evt via et af NSP'ens Docker images). På Wildfly findes en række tredjeparts biblioteker, der leveres med platformen - herunder også NSP Audit API.

Som default er de fleste af disse bibliotekter afskærmet og således ikke til rådighed for komponenten på afviklingstidspunktet - men via en særlig konfigurationsfil (som Wildfly forstår) kan det udtrykkes, at komponenten ønsker, at få adgang til et eller flere af disse biblioteker.

For at Wildfly kan stiller NSP Audit API til rådighed for en komponent skal filen /src/main/webapp/WEB-INF/jboss-deployment-structure.xml findes i Maven projektet og i det byggede modul og have følgende indhold:

...

Det er komponentens eget ansvar at sørge for, at der er sammenhæng mellem disse. Eventuelle versionsforskelle mellem det, som en komponent tror, at den inkluderefår stillet til rådighed, og det, som den rent faktisk inkluderer får stillet til rådighed, kan give en masse udfordringer og underlige fejl (NoSuchMethodException mv, ClassNotFoundException med flere), når komponenten afvikles og anvender NSP Audit API.

...

I ovenstående eksempel er det NSP Audit API version 1.0.1, der stilles til rådighed af den konkrete version af Wildfly, hvilket hænger fint sammen med det versionsnummer, der blev udtrykt i Maven afhængigheden (i pom.xml).

Udvikling af auditlogning

...

vha NSP Audit API

Når en komponent har fået sat afhængighed op til NSP Audit API, er den udvikleren klar til at begynde at anvende dette til auditlogningsformål.

...

  1. Oprettelse af en AuditBuilder til et kald (request) mod servicen, der ønsker at auditlogge
  2. Tilføjelse af konkrete auditloginformationer til konkret den oprettede AuditBuilder i forbindelse emd servicens udførelse af kald (request)med at servicen laver sit arbejde

Fordi AuditBuilder er koblet sammen med platformens håndtering af kald (request/response), er der ikke brug for at komponenten kalder en commit metode eller lign.

Der skal derfor ikke gøres mere end de to nævnte punkter. Disse gennemgåes i det følgende.

Oprettelse af AuditBuilder

Anvendelse af NSP Audit API er meget simpel. For hver request som komponenten modtager skal følgende linie kaldes:

...

Dette opretter en Audit Builder som kan føres med rundt i komponenten og kaldes hver gang audit information i forbindelse med kaldet opstårservicen har brug for at auditlogge noget.

Warning

Det er vigtigt at denne linie udføres på den samme tråd som kalder komponentens Servlet metoder, annoterede WebMethod metoder eller lign.

Dette sikrer at platformen kan koble builderen sammen med det request/response der er i gang.

...

Alternativt kan man lave en ny NSP Audit Provider og få den loadet ved at placere provider-configuration filen dk.sds.nsp.audit.AuditProvider i en passende META-INF/services folder. Se Java Service Loader dokumentationen for detaljer.

Warning

En leverance af en komponent til NSP må ikke indeholde en provider-configuration fil idet dette kunne påvirke andre komponenter på platformen.

I praksis vil der ikke være brug I praksis vil der ikke være brug for dette, da fallback development provider i de fleste tilfælde er fuldt ud dækkende.

Warning

En leverance af en komponent til NSP må ikke indeholde en provider-configuration fil idet dette kunne påvirke andre komponenter på platformen.

Tilføjelse af konkrete auditloginformationer

En AuditBuilder har 4 forskellige metoder til at tilføje audit information.

...

Fælles for alle metoder er at de kræver følgende argumenter:

  • component: Komponentens aftalte forkortelse. Ofte forkortelsen af det projekt som stod bag komponenten. F.eks. STS, DDS, SDM, DCC mv.
  • context: Navnet på den context som komponenten er i lige nu. Det kunne f.eks. være hvilken service der er kaldt i komponenten, hvilken delkomponent der er i brug mv.
  • type: En af de mulige værdier "SensitivePersonalInformation", "RegularPersonalInformation" eller "NonPersonalInformation". Alt efter om der er tale om følsomme personoplysninger, almindelige personoplysninger eller oplysninger der ikke er knyttet til en person. Det er vigtigt at der vælges den korrekte type da det har konsekvens for hvem der har adgang til data.
  • key: En valgfri nøgle for den information der tilføjes. F.eks "cpr", "cvr", "samtykke" eller lign.
  • value(s): Den eller de værdier der skal tilføjes til audit loggen.

...

I forhold til hvilke værdier, der skal auditlogges, så er det op til den enkelte komponent at afklare det juridske behov i det konkrete tilfælde.

Dokumentdelingsservice: Eksempel på auditlogning via NSP Audit API

I de forgående afsnit blev det gennemgået, hvordan en AuditBuilder skal oprettes og håndteres i en NSP komponent, der ønsker at auditlogge, og hvorledes auditloginformationer kan tilføjes i løbet af servicens behandling af et kald.

I dette afsnit kigger vi på konkrete eksempler på dette taget fra Dokumentdelingsservice.

Dokumentdelingsservice gør det muligt for anvendere at fremsøge lister af dokumenter for borgere med forskelligt indhold f.eks. aftaler, laboratoriesvar og stamkort. Der er behov for at auditlogge hvem, der har tilgået disse informationer hvornår.

Dokumentdelingsservice indeholder

Eksempel på auditlogning

Det demonstreres gennem eksemplet fra Dokumentdelingsservice, hvorledes anvendelsen af NSP Audit API kommer til udtryk i forhold til informationsniveau i den resulterende auditlog. Herigennem bliver det muligt for udviklere af NSP komponenter at forstå, hvilke informationer, der stammer fra afviklingsplatformen, og hvilke der stammer fra komponenten selv.

Tilsidst inkluderes en "dokumentationsskabelon", der kan anvendes som input til de konkrete driftsmanualer for de NSP komponenter, der anvender NSP Audit API.

Alle

...

Værdierne, der sendes med, er af typen Object. Metoden toString() bliver anvendt på de medsendte values objekter for at få dem serialiseret til er format, der kan logges. Som en undtagelse hertil skal nævnes values objekter af typen javax.json.JsonObject. Værdier af denne type håndteres specielt af NSP Audit API, der laver en pæn rendering i JSON format.

Dokumentdelingsservice: Eksempel på implementation af auditlogning via NSP Audit API

I de forgående afsnit blev det gennemgået, hvordan en AuditBuilder skal oprettes og håndteres i en NSP komponent, der ønsker at auditlogge, og hvorledes auditloginformationer kan tilføjes i løbet af servicens behandling af et kald.

I dette afsnit kigger vi på konkrete eksempler på dette taget fra Dokumentdelingsservice.

Dokumentdelingsservice gør det muligt for anvendere at fremsøge lister af dokumenter for borgere med forskelligt indhold f.eks. aftaler, laboratoriesvar og stamkort. Der er behov for at auditlogge hvem, der har tilgået disse informationer hvornår. Denne fremsøgningsservice kan anvendes både af borgere (IDWS snitflade) samt af sundhedsprofessionelle (DGWS snitflade).

Uanset om anvenderen er en borger eller en sundhedsprofessionel anvendes klassen DDSRegistryQueryImpl til at implementere selve fremsøgninglogikken - herunder også auditlogning af svaret:

Code Block
languagejava
titleFremsøgningslogik for Dokumentdelingsservice - herunder auditloging
collapsetrue
public class DDSRegistryQueryImpl {
	static Logger logger = Logger.getLogger(DDSRegistryQueryImpl.class);

	@Autowired
	private AuditLogning auditLogning;

	...

	public AdhocQueryResponse documentRegistryRegistryStoredQuery(AdhocQueryRequest adhocQueryRequestBody, DDSContext context) throws Exception {
		try {
			final AdhocQueryRequestWrapper adhocQueryRequestWrapper = new AdhocQueryRequestWrapper(adhocQueryRequestBody, context);
			String patientId = adhocQueryRequestWrapper.getPatientId();			
			...			
			AuditBuilder auditBuilder = Audit.createAuditBuilder();
			auditLogning.auditLogIti18Response(auditBuilder, patientId, context.getActingUserCivilRegistrationNumber(), context.getResponsibleUserCivilRegistrationNumber(), adhocQueryRequestBody.getAdhocQuery(), response);
			return response;
		} catch (NegativeConsentException e) {
			return AdhocQueryResponseWrapper.createNegativeConsentResponse();
		}
	}

Som det kan ses, så oprettes AuditBuilderen først og dernæst sendes denne samme med parametre fra kaldet og fra kaldskonteksten (CPR nummeret på den kaldende og ansvarlige person) ned i en hjælpeklasse AuditLogning, som Dokumentdelingsservicen anvender til kommunikation med Audit API.

I det følgende ses den kaldte metode auditLogIti18Response:

Code Block
languagejava
titleAuditLogning klasse til anvendelse af AuditAPI
collapsetrue
public class AuditLogning {
 
    public static final String KEY_PATIENT_CPR = "patient-cpr";
    public static final String KEY_USER_CPR = "bruger-cpr";
    public static final String KEY_USER_ON_BEHALF_OF_CPR = "on-behalf-of-cpr";
    public static final String KEY_DOCUMENT_ENTRY = "document_entry";
 
 
    private static final String ITI_18_CONTEXT = "documentRegistryAdhocQuery";
    private static final String ITI_43_CONTEXT = "documentRepositoryRetrieveDocumentSet";
 
    private static final String DOCUMENTENTRY_HOMECOMMUNITY_ID = "homecommunityid";
    private static final String DOCUMENTENTRY_REPOSITORY_ID = "repositoryid";
    private static final String DOCUMENTENTRY_DOCUMENT_ID = "documentid";
    private static final String DOCUMENTENTRY_TYPECODE = "typecode";
    private static final String KEY_QUERY_TYPECODE = "queryTypecode";
 
    private String componentName;
 
    public AuditLogning() {
        this("DDS");
    }
     
    public AuditLogning(String componentName) {
        this.componentName = componentName;
    }
 
    public void auditLogIti18Response(AuditBuilder auditBuilder, String patientCpr, String requestingUserCpr, String requestingUserOnBehalfOfCpr, AdhocQueryType adhocQueryType, AdhocQueryResponse adhocQueryResponse) {
 
        auditBuilder.addAuditInformation(componentName, ITI_18_CONTEXT, TypeOfInformation.SensitivePersonalInformation, KEY_PATIENT_CPR, patientCpr);
        if (requestingUserCpr != null) {
            auditBuilder.addAuditInformation(componentName, ITI_18_CONTEXT, TypeOfInformation.SensitivePersonalInformation, KEY_USER_CPR, requestingUserCpr);
        }
        if (requestingUserOnBehalfOfCpr != null) {
            auditBuilder.addAuditInformation(componentName, ITI_18_CONTEXT, TypeOfInformation.SensitivePersonalInformation, KEY_USER_ON_BEHALF_OF_CPR, requestingUserOnBehalfOfCpr);
        }
 
        if (adhocQueryType != null && adhocQueryType.getSlot() != null) {
            ValueListType vlt = XDSValueFinder.getSearchParameterTypeCode(adhocQueryType.getSlot());
            if (vlt != null && vlt.getValue() != null) {
                auditBuilder.addAuditInformation(componentName, ITI_18_CONTEXT, TypeOfInformation.NonPersonalInformation, KEY_QUERY_TYPECODE, vlt.getValue());
            }
        }
         
        if (adhocQueryResponse.getRegistryObjectList() != null && adhocQueryResponse.getRegistryObjectList().getIdentifiable() != null) {
            Iterator<JAXBElement<? extends oasis.names.tc.ebxml_regrep.xsd.rim._3.IdentifiableType>> identifiables = adhocQueryResponse.getRegistryObjectList().getIdentifiable().iterator();
            int count = 0;
            while (identifiables.hasNext()) {
                JAXBElement<? extends oasis.names.tc.ebxml_regrep.xsd.rim._3.IdentifiableType> identifiable = identifiables.next();
                ExtrinsicObjectType documentEntry = XDSValueFinder.getAsDocumentEntry(identifiable);
                DocumentEntryExternalId documentEntryExternalId = XDSValueFinder.getDocumentEntryExternalId(documentEntry);
                String typeCode = XDSValueFinder.getTypeCodeValueInClassificiationList(documentEntry.getClassification());
                addDocumentEntryAsAuditLogValue(auditBuilder, ITI_18_CONTEXT, count++, documentEntryExternalId, typeCode);
            }
        }
    }
 
    public void addDocumentEntryAsAuditLogValue(AuditBuilder auditBuilder, String context, int count, String homeCommunityId, String repositoryId, String documentId, String typeCode) {
         
        if (homeCommunityId != null) {
            auditBuilder.addAuditInformation(componentName, context, TypeOfInformation.NonPersonalInformation, formatKey(KEY_DOCUMENT_ENTRY, count, DOCUMENTENTRY_HOMECOMMUNITY_ID), homeCommunityId);
        }
        auditBuilder.addAuditInformation(componentName, context, TypeOfInformation.NonPersonalInformation, formatKey(KEY_DOCUMENT_ENTRY, count, DOCUMENTENTRY_REPOSITORY_ID), repositoryId);
        auditBuilder.addAuditInformation(componentName, context, TypeOfInformation.NonPersonalInformation, formatKey(KEY_DOCUMENT_ENTRY, count, DOCUMENTENTRY_DOCUMENT_ID), documentId);
 
        if (typeCode != null) {
            auditBuilder.addAuditInformation(componentName, context, TypeOfInformation.NonPersonalInformation, formatKey(KEY_DOCUMENT_ENTRY, count, DOCUMENTENTRY_TYPECODE), typeCode);
        }
    }
     
    public String formatKey(String prefix, int count, String postfix) {
        return prefix+"."+count+"."+postfix;
    }

Som det kan ses i det ovenstående, så kaldes addAuditInformation flere gange i forbindelse med en søgning. Anvendelse af konstanter sørger for, at parametrene componentName og context sendes ensartet videre til NSP Audit API.

Ved hver tilføjelse af auditinformation tages der aktivt stilling til oplysningernes følsomhed.

I Dokumentdelingsservicen auditlogges hele svaret dvs. alle de elementer, der fremsøges. I eksemplet ovenfor konstrueres en nøgle udfra bla en tæller (count) for at auditloggen kan indeholde en liste.

Effekt af NSP Audit API i NSP komponenter

I de forgående afsnit blev det gennemgået, hvordan NSP Audit API kan anvendes i NSP komponenters kode for let at kunne auditlogge information.

I det følgende demonstreres gennem eksempler fra Dokumentdelingsservice, hvorledes anvendelsen af NSP Audit API kommer til udtryk i forhold til informationsniveau i den resulterende auditlog.

Herigennem bliver det muligt for udviklere af NSP komponenter at forstå, hvilke informationer, der stammer fra afviklingsplatformen (således givet ved brugen af NSP Audit API), og hvilke der stammer fra komponenten selv.

Eksempel på auditlogninger fra Dokumentdelingsservice

I det forgående kapitel blev Dokumentdelingsservicens fremsøgningsservice brugs som eksempel på at vise, hvordan en konkret NSP service havde implementeret auditlogning. Igennem afvikling af Dokumentdelingsservicens integrationstest kan vi vise eksempler på, hvordan auditloggen kommer til at se ud, når fremsøgningsservicen anvendes. For komplethedens skyld har vi inkluderet to kald af fremsøgningsservicen: Et, hvor en borger fremsøger sine egne dokumenter og et, hvor en sundhedsprofessionel gør det samme.

Som det ses i eksemplerne nedenfor, så er auditlog-linjerne delt ind i forskellige sektioner.

Det er kun den sektion, der hedder audit, som den anvendende komponent kan påvirke. Hvis man sammenligner indholdet af denne sektion med kodeeksemplet i forgående afsnit, så vil man kunne genkende de enkelte linjer: Hvert kald giver anledning til en struktur i listen af "information".

Det er værd at bemærke, at NSP Audit API selv sørger for at logge soap headers, indhold fra det medsendte idkort eller token samt diverse kvantitative metrikker vedr kaldet. Det behøver man således ikke selv at logge som anvender af API'et.

I nedenstående eksempler bruges forkortelserne NPI, RPI og SPI, som står for Non-Personal Information, Regular Person Information og Sensitive Person Information.

En borger fremsøger egne dokumenter gennem dokumentdelingsservice (IDWS)

Ved at autentificere sig med en IDWS billet har en borger mulighed for at fremsøge sine egne dokumenter via Dokumentdelingsservicen. Kaldet rammer fremsøgningslogikken som blev vist i forgående kapitel, og følgende information ender i auditloggen:

Code Block
titleAuditlogning fra fremsøgning på Dokumentdelingsservice af borger
collapsetrue
{
   "time":"2021-10-13T14:21:38.115Z",
   "category":"dk.sds.nsp.audit.log.dds",
   "audit":{
      "timestamp":"2021-10-13T16:21:37.531+02:00",
      "components":[
         {
            "component":"DDS",
            "contexts":[
               {
                  "context":"documentRegistryAdhocQuery",
                  "information":[
                     {
                        "key":"patient-cpr",
                        "type":"SPI",
                        "value":"0207761919"
                     },
                     {
                        "key":"bruger-cpr",
                        "type":"SPI",
                        "value":"0207761919"
                     },
                     {
                        "key":"queryTypecode",
                        "type":"NPI",
                        "values":[
                           "('39289-4^^2.16.840.1.113883.6.1')"
                        ]
                     },
                     {
                        "key":"document_entry.0.homecommunityid",
                        "type":"NPI",
                        "value":""
                     },
                     {
                        "key":"document_entry.0.repositoryid",
                        "type":"NPI",
                        "value":"1.3.6.1.4.1.21367.2010.1.2.1125"
                     },
                     {
                        "key":"document_entry.0.documentid",
                        "type":"NPI",
                        "value":"0207761919.6052203964123326052.1537974544003"
                     },
                     {
                        "key":"document_entry.0.typecode",
                        "type":"NPI",
                        "value":"39289-4"
                     },
                     {
                        "key":"document_entry.1.homecommunityid",
                        "type":"NPI",
                        "value":""
                     },
                     {
                        "key":"document_entry.1.repositoryid",
                        "type":"NPI",
                        "value":"1.3.6.1.4.1.21367.2010.1.2.1125"
                     },
                     {
                        "key":"document_entry.1.documentid",
                        "type":"NPI",
                        "value":"5619531150207761919.6052203964123326052.1537974544003"
                     },
                     {
                        "key":"document_entry.1.typecode",
                        "type":"NPI",
                        "value":"39289-4"
                     },
                     {
                        "key":"document_entry.2.homecommunityid",
                        "type":"NPI",
                        "value":""
                     },
                     {
                        "key":"document_entry.2.repositoryid",
                        "type":"NPI",
                        "value":"1.3.6.1.4.1.21367.2010.1.2.1125"
                     },
                     {
                        "key":"document_entry.2.documentid",
                        "type":"NPI",
                        "value":"0207761919.678401000016005.10001"
                     },
                     {
                        "key":"document_entry.2.typecode",
                        "type":"NPI",
                        "value":"39289-4"
                     }
                  ]
               }
            ]
         }
      ]
   },
   "access":{
      "code":200,
      "duration":462,
      "httpHeaders":{
         "Content-Type":"application/soap+xml; charset=UTF-8"
      },
      "httpHost":"localhost",
      "idCardAttributes":{
         "dk:gov:saml:attribute:AssuranceLevel":"3",
         "dk:gov:saml:attribute:CprNumberIdentifier":"0207761919",
         "dk:gov:saml:attribute:SpecVer":"DK-SAML-2.0"
      },
      "method":"POST",
      "path":"/ddsregistry/idws",
      "query":"",
      "port":9090,
      "protocol":"http",
      "reqSize":13124,
      "resSize":22971,
      "soapHeaders":{
         "Audience":"https://audience.nspop.dk/dds",
         "Issuer":"TEST2-NSP-STS",
         "NameID":"C=DK,O=Ingen organisatorisk tilknytning,CN=Lars Larsen,Serial=PID:9208-2002-2-663031557285",
         "w3Action":"action",
         "w3MessageID":"urn:uuid:b1622648-c82e-4adc-b9fb-4c9a51b1df1d",
         "w3To":"http://localhost:9090/ddsregistry/idws"
      },
      "threadId":"default task-3",
      "time":"2021-10-13T16:21:37.531+02:00",
      "stats":{
         "handlerDuration":118,
         "RequestContentDuration":1,
         "ResponseContentDuration":0,
         "SecurityProtocolRequestDuration":10,
         "SecurityProtocolResponseDuration":101,
         "bufferAllocated":false,
         "usedBuffers":2,
         "activeBuffersInPool":2,
         "idleBuffersInPool":4
      }
   }
}


En sundhedsprofessionel fremsøger en borgers dokumenter gennem dokumentdelingsservice (DGWS)

Ved at autentificere sig med et SOSI idkort (DGWS) har en sundhedsprofessionel mulighed for at fremsøge en borgers dokumenter via Dokumentdelingsservicen. Kaldet rammer fremsøgningslogikken som blev vist i forgående kapitel, og følgende information ender i auditloggen:

Code Block
languagejs
titleAuditlogging fra fremsøgning på Dokumentdelingsservice (sundhedsprofessionel)
collapsetrue
{
   "time":"2021-10-13T14:04:07.387Z",
   "category":"dk.sds.nsp.audit.log.dds",
   "audit":{
      "timestamp":"2021-10-13T16:04:06.861+02:00",
      "components":[
         {
            "component":"DDS",
            "contexts":[
               {
                  "context":"documentRegistryAdhocQuery",
                  "information":[
                     {
                        "key":"patient-cpr",
                        "type":"SPI",
                        "value":"0106501010"
                     },
                     {
                        "key":"bruger-cpr",
                        "type":"SPI",
                        "value":"0804769723"
                     },
                     {
                        "key":"on-behalf-of-cpr",
                        "type":"SPI",
                        "value":"0804769723"
                     },
                     {
                        "key":"document_entry.0.homecommunityid",
                        "type":"NPI",
                        "value":""
                     },
                     {
                        "key":"document_entry.0.repositoryid",
                        "type":"NPI",
                        "value":"1.3.6.1.4.1.21367.2010.1.2.1125"
                     },
                     {
                        "key":"document_entry.0.documentid",
                        "type":"NPI",
                        "value":"0106501010.842938295.10000002"
                     },
                     {
                        "key":"document_entry.0.typecode",
                        "type":"NPI",
                        "value":"39289-4"
                     },
                     {
                        "key":"document_entry.1.homecommunityid",
                        "type":"NPI",
                        "value":""
                     },
                     {
                        "key":"document_entry.1.repositoryid",
                        "type":"NPI",
                        "value":"1.3.6.1.4.1.21367.2010.1.2.1125"
                     },
                     {
                        "key":"document_entry.1.documentid",
                        "type":"NPI",
                        "value":"0106501010.842938295.10000003"
                     },
                     {
                        "key":"document_entry.1.typecode",
                        "type":"NPI",
                        "value":"39289-4"
                     },
                     {
                        "key":"document_entry.2.homecommunityid",
                        "type":"NPI",
                        "value":""
                     },
                     {
                        "key":"document_entry.2.repositoryid",
                        "type":"NPI",
                        "value":"1.3.6.1.4.1.21367.2010.1.2.1125"
                     },
                     {
                        "key":"document_entry.2.documentid",
                        "type":"NPI",
                        "value":"0106501010.678401000016005.10000001"
                     },
                     {
                        "key":"document_entry.2.typecode",
                        "type":"NPI",
                        "value":"39289-4"
                     },
                     {
                        "key":"document_entry.3.homecommunityid",
                        "type":"NPI",
                        "value":"1.2.208.176.8.1.12"
                     },
                     {
                        "key":"document_entry.3.repositoryid",
                        "type":"NPI",
                        "value":"1.2.208.176.43210.8.10.12"
                     },
                     {
                        "key":"document_entry.3.documentid",
                        "type":"NPI",
                        "value":"1.2.208.176.43210.8.10.12^27434a41-cf20-4fb4-bdd7-c4bd7fc98cf2"
                     },
                     {
                        "key":"document_entry.3.typecode",
                        "type":"NPI",
                        "value":"52460-3"
                     },
                     {
                        "key":"document_entry.4.homecommunityid",
                        "type":"NPI",
                        "value":"1.2.208.176.8.1.12"
                     },
                     {
                        "key":"document_entry.4.repositoryid",
                        "type":"NPI",
                        "value":"1.2.208.176.43210.8.10.12"
                     },
                     {
                        "key":"document_entry.4.documentid",
                        "type":"NPI",
                        "value":"1.2.208.176.43210.8.10.12^fe950ffa-30e6-4f1d-b364-bd30e3b7a66b"
                     },
                     {
                        "key":"document_entry.4.typecode",
                        "type":"NPI",
                        "value":"PDC"
                     }
                  ]
               }
            ]
         }
      ]
   },
   "access":{
      "code":200,
      "duration":489,
      "httpHeaders":{
         "Content-Type":"application/soap+xml; charset=UTF-8"
      },
      "httpHost":"localhost",
      "idCardAttributes":{
         "medcom:CareProviderID":"33257872",
         "medcom:CareProviderName":"Sundhedsdatastyrelsen",
         "medcom:ITSystemName":"Test",
         "medcom:UserAuthorizationCode":"CBTH1",
         "medcom:UserOccupation":"Læge",
         "medcom:UserRole":"7170",
         "sosi:AuthenticationLevel":"4",
         "sosi:IDCardID":"ndbdsjE8LrtpFqHmzKL0Xw==",
         "sosi:IDCardType":"user",
         "sosi:IDCardVersion":"1.0.1"
      },
      "method":"POST",
      "path":"/ddsregistry",
      "query":"",
      "port":9090,
      "protocol":"http",
      "reqSize":9626,
      "resSize":33100,
      "soapHeaders":{
         "Issuer":"TEST2-NSP-STS",
         "MessageID":"AAABfHn3qv7YTBlq290B5FNPU0k=",
         "NameID":"SubjectDN={CN=Casper Rasmussen + SERIALNUMBER=CVR:33257872-RID:40718906, O=Sundhedsdatastyrelsen // CVR:33257872, C=DK},IssuerDN={CN=TRUST2408 Systemtest XXXIV CA, O=TRUST2408, C=DK},CertSerial={1604229135}",
         "w3Action":"urn:ihe:iti:2007:RegistryStoredQuery",
         "w3MessageID":"urn:uuid:07b2fb66-19c4-4bc7-8630-e427cebff032",
         "w3To":"http://localhost:9090/ddsregistry"
      },
      "threadId":"default task-58",
      "time":"2021-10-13T16:04:06.861+02:00",
      "stats":{
         "handlerDuration":33,
         "RequestContentDuration":3,
         "ResponseContentDuration":0,
         "SecurityProtocolRequestDuration":18,
         "SecurityProtocolResponseDuration":0,
         "bufferAllocated":false,
         "usedBuffers":2,
         "activeBuffersInPool":2,
         "idleBuffersInPool":4
      }
   }
}


Driftsdokumentation for NSP komponenter, der anvender NSP Audit API

Alle NSP komponenter skal i følge kravene dokumentere deres auditlogninger i driftsdokumentationen.

Når NSP Audit API anvendes, anbefales det at man for hver request angives hvilke audit informationer der logges ved at udfylde følgende skema:

KomponentKontekstTypeNøgleInformation





...

KomponentKontekstTypeNøgleInformation
STSSecurityTokenRequestIkke personligcvrCVR nummeret for den kaldende organisation
STSSecurityTokenRequestFølsommecprCPR nummeret på den person der skal have udsted et id kort.

Hvert kald til NSP Audit APIs addAuditInformation metode bør reflekteres i tabellen.