From 5eb0dc2adc658163ea7a3ccf37e5ac2a632914c0 Mon Sep 17 00:00:00 2001 From: Lee Surprenant Date: Wed, 18 Dec 2019 23:35:41 -0500 Subject: [PATCH] issue #518 - remove audit db from default config Its simply not used any more, so its silly to keep creating it. I also removed the `resourceName` concept from both the Audit Context object and also the FHIRConfiguration config props. In the future, I'd also like to remove the undocumented `fhirServer/audit/patientIdExtensionUrl` config property, but that one wasn't quite as clean to remove right now...we need to think through whether/how to include the data subject (e.g. Patient) identifier in the audit log in a more FHIR-native way. Finally, I included some unrelated minor updates to the `fhir-persistence-schema` README.md; now the examples all use the `default` tenant...this is the simplest option because otherwise everyone needs to understand our tenancy model just to get something working on Db2. Signed-off-by: Lee Surprenant --- .../ibm/fhir/audit/logging/beans/Context.java | 23 ---------- .../beans/impl/context/FHIRContext.java | 15 ------- .../fhir/audit/cadf/test/AuditBeansTest.java | 12 ------ .../ibm/fhir/config/FHIRConfiguration.java | 3 +- fhir-persistence-schema/README.md | 25 +++++++---- .../config/default/fhir-server-config.json | 42 ++++--------------- .../ibm/fhir/server/util/RestAuditLogger.java | 5 --- 7 files changed, 26 insertions(+), 99 deletions(-) diff --git a/fhir-audit/src/main/java/com/ibm/fhir/audit/logging/beans/Context.java b/fhir-audit/src/main/java/com/ibm/fhir/audit/logging/beans/Context.java index 5684eefc706..e42505f8cf4 100644 --- a/fhir-audit/src/main/java/com/ibm/fhir/audit/logging/beans/Context.java +++ b/fhir-audit/src/main/java/com/ibm/fhir/audit/logging/beans/Context.java @@ -138,14 +138,6 @@ public void setRequestUniqueId(String requestUniqueId) { this.requestUniqueId = requestUniqueId; } - public String getResourceName() { - return resourceName; - } - - public void setResourceName(String resourceName) { - this.resourceName = resourceName; - } - /** * Generates JSON from this object. */ @@ -191,10 +183,6 @@ public static String generate(Context obj) generator.write("purpose", obj.getPurpose()); } - if (obj.getResourceName() != null) { - generator.write("resource_name", obj.getResourceName()); - } - if (obj.getStartTime() != null) { generator.write("start_time", obj.getStartTime()); } @@ -275,12 +263,6 @@ public static Context parse(InputStream in) builder.purpose(purpose); } - t = jsonObject.get("resource_name"); - if (t != null) { - String resourceName = jsonObject.getString("resource_name"); - builder.resourceName(resourceName); - } - t = jsonObject.get("start_time"); if (t != null) { String startTime = jsonObject.getString("start_time"); @@ -387,11 +369,6 @@ public Builder requestUniqueId(String requestUniqueId) { return this; } - public Builder resourceName(String resourceName) { - context.setResourceName(resourceName); - return this; - } - public Context build() { return context; } diff --git a/fhir-audit/src/main/java/com/ibm/fhir/audit/logging/beans/impl/context/FHIRContext.java b/fhir-audit/src/main/java/com/ibm/fhir/audit/logging/beans/impl/context/FHIRContext.java index 9bc0ab8f94a..6c8d8bd006a 100644 --- a/fhir-audit/src/main/java/com/ibm/fhir/audit/logging/beans/impl/context/FHIRContext.java +++ b/fhir-audit/src/main/java/com/ibm/fhir/audit/logging/beans/impl/context/FHIRContext.java @@ -124,10 +124,6 @@ public static String generate(FHIRContext obj) generator.write("purpose", obj.getPurpose()); } - if (obj.getResourceName() != null) { - generator.write("resource_name", obj.getResourceName()); - } - if (obj.getStartTime() != null) { generator.write("start_time", obj.getStartTime()); } @@ -228,12 +224,6 @@ public static FHIRContext parse(InputStream in) builder.purpose(purpose); } - t = jsonObject.get("resource_name"); - if (t != null) { - String resourceName = jsonObject.getString("resource_name"); - builder.resourceName(resourceName); - } - t = jsonObject.get("start_time"); if (t != null) { String startTime = jsonObject.getString("start_time"); @@ -395,11 +385,6 @@ public FHIRBuilder requestUniqueId(String requestUniqueId) { return this; } - public FHIRBuilder resourceName(String resourceName) { - fhirContext.setResourceName(resourceName); - return this; - } - public FHIRContext build() { return fhirContext; } diff --git a/fhir-audit/src/test/java/com/ibm/fhir/audit/cadf/test/AuditBeansTest.java b/fhir-audit/src/test/java/com/ibm/fhir/audit/cadf/test/AuditBeansTest.java index eee499fe423..04b6d4c485a 100644 --- a/fhir-audit/src/test/java/com/ibm/fhir/audit/cadf/test/AuditBeansTest.java +++ b/fhir-audit/src/test/java/com/ibm/fhir/audit/cadf/test/AuditBeansTest.java @@ -130,7 +130,6 @@ public void testContextEmptyNull() throws FHIRException, IOException { assertNull(ctx.getPurpose()); assertNull(ctx.getQueryParameters()); assertNull(ctx.getRequestUniqueId()); - assertNull(ctx.getResourceName()); assertNull(ctx.getStartTime()); } @@ -175,7 +174,6 @@ public void testContext() throws FHIRException, IOException { builder.purpose("purpose"); builder.queryParameters("queryParameters"); builder.requestUniqueId("requestUniqueId"); - builder.resourceName("test"); builder.startTime("startTime"); Context ctx = builder.build(); @@ -204,9 +202,6 @@ public void testContext() throws FHIRException, IOException { assertNotNull(ctx.getRequestUniqueId()); assertEquals(ctx.getRequestUniqueId(), "requestUniqueId"); - assertNotNull(ctx.getResourceName()); - assertEquals(ctx.getResourceName(), "test"); - assertNotNull(ctx.getStartTime()); assertEquals(ctx.getStartTime(), "startTime"); @@ -236,9 +231,6 @@ public void testContext() throws FHIRException, IOException { assertNotNull(ctx.getRequestUniqueId()); assertEquals(ctx.getRequestUniqueId(), "requestUniqueId"); - assertNotNull(ctx.getResourceName()); - assertEquals(ctx.getResourceName(), "test"); - assertNotNull(ctx.getStartTime()); assertEquals(ctx.getStartTime(), "startTime"); } @@ -349,7 +341,6 @@ public void testFHIRContext() throws IOException, FHIRException { builder.purpose("purpose"); builder.queryParameters("queryParameters"); builder.requestUniqueId("requestUniqueId"); - builder.resourceName("test"); builder.startTime("startTime"); builder.clientCertCn("clientCertCn"); @@ -386,9 +377,6 @@ public void testFHIRContext() throws IOException, FHIRException { assertNotNull(fhirCtx.getRequestUniqueId()); assertEquals(fhirCtx.getRequestUniqueId(), "requestUniqueId"); - assertNotNull(fhirCtx.getResourceName()); - assertEquals(fhirCtx.getResourceName(), "test"); - assertNotNull(fhirCtx.getStartTime()); assertEquals(fhirCtx.getStartTime(), "startTime"); diff --git a/fhir-config/src/main/java/com/ibm/fhir/config/FHIRConfiguration.java b/fhir-config/src/main/java/com/ibm/fhir/config/FHIRConfiguration.java index 7e653d6da99..42fab83473c 100644 --- a/fhir-config/src/main/java/com/ibm/fhir/config/FHIRConfiguration.java +++ b/fhir-config/src/main/java/com/ibm/fhir/config/FHIRConfiguration.java @@ -48,8 +48,6 @@ public class FHIRConfiguration { public static final String PROPERTY_AUDIT_SERVICE_CLASS_NAME = "fhirServer/audit/serviceClassName"; public static final String PROPERTY_AUDIT_SERVICE_PROPERTIES = "fhirServer/audit/serviceProperties"; public static final String PROPERTY_AUDIT_PATIENT_ID_EXTURL = "fhirServer/audit/patientIdExtensionUrl"; - public static final String PROPERTY_AUDIT_RESOURCE_NAME_EXTURL = "fhirServer/audit/resourceNameExtensionUrl"; - public static final String PROPERTY_UPDATE_CREATE_ENABLED = "fhirServer/persistence/common/updateCreateEnabled"; // Notification config properties public static final String PROPERTY_NOTIFICATION_RESOURCE_TYPES = "fhirServer/notifications/common/includeResourceTypes"; @@ -59,6 +57,7 @@ public class FHIRConfiguration { public static final String PROPERTY_KAFKA_CONNECTIONPROPS = "fhirServer/notifications/kafka/connectionProperties"; // Persistence layer properties + public static final String PROPERTY_UPDATE_CREATE_ENABLED = "fhirServer/persistence/common/updateCreateEnabled"; public static final String PROPERTY_PERSISTENCE_FACTORY = "fhirServer/persistence/factoryClassname"; public static final String PROPERTY_DATASOURCES = "fhirServer/persistence/datasources"; public static final String PROPERTY_JDBC_BOOTSTRAP_DB = "fhirServer/persistence/jdbc/bootstrapDb"; diff --git a/fhir-persistence-schema/README.md b/fhir-persistence-schema/README.md index a0141efde04..b74202ef9c7 100644 --- a/fhir-persistence-schema/README.md +++ b/fhir-persistence-schema/README.md @@ -58,28 +58,33 @@ The following sections include common values for `OPTIONS`: --update-schema ``` -## Add a new tenant (e.g. tenant1) - -Don't forget to copy the tenant-key secret generated by --allocate-tenant. This key must be added to the datasource configuration to authorize the FHIR server to access this tenant. +## Grant privileges to data access user ``` --prop-file fhir.properties --schema-name FHIRDATA ---allocate-tenant tenant1 +--grant-to FHIRSERVER ``` +## Add a new tenant (e.g. default) -## Grant privileges to data access user +Don't forget to copy the tenant-key secret generated by --allocate-tenant. This key must be added to the datasource configuration to authorize the FHIR server to access this tenant. ``` --prop-file fhir.properties --schema-name FHIRDATA ---grant-to FHIRSERVER +--allocate-tenant default ``` +Note: for tenant names other than `default`, the server must determine the tenant id to use for each request. +By default, we get the tenant id from the `X-FHIR-TENANT-ID` header, but to trust this value requires a well-planned approach to security. +Once the server has determined the tenant id for a given request, it uses this to look up the tenantKey and the two are +used in conjunction to create or retrieve data for this tenant. +For more information on multi-tenancy, see section [4.9 Multi-tenancy of the IBM FHIR Server Users Guide](https://ibm.github.io/FHIR/guides/FHIRServerUsersGuide#49-multi-tenancy). + ## Configure tenant-key (example) -Edit `wlp/usr/servers/fhir-server/config/tenant1/fhir-server-config.json` and add the tenant-key captured from the add-tenant step above: +Edit `wlp/usr/servers/fhir-server/config/default/fhir-server-config.json` and add the tenant-key captured from the add-tenant step above: ``` "default": { @@ -101,12 +106,13 @@ Edit `wlp/usr/servers/fhir-server/config/tenant1/fhir-server-config.json` and ad } ``` + ## Test a tenant ``` --prop-file fhir-apikey.properties --schema-name FHIRDATA ---test-tenant TNT1 +--test-tenant default --tenant-key "" ``` @@ -118,9 +124,10 @@ Edit `wlp/usr/servers/fhir-server/config/tenant1/fhir-server-config.json` and ad --update-proc ``` -# Alternative: manually apply the schema changes +# Alternative: manually apply the schema To manually apply the DDL to a Db2 instance: + 1. Print the schema to files by executing the SchemaPrinter: `java -cp ./fhir-database-utils.jar:fhir-persistence-schema.jar com.ibm.fhir.schema.app.SchemaPrinter --to-file` diff --git a/fhir-server/liberty-config/config/default/fhir-server-config.json b/fhir-server/liberty-config/config/default/fhir-server-config.json index 2d4374fd988..7f70f302020 100644 --- a/fhir-server/liberty-config/config/default/fhir-server-config.json +++ b/fhir-server/liberty-config/config/default/fhir-server-config.json @@ -66,6 +66,15 @@ "__comment": "Configuration properties common to all persistence layer implementations", "updateCreateEnabled": true }, + "jdbc": { + "__comment": "Configuration properties for the JDBC persistence implementation", + "bootstrapDb": true, + "__comment": "Use jdbc/fhirProxyDataSource to use the proxy datasource.", + "dataSourceJndiName": "jdbc/fhirProxyDataSource", + "enableCodeSystemsCache": true, + "enableParameterNamesCache": true, + "enableResourceTypesCache": true + }, "datasources": { "default": { "type": "derby", @@ -88,40 +97,7 @@ "sslTrustStoreLocation": "resources/security/fhirTruststore.jks", "sslTrustStorePassword": "change-password" } - }, - "audit": { - "type": "derby", - "connectionProperties": { - "databaseName": "derby/auditDB", - "createDatabase": "create" - } - }, - "_db2_audit": { - "type": "db2", - "connectionProperties": { - "serverName": "localhost", - "portNumber": 50001, - "user": "db2inst1", - "password": "change-password", - "databaseName": "AUDITDB", - "currentSchema": "AUDIT1", - "driverType": 4, - "sslConnection": true, - "sslTrustStoreLocation": "resources/security/fhirTruststore.jks", - "sslTrustStorePassword": "change-password" - } } - }, - "jdbc": { - "__comment": "Configuration properties for the JDBC persistence implementation, Use jdbc/fhirProxyDataSource to use the proxy datasource.", - "bootstrapDb": true, - "dataSourceJndiName": "jdbc/fhirProxyDataSource", - "enableCodeSystemsCache": true, - "enableParameterNamesCache": true, - "enableResourceTypesCache": true - }, - "audit": { - "bootstrapDb": true } } } diff --git a/fhir-server/src/main/java/com/ibm/fhir/server/util/RestAuditLogger.java b/fhir-server/src/main/java/com/ibm/fhir/server/util/RestAuditLogger.java index 140c0c470e3..d45396c34a2 100644 --- a/fhir-server/src/main/java/com/ibm/fhir/server/util/RestAuditLogger.java +++ b/fhir-server/src/main/java/com/ibm/fhir/server/util/RestAuditLogger.java @@ -46,8 +46,6 @@ /** * This class provides convenience methods for FHIR Rest services that need to write FHIR audit log entries. - * @author markd - * */ public class RestAuditLogger { @@ -462,7 +460,6 @@ private static AuditLogEntry populateAuditLogEntry(AuditLogEntry entry, HttpServ StringBuffer requestUrl; String patientIdExtUrl; - String resourceNameExtUrl; List userList = new ArrayList<>(); // Build a list of possible user names. Pick the first non-null user name to include in the audit log entry. @@ -512,8 +509,6 @@ private static AuditLogEntry populateAuditLogEntry(AuditLogEntry entry, HttpServ patientIdExtUrl = FHIRConfigHelper.getStringProperty(FHIRConfiguration.PROPERTY_AUDIT_PATIENT_ID_EXTURL, null); entry.setPatientId(FHIRUtil.getExtensionStringValue(resource, patientIdExtUrl)); - resourceNameExtUrl = FHIRConfigHelper.getStringProperty(FHIRConfiguration.PROPERTY_AUDIT_RESOURCE_NAME_EXTURL, null); - entry.getContext().setResourceName((FHIRUtil.getExtensionStringValue(resource, resourceNameExtUrl))); entry.getContext().setRequestUniqueId(FHIRRequestContext.get().getRequestUniqueId()); log.exiting(CLASSNAME, METHODNAME);