Cette page explique comment utiliser les ressources de consentement FHIR pour déterminer l'accès aux données des magasins FHIR dans l'API Cloud Healthcare.
Configurer un magasin FHIR avec contrôle des accès
Pour configurer un datastore FHIR avec application du consentement, procédez comme suit:
Créez un magasin FHIR si vous n'en avez pas.
Définissez les paramètres
ConsentConfig
suivants du magasin FHIR pour activer l'application du consentement:version
: spécifie la version d'application de l'autorisation utilisée pour le magasin FHIR. Cette valeur ne peut être définie qu'une seule fois parCreateFhirStore
ouUpdateFhirStore
. Une fois la version définie, vous devez appelerApplyConsents
ouApplyAdminConsents
pour la modifier.access_enforced
: si la valeur esttrue
, lors de l'accès aux ressources FHIR, les en-têtes d'autorisation fournis sont vérifiés par rapport aux instructions d'autorisation fournies par les clients.consent_header_handling
: si la valeur estPERMIT_EMPTY_SCOPE
(par défaut), le serveur autorise les requêtes sans en-têteX-Consent-Scope
(ou vide). Si la valeur estREQUIRED_ON_READ
et queaccess_enforced
=true
, le serveur rejette toutes les requêtes sans en-têteX-Consent-Scope
(ou vide).
Configurer un nouveau magasin 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 disposez déjà d'un magasin, utilisez UpdateFhirStore
pour définir le ConsentConfig
avec l'application des autorisations version
en tant que V1
et définir 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 règles à l'aide d'une ressource de consentement
Les règles sont représentées par une ressource de consentement. L'objectif et l'utilisation des champs de ressources sont décrits dans la documentation du modèle de données.
Voici un exemple de toutes les ressources pouvant être créées pour cet exemple particulier.
Créer des ressources FHIR
L'exemple suivant montre comment exécuter un [groupe FHIR](/healthcare-api/docs/how-tos/fhir-bundles) pour renseigner les ressources suivantes:
- Une ressource de type Professionnel portant le nom Jeffrey Brown
- Une ressource de type Patient portant le nom Darcy Smith
- Une ressource de type Observation montrant la mesure de l'hémoglobine de Darcy (LOINC
718-7
) collectée par l'établissement Happy Hospital - Une ressource de type Observation montrant la mesure du glucose de Darcy (LOINC
15074-8
). - Consentement de Darcy pour autoriser Jeffrey Brown à utiliser l'application
App/123
pour accéder à ses données collectées par l'établissement Happy Hospital - Consentement de Darcy pour autoriser Jeffrey Brown à accéder à toutes ses données à des fins de traitement d'urgence (
ETREAT
) - Consentement de l'hôpital Happy Hospital pour autoriser Jeffrey Brown à accéder à toutes les données lors de recherches biomédicales (
BIORCH
) avec l'applicationApp/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 ressources de consentement R4 qui montrent comment les règles complexes peuvent être représentées.
Exemple d'instruction de consentement du patient
{ "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 de patient dans laquelle un patient f001
autorise un praticien f002
à lui fournir un traitement régulier représenté par TREAT
.
Le professionnel se trouve dans la zone géographique iso3166-1/CA
. Cette ressource de consentement autorise le professionnel de santé à accéder aux données du patient si les données répondent à toutes les conditions suivantes.
- Il s'agit d'un type
Encounter
avec l'IDEncounter/e001
. - Il provient de la source
http://somesystem.example.org/foo
. - Elle remplit au moins l'une des conditions suivantes sur le tag (les ressources peuvent être taguées en définissant les champs
system
etcode
de Meta.tag): - Contient la balise (
system
=http://terminology.hl7.org/CodeSystem/common-tags
etcode
=actionable
) - Possède les deux balises (
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
correspond àR
,N
,M
,L
ouU
.system
=http://terminology.hl7.org/CodeSystem/v3-ActCode
etcode
=PSY
.
Exemple de directive de stratégie 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 de stratégie d'administration qui autorise un praticien f002
à fournir un traitement régulier représenté par TREAT
. Le professionnel se trouve dans la zone géographique iso3166-1/CA
. Cette ressource de consentement permet au professionnel de santé d'accéder aux données du patient si elles remplissent toutes les conditions suivantes:
- Il s'agit d'un type
Encounter
avec l'IDEncounter/e001
. - Il provient de la source
http://somesystem.example.org/foo
. - Elle remplit au moins l'une des conditions suivantes sur le tag:
- Contient la balise (
system
=http://terminology.hl7.org/CodeSystem/common-tags
etcode
=actionable
) - Possède les deux balises (
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
correspond àR
,N
,M
,L
ouU
.system
=http://terminology.hl7.org/CodeSystem/v3-ActCode
etcode
=PSY
.
Exemple de directive de stratégie en cascade pour les administrateurs
{ "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 de stratégie en cascade d'administrateur qui autorise un praticien f002
à fournir un traitement régulier représenté par TREAT
. Le professionnel se trouve dans la zone géographique iso3166-1/CA
. Cette ressource de consentement permet au professionnel de santé d'accéder aux données de compartiment des patients avec le tag employee
. Tous les critères de ressources ne s'appliquent qu'aux ressources de base du compartiment, c'est-à-dire à la ressource Patient, car elle contrôle les ressources à partir desquelles la cascade doit être effectuée.
Appliquer les consentements des patients ou les règles des administrateurs
Appliquer les consentements du patient d'ici 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 "get" de l'opération](/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 avec 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 consentements et mis à jour l'accès consensuel de cinq ressources (un patient, deux consentements et deux observations).
Appliquer la stratégie d'administration par 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 "get" de l'opération](/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 avec 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 stratégie d'administration et mis à jour l'accès consensuel de sept ressources (un professionnel de santé, un patient, deux observations, deux consentements de patient et une stratégie d'administration).
L'application des autorisations stockées dans un magasin FHIR n'entrera en vigueur que lorsque ApplyConsents
(pour les autorisations des patients) ou ApplyAdminConsents
(pour les règles d'administration et les règles en cascade d'administration) sera appelé et terminé. Si vous ajoutez, modifiez ou supprimez des consentements 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 s'écouler quelques instants 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 des autorisations sur le dépôt FHIR pour la première fois, attendez la fin de l'opération de longue durée ApplyConsents
ou ApplyAdminConsents
avant d'effectuer des requêtes compatibles avec les autorisations.
Pour appeler ApplyConsents
sur un sous-ensemble de patients, vous pouvez utiliser les filtres suivants:
PatientScope
: pour exécuterApplyConsents
sur une liste d'ID de patient comportant jusqu'à 10 000 patientsTimeRange
: pour exécuterApplyConsent
sur une liste d'ID de ressources Patient dont les ressources d'autorisation sont mises à jour pendant 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, une liste vide annule l'application de toutes les règles d'administration du Play Store. 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 le ProgressCounter
de l'opération. Une fois l'opération terminée, un ApplyConsentsResponse est inclus dans Operation.response
.
Les compteurs dans ProgressCounter
et ApplyConsentsResponse
ou ApplyAdminConsentsResponse
sont décrits dans le tableau suivant.
ProgressCounter |
ApplyConsentsResponse ou ApplyAdminConsentsResponse |
Description |
---|---|---|
success |
consentApplySuccess |
Nombre de ressources de consentement traitées avec succès par l'opération. |
failure |
consentApplyFailure |
Nombre de ressources d'autorisation 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 des autorisations à l'aide de CheckConsentEnforcementStatus ou CheckPatientConsentEnforcementStatus pour récupérer les informations relatives aux erreurs. |
secondarySuccess |
affectedResources |
Lorsque validateOnly est false , il représente le nombre de ressources FHIR qui ont été réindexées en raison de l'effet du changement de consentement. |
secondaryFailure |
failedResources |
Lorsque validateOnly est false , il représente le nombre de ressources FHIR dont l'autorisation a peut-être changé, mais qui n'ont pas été réindexées. Cela peut avoir un impact sur la recherche avec le contexte de consentement, mais pas sur les 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 de l'application d'un seul consentement 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 l'autorisation a été appliquée pour la dernière fois.versionId
: représente l'ID de version utilisé pour l'application de l'autorisation.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 les règles d'administration, CheckConsentEnforcementStatus
ne peut être utilisé que pour vérifier l'état d'application d'une seule règle d'administration de consentement. Vous pouvez également utiliser fhirStores.get
pour afficher toutes les règles d'administration actives appliquées au magasin.
État de l'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 d'autorisation dans laquelle la ressource d'autorisation 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 d'autorisation qui peut être conforme aux spécifications FHIR, mais qui ne peut pas être appliqué. Cela est dû à l'implémentation limitée de l'application du consentement FHIR avec le niveau actuel de prise en charge des fonctionnalités.ENFORCEMENT_LIMIT_EXCEEDED
: état lorsque le format de la ressource d'autorisation FHIR et le niveau de prise en charge de la ressource sont exempts d'erreurs, mais qu'une ou plusieurs des conditions suivantes sont vraies: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 permet de rechercher des ressources FHIR dans un magasin FHIR donné avec les paramètres actor
, purpose
et environment
. La réponse ne contient que les ressources pour lesquelles l'utilisateur a donné son consentement.
Rechercher des ressources FHIR avec un champ d'application d'autorisation
- Le professionnel 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 médecin Jeffrey Brown (identifié par
Practitioner/12942879-f89f-41ae-aa80-0b911b649833
) à l'aide de l'applicationApp/123
recherche toutes les observations du patient Darcy. - Le médecin 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 médecin Jeffrey Brown (identifié par
Practitioner/12942879-f89f-41ae-aa80-0b911b649833
) effectue des recherches sur les observations avecstatus=final
avec deux objectifs : le traitement et la recherche - Un 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 en chaîne. Comme le scénario d'autorisation actor/Practitioner/12942879-f89f-41ae-aa80-0b911b649833 env/App/123
consiste en l'accès refusé à la ressource du patient Darcy (identifié 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 la requête "X-Consent-Scope".
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?"
Étant donné que 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 le contexte d'autorisation
L'API Cloud Healthcare permet d'obtenir une ressource FHIR dans un magasin FHIR donné avec les paramètres actor
, purpose
et environment
comme paramètres de requête. La réponse ne contient que les ressources pour lesquelles l'utilisateur a donné son consentement.
Obtenir des ressources FHIR avec un champ d'application d'autorisation
- Le professionnel 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 professionnel 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 professionnel de santé Jeffrey Brown (identifié par
Practitioner/12942879-f89f-41ae-aa80-0b911b649833
) qui mène 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 médecin Jeffrey Brown (identifié par
Practitioner/12942879-f89f-41ae-aa80-0b911b649833
) demande un accès non autorisé d'urgence au dossier d'un patient, à l'aide du protocole "briser la 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 l'auteur de la requête a reçu l'autorisation, la réponse correspond au contenu de la ressource d'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 de l'émetteur de la requête (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"
Étant donné que l'auteur de la requête a reçu l'autorisation, 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"
Étant donné que la méthode d'autorisation du consentement est btg
, le serveur ignore les vérifications du 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 } }
Configurer l'en-tête de consentement
Les sections suivantes décrivent les méthodes d'application du consentement prises en charge par l'API Cloud Healthcare, ainsi que la façon dont l'accès aux ressources est appliqué lorsque vous effectuez une requête tenant compte du consentement.
Lors d'une requête, votre serveur d'autorisation est chargé de générer des jetons d'accès avec le champ d'application de l'autorisation approprié.
Définir l'en-tête HTTP
Les champs d'application du 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 approuvées
Cette section n'est obligatoire que si vous utilisez un serveur d'autorisation contrôlé par le client. Dans ce cas, vous devez également utiliser un proxy 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 le consentement direct sans avoir besoin d'un proxy SMART ou d'un autre proxy pour effectuer la conversion entre les 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 approuvés peuvent également utiliser les entrées de portée 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 fournit une prise en charge intégrée de l'application du consentement FHIR en fonction des champs d'application du consentement d'entrée. Il incombe aux administrateurs du magasin FHIR de créer et de configurer un serveur d'autorisation en dehors de l'API Cloud Healthcare qui accorde des champs d'application d'autorisation.
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 tenant compte du consentement.
Autorise l'implémentation de FHIR dans l'API Cloud Healthcare à inclure des jetons d'accès tenant compte du consentement dans le modèle de gestion et d'autorisation 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 à partir de l'API Cloud Healthcare via SMARTProxy, ce qui suit 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 section Contrôler l'accès aux ressources de l'API Cloud Healthcare. Pour configurer un proxy, consultez les bonnes pratiques générales.
Journaux d'audit Cloud
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 requête d'accès ou de modification de l'application des règles d'accès des ressources.
Accéder aux journaux d'audit
Si les journaux d'audit sont activés sur le dépôt 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
:consentConfig.accessEnforced
est défini surfalse
pour la configuration du magasin FHIR et les requêtes tenant compte du consentement ne sont pas autorisées.emptyScope
:consentConfig.accessEnforced
est défini surtrue
pour le magasin FHIR, mais aucun en-tête de champ d'application d'autorisation n'a été inclus. Par conséquent, les consentements n'ont pas été appliqués.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. En conséquence, les autorisations ont été évaluées et appliquées à la demande.btg
:btg
a été fourni dans l'en-tête du champ d'application d'autorisation de 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 examinée qu'après l'audit.bypass
: la requête FHIR ne contenait quebypass
dans l'en-tête du champ d'application d'autorisation. Par conséquent, les vérifications du consentement ont été ignorées. Cette requête est destinée à être utilisée par un workflow approuvé (par exemple, un administrateur ou une application approuvée au lieu des utilisateurs finaux) afin que ce journal des audits soit différent debtg
, qui est utilisé pour les vérifications de gouvernance des données.
Vous pouvez également définir access_determination_log_config
sur VERBOSE
pour enregistrer plus d'informations sur les raisons pour lesquelles une requête est accordée ou refusée.
Journaux d'audit des modifications d'application des règles d'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 sur la ressource modifiée et son compartiment peut changer en raison de la stratégie de cascade d'administration. Cela déclenchera une réindexation de toutes ses ressources de compartiment. La progression de l'indexation pour chaque mise à jour de la ressource de base du 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 l'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
à l'horodatage de la mise à jour de la ressource patient. Si l'opération vient de commencer, jsonPayload.state="STATE_STARTED"
et jsonPayload.affectedResources
ne sont pas présents.
Contraintes et limites
Cette section présente les contraintes et les limites de 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 |
|
Performance |
|
Bonnes pratiques
Les sections suivantes décrivent les bonnes pratiques à suivre lorsque vous utilisez le contrôle des accès FHIR.
Bonnes pratiques générales
N'import pas de ressources FHIR et n'appelez pas
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 d'autorisation, le modèle d'application ne sera pas affecté et le traitement des autorisations ou des règles d'administration ne sera pas nécessaire.N'créez pas de recherches personnalisées et n'appelez pas
ApplyConsents
en parallèle. Nous vous recommandons de le faire l'un après l'autre.Si vos workflows nécessitent d'appeler plusieurs
ApplyConsents
sur desPatientScope
disjoints, ils peuvent être appelés en parallèle.ApplyAdminConsents
peut s'exécuter en parallèle avec un nombre illimité deApplyConsents
, mais pas avec un autreApplyAdminConsents
.Lorsque vous configurez le proxy, limitez le compte de service IAM avec des autorisations en lecture seule pour éviter d'écrire les données d'un patient dans les dossiers d'un autre.
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 consentements en cascade sont appliqués, les ressources de base du compartiment doivent d'abord être importées, puis les autres ressources du compartiment. Vous pouvez également encapsuler toutes les ressources de compartiment dans un seul groupe et les ingérer à 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 aux autorisations
Pour configurer un datastore existant pour l'accès aux autorisations, 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 consentements des patients ou les règles des administrateurs
ApplyConsents
pour les autorisations 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 en cascade d'administration.
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 la fonction 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 ensemble de patients.Vous pouvez également exécuter
ApplyConsents
périodiquement à l'aide du filtreTimeRange
. Ce filtre est utile lorsque la mise à jour immédiate n'est pas essentielle. Par exemple, la requête suivante actualise l'application des modifications d'autorisation entre le 20 et le 21 septembre 2022 (UTC 0AM).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"
Utiliser la vue des autorisations FHIR
Le lecteur de consentement FHIR affiche les stratégies de contrôle des accès. Il fournit un tableau contenant des champs d'application du consentement pour représenter les règles de contrôle des accès FHIR.
Avant de pouvoir utiliser l'outil de visualisation du consentement FHIR, assurez-vous que:
Le paramètre
disableResourceVersioning
du store FHIR doit êtrefalse
. Ce paramètre ne peut plus être modifié une fois le store FHIR créé. Pour créer un magasin FHIR, consultez la section Créer un magasin FHIR.Le store FHIR est configuré pour l'application du consentement.
Pour afficher le Visionneuse de consentement FHIR, procédez comme suit:
Console
Dans la console Google Cloud, accédez à la page Navigateur.
Sélectionnez l'ensemble de données contenant le magasin FHIR dont vous souhaitez afficher les règles d'autorisation appliquées.
Sur la page Datastores (Datastores), dans la liste Datastores (Datastores), sélectionnez le magasin FHIR dont vous souhaitez afficher les stratégies d'autorisation appliquées.
Sur la page Informations sur le data store, cliquez sur l'onglet Consentement. Les champs d'application du consentement s'affichent.