Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

feat: Add data validation for subscription #543

Merged
merged 6 commits into from
Jan 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions USING_SUBSCRIPTIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Subscriptions

The FHIR Subscription resource is used to define a push-based subscription from a server to another system.
Once a subscription is registered with the server, the server checks every resource that is created or updated,
and if the resource matches the given criteria, it sends a message on the defined "channel" so that another system can take an appropriate action.

## Enabling multi-tenancy

Subscriptions are an opt-in feature. Enabling subscriptions incurs a cost even if there are no active subscriptions.

To enable it, follow the steps below:

1. Update the method `getAllowListedSubscriptionEndpoints` in `src/subscriptions/allowList.ts` to include endpoints allowed for recieving subscriptions.

2. Use the `enableSubscriptions` option when deploying the stack

```bash
serverless deploy --enableSubscriptions true
```

## Supported Subscriptions

Subscriptions satisfying the following restrictions are supported:

1. channel.type must be rest-hook
2. channel.endpoint must be allow-listed
3. channel.endpoint must use HTTPS
4. channel.payload must be application/fhir+json if present.
5. channel.criteria must be a valid search query that is supported by FWoA.
6. status must be requested or off
7. Number of active Subscriptions does not exceed 300
9 changes: 9 additions & 0 deletions serverless.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ custom:
config: ${file(serverless_config.json)}
useHapiValidator: ${opt:useHapiValidator, 'false'}
enableMultiTenancy: ${opt:enableMultiTenancy, 'false'}
enableSubscriptions: ${opt:enableSubscriptions, 'false'}
logLevel: ${opt:logLevel, 'error'}
enableESHardDelete: ${opt:enableESHardDelete, 'false'}
patientCompartmentFileV3: 'patientCompartmentSearchParams.3.0.2.json'
Expand Down Expand Up @@ -64,6 +65,7 @@ provider:
- !ImportValue 'fhir-service-validator-lambda-${self:custom.stage}'
- !Ref AWS::NoValue
ENABLE_MULTI_TENANCY: !Ref EnableMultiTenancy
ENABLE_SUBSCRIPTIONS: !Ref EnableSubscriptions
LOG_LEVEL: '${self:custom.logLevel}'
apiKeys:
- name: 'developer-key-${self:custom.stage}' # Full name must be known at package-time
Expand Down Expand Up @@ -230,6 +232,13 @@ resources:
- 'true'
- 'false'
Description: whether or not to enable multi-tenancy
EnableSubscriptions:
Type: String
Default: ${self:custom.enableSubscriptions}
AllowedValues:
- 'true'
- 'false'
Description: whether or not to enable subscriptions
logLevel:
Type: String
Default: ${self:custom.logLevel}
Expand Down
120 changes: 66 additions & 54 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@ import {
} from 'fhir-works-on-aws-persistence-ddb';
import JsonSchemaValidator from 'fhir-works-on-aws-routing/lib/router/validation/jsonSchemaValidator';
import HapiFhirLambdaValidator from 'fhir-works-on-aws-routing/lib/router/validation/hapiFhirLambdaValidator';
import SubscriptionValidator from 'fhir-works-on-aws-routing/lib/router/validation/subscriptionValidator';
import RBACRules from './RBACRules';
import { loadImplementationGuides } from './implementationGuides/loadCompiledIGs';
import getAllowListedSubscriptionEndpoints from './subscriptions/allowList';

const { IS_OFFLINE, ENABLE_MULTI_TENANCY } = process.env;
const { IS_OFFLINE, ENABLE_MULTI_TENANCY, ENABLE_SUBSCRIPTIONS } = process.env;

const enableMultiTenancy = ENABLE_MULTI_TENANCY === 'true';
const enableSubscriptions = ENABLE_SUBSCRIPTIONS === 'true';

export const fhirVersion: FhirVersion = '4.0.1';
const baseResources = fhirVersion === '4.0.1' ? BASE_R4_RESOURCES : BASE_STU3_RESOURCES;
Expand Down Expand Up @@ -65,72 +68,81 @@ const esSearch = new ElasticSearchService(
undefined,
{ enableMultiTenancy },
);

const s3DataService = new S3DataService(dynamoDbDataService, fhirVersion, { enableMultiTenancy });

const OAuthUrl =
process.env.OAUTH2_DOMAIN_ENDPOINT === '[object Object]' || process.env.OAUTH2_DOMAIN_ENDPOINT === undefined
? 'https://OAUTH2.com'
: process.env.OAUTH2_DOMAIN_ENDPOINT;

