diff --git a/.gitignore b/.gitignore index 2c4dab1fde2..5644f0046d9 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,9 @@ *.iml .idea/ +# VS Code +.vscode/ + # Mac OS X .DS_Store diff --git a/fhir-parent/pom.xml b/fhir-parent/pom.xml index 18f412a95bc..1fc749c2e0f 100644 --- a/fhir-parent/pom.xml +++ b/fhir-parent/pom.xml @@ -756,6 +756,11 @@ + + io.openliberty.tools + liberty-maven-plugin + 3.4.0 + com.spotify dockerfile-maven-plugin diff --git a/fhir-server-webapp/pom.xml b/fhir-server-webapp/pom.xml index d37e9d4c3ee..f0a2ced5ce6 100644 --- a/fhir-server-webapp/pom.xml +++ b/fhir-server-webapp/pom.xml @@ -87,9 +87,16 @@ jakarta.servlet-api provided + + org.apache.derby + derby + ${derby.version} + test + + ${fhir.server.war.name} maven-war-plugin @@ -97,6 +104,35 @@ ${fhir.server.war.name} + + io.openliberty.tools + liberty-maven-plugin + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.2 + + + copy-derby-dependency + package + + copy-dependencies + + + derby + ${project.build.directory}/liberty/wlp/usr/shared/lib/derby/ + + + + diff --git a/fhir-server-webapp/src/main/liberty/config/config/default/extension-search-parameters.json b/fhir-server-webapp/src/main/liberty/config/config/default/extension-search-parameters.json new file mode 100644 index 00000000000..23e3adda7db --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/config/default/extension-search-parameters.json @@ -0,0 +1,9 @@ +{ + "resourceType": "Bundle", + "id": "searchParams", + "meta": { + "lastUpdated": "2018-12-27T22:37:54.724+11:00" + }, + "type": "collection", + "entry": [] +} diff --git a/fhir-server-webapp/src/main/liberty/config/config/default/extension-search-parameters.md b/fhir-server-webapp/src/main/liberty/config/config/default/extension-search-parameters.md new file mode 100644 index 00000000000..5c06f076d93 --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/config/default/extension-search-parameters.md @@ -0,0 +1,52 @@ +Modify the Bundle to add your Search Parameter definitions. + +An example as follows: + +{ + "resourceType": "Bundle", + "id": "searchParams", + "meta": { + "lastUpdated": "2019-07-12T22:37:54.724+11:00" + }, + "type": "collection", + "entry": [{ + "fullUrl": "http://ibm.com/fhir/SearchParameter/Patient-favorite-color", + "resource": { + "resourceType": "SearchParameter", + "id": "Patient-favorite-color", + "url": "http://ibm.com/fhir/SearchParameter/Patient-favorite-color", + "version": "4.0.0", + "name": "favorite-color", + "status": "draft", + "experimental": false, + "date": "2018-12-27T22:37:54+11:00", + "publisher": "IBM FHIR Server Test", + "contact": [{ + "telecom": [{ + "system": "url", + "value": "http://ibm.com/fhir" + }] + }, + { + "telecom": [{ + "system": "url", + "value": "http://ibm.com/fhir" + }] + }], + "description": "the patient's favorite color", + "code": "favorite-color", + "base": ["Patient"], + "type": "string", + "xpathUsage": "normal", + "xpath": "f:Patient/f:extension[@url='http://ibm.com/fhir/extension/Patient/favorite-color']/f:valueString", + "expression": "Patient.extension.where(url='http://ibm.com/fhir/extension/Patient/favorite-color').valueString", + "multipleOr": true, + "multipleAnd": true, + "modifier": [] + } + }] +} + + + +FHIR® is the registered trademark of HL7 and is used with the permission of HL7. \ No newline at end of file diff --git a/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config-audit-cicd.json b/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config-audit-cicd.json new file mode 100644 index 00000000000..45a2485bb3e --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config-audit-cicd.json @@ -0,0 +1,146 @@ +{ + "__comment": "FHIR Server configuration", + "fhirServer": { + "core": { + "tenantIdHeaderName": "X-FHIR-TENANT-ID", + "datastoreIdHeaderName": "X-FHIR-DSID", + "checkReferenceTypes": true, + "conditionalDeleteMaxNumber": 10, + "serverRegistryResourceProviderEnabled": true, + "disabledOperations": "" + }, + "security": { + "cors": true, + "basic": { + "enabled": true + }, + "certificates": { + "enabled": true + }, + "oauth": { + "enabled": false, + "regUrl": "https://:9443/oauth2/endpoint/oauth2-provider/registration", + "authUrl": "https://:9443/oauth2/endpoint/oauth2-provider/authorize", + "tokenUrl": "https://:9443/oauth2/endpoint/oauth2-provider/token", + "smart": { + "enabled": false, + "scopes": ["openid", + "profile", + "fhirUser", + "launch/patient", + "patient/*.*", + "offline_access"], + "capabilities": ["sso-openid-connect", + "launch-standalone", + "client-public", + "client-confidential-symmetric", + "permission-offline", + "context-standalone-patient", + "permission-patient"] + } + } + }, + "notifications": { + "common": { + "__comment_includeResourceTypes": ["QuestionnaireResponse", + "CarePlan", + "MedicationAdministration", + "Device", + "DeviceComponent", + "DeviceMetric", + "MedicationOrder", + "Observation"] + }, + "websocket": { + "__comment": "only enable this for single-tenant, single-server deployments", + "enabled": false + }, + "kafka": { + "enabled": false, + "topicName": "fhirNotifications", + "connectionProperties": { + "group.id": "securing-kafka-group", + "bootstrap.servers": "localhost:9093", + "security.protocol": "SSL", + "ssl.truststore.location": "resources/security/kafka.client.truststore.p12", + "ssl.truststore.password": "change-password", + "ssl.keystore.location": "resources/security/kafka.client.keystore.p12", + "ssl.keystore.password": "change-password", + "ssl.key.password": "change-password", + "ssl.truststore.type": "PKCS12", + "ssl.keystore.type": "PKCS12", + "acks": "all", + "retries": "60", + "request.timeout.ms": "10000", + "max.block.ms": "60000", + "max.in.flight.requests.per.connection": "5" + } + }, + "nats": { + "enabled": false, + "cluster": "nats-streaming", + "channel": "fhirNotifications", + "clientId": "fhir-server", + "servers": "nats://nats-node1:4222,nats://nats-node2:4222,nats://nats-node3:4222", + "useTLS": false, + "truststoreLocation": "resources/security/nats.client.truststore.jks", + "truststorePassword": "change-password", + "keystoreLocation": "resources/security/nats.client.keystore.jks", + "keystorePassword": "change-password" + } + }, + "audit": { + "serviceClassName": "com.ibm.fhir.audit.impl.KafkaService", + "serviceProperties": { + "load": "config", + "mapper": "cadf", + "auditTopic": "FHIR_AUDIT", + "geoCity": "Hamil", + "geoState": "Texas", + "geoCounty": "USA", + "kafka": { + "bootstrap.servers": "kafka-1:19092,kafka-2:29092", + "security.protocol": "SSL", + "ssl.protocol": "TLSv1.2", + "ssl.enabled.protocols": "TLSv1.2", + "ssl.endpoint.identification.algorithm": "", + "ssl.keystore.filename": "/config/config/default/kafka.producer.keystore.jks", + "ssl.key.credentials": "/config/config/default/producer_sslkey_creds", + "ssl.keystore.location": "/config/config/default/kafka.producer.keystore.jks", + "ssl.truststore.location": "/config/config/default/kafka.producer.truststore.jks", + "ssl.client.auth": "requested", + "ssl.keystore.credentials": "/config/config/default/producer_keystore_creds", + "ssl.keystore.password": "change-password", + "security.inter.broker.protocol": "SSL", + "ssl.key.password": "change-password", + "ssl.truststore.password": "change-password", + "ssl.truststore.filename": "/config/config/default/kafka.producer.truststore.jks", + "ssl.truststore.credentials": "/config/config/default/producer_truststore_creds" + } + } + }, + "persistence": { + "factoryClassname": "com.ibm.fhir.persistence.jdbc.FHIRPersistenceJDBCFactory", + "common": { + "__comment": "Configuration properties common to all persistence layer implementations", + "updateCreateEnabled": true + }, + "jdbc": { + "__comment": "Configuration properties for the JDBC persistence implementation", + "enableCodeSystemsCache": true, + "enableParameterNamesCache": true, + "enableResourceTypesCache": true + }, + "datasources": { + "default": { + "jndiName": "jdbc/bootstrap_default_default", + "type": "derby", + "currentSchema": "APP" + } + } + }, + "bulkdata": { + "enabled": false + } + } +} diff --git a/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config-audit-config.json b/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config-audit-config.json new file mode 100644 index 00000000000..7957a084744 --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config-audit-config.json @@ -0,0 +1,137 @@ +{ + "__comment": "FHIR Server configuration", + "fhirServer": { + "core": { + "tenantIdHeaderName": "X-FHIR-TENANT-ID", + "datastoreIdHeaderName": "X-FHIR-DSID", + "checkReferenceTypes": true, + "conditionalDeleteMaxNumber": 10, + "serverRegistryResourceProviderEnabled": true, + "disabledOperations": "" + }, + "security": { + "cors": true, + "basic": { + "enabled": true + }, + "certificates": { + "enabled": true + }, + "oauth": { + "enabled": false, + "regUrl": "https://:9443/oauth2/endpoint/oauth2-provider/registration", + "authUrl": "https://:9443/oauth2/endpoint/oauth2-provider/authorize", + "tokenUrl": "https://:9443/oauth2/endpoint/oauth2-provider/token", + "smart": { + "enabled": false, + "scopes": ["openid", "profile", "fhirUser", "launch/patient", "patient/*.*", "offline_access"], + "capabilities": [ + "sso-openid-connect", + "launch-standalone", + "client-public", + "client-confidential-symmetric", + "permission-offline", + "context-standalone-patient", + "permission-patient" + ] + } + } + }, + "notifications": { + "common": { + "__comment_includeResourceTypes": [ + "QuestionnaireResponse", + "CarePlan", + "MedicationAdministration", + "Device", + "DeviceComponent", + "DeviceMetric", + "MedicationOrder", + "Observation" + ] + }, + "websocket": { + "__comment": "only enable this for single-tenant, single-server deployments", + "enabled": false + }, + "kafka": { + "enabled": false, + "topicName": "fhirNotifications", + "connectionProperties": { + "group.id": "securing-kafka-group", + "bootstrap.servers": "localhost:9093", + "security.protocol": "SSL", + "ssl.truststore.location": "resources/security/kafka.client.truststore.p12", + "ssl.truststore.password": "change-password", + "ssl.keystore.location": "resources/security/kafka.client.keystore.p12", + "ssl.keystore.password": "change-password", + "ssl.key.password": "change-password", + "ssl.truststore.type": "PKCS12", + "ssl.keystore.type": "PKCS12", + "acks": "all", + "retries": "60", + "request.timeout.ms": "10000", + "max.block.ms": "60000", + "max.in.flight.requests.per.connection": "5" + } + }, + "nats": { + "enabled": false, + "cluster": "nats-streaming", + "channel": "fhirNotifications", + "clientId": "fhir-server", + "servers": "nats://nats-node1:4222,nats://nats-node2:4222,nats://nats-node3:4222", + "useTLS": false, + "truststoreLocation": "resources/security/nats.client.truststore.jks", + "truststorePassword": "change-password", + "keystoreLocation": "resources/security/nats.client.keystore.jks", + "keystorePassword": "change-password" + } + }, + "audit": { + "serviceClassName" : "com.ibm.fhir.audit.impl.KafkaService", + "serviceProperties": { + "load": "config", + "mapper": "cadf", + "auditTopic": "FHIR_AUDIT", + "geoCity": "Dallas", + "geoState": "TX", + "geoCounty": "US", + "kafka" : { + "sasl.jaas.config": "org.apache.kafka.common.security.plain.PlainLoginModule required username=\"token\" password=\"apiKeyCanGoHere\";", + "bootstrap.servers": "broker-1:9093,broker-2:9093", + "sasl.mechanism": "PLAIN", + "security.protocol": "SASL_SSL", + "ssl.protocol": "TLSv1.2", + "ssl.enabled.protocols": "TLSv1.2", + "ssl.endpoint.identification.algorithm": "HTTPS" + }, + "kafkaServers": "broker-1:9093,broker-2:9093", + "kafkaApiKey": "apiKeyCanGoHere" + } + }, + "persistence": { + "factoryClassname": "com.ibm.fhir.persistence.jdbc.FHIRPersistenceJDBCFactory", + "common": { + "__comment": "Configuration properties common to all persistence layer implementations", + "updateCreateEnabled": true + }, + "jdbc": { + "__comment": "Configuration properties for the JDBC persistence implementation", + "enableCodeSystemsCache": true, + "enableParameterNamesCache": true, + "enableResourceTypesCache": true + }, + "datasources": { + "default": { + "jndiName": "jdbc/bootstrap_default_default", + "type": "derby", + "currentSchema": "APP" + } + } + }, + "bulkdata": { + "enabled": false + } + } +} diff --git a/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config-audit-environment.json b/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config-audit-environment.json new file mode 100644 index 00000000000..6422b1f997b --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config-audit-environment.json @@ -0,0 +1,124 @@ +{ + "__comment": "FHIR Server configuration", + "fhirServer": { + "core": { + "tenantIdHeaderName": "X-FHIR-TENANT-ID", + "datastoreIdHeaderName": "X-FHIR-DSID", + "checkReferenceTypes": true, + "conditionalDeleteMaxNumber": 10, + "serverRegistryResourceProviderEnabled": true, + "disabledOperations": "" + }, + "security": { + "cors": true, + "basic": { + "enabled": true + }, + "certificates": { + "enabled": true + }, + "oauth": { + "enabled": false, + "regUrl": "https://:9443/oauth2/endpoint/oauth2-provider/registration", + "authUrl": "https://:9443/oauth2/endpoint/oauth2-provider/authorize", + "tokenUrl": "https://:9443/oauth2/endpoint/oauth2-provider/token", + "smart": { + "enabled": false, + "scopes": ["openid", "profile", "fhirUser", "launch/patient", "patient/*.*", "offline_access"], + "capabilities": [ + "sso-openid-connect", + "launch-standalone", + "client-public", + "client-confidential-symmetric", + "permission-offline", + "context-standalone-patient", + "permission-patient" + ] + } + } + }, + "notifications": { + "common": { + "__comment_includeResourceTypes": [ + "QuestionnaireResponse", + "CarePlan", + "MedicationAdministration", + "Device", + "DeviceComponent", + "DeviceMetric", + "MedicationOrder", + "Observation" + ] + }, + "websocket": { + "__comment": "only enable this for single-tenant, single-server deployments", + "enabled": false + }, + "kafka": { + "enabled": false, + "topicName": "fhirNotifications", + "connectionProperties": { + "group.id": "securing-kafka-group", + "bootstrap.servers": "localhost:9093", + "security.protocol": "SSL", + "ssl.truststore.location": "resources/security/kafka.client.truststore.p12", + "ssl.truststore.password": "change-password", + "ssl.keystore.location": "resources/security/kafka.client.keystore.p12", + "ssl.keystore.password": "change-password", + "ssl.key.password": "change-password", + "ssl.truststore.type": "PKCS12", + "ssl.keystore.type": "PKCS12", + "acks": "all", + "retries": "60", + "request.timeout.ms": "10000", + "max.block.ms": "60000", + "max.in.flight.requests.per.connection": "5" + } + }, + "nats": { + "enabled": false, + "cluster": "nats-streaming", + "channel": "fhirNotifications", + "clientId": "fhir-server", + "servers": "nats://nats-node1:4222,nats://nats-node2:4222,nats://nats-node3:4222", + "useTLS": false, + "truststoreLocation": "resources/security/nats.client.truststore.jks", + "truststorePassword": "change-password", + "keystoreLocation": "resources/security/nats.client.keystore.jks", + "keystorePassword": "change-password" + } + }, + "audit": { + "serviceClassName" : "com.ibm.fhir.audit.impl.KafkaService", + "serviceProperties" : { + "auditTopic": "FHIR_AUDIT", + "geoCity": "Dallas", + "geoState": "TX", + "geoCounty": "US" + } + }, + "persistence": { + "factoryClassname": "com.ibm.fhir.persistence.jdbc.FHIRPersistenceJDBCFactory", + "common": { + "__comment": "Configuration properties common to all persistence layer implementations", + "updateCreateEnabled": true + }, + "jdbc": { + "__comment": "Configuration properties for the JDBC persistence implementation", + "enableCodeSystemsCache": true, + "enableParameterNamesCache": true, + "enableResourceTypesCache": true + }, + "datasources": { + "default": { + "jndiName": "jdbc/bootstrap_default_default", + "type": "derby", + "currentSchema": "APP" + } + } + }, + "bulkdata": { + "enabled": false + } + } +} diff --git a/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config-db2.json b/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config-db2.json new file mode 100644 index 00000000000..f2073c54cc0 --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config-db2.json @@ -0,0 +1,203 @@ +{ + "__comment": "FHIR Server configuration", + "fhirServer": { + "core": { + "tenantIdHeaderName": "X-FHIR-TENANT-ID", + "datastoreIdHeaderName": "X-FHIR-DSID", + "originalRequestUriHeaderName": "X-FHIR-FORWARDED-URL", + "checkReferenceTypes": true, + "conditionalDeleteMaxNumber": 10, + "capabilityStatementCacheTimeout": 60, + "serverRegistryResourceProviderEnabled": true, + "disabledOperations": "" + }, + "security": { + "cors": true, + "basic": { + "enabled": true + }, + "certificates": { + "enabled": true + }, + "oauth": { + "enabled": false, + "regUrl": "https://:9443/oauth2/endpoint/oauth2-provider/registration", + "authUrl": "https://:9443/oauth2/endpoint/oauth2-provider/authorize", + "tokenUrl": "https://:9443/oauth2/endpoint/oauth2-provider/token", + "smart": { + "enabled": false, + "scopes": ["openid", "profile", "fhirUser", "launch/patient", "patient/*.*", "offline_access"], + "capabilities": [ + "sso-openid-connect", + "launch-standalone", + "client-public", + "client-confidential-symmetric", + "permission-offline", + "context-standalone-patient", + "permission-patient" + ] + } + } + }, + "notifications": { + "common": { + "__comment_includeResourceTypes": [ + "QuestionnaireResponse", + "CarePlan", + "MedicationAdministration", + "Device", + "DeviceComponent", + "DeviceMetric", + "MedicationOrder", + "Observation" + ] + }, + "websocket": { + "enabled": true + }, + "kafka": { + "enabled": false, + "topicName": "fhirNotifications", + "connectionProperties": { + "group.id": "securing-kafka-group", + "bootstrap.servers": "localhost:9093", + "security.protocol": "SSL", + "ssl.truststore.location": "resources/security/kafka.client.truststore.p12", + "ssl.truststore.password": "change-password", + "ssl.keystore.location": "resources/security/kafka.client.keystore.p12", + "ssl.keystore.password": "change-password", + "ssl.key.password": "change-password", + "ssl.truststore.type": "PKCS12", + "ssl.keystore.type": "PKCS12", + "acks": "all", + "retries": "60", + "request.timeout.ms": "10000", + "max.block.ms": "60000", + "max.in.flight.requests.per.connection": "5" + } + }, + "nats": { + "enabled": true, + "cluster": "nats-streaming", + "channel": "fhirNotifications", + "clientId": "fhir-server", + "servers": "nats://nats-node1:4222,nats://nats-node2:4222,nats://nats-node3:4222", + "useTLS": false, + "truststoreLocation": "resources/security/nats.client.truststore.jks", + "truststorePassword": "change-password", + "keystoreLocation": "resources/security/nats.client.keystore.jks", + "keystorePassword": "change-password" + } + }, + "audit": { + "serviceClassName" : "com.ibm.fhir.audit.impl.NopService", + "serviceProperties" : { + } + }, + "persistence": { + "factoryClassname": "com.ibm.fhir.persistence.jdbc.FHIRPersistenceJDBCFactory", + "common": { + "__comment": "Configuration properties common to all persistence layer implementations", + "updateCreateEnabled": true + }, + "jdbc": { + "__comment": "Configuration properties for the JDBC persistence implementation", + "enableCodeSystemsCache": true, + "enableParameterNamesCache": true, + "enableResourceTypesCache": true + }, + "datasources": { + "default": { + "type": "db2", + "currentSchema": "fhirdata", + "tenantKey": "", + "hints" : { + "search.reopt": "ONCE" + } + } + } + }, + "bulkdata": { + "enabled": true, + "core": { + "api": { + "url": "https://localhost:9443/ibm/api/batch", + "user": "fhiradmin", + "password": "change-password", + "truststore": "resources/security/fhirTrustStore.p12", + "truststorePassword": "change-password", + "trustAll": true + }, + "cos" : { + "partUploadTriggerSizeMB": 10, + "objectSizeThresholdMB": 200, + "objectResourceCountThreshold": 200000, + "useServerTruststore": true + }, + "file" : { + "writeTriggerSizeMB": 1, + "sizeThresholdMB": 200, + "resourceCountThreshold": 200000 + }, + "pageSize": 100, + "batchIdEncryptionKey": "change-password", + "maxPartitions": 3, + "maxInputs": 5 + }, + "storageProviders": { + "default" : { + "type": "file", + "_type": "ibm-cos|aws-s3|file|https|azure-blob", + "validBaseUrls": [], + "fileBase": "/output/bulkdata", + "enableParquet": false, + "disableBaseUrlValidation": true, + "disableOperationOutcomes": true, + "duplicationCheck": false, + "validateResources": false + }, + "minio" : { + "type": "aws-s3", + "bucketName": "fhirbulkdata", + "location": "us", + "endpointInternal": "https://minio:9000", + "endpointExternal": "https://localhost:9000", + "auth" : { + "type": "hmac", + "accessKeyId": "minio", + "secretAccessKey": "change-password" + }, + "enableParquet": false, + "disableBaseUrlValidation": true, + "disableOperationOutcomes": true, + "duplicationCheck": false, + "validateResources": false, + "create": false, + "presigned": true + }, + "azure" : { + "type": "azure-blob", + "_type": "ibm-cos|aws-s3|file|https|azure-blob", + "bucketName": "fhirbulkdata", + "auth" : { + "type": "connection", + "connection": "DefaultEndpointsProtocol=https;AccountName=XYZ;AccountKey=XYZKEY;EndpointSuffix=core.windows.net" + }, + "disableOperationOutcomes": true, + "duplicationCheck": false, + "validateResources": false, + "create": false + } + } + }, + "operations": { + "erase": { + "enabled": true, + "allowedRoles": [ + "FHIROperationAdmin", + "FHIRUsers" + ] + } + } + } +} diff --git a/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config-notifications-cicd.json b/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config-notifications-cicd.json new file mode 100644 index 00000000000..6fa67308d4e --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config-notifications-cicd.json @@ -0,0 +1,156 @@ +{ + "__comment": "FHIR Server configuration", + "fhirServer": { + "core": { + "tenantIdHeaderName": "X-FHIR-TENANT-ID", + "datastoreIdHeaderName": "X-FHIR-DSID", + "checkReferenceTypes": true, + "conditionalDeleteMaxNumber": 10, + "serverRegistryResourceProviderEnabled": true, + "disabledOperations": "" + }, + "security": { + "cors": true, + "basic": { + "enabled": true + }, + "certificates": { + "enabled": true + }, + "oauth": { + "enabled": false, + "regUrl": "https://:9443/oauth2/endpoint/oauth2-provider/registration", + "authUrl": "https://:9443/oauth2/endpoint/oauth2-provider/authorize", + "tokenUrl": "https://:9443/oauth2/endpoint/oauth2-provider/token", + "smart": { + "enabled": false, + "scopes": ["openid", + "profile", + "fhirUser", + "launch/patient", + "patient/*.*", + "offline_access"], + "capabilities": ["sso-openid-connect", + "launch-standalone", + "client-public", + "client-confidential-symmetric", + "permission-offline", + "context-standalone-patient", + "permission-patient"] + } + } + }, + "notifications": { + "common": { + "includeResourceTypes": [ + "Patiennt", + "QuestionnaireResponse", + "CarePlan", + "MedicationAdministration", + "Device", + "DeviceComponent", + "DeviceMetric", + "MedicationOrder", + "Observation"] + }, + "websocket": { + "__comment": "only enable this for single-tenant, single-server deployments", + "enabled": false + }, + "kafka": { + "enabled": true, + "topicName": "FHIR_NOTIFICATIONS", + "connectionProperties": { + "group.id": "securing-kafka-group", + "bootstrap.servers": "kafka-1:19092,kafka-2:29092", + "security.protocol": "SSL", + "ssl.protocol": "TLSv1.2", + "ssl.enabled.protocols": "TLSv1.2", + "ssl.endpoint.identification.algorithm": "", + "ssl.keystore.filename": "/config/config/default/kafka.producer.keystore.jks", + "ssl.key.credentials": "/config/config/default/producer_sslkey_creds", + "ssl.keystore.location": "/config/config/default/kafka.producer.keystore.jks", + "ssl.truststore.location": "/config/config/default/kafka.producer.truststore.jks", + "ssl.client.auth": "requested", + "ssl.keystore.credentials": "/config/config/default/producer_keystore_creds", + "ssl.keystore.password": "change-password", + "security.inter.broker.protocol": "SSL", + "ssl.key.password": "change-password", + "ssl.truststore.password": "change-password", + "ssl.truststore.filename": "/config/config/default/kafka.producer.truststore.jks", + "ssl.truststore.credentials": "/config/config/default/producer_truststore_creds", + "acks": "all", + "retries": "60", + "request.timeout.ms": "10000", + "max.block.ms": "60000", + "max.in.flight.requests.per.connection": "5" + } + }, + "nats": { + "enabled": false, + "cluster": "nats-streaming", + "channel": "fhirNotifications", + "clientId": "fhir-server", + "servers": "nats://nats-node1:4222,nats://nats-node2:4222,nats://nats-node3:4222", + "useTLS": false, + "truststoreLocation": "resources/security/nats.client.truststore.jks", + "truststorePassword": "change-password", + "keystoreLocation": "resources/security/nats.client.keystore.jks", + "keystorePassword": "change-password" + } + }, + "audit": { + "serviceClassName": "com.ibm.fhir.audit.impl.NopService", + "serviceProperties": { + "load": "config", + "mapper": "cadf", + "auditTopic": "FHIR_AUDIT", + "geoCity": "Hamil", + "geoState": "Texas", + "geoCounty": "USA", + "kafka": { + "bootstrap.servers": "kafka-1:19092,kafka-2:29092", + "security.protocol": "SSL", + "ssl.protocol": "TLSv1.2", + "ssl.enabled.protocols": "TLSv1.2", + "ssl.endpoint.identification.algorithm": "", + "ssl.keystore.filename": "/config/config/default/kafka.producer.keystore.jks", + "ssl.key.credentials": "/config/config/default/producer_sslkey_creds", + "ssl.keystore.location": "/config/config/default/kafka.producer.keystore.jks", + "ssl.truststore.location": "/config/config/default/kafka.producer.truststore.jks", + "ssl.client.auth": "requested", + "ssl.keystore.credentials": "/config/config/default/producer_keystore_creds", + "ssl.keystore.password": "change-password", + "security.inter.broker.protocol": "SSL", + "ssl.key.password": "change-password", + "ssl.truststore.password": "change-password", + "ssl.truststore.filename": "/config/config/default/kafka.producer.truststore.jks", + "ssl.truststore.credentials": "/config/config/default/producer_truststore_creds" + } + } + }, + "persistence": { + "factoryClassname": "com.ibm.fhir.persistence.jdbc.FHIRPersistenceJDBCFactory", + "common": { + "__comment": "Configuration properties common to all persistence layer implementations", + "updateCreateEnabled": true + }, + "jdbc": { + "__comment": "Configuration properties for the JDBC persistence implementation", + "enableCodeSystemsCache": true, + "enableParameterNamesCache": true, + "enableResourceTypesCache": true + }, + "datasources": { + "default": { + "jndiName": "jdbc/bootstrap_default_default", + "type": "derby", + "currentSchema": "APP" + } + } + }, + "bulkdata": { + "enabled": false + } + } +} diff --git a/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config-postgresql.json b/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config-postgresql.json new file mode 100644 index 00000000000..a60f91cd9d8 --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config-postgresql.json @@ -0,0 +1,82 @@ +{ + "__comment": "FHIR Server configuration", + "fhirServer": { + "core": { + "tenantIdHeaderName": "X-FHIR-TENANT-ID", + "datastoreIdHeaderName": "X-FHIR-DSID", + "originalRequestUriHeaderName": "X-FHIR-FORWARDED-URL", + "checkReferenceTypes": true, + "conditionalDeleteMaxNumber": 10, + "serverRegistryResourceProviderEnabled": true, + "disabledOperations": "" + }, + "security": { + "cors": true, + "basic": { + "enabled": true + }, + "certificates": { + "enabled": true + }, + "oauth": { + "enabled": false, + "regUrl": "https://:9443/oauth2/endpoint/oauth2-provider/registration", + "authUrl": "https://:9443/oauth2/endpoint/oauth2-provider/authorize", + "tokenUrl": "https://:9443/oauth2/endpoint/oauth2-provider/token", + "smart": { + "enabled": false, + "scopes": ["openid", "profile", "fhirUser", "launch/patient", "patient/*.*", "offline_access"], + "capabilities": [ + "sso-openid-connect", + "launch-standalone", + "client-public", + "client-confidential-symmetric", + "permission-offline", + "context-standalone-patient", + "permission-patient" + ] + } + } + }, + "audit": { + "serviceClassName" : "com.ibm.fhir.audit.impl.NopService", + "serviceProperties" : { + } + }, + "persistence": { + "factoryClassname": "com.ibm.fhir.persistence.jdbc.FHIRPersistenceJDBCFactory", + "common": { + "__comment": "Configuration properties common to all persistence layer implementations", + "updateCreateEnabled": true + }, + "jdbc": { + "__comment": "Configuration properties for the JDBC persistence implementation", + "enableCodeSystemsCache": true, + "enableParameterNamesCache": true, + "enableResourceTypesCache": true + }, + "datasources": { + "default": { + "type": "postgresql", + "currentSchema": "fhirdata", + "searchOptimizerOptions": { + "from_collapse_limit": 12, + "join_collapse_limit": 12 + } + } + } + }, + "bulkdata": { + "enabled": false + }, + "operations": { + "erase": { + "enabled": true, + "allowedRoles": [ + "FHIROperationAdmin", + "FHIRUsers" + ] + } + } + } +} diff --git a/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config.json b/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config.json new file mode 100644 index 00000000000..e08fe80beeb --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config.json @@ -0,0 +1,208 @@ +{ + "__comment": "FHIR Server configuration", + "fhirServer": { + "core": { + "tenantIdHeaderName": "X-FHIR-TENANT-ID", + "datastoreIdHeaderName": "X-FHIR-DSID", + "originalRequestUriHeaderName": "X-FHIR-FORWARDED-URL", + "checkReferenceTypes": true, + "conditionalDeleteMaxNumber": 10, + "serverRegistryResourceProviderEnabled": true, + "disabledOperations": "" + }, + "search": { + "useStoredCompartmentParam": true + }, + "security": { + "cors": true, + "basic": { + "enabled": true + }, + "certificates": { + "enabled": true + }, + "oauth": { + "enabled": false, + "regUrl": "https://:9443/oauth2/endpoint/oauth2-provider/registration", + "authUrl": "https://:9443/oauth2/endpoint/oauth2-provider/authorize", + "tokenUrl": "https://:9443/oauth2/endpoint/oauth2-provider/token", + "smart": { + "enabled": false, + "scopes": ["openid", "profile", "fhirUser", "launch/patient", "patient/*.*", "offline_access"], + "capabilities": [ + "sso-openid-connect", + "launch-standalone", + "client-public", + "client-confidential-symmetric", + "permission-offline", + "context-standalone-patient", + "permission-patient" + ] + } + } + }, + "notifications": { + "common": { + "__comment_includeResourceTypes": [ + "QuestionnaireResponse", + "CarePlan", + "MedicationAdministration", + "Device", + "DeviceComponent", + "DeviceMetric", + "MedicationOrder", + "Observation" + ] + }, + "websocket": { + "__comment": "only enable this for single-tenant, single-server deployments", + "enabled": false + }, + "kafka": { + "enabled": false, + "topicName": "fhirNotifications", + "connectionProperties": { + "group.id": "securing-kafka-group", + "bootstrap.servers": "localhost:9093", + "security.protocol": "SSL", + "ssl.truststore.location": "resources/security/kafka.client.truststore.p12", + "ssl.truststore.password": "change-password", + "ssl.keystore.location": "resources/security/kafka.client.keystore.p12", + "ssl.keystore.password": "change-password", + "ssl.key.password": "change-password", + "ssl.truststore.type": "PKCS12", + "ssl.keystore.type": "PKCS12", + "acks": "all", + "retries": "60", + "request.timeout.ms": "10000", + "max.block.ms": "60000", + "max.in.flight.requests.per.connection": "5" + } + }, + "nats": { + "enabled": false, + "cluster": "nats-streaming", + "channel": "fhirNotifications", + "clientId": "fhir-server", + "servers": "nats://nats-node1:4222,nats://nats-node2:4222,nats://nats-node3:4222", + "useTLS": false, + "truststoreLocation": "resources/security/nats.client.truststore.jks", + "truststorePassword": "change-password", + "keystoreLocation": "resources/security/nats.client.keystore.jks", + "keystorePassword": "change-password" + } + }, + "audit": { + "serviceClassName" : "com.ibm.fhir.audit.impl.NopService", + "serviceProperties" : { + } + }, + "persistence": { + "factoryClassname": "com.ibm.fhir.persistence.jdbc.FHIRPersistenceJDBCFactory", + "common": { + "__comment": "Configuration properties common to all persistence layer implementations", + "updateCreateEnabled": true + }, + "jdbc": { + "__comment": "Configuration properties for the JDBC persistence implementation", + "enableCodeSystemsCache": true, + "enableParameterNamesCache": true, + "enableResourceTypesCache": true + }, + "datasources": { + "default": { + "jndiName": "jdbc/bootstrap_default_default", + "type": "derby", + "currentSchema": "APP" + }, + "_db2sample": { + "type": "db2", + "tenantKey": "", + "currentSchema": "fhirdata", + "hints" : { + "search.reopt": "ONCE" + } + }, + "_pgsample": { + "type": "postgresql", + "currentSchema": "fhirdata", + "searchOptimizerOptions": { + "from_collapse_limit": 12, + "join_collapse_limit": 12 + } + } + } + }, + "bulkdata": { + "enabled": true, + "core": { + "api": { + "url": "https://localhost:9443/ibm/api/batch", + "user": "fhiradmin", + "password": "change-password", + "truststore": "resources/security/fhirTrustStore.p12", + "truststorePassword": "change-password", + "trustAll": true + }, + "cos" : { + "partUploadTriggerSizeMB": 10, + "objectSizeThresholdMB": 200, + "objectResourceCountThreshold": 200000, + "useServerTruststore": true, + "presignedExpiry": 86400 + }, + "file" : { + "writeTriggerSizeMB": 1, + "sizeThresholdMB": 200, + "resourceCountThreshold": 200000 + }, + "pageSize": 100, + "batchIdEncryptionKey": "change-password", + "maxPartitions": 3, + "maxInputs": 5, + "maxChunkReadTime": "90000", + "systemExportImpl": "fast", + "defaultExportProvider": "default", + "defaultImportProvider": "default" + }, + "storageProviders": { + "default" : { + "type": "file", + "_type": "ibm-cos|aws-s3|file|https|azure-blob", + "validBaseUrls": [], + "fileBase": "/output/bulkdata", + "bucketName": "fhir-performance", + "location": "us", + "endpointInternal": "https://s3.us-east.cloud-object-storage.appdomain.cloud", + "endpointExternal": "https://s3.us-east.cloud-object-storage.appdomain.cloud", + "auth" : { + "type": "hmac", + "accessKeyId": "key", + "secretAccessKey": "secret" + }, + "_iam_auth" : { + "type": "iam", + "iamApiKey": "apiKey", + "iamResourceInstanceId": "resourceId" + }, + "enableParquet": false, + "disableBaseUrlValidation": true, + "disableOperationOutcomes": true, + "duplicationCheck": false, + "validateResources": false, + "create": false, + "presigned": true + } + } + }, + "operations": { + "erase": { + "enabled": true, + "allowedRoles": [ + "FHIROperationAdmin", + "FHIRUsers" + ] + } + } + } +} diff --git a/fhir-server-webapp/src/main/liberty/config/configDropins/defaults/bulkdata.xml b/fhir-server-webapp/src/main/liberty/config/configDropins/defaults/bulkdata.xml new file mode 100644 index 00000000000..2fa1e548062 --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/configDropins/defaults/bulkdata.xml @@ -0,0 +1,40 @@ + + + + batch-1.0 + batchManagement-1.0 + jdbc-4.1 + servlet-4.0 + transportSecurity-1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fhir-server-webapp/src/main/liberty/config/configDropins/defaults/datasource.xml b/fhir-server-webapp/src/main/liberty/config/configDropins/defaults/datasource.xml new file mode 100644 index 00000000000..3571c4c7aff --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/configDropins/defaults/datasource.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/fhir-server-webapp/src/main/liberty/config/configDropins/defaults/keystore.xml b/fhir-server-webapp/src/main/liberty/config/configDropins/defaults/keystore.xml new file mode 100644 index 00000000000..e3f265ce8df --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/configDropins/defaults/keystore.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/fhir-server-webapp/src/main/liberty/config/configDropins/defaults/openapi.xml b/fhir-server-webapp/src/main/liberty/config/configDropins/defaults/openapi.xml new file mode 100644 index 00000000000..0ed602121de --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/configDropins/defaults/openapi.xml @@ -0,0 +1,9 @@ + + + mpOpenAPI-2.0 + + + + + + \ No newline at end of file diff --git a/fhir-server-webapp/src/main/liberty/config/configDropins/defaults/transaction-manager.xml b/fhir-server-webapp/src/main/liberty/config/configDropins/defaults/transaction-manager.xml new file mode 100644 index 00000000000..310e0889d41 --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/configDropins/defaults/transaction-manager.xml @@ -0,0 +1,7 @@ + + + jdbc-4.1 + + + + \ No newline at end of file diff --git a/fhir-server-webapp/src/main/liberty/config/configDropins/defaults/trustDefault.xml b/fhir-server-webapp/src/main/liberty/config/configDropins/defaults/trustDefault.xml new file mode 100644 index 00000000000..40d2eeef69c --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/configDropins/defaults/trustDefault.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/README.md b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/README.md new file mode 100644 index 00000000000..b3cff423560 --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/README.md @@ -0,0 +1,13 @@ +This readme applies to all files in this folder: + +# Datasources used for server integration tests + +``` +datasource-db2.xml +datasource-derby.xml +datasource-postgresql.xml +``` + +These files are copied to the overrides folder and renamed to datasource.xml. + +Only one of these datasource definition files should be copied into the target Liberty configDropins/overrides folder. If more than one of these is present at the same time it will break the Liberty configuration because the datasource ids and JNDI location are common among the files. \ No newline at end of file diff --git a/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/cors.xml b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/cors.xml new file mode 100644 index 00000000000..078dd720ad4 --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/cors.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/datasource-db2.xml b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/datasource-db2.xml new file mode 100644 index 00000000000..fa317fb413e --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/datasource-db2.xml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/datasource-derby.xml b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/datasource-derby.xml new file mode 100644 index 00000000000..a365dc543d0 --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/datasource-derby.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/datasource-postgresql.xml b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/datasource-postgresql.xml new file mode 100644 index 00000000000..55e4e0c1aed --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/datasource-postgresql.xml @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/db2-cloud/bulkdata.xml b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/db2-cloud/bulkdata.xml new file mode 100644 index 00000000000..501254d9612 --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/db2-cloud/bulkdata.xml @@ -0,0 +1,55 @@ + + + + batch-1.0 + batchManagement-1.0 + jdbc-4.1 + servlet-4.0 + transportSecurity-1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/db2/bulkdata.xml b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/db2/bulkdata.xml new file mode 100644 index 00000000000..cb7ecf7bddc --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/db2/bulkdata.xml @@ -0,0 +1,58 @@ + + + + batch-1.0 + batchManagement-1.0 + jdbc-4.1 + servlet-4.0 + transportSecurity-1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/jvm.options b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/jvm.options new file mode 100644 index 00000000000..53cd8148142 --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/jvm.options @@ -0,0 +1,7 @@ +# Reduced heap size for constrained environments + +# Initial heap size (same as max so no reallocations will occur) +-Xms3072M + +# Maximum heap size +-Xmx3072M \ No newline at end of file diff --git a/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/jwtRS.xml b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/jwtRS.xml new file mode 100644 index 00000000000..ab521345842 --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/jwtRS.xml @@ -0,0 +1,31 @@ + + + + mpJwt-1.1 + + + + + + + + + + + + + + + + + + + + diff --git a/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/postgres/bulkdata.xml b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/postgres/bulkdata.xml new file mode 100644 index 00000000000..60a74d2e59e --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/configDropins/disabled/postgres/bulkdata.xml @@ -0,0 +1,54 @@ + + + + batch-1.0 + batchManagement-1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fhir-server-webapp/src/main/liberty/config/configDropins/overrides/.empty b/fhir-server-webapp/src/main/liberty/config/configDropins/overrides/.empty new file mode 100644 index 00000000000..e69de29bb2d diff --git a/fhir-server-webapp/src/main/liberty/config/resources/security/fhirKeyStore.p12 b/fhir-server-webapp/src/main/liberty/config/resources/security/fhirKeyStore.p12 new file mode 100644 index 00000000000..718148f9444 Binary files /dev/null and b/fhir-server-webapp/src/main/liberty/config/resources/security/fhirKeyStore.p12 differ diff --git a/fhir-server-webapp/src/main/liberty/config/resources/security/fhirTrustStore.p12 b/fhir-server-webapp/src/main/liberty/config/resources/security/fhirTrustStore.p12 new file mode 100644 index 00000000000..5413314c6f3 Binary files /dev/null and b/fhir-server-webapp/src/main/liberty/config/resources/security/fhirTrustStore.p12 differ diff --git a/fhir-server-webapp/src/main/liberty/config/resources/security/kafka.client.keystore.p12 b/fhir-server-webapp/src/main/liberty/config/resources/security/kafka.client.keystore.p12 new file mode 100644 index 00000000000..799fb7f82f3 Binary files /dev/null and b/fhir-server-webapp/src/main/liberty/config/resources/security/kafka.client.keystore.p12 differ diff --git a/fhir-server-webapp/src/main/liberty/config/resources/security/kafka.client.truststore.p12 b/fhir-server-webapp/src/main/liberty/config/resources/security/kafka.client.truststore.p12 new file mode 100644 index 00000000000..a680e8e1b2d Binary files /dev/null and b/fhir-server-webapp/src/main/liberty/config/resources/security/kafka.client.truststore.p12 differ diff --git a/fhir-server-webapp/src/main/liberty/config/server.env b/fhir-server-webapp/src/main/liberty/config/server.env new file mode 100644 index 00000000000..ee2c923f826 --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/server.env @@ -0,0 +1 @@ +TZ=UTC \ No newline at end of file diff --git a/fhir-server-webapp/src/main/liberty/config/server.xml b/fhir-server-webapp/src/main/liberty/config/server.xml new file mode 100644 index 00000000000..d2bc1701ba5 --- /dev/null +++ b/fhir-server-webapp/src/main/liberty/config/server.xml @@ -0,0 +1,119 @@ + + + + + transportSecurity-1.0 + appSecurity-2.0 + jaxrs-2.1 + servlet-4.0 + jsonp-1.1 + + jdbc-4.1 + websocket-1.1 + localConnector-1.0 + + mpJwt-1.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +