Cette page explique comment utiliser les ressources de consentement FHIR pour déterminer l'accès aux données des stores FHIR dans l'API Cloud Healthcare.
Configurer un store FHIR pour lequel le contrôle des accès est activé
Pour configurer un store FHIR avec l'application du consentement, procédez comme suit:
Créez un store FHIR si vous n'en avez pas déjà un.
Définissez les paramètres
ConsentConfig
du store FHIR suivant pour activer l'application du consentement:version
: spécifie la version d'application du consentement utilisée pour le store FHIR. Cette valeur ne peut être définie qu'une seule fois parCreateFhirStore
ouUpdateFhirStore
. Une fois qu'il est défini, vous devez appelerApplyConsents
ouApplyAdminConsents
pour modifier la version.access_enforced
: si la valeur esttrue
, lors de l'accès aux ressources FHIR, les en-têtes de consentement fournis seront vérifiés par rapport aux directives de consentement données par les consommateurs.consent_header_handling
: si ce champ est défini surPERMIT_EMPTY_SCOPE
(valeur par défaut), le serveur autorise les requêtes sans en-têteX-Consent-Scope
(ou vide). Si ce paramètre est défini surREQUIRED_ON_READ
et queaccess_enforced
correspond àtrue
, le serveur rejette toutes les requêtes sans en-têteX-Consent-Scope
(ou vide).
Configurer un nouveau store FHIR avec ConsentConfig
curl -X POST \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "Content-Type: application/json" \ --data "{ 'version': 'R4', 'enableUpdateCreate': true, 'consentConfig': { 'version': 'V1', 'accessEnforced': true } }" "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores?fhirStoreId=FHIR_STORE_ID"
Vous devriez recevoir une réponse JSON de ce type :
{ "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID", "version": "R4", "enableUpdateCreate": true, "consentConfig": { "version": "V1" } }
Si vous avez déjà un magasin existant, utilisez UpdateFhirStore
pour définir ConsentConfig
avec l'version
d'application du consentement sur V1
et accessEnforced
sur true
.
curl -X PATCH \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "Content-Type: application/json" \ --data "{ 'consentConfig': { 'version': 'V1', 'accessEnforced': true } }" "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID?update_mask=consentConfig"
Définir des stratégies à l'aide de la ressource de consentement
Les règles sont représentées par la ressource Consent. L'objectif et l'utilisation des champs de ressources sont décrits dans la documentation sur le modèle de données.
Voici un exemple de toutes les ressources pouvant être créées pour cet exemple spécifique.
Créer des ressources FHIR
L'exemple suivant montre comment exécuter un [bundle FHIR](/healthcare-api/docs/how-tos/fhir-bundles) pour remplir les ressources suivantes:
- Une ressource de type Professionnel portant le nom Jeffrey Brown
- Une ressource de type Patient portant le nom Darcy Smith
- Ressource d'observation montrant la mesure de l'hémoglobine de Darcy (LOINC
718-7
) collectée par le Happy Hospital - Ressource d'observation montrant la mesure du taux de glucose de Darcy (LOINC
15074-8
). - Autorisation de Darcy autorisant Jeffrey Brown à utiliser l'application
App/123
à accéder à ses données collectées par le Happy Hospital - Autorisation de Darcy autorisant Jeffrey Brown à accéder à ses données pour un traitement d'urgence (
ETREAT
) - Autorisation de Happy Hospital autorisant Jeffrey Brown à accéder à toutes les données lorsqu'il effectue des recherches biomédicales (
BIORCH
) avec la demandeApp/golden
cat > bundle.json << 'EOF' { "resourceType": "Bundle", "type": "transaction", "entry": [ { "request": {"method": "PUT", "url": "Practitioner/12942879-f89f-41ae-aa80-0b911b649833"}, "resource": { "active": true, "birthDate": "1970-05-23", "gender": "male", "id": "12942879-f89f-41ae-aa80-0b911b649833", "name": [{ "family": "Brown", "given": ["Jeffrey"], "use": "official" }], "resourceType": "Practitioner" } }, { "request": {"method": "PUT", "url": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2"}, "resource": { "active": true, "birthDate": "1990-01-01", "gender": "female", "id": "3c6aa096-c054-4c22-b2b4-1e4a4d203de2", "name": [{ "family": "Smith", "given": ["Darcy"], "use": "official" }], "meta": { "tag": [{ "system": "http://terminology.hl7.org/CodeSystem/common-tags", "code": "employee" }] }, "resourceType": "Patient" } }, { "request": {"method": "PUT", "url": "Observation/7473784b-46a8-470c-b9a6-fe38a01025aa"}, "resource": { "id": "7473784b-46a8-470c-b9a6-fe38a01025aa", "meta": {"source": "http://example.com/HappyHospital"}, "code": { "coding": [{ "code": "718-7", "system": "http://loinc.org", "display": "Hemoglobin [Mass/volume] in Blood" }] }, "effectivePeriod": {"start": "2021-12-10T05:30:10+01:00"}, "issued": "2021-12-10T13:30:10+01:00", "resourceType": "Observation", "status": "final", "subject": {"reference": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2"}, "valueQuantity": { "code": "g/dL", "system": "http://unitsofmeasure.org", "unit": "g/dl", "value": 7.2 } } }, { "request": {"method": "PUT", "url": "Observation/68583624-9921-4158-8754-2a306c689abd"}, "resource": { "id": "68583624-9921-4158-8754-2a306c689abd", "code": { "coding": [{ "code": "15074-8", "system": "http://loinc.org", "display": "Glucose [Moles/volume] in Blood" }] }, "effectivePeriod": {"start": "2021-12-01T05:30:10+01:00"}, "issued": "2021-12-01T13:30:10+01:00", "resourceType": "Observation", "status": "final", "subject": {"reference": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2"}, "valueQuantity": { "code": "mmol/L", "system": "http://unitsofmeasure.org", "unit": "mmol/l", "value": 6.3 } } }, { "request": {"method": "PUT", "url": "Consent/10998b60-a252-405f-aa47-0702554ddc8e"}, "resource": { "category": [{ "coding": [{ "code": "59284-0", "system": "http://terminology.hl7.org/CodeSystem/consentcategorycodes" }] }], "id": "10998b60-a252-405f-aa47-0702554ddc8e", "patient": {"reference": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2"}, "policyRule": { "coding": [{ "code": "OPTIN", "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode" }] }, "provision": { "actor": [ { "reference": {"reference": "Practitioner/12942879-f89f-41ae-aa80-0b911b649833"}, "role": { "coding": [{ "code": "GRANTEE", "system": "http://terminology.hl7.org/CodeSystem/v3-RoleCode" }] } } ], "extension": [ { "url": "https://g.co/fhir/medicalrecords/Environment", "valueCodeableConcept": { "coding": [{ "code": "123", "system": "App" }] } }, { "url": "https://g.co/fhir/medicalrecords/DataSource", "valueUri": "http://example.com/HappyHospital" } ], "type": "permit" }, "resourceType": "Consent", "scope": { "coding": [{ "code": "patient-privacy", "system": "http://terminology.hl7.org/CodeSystem/consentscope" }] }, "status": "active" } }, { "request": {"method": "PUT", "url": "Consent/73c54e8d-2789-403b-9dee-13085c5d5e34"}, "resource": { "category": [{ "coding": [{ "code": "59284-0", "system": "http://terminology.hl7.org/CodeSystem/consentcategorycodes" }] }], "id": "73c54e8d-2789-403b-9dee-13085c5d5e34", "patient": {"reference": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2"}, "policyRule": { "coding": [{ "code": "OPTIN", "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode" }] }, "provision": { "actor": [ { "reference": {"reference": "Practitioner/12942879-f89f-41ae-aa80-0b911b649833"}, "role": { "coding": [{ "code": "GRANTEE", "system": "http://terminology.hl7.org/CodeSystem/v3-RoleCode" }] } } ], "purpose": [{ "code": "ETREAT", "system": "http://terminology.hl7.org/CodeSystem/v3-ActReason" }], "type": "permit" }, "resourceType": "Consent", "scope": { "coding": [{ "code": "patient-privacy", "system": "http://terminology.hl7.org/CodeSystem/consentscope" }] }, "status": "active" } }, { "request": {"method": "PUT", "url": "Consent/5c8e3f8a-9fd5-480d-a08e-f29b89feccde"}, "resource": { "category": [{ "coding": [{ "code": "57017-6", "system": "http://loinc.org" }] }], "id": "5c8e3f8a-9fd5-480d-a08e-f29b89feccde", "patient": {}, "extension": [{ "url": "https://g.co/fhir/medicalrecords/ConsentAdminPolicy" }], "policyRule": { "coding": [{ "code": "OPTIN", "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode" }] }, "provision": { "actor": [ { "reference": {"reference": "Practitioner/12942879-f89f-41ae-aa80-0b911b649833"}, "role": { "coding": [{ "code": "GRANTEE", "system": "http://terminology.hl7.org/CodeSystem/v3-RoleCode" }] } } ], "purpose": [{ "code": "BIORCH", "system": "http://terminology.hl7.org/CodeSystem/v3-ActReason" }], "extension": [ { "url": "https://g.co/fhir/medicalrecords/Environment", "valueCodeableConcept": { "coding": [{ "code": "golden", "system": "App" }] } } ], "type": "permit" }, "resourceType": "Consent", "scope": {}, "status": "active" } } ] } EOF curl -X POST \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "Content-Type: application/fhir+json; charset=utf-8" \ --data @bundle.json \ "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir"
Vous devriez recevoir une réponse JSON de ce type :
{ "entry": [ { "response": { "etag": "W/\"VERSION_ID\"", "lastModified": "2022-09-01T17:31:40.423469+00:00", "location": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Practitioner/12942879-f89f-41ae-aa80-0b911b649833/_history/VERSION_ID", "status": "201 Created" } }, { "response": { "etag": "W/\"VERSION_ID\"", "lastModified": "2022-09-01T17:31:40.423469+00:00", "location": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2/_history/VERSION_ID", "status": "201 Created" } }, { "response": { "etag": "W/\"VERSION_ID\"", "lastModified": "2022-09-01T17:31:40.423469+00:00", "location": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/7473784b-46a8-470c-b9a6-fe38a01025aa/_history/VERSION_ID", "status": "201 Created" } }, { "response": { "etag": "W/\"VERSION_ID\"", "lastModified": "2022-09-01T17:31:40.423469+00:00", "location": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/68583624-9921-4158-8754-2a306c689abd/_history/VERSION_ID", "status": "201 Created" } }, { "response": { "etag": "W/\"VERSION_ID\"", "lastModified": "2022-09-01T17:31:40.423469+00:00", "location": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Consent/10998b60-a252-405f-aa47-0702554ddc8e/_history/VERSION_ID", "status": "201 Created" } }, { "response": { "etag": "W/\"VERSION_ID\"", "lastModified": "2022-09-01T17:31:40.423469+00:00", "location": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Consent/73c54e8d-2789-403b-9dee-13085c5d5e34/_history/VERSION_ID", "status": "201 Created" } }, { "response": { "etag": "W/\"VERSION_ID\"", "lastModified": "2022-09-01T17:31:40.423469+00:00", "location": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Consent/5c8e3f8a-9fd5-480d-a08e-f29b89feccde/_history/VERSION_ID", "status": "201 Created" } } ], "resourceType": "Bundle", "type": "transaction-response" }
Vous trouverez ci-dessous d'autres exemples de ressource de consentement R4, qui montrent comment les stratégies complexes peuvent être représentées.
Exemple de directive sur le consentement des patients
{ "resourceType": "Consent", "id": "patient-consent-example", "patient": { "reference": "Patient/f001" }, "category": [ { "coding": [ { "system": "http://loinc.org", "code": "59284-0" } ] } ], "scope": { "coding": [ { "system": "http://terminology.hl7.org/CodeSystem/consentscope", "code": "patient-privacy" } ] }, "policyRule": { "coding": [ { "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "OPTIN" } ] }, "status": "active", "provision": { "type": "permit", "actor": [ { "reference": { "reference": "Practitioner/f002" }, "role": { "coding": [ { "system": "http://terminology.hl7.org/CodeSystem/v3-RoleCode", "code": "GRANTEE" } ] } } ], "purpose": [ { "system": "http://terminology.hl7.org/CodeSystem/v3-ActReason", "code": "TREAT" } ], "class": [ { "system": "http://hl7.org/fhir/resource-types", "code": "Encounter" } ], "data": [ { "meaning": "instance", "reference": { "reference": "Encounter/e001" } } ], "extension": [ { "url": "https://g.co/fhir/medicalrecords/Environment", "valueCodeableConcept": { "coding": [ { "system": "iso3166-1", "code": "CA" } ] } }, { "url": "https://g.co/fhir/medicalrecords/DataTag", "valueCoding": { "system": "http://terminology.hl7.org/CodeSystem/common-tags", "code": "actionable" } }, { "url": "https://g.co/fhir/medicalrecords/DataTag", "extension": [ { "url": "https://g.co/fhir/medicalrecords/DataTag", "valueCoding": { "system": "http://example.com/custom-tags", "code": "archived" } }, { "url": "https://g.co/fhir/medicalrecords/DataTag", "valueCoding": { "system": "http://example.com/custom-tags", "code": "insensitive" } } ] }, { "url": "https://g.co/fhir/medicalrecords/DataSource", "valueUri": "http://somesystem.example.org/foo" } ], "securityLabel": [ { "system": "http://terminology.hl7.org/CodeSystem/v3-Confidentiality", "code": "R" }, { "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "PSY" } ] } }
L'exemple précédent représente une ressource de consentement du patient dans laquelle un patient f001
autorise un praticien f002
dans le but de fournir un traitement régulier représenté par TREAT
.
Le professionnel provient du iso3166-1/CA
de géolocalisation. Cette ressource de consentement permet au praticien d'accéder aux données du patient si celles-ci remplissent toutes les conditions suivantes.
- Il s'agit d'un type
Encounter
avec l'IDEncounter/e001
. - Elle provient de la source
http://somesystem.example.org/foo
. - Elle remplit au moins l'une des conditions suivantes sur la balise (vous pouvez ajouter des tags aux ressources en définissant les champs
system
etcode
de Meta.tag): - Contient la balise (
system
=http://terminology.hl7.org/CodeSystem/common-tags
etcode
=actionable
) - Comporte les deux tags (
system
=http://example.com/custom-tags
etcode
=archived
) et (system
=http://example.com/custom-tags
etcode
=insensitive
) - Il comporte au moins l'un des libellés de sécurité suivants
system
=http://terminology.hl7.org/CodeSystem/v3-Confidentiality
etcode
est l'un des éléments suivants :R
,N
,M
,L
,U
.system
=http://terminology.hl7.org/CodeSystem/v3-ActCode
etcode
=PSY
.
Exemple de directive pour les règles d'administration
{ "resourceType": "Consent", "id": "admin-policy-example", "patient": {}, "extension": [{ "url": "https://g.co/fhir/medicalrecords/ConsentAdminPolicy" }], "category": [ { "coding": [ { "system": "http://loinc.org", "code": "57017-6" } ] } ], "scope": {}, "policyRule": { "coding": [ { "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "OPTIN" } ] }, "status": "active", "provision": { "type": "permit", "actor": [ { "reference": { "reference": "Practitioner/f002" }, "role": { "coding": [ { "system": "http://terminology.hl7.org/CodeSystem/v3-RoleCode", "code": "GRANTEE" } ] } } ], "purpose": [ { "system": "http://terminology.hl7.org/CodeSystem/v3-ActReason", "code": "TREAT" } ], "class": [ { "system": "http://hl7.org/fhir/resource-types", "code": "Encounter" } ], "data": [ { "meaning": "instance", "reference": { "reference": "Encounter/e001" } } ], "extension": [ { "url": "https://g.co/fhir/medicalrecords/Environment", "valueCodeableConcept": { "coding": [ { "system": "iso3166-1", "code": "CA" } ] } }, { "url": "https://g.co/fhir/medicalrecords/DataTag", "valueCoding": { "system": "http://terminology.hl7.org/CodeSystem/common-tags", "code": "actionable" } }, { "url": "https://g.co/fhir/medicalrecords/DataTag", "extension": [ { "url": "https://g.co/fhir/medicalrecords/DataTag", "valueCoding": { "system": "http://example.com/custom-tags", "code": "archived" } }, { "url": "https://g.co/fhir/medicalrecords/DataTag", "valueCoding": { "system": "http://example.com/custom-tags", "code": "insensitive" } } ] }, { "url": "https://g.co/fhir/medicalrecords/DataSource", "valueUri": "http://somesystem.example.org/foo" } ], "securityLabel": [ { "system": "http://terminology.hl7.org/CodeSystem/v3-Confidentiality", "code": "R" }, { "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "PSY" } ] } }
L'exemple précédent représente une ressource de consentement pour une règle d'administration qui accorde l'autorisation à un professionnel f002
dans le but de fournir un traitement standard représenté par TREAT
. Le professionnel se trouve dans la zone géographique suivante : iso3166-1/CA
. Cette ressource Consent permet au praticien d'accéder aux données du patient si celles-ci remplissent toutes les conditions suivantes:
- Il s'agit d'un type
Encounter
avec l'IDEncounter/e001
. - Elle provient de la source
http://somesystem.example.org/foo
. - Elle remplit au moins l'une des conditions suivantes sur la balise:
- Contient la balise (
system
=http://terminology.hl7.org/CodeSystem/common-tags
etcode
=actionable
) - Comporte les deux tags (
system
=http://example.com/custom-tags
etcode
=archived
) et (system
=http://example.com/custom-tags
etcode
=insensitive
) - Il comporte au moins l'un des libellés de sécurité suivants
system
=http://terminology.hl7.org/CodeSystem/v3-Confidentiality
etcode
est l'un des éléments suivants :R
,N
,M
,L
,U
.system
=http://terminology.hl7.org/CodeSystem/v3-ActCode
etcode
=PSY
.
Exemple de règle d'administration en cascade
{ "resourceType": "Consent", "id": "admin-cascading-policy-example", "patient": {}, "extension": [ { "url": "https://g.co/fhir/medicalrecords/ConsentAdminPolicy" }, { "url": "https://g.co/fhir/medicalrecords/CascadingPolicy" } ], "category": [ { "coding": [ { "system": "http://loinc.org", "code": "57017-6" } ] } ], "scope": {}, "policyRule": { "coding": [ { "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "OPTIN" } ] }, "status": "active", "provision": { "type": "permit", "actor": [ { "reference": { "reference": "Practitioner/f002" }, "role": { "coding": [ { "system": "http://terminology.hl7.org/CodeSystem/v3-RoleCode", "code": "GRANTEE" } ] } } ], "purpose": [ { "system": "http://terminology.hl7.org/CodeSystem/v3-ActReason", "code": "TREAT" } ], "class": [ { "system": "http://hl7.org/fhir/resource-types", "code": "Patient" } ], "extension": [ { "url": "https://g.co/fhir/medicalrecords/Environment", "valueCodeableConcept": { "coding": [ { "system": "iso3166-1", "code": "CA" } ] } }, { "url": "https://g.co/fhir/medicalrecords/DataTag", "valueCoding": { "system": "http://terminology.hl7.org/CodeSystem/common-tags", "code": "employee" } } ] } }
L'exemple précédent représente une ressource de consentement d'une règle de cascade d'annonces destinée aux administrateurs et accordant l'autorisation à un professionnel f002
dans le but de fournir un traitement normal représenté par TREAT
. Le professionnel provient de la géolocalisation iso3166-1/CA
. Cette ressource Consent permet au praticien d'accéder aux données des compartiments des patients portant la balise employee
. Tous les critères de ressources ne s'appliquent qu'aux ressources de base par compartiment, c'est-à-dire à la ressource patient, car elles contrôlent les ressources à partir desquelles la cascade doit s'effectuer.
Appliquez les autorisations des patients ou les règles d'administration
Appliquez l'autorisation du patient d'ici le ApplyConsents
curl -X POST \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "Content-Type: application/json" \ --data "{'validateOnly': false}" \ "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:applyConsents"
Vous devriez recevoir une réponse JSON de ce type :
{ "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID" }
La réponse contient un nom d'opération. Pour suivre l'état de l'opération, vous pouvez utiliser la [méthode d'opération "get"](/healthcare-api/docs/reference/rest/v1/projects.locations.datasets.operations/get):
curl -X GET \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"
Une fois l'opération terminée, le serveur renvoie une réponse indiquant l'état de l'opération au format JSON:
{ "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"", "metadata": { "@type": "type.googleapis.com/google.cloud.healthcare.v1beta1.OperationMetadata", "apiMethodName": "google.cloud.healthcare.v1beta1.fhir.FhirStoreService.ApplyConsents", "createTime": "CREATE_TIME", "endTime": "END_TIME", "logsUrl": "https://console.cloud.google.com/logs/query/CLOUD_LOGGING_URL", "counter": { "success": "2", "secondarySuccess": "5" } }, "done": true, "response": { "@type": "type.googleapis.com/google.cloud.healthcare.v1beta1.fhir.ApplyConsentsResponse", "consentApplySuccess": "2", "affectedResources": "5" } }
Cette réponse indique que le serveur a bien traité deux autorisations et mis à jour l'accès consensuel pour cinq ressources (1 patient, 2 autorisations et 2 observations).
Appliquer la règle d'administration d'ici le ApplyAdminConsents
curl -X POST \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "Content-Type: application/json" \ --data "{ 'validateOnly': false, 'newConsentsList': { 'names': ['projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Consent/5c8e3f8a-9fd5-480d-a08e-f29b89feccde/_history/VERSION_ID'] } }" \ "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:applyAdminConsents"
Vous devriez recevoir une réponse JSON de ce type :
{ "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID" }
La réponse contient un nom d'opération. Pour suivre l'état de l'opération, vous pouvez utiliser la [méthode d'opération "get"](/healthcare-api/docs/reference/rest/v1/projects.locations.datasets.operations/get):
curl -X GET \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"
Une fois l'opération terminée, le serveur renvoie une réponse indiquant l'état de l'opération au format JSON:
{ "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"", "metadata": { "@type": "type.googleapis.com/google.cloud.healthcare.v1beta1.OperationMetadata", "apiMethodName": "google.cloud.healthcare.v1beta1.fhir.FhirStoreService.ApplyAdminConsents", "createTime": "CREATE_TIME", "endTime": "END_TIME", "logsUrl": "https://console.cloud.google.com/logs/query/CLOUD_LOGGING_URL", "counter": { "success": "1", "secondarySuccess": "7" } }, "done": true, "response": { "@type": "type.googleapis.com/google.cloud.healthcare.v1beta1.fhir.ApplyAdminConsentsResponse", "consentApplySuccess": "1", "affectedResources": "7" } }
Cette réponse indique que le serveur a bien traité une règle d'administration et mis à jour l'accès consensuel à sept ressources (un professionnel, un patient, deux observations, deux autorisations du patient et une règle d'administration).
L'application des autorisations stockées dans un store FHIR n'entrera en vigueur que lorsque ApplyConsents
(pour les consentements des patients) ou ApplyAdminConsents
(pour les règles d'administration et les règles d'administration en cascade) n'aura pas été appelé et finalisé. Si vous ajoutez, modifiez ou supprimez des autorisations après avoir exécuté ApplyConsents
ou ApplyAdminConsents
, vous devez l'exécuter à nouveau pour que ces consentements soient inclus dans le modèle d'application.
Les ressources FHIR sont indexées de manière asynchrone. Il peut donc y avoir un léger décalage entre le moment où ApplyConsents
ou ApplyAdminConsents
se termine et le moment où le modèle d'application apparaît dans les résultats de recherche. Ce délai n'est attendu que pour les requêtes de recherche.
Si vous configurez l'application du consentement pour la première fois dans le store FHIR, attendez que l'opération de longue durée ApplyConsents
ou ApplyAdminConsents
soit terminée avant d'effectuer des requêtes basées sur le consentement.
Pour appeler ApplyConsents
sur un sous-ensemble de patients, vous pouvez utiliser les filtres suivants:
PatientScope
: permet d'exécuterApplyConsents
sur une liste d'ID de patients comptant jusqu'à 10 000 patientsTimeRange
: permet d'exécuterApplyConsent
sur une liste d'ID de ressources de patients dont les ressources de consentement sont mises à jour au cours d'une certaine période.
Pour appeler ApplyAdminConsents
: vous devez fournir la liste complète de toutes les règles que vous souhaitez appliquer (et non une liste incrémentielle). Par conséquent, si la liste est vide, l'application de toutes les règles d'administration du store sera annulée. Chaque stratégie doit être un nom de version de ressource si le magasin FHIR gère les versions, et un nom de ressource dans le cas contraire.
Vous pouvez utiliser operations.get
pour récupérer la valeur ProgressCounter
de l'opération. Une fois l'opération terminée, une réponse ApplyConsentsResponse est incluse dans Operation.response
.
Les compteurs de ProgressCounter
et ApplyConsentsResponse
ou ApplyAdminConsentsResponse
sont décrits dans le tableau suivant.
ProgressCounter |
ApplyConsentsResponse ou ApplyAdminConsentsResponse |
Description |
---|---|---|
success |
consentApplySuccess |
Nombre de ressources de consentement que l'opération a bien traitées. |
failure |
consentApplyFailure |
Nombre de ressources de consentement non compatibles ou non valides. Vous pouvez afficher les journaux d'erreurs dans Cloud Logging ou, lorsque validateOnly est défini sur false , vérifier l'état de l'application du consentement à l'aide de CheckConsentEnforcementStatus ou de CheckPatientConsentEnforcementStatus pour récupérer les détails de l'erreur. |
secondarySuccess |
affectedResources |
Lorsque validateOnly est défini sur false , cela représente le nombre de ressources FHIR qui ont été réindexées avec succès en raison de l'effet de la modification du consentement. |
secondaryFailure |
failedResources |
Lorsque validateOnly est défini sur false , cela représente le nombre de ressources FHIR susceptibles d'avoir une modification du consentement, mais dont la réindexation a échoué. Cela peut affecter la recherche avec contexte de consentement, mais pas d'autres méthodes. Pour afficher les détails de l'erreur, vous pouvez afficher les journaux d'erreurs dans Cloud Logging. |
Lorsque les ressources de consentement FHIR sont traitées, vous pouvez utiliser les API suivantes pour vérifier l'état d'application d'un consentement unique ou de tous les consentements d'un patient:
CheckConsentEnforcementStatus
: renvoie une valeurParameters
(STU3 ,R4) qui répertorie les paramètres suivants:id
: ID de la ressource d'autorisationlastUpdated
: représente l'heure à laquelle le consentement a été appliqué pour la dernière fois.versionId
: représente l'ID de version utilisé pour l'application du consentement.consent-enforcement-status
: état de l'application de l'autorisation.
CheckPatientConsentEnforcementStatus
: renvoie une valeurBundle
(STU3 ,R4) de la ressourceParameters
(STU3 ,R4) constituée de l'état d'application de toutes les autorisations d'un seul patient
Pour une règle d'administration, CheckConsentEnforcementStatus
ne peut être utilisé que pour vérifier l'état d'application d'une seule règle d'administration du consentement. Vous pouvez également utiliser fhirStores.get
pour afficher toutes les règles d'administration actives appliquées au magasin.
État d'application du consentement
consent-enforcement-status
peut avoir l'une des valeurs suivantes:
OFF
: représente l'état d'application par défaut d'une nouvelle ressource Consent dans laquelle la ressource Consent n'a jamais été traitée.ENFORCEABLE
: état dans lequel la ressource d'autorisation a été traitée.INACTIVE
: état inactif dans lequel la ressource d'autorisation est ignorée.UNSUPPORTED
: état d'une ressource Consent qui peut être conforme aux spécifications FHIR, mais qui n'est pas applicable. Cela est dû à l'implémentation limitée de l'application du consentement FHIR avec le niveau actuel de compatibilité des fonctionnalités.ENFORCEMENT_LIMIT_EXCEEDED
: état lorsque le format de la ressource de consentement FHIR et son niveau de compatibilité sont sans erreur, mais une ou plusieurs des conditions suivantes sont remplies:Le patient dispose d'un large ensemble de ressources d'autorisation.
La taille des instructions d'autorisation pour toutes les autorisations actives est supérieure à la taille maximale autorisée pour appliquer les instructions d'autorisation d'un serveur FHIR.
Rechercher dans le contexte d'autorisation
L'API Cloud Healthcare prend en charge les recherches de ressources FHIR dans un store FHIR donné avec les paramètres de requête actor
, purpose
et environment
. La réponse ne contient que les ressources autorisées.
Rechercher des ressources FHIR avec un champ d'application d'autorisation
- Le praticien Jeffrey Brown (identifié par
Practitioner/12942879-f89f-41ae-aa80-0b911b649833
) à l'aide d'une application de confianceApp/123
recherche toutes les observations avecstatus=final
. - Le praticien Jeffrey Brown (identifié par
Practitioner/12942879-f89f-41ae-aa80-0b911b649833
) à l'aide de l'applicationApp/123
recherche toutes les observations du patient Darcy. - Le praticien Jeffrey Brown (identifié par
Practitioner/12942879-f89f-41ae-aa80-0b911b649833
) à l'aide de l'applicationApp/123
recherche toutes les observations du patient Darcy à des fins de traitement d'urgence. - Le praticien Jeffrey Brown (identifié par
Practitioner/12942879-f89f-41ae-aa80-0b911b649833
) recherche les observations avecstatus=final
pour deux raisons : le traitement et la recherche. - L'administrateur informatique d'un hôpital utilise
bypass
pour rechercher tous les praticiens de l'hôpital.
curl -X GET \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "X-Consent-Scope: actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833 env/App/123" \ "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation?status=final"
Vous devriez recevoir une réponse JSON de ce type :
{ "entry": [ { "fullUrl": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION_ID/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/7473784b-46a8-470c-b9a6-fe38a01025aa", "resource": { "code": { "coding": [ { "code": "718-7", "display": "Hemoglobin [Mass/volume] in Blood", "system": "http://loinc.org" } ] }, "effectivePeriod": { "start": "2021-12-10T05:30:10+01:00" }, "id": "7473784b-46a8-470c-b9a6-fe38a01025aa", "issued": "2021-12-10T13:30:10+01:00", "meta": { "lastUpdated": "2022-09-01T17:31:40.423469+00:00", "source": "http://example.com/HappyHospital", "versionId": "VERSION_ID" }, "resourceType": "Observation", "status": "final", "subject": { "reference": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2" }, "valueQuantity": { "code": "g/dL", "system": "http://unitsofmeasure.org", "unit": "g/dl", "value": 7.2 } }, "search": { "mode": "match" } } ], "link": [ { "relation": "search", "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?status=final" }, { "relation": "first", "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?status=final" }, { "relation": "self", "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?status=final" } ], "resourceType": "Bundle", "total": 1, "type": "searchset" }
curl -X GET \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "X-Consent-Scope: actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833 env/App/123" \ "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation?subject:Patient.name=Darcy"
Vous devriez recevoir une réponse JSON de ce type :
{ "link": [ { "relation": "search", "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?subject%3APatient.name=Darcy" }, { "relation": "first", "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?subject%3APatient.name=Darcy" }, { "relation": "self", "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?subject%3APatient.name=Darcy" } ], "resourceType": "Bundle", "total": 0, "type": "searchset" }
La requête précédente est une recherche enchaînée. Étant donné que le scénario de consentement actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833 env/App/123
se voit refuser l'accès à la ressource Patient Darcy (identifiée par Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2
), le serveur FHIR ne renvoie aucune observation du patient comme si le patient n'existait pas.
curl -X GET \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "X-Consent-Scope: actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833 purp/v3/ETREAT env/App/123" \ "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation?subject:Patient.name=Darcy"
Vous devriez recevoir une réponse JSON de ce type :
{ "entry": [ { "fullUrl": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/68583624-9921-4158-8754-2a306c689abd", "resource": { "code": { "coding": [ { "code": "15074-8", "display": "Glucose [Moles/volume] in Blood", "system": "http://loinc.org" } ] }, "effectivePeriod": { "start": "2021-12-01T05:30:10+01:00" }, "id": "68583624-9921-4158-8754-2a306c689abd", "issued": "2021-12-01T13:30:10+01:00", "meta": { "lastUpdated": "2022-09-01T17:31:40.423469+00:00", "versionId": "VERSION_ID" }, "resourceType": "Observation", "status": "final", "subject": { "reference": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2" }, "valueQuantity": { "code": "mmol/L", "system": "http://unitsofmeasure.org", "unit": "mmol/l", "value": 6.3 } }, "search": { "mode": "match" } }, { "fullUrl": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/7473784b-46a8-470c-b9a6-fe38a01025aa", "resource": { "code": { "coding": [ { "code": "718-7", "display": "Hemoglobin [Mass/volume] in Blood", "system": "http://loinc.org" } ] }, "effectivePeriod": { "start": "2021-12-10T05:30:10+01:00" }, "id": "7473784b-46a8-470c-b9a6-fe38a01025aa", "issued": "2021-12-10T13:30:10+01:00", "meta": { "lastUpdated": "2022-09-01T17:31:40.423469+00:00", "source": "http://example.com/HappyHospital", "versionId": "VERSION_ID" }, "resourceType": "Observation", "status": "final", "subject": { "reference": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2" }, "valueQuantity": { "code": "g/dL", "system": "http://unitsofmeasure.org", "unit": "g/dl", "value": 7.2 } }, "search": { "mode": "match" } } ], "link": [ { "relation": "search", "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?subject:Patient.name=Darcy" }, { "relation": "first", "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?subject:Patient.name=Darcy" }, { "relation": "self", "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/?subject:Patient.name=Darcy" } ], "resourceType": "Bundle", "total": 2, "type": "searchset" }
curl -X GET \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "X-Consent-Scope: actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833 purp/v3/TREAT purp/v3/HRESCH" \ "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation?status=final"
Vous devriez recevoir une réponse JSON de ce type :
{ "issue": [ { "code": "security", "details": { "text": "permission_denied" }, "diagnostics": "the maximum number of allowed consent purpose scopes is 1, got 2", "severity": "error" } ], "resourceType": "OperationOutcome" }
Dans ce cas, le professionnel Jeffrey Brown doit supprimer un objectif inutile de "X-Consent-Scope" dans la demande.
curl -X GET \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "X-Consent-Scope: bypass actor/Admin/ef0592c9-6724-467e-878d-f879e537cd15 env/net/HappyNet" \ "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Practitioner?"
Comme bypass
est fourni, les vérifications du consentement ont été ignorées. Vous devriez recevoir une réponse JSON semblable à celle-ci:
{ "entry": [ { "fullUrl": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Practitioner/12942879-f89f-41ae-aa80-0b911b649833", "resource": { "active": true, "birthDate": "1970-05-23", "gender": "male", "id": "12942879-f89f-41ae-aa80-0b911b649833", "meta": { "lastUpdated": "2022-09-01T17:31:40.423469+00:00", "versionId": "VERSION_ID" }, "name": [ { "family": "Brown", "given": [ "Jeffrey" ], "use": "official" } ], "resourceType": "Practitioner" }, "search": { "mode": "match" } } ], "link": [ { "relation": "search", "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Practitioner/?" }, { "relation": "first", "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Practitioner/?" }, { "relation": "self", "url": "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Practitioner/?" } ], "resourceType": "Bundle", "total": 1, "type": "searchset" }
Obtenir une ressource avec un contexte de consentement
L'API Cloud Healthcare permet d'obtenir des ressources FHIR dans un magasin FHIR donné avec les paramètres de requête actor
, purpose
et environment
. La réponse ne contient que les ressources autorisées.
Obtenir des ressources FHIR avec un champ d'application de consentement
- Le praticien Jeffrey Brown (identifié par
Practitioner/12942879-f89f-41ae-aa80-0b911b649833
) à l'aide de l'applicationApp/123
lit la mesure de l'hémoglobine du patient (dans cet exemple,Observation/7473784b-46a8-470c-b9a6-fe38a01025aa
). - Le praticien Jeffrey Brown (identifié par
Practitioner/12942879-f89f-41ae-aa80-0b911b649833
) à l'aide de l'application inconnueApp/unknown
lit la mesure de l'hémoglobine du patient (dans cet exemple,Observation/7473784b-46a8-470c-b9a6-fe38a01025aa
). - Le praticien Jeffrey Brown (identifié par
Practitioner/12942879-f89f-41ae-aa80-0b911b649833
) effectuant des recherches biomédicales à l'aide de l'applicationApp/golden
lit la date de naissance de Darcy (dans cet exemple,Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2
). - Le praticien Jeffrey Brown (identifié par
Practitioner/12942879-f89f-41ae-aa80-0b911b649833
) demande un accès d'urgence non autorisé au dossier d'un patient à l'aide du protocole "bris de glace". (dans cet exemple,Observation/7473784b-46a8-470c-b9a6-fe38a01025aa
).
curl -X GET \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "X-Consent-Scope: actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833 env/App/123" \ "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/7473784b-46a8-470c-b9a6-fe38a01025aa"
Comme le demandeur a reçu son consentement, la réponse correspond au contenu de la ressource Observation.
{ "code": { "coding": [ { "code": "718-7", "display": "Hemoglobin [Mass/volume] in Blood", "system": "http://loinc.org" } ] }, "effectivePeriod": { "start": "2021-12-10T05:30:10+01:00" }, "id": "7473784b-46a8-470c-b9a6-fe38a01025aa", "issued": "2021-12-10T13:30:10+01:00", "meta": { "lastUpdated": "2022-09-01T17:31:40.423469+00:00", "source": "http://example.com/HappyHospital", "versionId": "VERSION_ID" }, "resourceType": "Observation", "status": "final", "subject": { "reference": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2" }, "valueQuantity": { "code": "g/dL", "system": "http://unitsofmeasure.org", "unit": "g/dl", "value": 7.2 } }
curl -X GET \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "X-Consent-Scope: actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833 env/App/unknown" \ "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/7473784b-46a8-470c-b9a6-fe38a01025aa"
Étant donné que l'accès aux limites du demandeur ("App/unknown") n'est pas autorisé par le consentement du patient, la requête est refusée.
{ "issue": [ { "code": "security", "details": { "text": "permission_denied" }, "diagnostics": "Consent access denied or the resource being accessed does not exist", "severity": "error" } ], "resourceType": "OperationOutcome" }
curl -X GET \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "X-Consent-Scope: actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833 purp/v3/BIORCH env/App/golden" \ "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2"
Comme le demandeur a reçu son consentement, la réponse correspond au contenu de la ressource Patient.
{ "active": true, "birthDate": "1990-01-01", "gender": "female", "id": "3c6aa096-c054-4c22-b2b4-1e4a4d203de2", "meta": { "lastUpdated": "2022-09-01T17:31:40.423469+00:00", "versionId": "VERSION_ID", "tag": [{ "system": "http://terminology.hl7.org/CodeSystem/common-tags", "code": "employee" }] }, "name": [ { "family": "Smith", "given": [ "Darcy" ], "use": "official" } ], "resourceType": "Patient" }
curl -X GET \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "X-Consent-Scope: btg actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833" \ "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Observation/7473784b-46a8-470c-b9a6-fe38a01025aa"
Comme la méthode d'autorisation du consentement est btg
, le serveur ignore les vérifications du consentement. La réponse est le contenu de la ressource Observation.
{ "code": { "coding": [ { "code": "718-7", "display": "Hemoglobin [Mass/volume] in Blood", "system": "http://loinc.org" } ] }, "effectivePeriod": { "start": "2021-12-10T05:30:10+01:00" }, "id": "7473784b-46a8-470c-b9a6-fe38a01025aa", "issued": "2021-12-10T13:30:10+01:00", "meta": { "lastUpdated": "2022-09-01T17:31:40.423469+00:00", "source": "http://example.com/HappyHospital", "versionId": "VERSION_ID" }, "resourceType": "Observation", "status": "final", "subject": { "reference": "Patient/3c6aa096-c054-4c22-b2b4-1e4a4d203de2" }, "valueQuantity": { "code": "g/dL", "system": "http://unitsofmeasure.org", "unit": "g/dl", "value": 7.2 } }
Configurer l'en-tête de consentement
Les sections suivantes décrivent les méthodes d'application du consentement compatibles avec l'API Cloud Healthcare et comment l'accès aux ressources est appliqué lorsque vous effectuez une requête en tenant compte du consentement.
Lorsque vous effectuez une requête, votre serveur d'autorisation est chargé de générer des jetons d'accès avec le champ d'application de consentement approprié.
Définir l'en-tête HTTP
Les champs d'application de consentement sont transmis à l'API Cloud Healthcare à l'aide de l'en-tête HTTP X-Consent-Scope
. L'API Cloud Healthcare utilise cet en-tête pour appliquer un contrôle d'accès basé sur le consentement pour les données des magasins FHIR.
Une requête FHIR accepte un nombre limité de champs d'application d'entrée d'autorisations. Vous pouvez inclure jusqu'à trois entrées de actor
, une de purp
et une de env
dans une requête FHIR donnée.
Pour les champs d'application spéciaux, une requête FHIR peut prendre en charge btg
ou bypass
.
Définir des en-têtes HTTP pour les applications de confiance
Cette section n'est requise que si vous utilisez un serveur d'autorisation contrôlé par le client. Dans ce cas, vous devez également utiliser un SMARTproxy ou un proxy similaire.
Certaines applications approuvées peuvent appeler directement l'API Cloud Healthcare avec les champs d'application du consentement dans l'en-tête HTTP spécifié. Cela permet d'appliquer directement le consentement sans qu'un SMARTproxy ou un autre proxy ne soit nécessaire pour effectuer la conversion entre des serveurs d'autorisation externes et Google Cloud.
Par exemple, votre application peut être enregistrée pour un sous-ensemble de champs d'application, tel que le champ d'application environment
d'une application, ou l'application peut présenter un widget de sélection pour définir certaines entrées de champ d'application, telles que le purpose
de l'accesseur.
Un utilisateur ou une application de confiance peut également utiliser les entrées de champ d'application btg
ou bypass
, qui sont soumises à des examens post-audit.
Configurer le serveur d'autorisation pour les champs d'application des autorisations
L'API Cloud Healthcare offre une prise en charge intégrée pour l'application du consentement FHIR en fonction des champs d'application du consentement d'entrée. Les administrateurs de store FHIR sont chargés de créer et de configurer un serveur d'autorisation en dehors de l'API Cloud Healthcare qui accorde des champs d'application de consentement.
Exemple de jeton d'accès
L'exemple suivant montre un jeton d'accès encodé en base64 :
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzM4NCJ9.eyJpc3MiOiJjb25zZW50LnRva2VuLm9yZyIsImlhdCI6MTYxMjg4NDA4NSwiZXhwIjoxNjQ0NDIwMDg1LCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJkb2N0b3IuZ2FicmllbGFAZXhhbXBsZS5jb20iLCJzY29wZSI6Im9pZGMgYWN0b3IvUHJhY3RpdGlvbmVyLzEyMyBhY3Rvci9Hcm91cC85OTkgcHVycC92My9UUkVBVCBlbnYvQXBwL2FiYyJ9.fC7ljkVUUx8fwUOrJuONcrqA-WKC-k_Bclzlgds0Cq6H_gEe3nUjPlSOCTQsIdYB
Après avoir décodé le jeton d'accès, vous pouvez voir qu'il contient la charge utile suivante :
{
"iss": "consent.token.org",
"iat": 1612884085,
"exp": 1644420085,
"aud": "www.example.com",
"sub": "doctor.gabriela@example.com",
"scope": "oidc actor/Practitioner/123 actor/Group/999 purp/v3/TREAT env/App/abc"
}
Configurer SMARTProxy
SMARTProxy est un proxy Open Source de Google qui fournit les fonctionnalités suivantes :
Permet au serveur FHIR de l'API Cloud Healthcare d'accepter et de valider les jetons d'accès compatibles avec le consentement.
Permet à la mise en œuvre FHIR dans l'API Cloud Healthcare d'inclure des jetons d'accès compatibles avec le consentement dans le cadre du modèle d'autorisation et de gestion de l'API Cloud Healthcare.
Compatible également avec les fonctionnalités de jeton pour l'assistance SMART sur FHIR.
Lorsque vous effectuez une requête pour récupérer des données de l'API Cloud Healthcare via SMARTProxy, voici ce qui se produit:
SMARTProxy accepte une requête d'un client contenant un jeton compatible avec le consentement.
SMARTProxy valide le jeton compatible avec le consentement via un serveur d'autorisation JWT que vous possédez.
SMARTProxy lit les champs d'application à partir du jeton compatible avec le consentement et les transmet à l'API Cloud Healthcare via l'en-tête HTTP.
L'API Cloud Healthcare reçoit les en-têtes et les valide pour appliquer les instructions d'autorisation sur la requête. L'API Cloud Healthcare renvoie ensuite une réponse via le SMARTProxy au client.
Configurer un compte de service Google Cloud
Un proxy ne peut posséder qu'un seul compte de service Google Cloud. Si plusieurs clients utilisent le même proxy, ils utilisent le même compte de service. Soyez prudent lorsque vous partagez un compte de service avec plusieurs clients pour les raisons suivantes :
Pour lire les données FHIR dans l'API Cloud Healthcare, le compte de service peut être configuré pour disposer d'autorisations étendues en lecture et en écriture. Pour en savoir plus sur les autorisations, consultez la page Contrôler l'accès aux ressources de l'API Cloud Healthcare. Consultez les bonnes pratiques générales pour configurer le proxy.
Cloud Audit Logs
L'adresse e-mail principale est associée au compte de service.
Par exemple, si vous appelez l'API Cloud Healthcare directement à l'aide de votre compte Google pour l'authentification, Cloud Audit Logging enregistre votre adresse e-mail comme adresse e-mail principale. Lorsque vous utilisez un proxy pour appeler l'API Cloud Healthcare, le proxy utilise son propre compte de service, l'adresse e-mail principale est celle du compte de service et le compte d'origine n'est pas défini.
Journaux d'audit
Les journaux d'audit sont générés en cas de demande d'accès ou de modification de l'application des accès aux ressources.
Accéder aux journaux d'audit
Si les journaux d'audit sont activés sur le store FHIR, un champ de métadonnées consentMode
est inclus dans les journaux d'audit disponibles dans Cloud Logging. consentMode
peut avoir l'une des valeurs suivantes:
off
: dans la configuration du store FHIR,consentConfig.accessEnforced
est défini surfalse
et n'autorise pas les requêtes basées sur le consentement.emptyScope
:consentConfig.accessEnforced
est défini surtrue
pour le store FHIR, mais aucun en-tête de champ d'application du consentement n'a été inclus. Par conséquent, le consentement n'a pas été appliqué.enforced
:consentConfig.accessEnforced
est défini surtrue
pour le magasin FHIR et l'en-tête du champ d'application d'autorisation est présent. Par conséquent, les consentements ont été évalués et appliqués à la demande.btg
:btg
est indiqué dans l'en-tête du champ d'application du consentement pour la requête FHIR. Par conséquent, les vérifications du consentement ont été ignorées. Cette demande est destinée à être utilisée en cas d'urgence et n'est sujette qu'à un examen post-audit.bypass
: seulbypass
est indiqué dans l'en-tête du champ d'application du consentement pour la requête FHIR. Par conséquent, les vérifications du consentement ont été ignorées. Cette requête est destinée à être utilisée par un workflow de confiance (tel qu'un administrateur ou une application de confiance plutôt que des utilisateurs finaux) afin que ce journal d'audit soit différent dubtg
, utilisé pour les vérifications de gouvernance des données.
Vous pouvez éventuellement définir access_determination_log_config
sur VERBOSE
pour enregistrer plus d'informations sur les raisons pour lesquelles une requête est acceptée ou refusée.
Journaux d'audit des modifications liées à l'application des accès
Lorsque la ressource de base du compartiment change (par exemple, en supprimant la balise employee
d'un patient): le contrôle des accès à la ressource modifiée et à son compartiment peut changer en raison de la règle d'administration en cascade. Cela déclenchera la réindexation sur
toutes ses ressources de compartiment. La progression de la réindexation pour chaque mise à jour des ressources de base par compartiment peut être suivie dans Cloud Logging avec le filtre jsonPayload.@type="type.googleapis.com/google.cloud.healthcare.logging.FhirConsentCascadeLogEntry"
.
Exemple de journal de progression de la réindexation en cascade
{ "insertId": "tz2gtza8", "jsonPayload": { "@type": "type.googleapis.com/google.cloud.healthcare.logging.FhirConsentCascadeLogEntry", "state": "STATE_FINISHED", "affectedResources": "2", "lastUpdated": "YYYY-MM-DDTHH:MM:SS+ZZ:ZZ", "compartmentBaseResourceName": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Patient/PATIENT_RESOURCE_ID/_history/PATIENT_RESOURCE_VERSION" }, "resource": { "type": "healthcare_fhir_store", "labels": { "location": "LOCATION", "dataset_id": "DATASET_ID", "fhir_store_id": "FHIR_STORE_ID", "project_id": "PROJECT_ID" } }, "timestamp": "YYYY-MM-DDTHH:MM:SS+ZZ:ZZ", "severity": "INFO", "logName": "projects/PROJECT_ID/logs/healthcare.googleapis.com%2Fconsent_cascading_fhir", "receiveTimestamp": "YYYY-MM-DDTHH:MM:SS+ZZ:ZZ" }
jsonPayload.state
correspond à l'état de l'opération de réindexation, jsonPayload.affectedResources
au nombre de ressources de compartiment réindexées et jsonPayload.lastUpdated
correspond au code temporel de la mise à jour des ressources du patient. Si l'opération vient de commencer, jsonPayload.state="STATE_STARTED"
et jsonPayload.affectedResources
ne seront pas présents.
Contraintes et limites
Cette section présente les contraintes et les limites pour FHIR R4, mais les mêmes contraintes et limites s'appliquent à FHIR STU3.
Type | Contraintes et limites |
---|---|
Ressource de consentement unique |
|
Modèle d'application |
|
X-Consent-Scope |
|
Méthodes acceptées |
|
Performances |
|
Bonnes pratiques
Les sections suivantes décrivent les meilleures pratiques lors de l'utilisation du contrôle des accès FHIR.
Bonnes pratiques générales
N'import de ressources FHIR et appelez
ApplyConsents
ouApplyAdminConsents
en parallèle. Nous vous recommandons d'importer d'abord les ressources FHIR, puis d'appelerApplyConsents
ouApplyAdminConsents
. Toutefois, si les ressources à importer n'incluent aucune ressource de patient ou de consentement, le modèle d'application ne sera pas affecté et le traitement des autorisations ou des règles d'administration n'est pas nécessaire.Ne créez pas de recherches personnalisées et n'appelez
ApplyConsents
en parallèle. Nous vous recommandons de le faire l'un après l'autre.Si vos workflows nécessitent l'appel de plusieurs
ApplyConsents
sur desPatientScope
disjoints, vous pouvez les appeler en parallèle.ApplyAdminConsents
peut s'exécuter en parallèle avec n'importe quel nombre d'ApplyConsents
, mais pas avec un autreApplyAdminConsents
.Lors de la configuration du proxy, limitez le compte de service IAM à des autorisations en lecture seule pour éviter d'écrire les données d'un patient dans les dossiers d'un autre patient.
N'utilisez pas le proxy de consentement lorsque vous créez ou mettez à jour des enregistrements.
Validez toutes les requêtes d'écriture pour éviter toute modification croisée de données patient.
Lorsque les autorisations en cascade sont appliquées, les ressources de base par compartiment doivent d'abord être importées, suivies des ressources de compartiment restantes. Toutes les ressources du compartiment peuvent également être encapsulées dans un seul bundle et ingérées à l'aide de
fhir.executeBundle
.
Supprimer la ressource Patient
Lorsque vous supprimez une ressource Patient, si vous souhaitez également supprimer l'application des autorisations pour ce patient (en particulier lorsque FhirStore.disableReferentialIntegrity
est défini sur "true"), nous vous recommandons de suivre l'ordre des étapes suivantes :
Supprimez toutes les ressources d'autorisation appartenant à la ressource Patient.
Appelez
ApplyConsents
avec le filtrePatientScope
.
Configurer un magasin existant pour l'accès au consentement
Pour configurer un magasin existant pour l'accès au consentement, procédez comme suit:
Utiliser
UpdateFhirStore
pour définir leConsentConfig
avec l'application des autorisationsversion
en tant queV1
et définiraccessEnforced
surtrue
.curl -X PATCH \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "Content-Type: application/json" \ --data "{ 'consentConfig': { 'version': 'V1', 'accessEnforced': true } }" "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID?update_mask=consentConfig"
Traiter les autorisations des patients ou les règles d'administration
ApplyConsents
pour l'autorisation des patients
curl -X POST \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "Content-Type: application/json" \ --data "{'validateOnly': false}" \ "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:applyConsents"
ApplyAdminConsents
pour les règles d'administration et les règles d'administration en cascade.
curl -X POST \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "Content-Type: application/json" \ --data "{ 'newConsentsList': { 'names': [ 'projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Consent/RESOURCE_ID_1/_history/VERSION_ID_1', ... 'projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/Consent/RESOURCE_ID_N/_history/VERSION_ID_N' ] }, 'validateOnly': false }" \ "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:applyAdminConsents"
Fréquence d'exécution de "ApplyConsents" ou "ApplyAdminConsents"
Lorsque le champ
ConsentConfig
n'est plus défini, le champConsentConfig
n'est pas défini lors de la création d'un magasin FHIR ni lors de l'effacement du champConsentConfig
. Une fois que le champConsentConfig
n'est plus défini, vous devez répéter la configuration du magasin pour l'accès aux autorisations avant d'effectuer des requêtes compatibles avec les autorisations pour éviter d'évaluer des règles d'application des autorisations obsolètes.Le modèle d'application change: lorsqu'une ressource d'autorisation est créée, mise à jour ou supprimée, le modèle d'application change. Dans ce cas, vous devez appeler
ApplyConsents
ouApplyAdminConsents
pour que ces modifications soient prises en compte.Si vous souhaitez effectuer un suivi des patients dont les autorisations ont été modifiées, nous vous recommandons d'utiliser le filtre
PatientScope
pour éviter de relancer le traitement sur l'ensemble du magasin. Ce filtre est utile pour actualiser immédiatement l'application d'un petit groupe de patients.Vous pouvez également exécuter régulièrement
ApplyConsents
à l'aide du filtreTimeRange
. Ce filtre est utile lorsqu'il n'est pas nécessaire d'actualiser immédiatement la page. Par exemple, la requête suivante actualise l'application des modifications du consentement entre UTC 0AM 2022-09-20 et UTC 0AM 2022-09-21.curl -X POST \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "Content-Type: application/json" \ --data "{ 'validateOnly': false, 'timeRange': { 'start': '2022-09-20T00:00:00Z', 'end': '2022-09-21T00:00:00Z', } }" \ "https://healthcare.googleapis.com/v1beta1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:applyConsents"