export const getFhirConfig = async (): Promise<FhirConfig> => ({
configVersion: 1.0,
productInfo: {
orgName: 'Organization Name',
},
auth: {
authorization: authService,
// Used in Capability Statement Generation only
strategy: {
service: 'OAuth',
oauthPolicy: {
authorizationEndpoint: `${OAuthUrl}/authorize`,
tokenEndpoint: `${OAuthUrl}/token`,
export const getFhirConfig = async (): Promise<FhirConfig> => {
if (enableSubscriptions) {
const subscriptionAllowList = await getAllowListedSubscriptionEndpoints();
validators.push(
new SubscriptionValidator(esSearch, dynamoDbDataService, subscriptionAllowList, { enableMultiTenancy }),
);
}
return {
configVersion: 1.0,
productInfo: {
orgName: 'Organization Name',
},
auth: {
authorization: authService,
// Used in Capability Statement Generation only
strategy: {
service: 'OAuth',
oauthPolicy: {
authorizationEndpoint: `${OAuthUrl}/authorize`,
tokenEndpoint: `${OAuthUrl}/token`,
},
},
},
},
server: {
// When running serverless offline, env vars are expressed as '[object Object]'
// https://github.com/serverless/serverless/issues/7087
// As of May 14, 2020, this bug has not been fixed and merged in
// https://github.com/serverless/serverless/pull/7147
url:
process.env.API_URL === '[object Object]' || process.env.API_URL === undefined
? 'https://API_URL.com'
: process.env.API_URL,
},
validators,
profile: {
systemOperations: ['transaction'],
bundle: dynamoDbBundleService,
compiledImplementationGuides: loadImplementationGuides('fhir-works-on-aws-routing'),
systemHistory: stubs.history,
systemSearch: stubs.search,
bulkDataAccess: dynamoDbDataService,
fhirVersion,
genericResource: {
operations: ['create', 'read', 'update', 'delete', 'vread', 'search-type'],
fhirVersions: [fhirVersion],
persistence: dynamoDbDataService,
typeSearch: esSearch,
typeHistory: stubs.history,
server: {
// When running serverless offline, env vars are expressed as '[object Object]'
// https://github.com/serverless/serverless/issues/7087
// As of May 14, 2020, this bug has not been fixed and merged in
// https://github.com/serverless/serverless/pull/7147
url:
process.env.API_URL === '[object Object]' || process.env.API_URL === undefined
? 'https://API_URL.com'
: process.env.API_URL,
},
resources: {
Binary: {
operations: ['create', 'read', 'update', 'delete', 'vread'],
validators,
profile: {
systemOperations: ['transaction'],
bundle: dynamoDbBundleService,
compiledImplementationGuides: loadImplementationGuides('fhir-works-on-aws-routing'),
systemHistory: stubs.history,
systemSearch: stubs.search,
bulkDataAccess: dynamoDbDataService,
fhirVersion,
genericResource: {
operations: ['create', 'read', 'update', 'delete', 'vread', 'search-type'],
fhirVersions: [fhirVersion],
persistence: s3DataService,
typeSearch: stubs.search,
persistence: dynamoDbDataService,
typeSearch: esSearch,
typeHistory: stubs.history,
},
resources: {
Binary: {
operations: ['create', 'read', 'update', 'delete', 'vread'],
fhirVersions: [fhirVersion],
persistence: s3DataService,
typeSearch: stubs.search,
typeHistory: stubs.history,
},
},
},
},
multiTenancyConfig: enableMultiTenancy
? {
enableMultiTenancy: true,
useTenantSpecificUrl: true,
tenantIdClaimPath: 'custom:tenantId',
}
: undefined,
});
multiTenancyConfig: enableMultiTenancy
? {
enableMultiTenancy: true,
useTenantSpecificUrl: true,
tenantIdClaimPath: 'custom:tenantId',
}
: undefined,
};
};

export const genericResources = baseResources;
21 changes: 21 additions & 0 deletions src/subscriptions/allowList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

import { SubscriptionEndpoint } from 'fhir-works-on-aws-routing/lib/router/validation/subscriptionValidator';

const getAllowListedSubscriptionEndpoints = async (): Promise<SubscriptionEndpoint[]> => {
return [];
// Add here the endpoints that are allowed in Subscriptions
// [
// {
// endpoint: string | RegExp;
// headers?: string[];
// tenantId? string;
// }
// ...
// ]
};

export default getAllowListedSubscriptionEndpoints;