diff --git a/.shellcheckrc b/.shellcheckrc new file mode 100644 index 000000000..6d17a4e9c --- /dev/null +++ b/.shellcheckrc @@ -0,0 +1,2 @@ + +disable=SC1090,SC1091 diff --git a/README.md b/README.md index dbc6dcde4..c649125a0 100644 --- a/README.md +++ b/README.md @@ -332,7 +332,7 @@ For database documentation: [/docs/database.md](/docs/database.md) 1. Checkout `main` branch for `CDCgov/trusted-intermediary` 2. Run `./generate_env.sh` to generate `.env` file with required environment variables -3. Run TI with `./gradlew clean app:run` +3. Run TI with `./gradlew clean run` #### ReportStream Setup @@ -341,17 +341,14 @@ After enabling this option it is recommended that you delete all docker images a with this option enabled. 1. Checkout `master` branch for `CDCgov/prime-reportstream` -2. Create a symbolic link or copy the scripts found at [/scripts/rs](/scripts/rs) to `prime-reportstream/prime-router` - - **Note**: follow the instructions in [/scripts/rs/readme.md](/scripts/rs/readme.md) to set up the environment variable -3. CD to `prime-reportstream/prime-router` -4. Run the `./cleanslate` script. For more information you can refer to the [ReportStream docs](https://github.com/CDCgov/prime-reportstream/blob/master/prime-router/docs/docs-deprecated/getting-started/getting-started.md#building-the-baseline) -5. If attempting to access the metadata endpoint in ReportStream add the variable `ETOR_TI_baseurl="http://host.docker.internal:8080"` to `.prime-router/.vault/env/.env.local` file before building the container -6. Run RS with `docker compose up --build -d` -7. Run the `reset.sh` script to reset the database -8. Run the `update_org_yaml.sh` script to update the RS organization settings -9. Run the `load-etor-org-settings.sh` to apply the ETOR organization settings -10. Run the `setup-local-vault.sh` script to set up the local vault secrets - - You can verify that the script created the secrets successfully by going to `http://localhost:8200/` in your browser, use the token in `prime-router/.vault/env/.env.local` to authenticate, and then go to `Secrets engines` > `secret/` to check the available secrets +2. Build RS (for more information please refer to the [ReportStream docs](https://github.com/CDCgov/prime-reportstream/blob/master/prime-router/docs/getting-started/README.md)): + - If building for the first time, run: `./cleanslate` in `prime-reportstream/prime-router` + - Otherwise run: `./gradlew clean package` in `prime-reportstream` root folder + - If attempting to access the metadata endpoint in RS add the variable `ETOR_TI_baseurl="http://host.docker.internal:8080"` to `prime-router/.vault/env/.env.local` file before building the container +3. Run RS with `docker compose up -d`. You may also use `./gradlew quickRun` +4. Run the RS setup script in this repository: `/scripts/setup/setup-reportstream.sh` + - Before running the script, make sure to follow the instructions in [/scripts/README.md](/scripts/README.md) + - You can verify the script created vault secrets successfully by going to `http://localhost:8200/` in your browser, use the token in `prime-router/.vault/env/.env.local` to authenticate, and then go to `Secrets engines` > `secret/` to check the available secrets #### Submit request to ReportStream diff --git a/scripts/.env.template b/scripts/.env.template new file mode 100644 index 000000000..747dfb36b --- /dev/null +++ b/scripts/.env.template @@ -0,0 +1,26 @@ +# Core settings +# Use $HOME or the full path to your home directory instead of ~ +CDCTI_HOME="/path/to/trusted-intermediary" +RS_HOME="/path/to/prime-reportstream" + +# API URLs +RS_LCL_API_URL="http://localhost:7071" +RS_STG_API_URL="https://staging.prime.cdc.gov:443" +RS_PRD_API_URL="https://prime.cdc.gov:443" +TI_LCL_API_URL="http://localhost:8080" +TI_STG_API_URL="https://cdcti-stg-api.azurewebsites.net:443" +TI_PRD_API_URL="https://cdcti-prd-api.azurewebsites.net:443" + +# Client keys +TI_LOCAL_PRIVATE_KEY_PATH="${CDCTI_HOME}/mock_credentials/organization-trusted-intermediary-private-key-local.pem" +TI_LOCAL_PUBLIC_KEY_PATH="${CDCTI_HOME}/mock_credentials/organization-trusted-intermediary-public-key-local.pem" +RS_LOCAL_PRIVATE_KEY_PATH="${CDCTI_HOME}/mock_credentials/organization-report-stream-private-key-local.pem" + +# Storage settings +AZURITE_CONNECTION_STRING="DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://localhost:10000/devstoreaccount1;" # pragma: allowlist secret + +# Message snapshot suffixes +FILE_NAME_SUFFIX_STEP_0="_0_initial_message" +FILE_NAME_SUFFIX_STEP_1="_1_hl7_translation" +FILE_NAME_SUFFIX_STEP_2="_2_fhir_transformation" +FILE_NAME_SUFFIX_STEP_3="_3_hl7_translation_final" diff --git a/scripts/README.md b/scripts/README.md index 3fa583ac1..2e8ae53b4 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,3 +1,236 @@ # Scripts -These scripts rely in a `CDCTI_HOME` environment variable that needs to be set in your environment to your local path to the CDC-TI codebase. You may update and run the `start-here.sh` script to set it. You may also want to add it to your shell's startup file to persist it. +## Setup + +Follow the instructions below to load the environments variables required for these scripts + +1. Copy `.env.template` to `.env` + ``` + cp .env.template .env + ``` +2. Edit `.env` and make sure to update at least: + - `CDCTI_HOME`: local path to the `trusted-intermediary` codebase + - `RS_HOME`: local path to the `prime-reportstream` codebase + - **Note**: if you don't set `CDCTI_HOME`, none of these scripts will work. Also, please use `$HOME` or the full path to your home directory instead of `~` +3. Export the environment variables in `.env` by running + ``` + set -a; source .env; set +a + ``` + **Note**: you may also want to add it to your shell's startup file so you don't need to run it for every terminal session. +4. Run your script + +## Available Scripts + +### submit.sh + +Sends a HL7 message to RS and tracks its status throughout the flow until final delivery. When running locally, it grabs the snapshots of the file in azurite after converting to FHIR, after applying transformations in TI, and after converting back to HL7; and it copies those files to the same folder where the submitted file is. If running in a deployed environment we currently don't have a way to download the files from Azure, but the script will print the relative path for the files in the blob storage container. + +#### Requirements + +- hurl +- jq +- azure-cli + +#### Usage + +``` +Usage: ./submit.sh -f [-e ] + +Options: + -f Message file path (Required) + -e Environment: local|staging|production (Default: local) + -x Path to the client private key for authentication with RS API (Required for non-local environments) + -z Path to the client private key for authentication with TI API (Optional for all environments) + -h Display this help and exit +``` + +### rs.sh + +Submit requests to RS API endpoints + +#### Requirements + +- hurl +- jwt-cli + +#### Usage + +``` +Usage: ./rs.sh [OPTIONS] + +ENDPOINT_NAME: + The name of the endpoint to call (required) + +Options: + -f Path to the hl7/fhir file to submit (Required for waters API) + -r Root path to the hl7/fhir files (Default: /Users/bbogado/Code/Flexion/CDC-TI/trusted-intermediary/examples/) + -t Content type for the message (Default: application/hl7-v2) + -e Environment: local|staging|production (Default: local) + -c Client ID (Default: flexion) + -s Client sender (Default: simulated-sender) + -k Path to the client private key (Required for non-local environments) + -i Submission ID for history API (Required for history API) + -v Verbose mode + -h Display this help and exit +``` + +#### Examples + +Sending an order to local environment + +``` +./rs.sh waters -f Test/Orders/003_AL_ORM_O01_NBS_Fully_Populated_0_initial_message.hl7 +``` + +Sending a result to local environment + +``` +./rs.sh waters -f Test/Results/002_AL_ORU_R01_NBS_Fully_Populated_0_initial_message.hl7 +``` + +Sending an order to staging + +``` +./rs.sh waters -f Test/Orders/003_AL_ORM_O01_NBS_Fully_Populated_0_initial_message.hl7 -e staging -k /path/to/client/staging/private/key +``` + +Checking the history in local environment for a submission id + +``` +./rs.sh history -i 100 +``` + +Checking the history in staging for a submission id + +``` +./rs.sh history -i 100 -e staging -k /path/to/client/staging/private/key +``` + +### ti.sh + +Submit requests to TI API endpoints + +#### Requirements + +- hurl +- jwt-cli + +#### Usage + +``` +Usage: ./ti.sh [OPTIONS] + +ENDPOINT_NAME: + The name of the endpoint to call (required) + +Options: + -f Path to the hl7/fhir file to submit (Required for orders and results APIs) + -r Root path to the hl7/fhir files (Default: /Users/bbogado/Code/Flexion/CDC-TI/trusted-intermediary/examples/) + -e Environment: local|staging (Default: local) + -c Client ID to create JWT with (Default: report-stream) + -k Path to the client private key (Required for non-local environments) + -i Submission ID for metadata API (Required for orders, results and metadata API) + -v Verbose mode + -h Display this help and exit +``` + +#### Examples + +Submit an order to local environment: +``` +./ti.sh orders -f Test/Orders/003_AL_ORM_O01_NBS_Fully_Populated_1_hl7_translation.fhir -i 100 +``` + +Submit an order to staging: +``` +./ti.sh orders -f Test/Orders/003_AL_ORM_O01_NBS_Fully_Populated_0_initial_message.hl7 -e staging -k /path/to/client/staging/private/key + +``` + +Submit a result to local environment: +``` +./ti.sh results -f Test/Results/002_AL_ORU_R01_NBS_Fully_Populated_1_hl7_translation.fhir -i 100 +``` + +Get metadata from local environment: +``` +./ti.sh metadata -i 100 +``` + +Authenticate to local environment: +``` +./ti.sh auth +``` + +Get OpenAPI docs from local environment: +``` +./ti.sh openapi +``` + +Get Health info from local environment: +``` +./ti.sh health +``` + +### epic.sh + +Submit requests to Epic API endpoints + +#### Requirements + +- hurl + +#### Before running the script + +- Add the `client` id to `epic.sh` +- Update the `secret` variable path + +#### Usage + +`./epic.sh results` + +### setup/update-examples-snapshots.sh + +Sends all the HL7 files with `_0_initial_message.hl7` suffix in the `/examples` folder to a locally running RS instance. As the `submit.sh` script, it downloads the snapshots at each stage. This script is helpful to keep all the message snapshots in the examples folder up to date + +#### Requirements + +- hurl +- jq +- azure-cli + +#### Usage + +``` +./update-examples-snapshots.sh +``` + +### setup/setup-reportstream.sh + +Setup script for ReportStream + +#### Requirements + +- yq + +#### Usage + +``` +./setup-reportstream.sh +``` + +### lib/common.sh + +Utility functions shared by scripts + +### lib/submission-utils.sh + +Functions to submit requests to RS, check the submission status throughout the whole flow, and downloading snapshots from azurite + +## Resources + +- [hurl](https://hurl.dev/) +- [jq](https://jqlang.github.io/jq/) +- [yq](https://github.com/mikefarah/yq) +- [azure-cli](https://learn.microsoft.com/en-us/cli/azure/) +- [jwt-cli](https://github.com/mike-engel/jwt-cli) diff --git a/scripts/hurl/epic.sh b/scripts/epic.sh similarity index 61% rename from scripts/hurl/epic.sh rename to scripts/epic.sh index 57835798d..e1aabbb00 100755 --- a/scripts/hurl/epic.sh +++ b/scripts/epic.sh @@ -1,6 +1,7 @@ #!/bin/bash -source ./utils.sh +[ -z "${CDCTI_HOME}" ] && echo "Error: Environment variable CDCTI_HOME is not set. Please refer to /scripts/README.md for instructions" && exit 1 +source "$CDCTI_HOME/scripts/lib/common.sh" client= audience=https://epicproxy-np.et0502.epichosted.com/FhirProxy/oauth2/token @@ -15,5 +16,5 @@ hurl \ --variable "fpath=$fpath" \ --file-root "$root" \ --variable "jwt=$jwt_token" \ - epic/results.hurl \ - $@ + "$CDCTI_HOME"/scripts/epic/results.hurl \ + "$@" diff --git a/scripts/hurl/README.md b/scripts/hurl/README.md deleted file mode 100644 index 576a9fb75..000000000 --- a/scripts/hurl/README.md +++ /dev/null @@ -1,161 +0,0 @@ -# Hurl Scripts - -## Requirements - -- [hurl](https://hurl.dev/) -- [jq](https://jqlang.github.io/jq/) -- [azure-cli](https://learn.microsoft.com/en-us/cli/azure/) -- [jwt-cli](https://github.com/mike-engel/jwt-cli) -- `CDCTI_HOME` environment variable ([see here](../README.md)) - -## Available Hurl Scripts - -### ReportStream - -#### Usage - -``` -Usage: ./rs.sh [OPTIONS] - -ENDPOINT_NAME: - The name of the endpoint to call (required) - -Options: - -f Path to the hl7/fhir file to submit (Required for waters API) - -r Root path to the hl7/fhir files (Default: /Users/bbogado/Code/Flexion/CDC-TI/trusted-intermediary/examples/) - -t Content type for the message (Default: application/hl7-v2) - -e Environment: local|staging|production (Default: local) - -c Client ID (Default: flexion) - -s Client sender (Default: simulated-sender) - -k Path to the client private key (Required for non-local environments) - -i Submission ID for history API (Required for history API) - -v Verbose mode - -h Display this help and exit - -Environment Variables: - CDCTI_HOME Base directory for CDC TI repository (Required) -``` - -#### Examples - -Sending an order to local environment - -``` -./rs.sh waters -f Test/Orders/003_AL_ORM_O01_NBS_Fully_Populated_0_initial_message.hl7 -``` - -Sending a result to local environment - -``` -./rs.sh waters -f Test/Results/002_AL_ORU_R01_NBS_Fully_Populated_0_initial_message.hl7 -``` - -Sending an order to staging - -``` -./rs.sh waters -f Test/Orders/003_AL_ORM_O01_NBS_Fully_Populated_0_initial_message.hl7 -e staging -k /path/to/client/staging/private/key -``` - -Checking the history in local environment for a submission id - -``` -./rs.sh history -i 100 -``` - -Checking the history in staging for a submission id - -``` -./rs.sh history -i 100 -e staging -k /path/to/client/staging/private/key -``` - -### CDC Intermediary - -#### Usage - -``` -Usage: ./ti.sh [OPTIONS] - -ENDPOINT_NAME: - The name of the endpoint to call (required) - -Options: - -f Path to the hl7/fhir file to submit (Required for orders and results APIs) - -r Root path to the hl7/fhir files (Default: /Users/bbogado/Code/Flexion/CDC-TI/trusted-intermediary/examples/) - -e Environment: local|staging (Default: local) - -c Client ID to create JWT with (Default: report-stream) - -k Path to the client private key (Required for non-local environments) - -i Submission ID for metadata API (Required for orders, results and metadata API) - -v Verbose mode - -h Display this help and exit - -Environment Variables: - CDCTI_HOME Base directory for CDC TI repository (Required) -``` - -#### Examples - -Submit an order to local environment: -``` -./ti.sh orders -f Test/Orders/003_AL_ORM_O01_NBS_Fully_Populated_1_hl7_translation.fhir -i 100 -``` - -Submit an order to staging: -``` -./ti.sh orders -f Test/Orders/003_AL_ORM_O01_NBS_Fully_Populated_0_initial_message.hl7 -e staging -k /path/to/client/staging/private/key - -``` - -Submit a result to local environment: -``` -./ti.sh results -f Test/Results/002_AL_ORU_R01_NBS_Fully_Populated_1_hl7_translation.fhir -i 100 -``` - -Get metadata from local environment: -``` -./ti.sh metadata -i 100 -``` - -Authenticate to local environment: -``` -./ti.sh auth -``` - -Get OpenAPI docs from local environment: -``` -./ti.rs openapi -``` - -Get Health info from local environment: -``` -./ti.sh health -``` - -### Epic/UCSD - -#### Before running the script - -- Add the `client` id to `epic.rs` -- Update the `secret` variable path - -#### Usage - -`./epic.sh results` - -## High Level Scripts - -- `submit_message.sh`: sends a HL7 message to RS and tracks its status throughout the flow until final delivery. When running locally, it grabs the snapshots of the file in azurite after converting to FHIR, after applying transformations in TI, and after converting back to HL7; and it copies those files to the same folder where the submitted file is. If running in a deployed environment we currently don't have a way to download the files from Azure, but the script will print the relative path for the files in the blob storage container. - ``` - Usage: submit_message.sh -f [-e ] - - Options: - -f Message file path (Required) - -e Environment: local|staging|production (Default: ) - -x Path to the client private key for authentication with RS API (Required for non-local environments) - -z Path to the client private key for authentication with TI API (Optional for all environments) - -h Display this help and exit - ``` -- `update_examples.sh`: sends all the HL7 files with `_0_initial_message.hl7` suffix in the `/examples` folder to a locally running RS instance. As the previous script, it copies the snapshots at each stage - ``` - ./update_examples.sh - ``` -- `utils.sh`: utility functions for the previous scripts. It has functions to submit requests to RS, check the submission status throughout the whole flow, and downloading snapshots from azurite diff --git a/scripts/lib/common.sh b/scripts/lib/common.sh new file mode 100755 index 000000000..a4702d178 --- /dev/null +++ b/scripts/lib/common.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +load_env() { + local env_file="$CDCTI_HOME/scripts/.env" + if [[ -f "$env_file" ]]; then + source "$env_file" + else + echo "Error: $env_file file not found" >&2 + return 1 + fi +} +load_env || exit 1 + +fail() { + echo "Error: $1" >&2 + exit 1 +} + +check_env_vars() { + local env_vars=("$@") + for var in "${env_vars[@]}"; do + if [ -z "${!var}" ]; then + echo "Error: Environment variable '$var' is not set" + exit 1 + fi + done +} + +check_installed_commands() { + for cmd in "$@"; do + if ! command -v "$cmd" &>/dev/null; then + echo "$cmd could not be found. Please install $cmd to proceed." + exit 1 + fi + done +} + +check_apis() { + for service in "$@"; do + if ! curl -s --head --fail "$service" | grep "200 OK" >/dev/null; then + echo "The service at $service is not reachable" + exit 1 + fi + done +} + +get_api_url() { + local env=$1 + local type=$2 + + case "$type" in + "rs") + case "$env" in + "local") echo "$RS_LCL_API_URL" ;; + "staging") echo "$RS_STG_API_URL" ;; + "production") echo "$RS_PRD_API_URL" ;; + *) + echo "Invalid environment: $env" >&2 + exit 1 + ;; + esac + ;; + "ti") + case "$env" in + "local") echo "$TI_LCL_API_URL" ;; + "staging") echo "$TI_STG_API_URL" ;; + "production") echo "$TI_PRD_API_URL" ;; + *) + echo "Invalid environment: $env" >&2 + exit 1 + ;; + esac + ;; + esac +} + +extract_host_from_url() { + local url=$1 + echo "$url" | sed 's|^.*://\([^/:]*\)[:/].*|\1|' +} + +generate_jwt() { + # requires: jwt-cli + local client=$1 + local audience=$2 + local secret_path=$3 + + jwt encode \ + --exp='+5min' \ + --jti "$(uuidgen)" \ + --alg RS256 \ + -k "$client" \ + -i "$client" \ + -s "$client" \ + -a "$audience" \ + --no-iat \ + -S "@$secret_path" +} diff --git a/scripts/hurl/utils.sh b/scripts/lib/submission-utils.sh similarity index 67% rename from scripts/hurl/utils.sh rename to scripts/lib/submission-utils.sh index b9d8903f7..21a72e2b7 100755 --- a/scripts/hurl/utils.sh +++ b/scripts/lib/submission-utils.sh @@ -1,108 +1,5 @@ #!/bin/bash -FILE_NAME_SUFFIX_STEP_0="_0_initial_message" -FILE_NAME_SUFFIX_STEP_1="_1_hl7_translation" -FILE_NAME_SUFFIX_STEP_2="_2_fhir_transformation" -FILE_NAME_SUFFIX_STEP_3="_3_hl7_translation_final" - -AZURITE_CONNECTION_STRING="DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://localhost:10000/devstoreaccount1;" # pragma: allowlist secret - -RS_API_LCL_URL="http://localhost:7071" -RS_API_STG_URL="https://staging.prime.cdc.gov:443" -RS_API_PRD_URL="https://prime.cdc.gov:443" -TI_API_LCL_URL="http://localhost:8080" -TI_API_STG_URL="https://cdcti-stg-api.azurewebsites.net:443" -TI_API_PRD_URL="https://cdcti-prd-api.azurewebsites.net:443" - -RS_CLIENT_LOCAL_PRIVATE_KEY_PATH="$CDCTI_HOME/mock_credentials/organization-trusted-intermediary-private-key-local.pem" -TI_CLIENT_LOCAL_PRIVATE_KEY_PATH="$CDCTI_HOME/mock_credentials/organization-report-stream-private-key-local.pem" - -fail() { - echo "Error: $1" >&2 - exit 1 -} - -check_installed_commands() { - for cmd in "$@"; do - if ! command -v "$cmd" &>/dev/null; then - echo "$cmd could not be found. Please install $cmd to proceed." - exit 1 - fi - done -} - -check_apis() { - for service in "$@"; do - if ! curl -s --head --fail "$service" | grep "200 OK" >/dev/null; then - echo "The service at $service is not reachable" - exit 1 - fi - done -} - -check_env_vars() { - local env_vars=("$@") - for var in "${env_vars[@]}"; do - if [ -z "${!var}" ]; then - echo "Error: Environment variable '$var' is not set" - exit 1 - fi - done -} - -get_api_url() { - local env=$1 - local type=$2 - - case "$type" in - "rs") - case "$env" in - "local") echo $RS_API_LCL_URL ;; - "staging") echo $RS_API_STG_URL ;; - "production") echo $RS_API_PRD_URL ;; - *) - echo "Invalid environment: $env" >&2 - exit 1 - ;; - esac - ;; - "ti") - case "$env" in - "local") echo $TI_API_LCL_URL ;; - "staging") echo $TI_API_STG_URL ;; - "production") echo $TI_API_PRD_URL ;; - *) - echo "Invalid environment: $env" >&2 - exit 1 - ;; - esac - ;; - esac -} - -extract_host_from_url() { - local url=$1 - echo "$url" | sed 's|^.*://\([^/:]*\)[:/].*|\1|' -} - -generate_jwt() { - # requires: jwt-cli - local client=$1 - local audience=$2 - local secret_path=$3 - - jwt encode \ - --exp='+5min' \ - --jti "$(uuidgen)" \ - --alg RS256 \ - -k "$client" \ - -i "$client" \ - -s "$client" \ - -a "$audience" \ - --no-iat \ - -S "@$secret_path" -} - extract_rs_history_submission_id() { # requires: jq local history_response=$1 @@ -153,7 +50,7 @@ check_submission_status() { start_time=$(date +%s) while true; do - history_response=$(./rs.sh history -i "$submission_id" -e "$env" -k "$private_key") || { + history_response=$("$CDCTI_HOME"/scripts/rs.sh history -i "$submission_id" -e "$env" -k "$private_key") || { exit_code=$? if [ $exit_code -ne 0 ]; then fail "Expected exit code 0 but got $exit_code for RS history API call" @@ -212,7 +109,7 @@ submit_message() { echo "Assuming receivers are '$first_leg_receiver' and '$second_leg_receiver' because of MSH-9 value '$msh9'" - waters_response=$(./rs.sh waters -f "$message_file_name" -r "$message_file_path" -e "$env" -k "$rs_client_private_key") || { + waters_response=$("$CDCTI_HOME"/scripts/rs.sh waters -f "$message_file_name" -r "$message_file_path" -e "$env" -k "$rs_client_private_key") || { exit_code=$? if [ $exit_code -ne 0 ]; then fail "Expected exit code 0 but got $exit_code for RS waters API call" @@ -239,7 +136,7 @@ submit_message() { echo "[Intermediary] Getting outbound submission ID" if [ -n "$ti_client_private_key" ]; then echo " Attempting to get outbound submission ID from TI's metadata API..." - metadata_response=$(./ti.sh metadata -i "$inbound_submission_id" -e "$env" -k "$ti_client_private_key") || { + metadata_response=$("$CDCTI_HOME"/scripts/ti.sh metadata -i "$inbound_submission_id" -e "$env" -k "$ti_client_private_key") || { echo "Failed to get metadata for inbound submission ID: $inbound_submission_id" outbound_submission_id="" } diff --git a/scripts/hurl/rs.sh b/scripts/rs.sh similarity index 84% rename from scripts/hurl/rs.sh rename to scripts/rs.sh index 39a65d669..1a5da946a 100755 --- a/scripts/hurl/rs.sh +++ b/scripts/rs.sh @@ -1,6 +1,7 @@ #!/bin/bash -source ./utils.sh +[ -z "${CDCTI_HOME}" ] && echo "Error: Environment variable CDCTI_HOME is not set. Please refer to /scripts/README.md for instructions" && exit 1 +source "$CDCTI_HOME/scripts/lib/common.sh" # default values env=local @@ -11,7 +12,7 @@ client_sender=simulated-sender show_usage() { cat < [OPTIONS] +Usage: ./$(basename "$0") [OPTIONS] ENDPOINT_NAME: The name of the endpoint to call (required) @@ -27,9 +28,6 @@ Options: -i Submission ID for history API (Required for history API) -v Verbose mode -h Display this help and exit - -Environment Variables: - CDCTI_HOME Base directory for CDC TI repository (Required) EOF } @@ -40,7 +38,7 @@ parse_arguments() { fi [ $# -eq 0 ] && fail "Missing required argument " - endpoint_name="rs/$1.hurl" + hurl_file_path="$CDCTI_HOME/scripts/hurl/rs/$1.hurl" shift # Remove endpoint name from args while getopts ':f:r:t:e:c:s:k:i:v' opt; do @@ -58,16 +56,16 @@ parse_arguments() { esac done - shift "$(($OPTIND - 1))" + shift "$((OPTIND - 1))" remaining_args="$*" } setup_credentials() { if [ -z "$private_key" ] && [ "$client_id" = "flexion" ] && [ "$env" = "local" ]; then - if [ -f "$RS_CLIENT_LOCAL_PRIVATE_KEY_PATH" ]; then - private_key="$RS_CLIENT_LOCAL_PRIVATE_KEY_PATH" + if [ -f "$TI_LOCAL_PRIVATE_KEY_PATH" ]; then + private_key="$TI_LOCAL_PRIVATE_KEY_PATH" else - fail "Local environment client private key not found at: $RS_CLIENT_LOCAL_PRIVATE_KEY_PATH" + fail "Local environment client private key not found at: $TI_LOCAL_PRIVATE_KEY_PATH" fi fi @@ -93,11 +91,10 @@ run_hurl_command() { --variable "jwt=$jwt_token" \ ${submission_id:-} \ ${verbose:-} \ - "$endpoint_name" \ + "$hurl_file_path" \ ${remaining_args:+$remaining_args} } -check_env_vars CDCTI_HOME parse_arguments "$@" setup_credentials run_hurl_command diff --git a/scripts/rs/README.md b/scripts/rs/README.md deleted file mode 100644 index ebf318acf..000000000 --- a/scripts/rs/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# ReportStream Scripts - -The scripts in this folder are meant to be copied and run in the [prime-reportstream](https://github.com/CDCgov/prime-reportstream) codebase inside the `prime-router` folder. You can also create symbolic links instead of copying the files in order to keep them up-to-date. diff --git a/scripts/rs/load-etor-org-settings.sh b/scripts/rs/load-etor-org-settings.sh deleted file mode 100755 index 9eae5d39e..000000000 --- a/scripts/rs/load-etor-org-settings.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash - -# This script loads the ETOR organization settings and adds the public keys for the senders. -# NOTE: Remember to run this script inside the prime-router directory of the prime-reportstream codebase -# Make sure to add a CDCTI_HOME environment variable pointing to the trusted-intermediary directory -# export CDCTI_HOME="/path/to/trusted-intermediary" -# You'll also need to set the path to the keys if running in a non-local environment - -env=${1:-"local"} - -if [ "$env" = "local" ]; then - echo "Using local public keys" - flexion_key="$CDCTI_HOME/mock_credentials/organization-trusted-intermediary-public-key-local.pem" - # al_phl_key="/path/to/organization-al-phl-public-key-local.pem" - # oracle_rln_key="/path/to/organization-oracle-rln-public-key-local.pem" - # la_phl_key="/path/to/organization-la-phl-public-key-local.pem" - # la_ochsner_key="/path/to/organization-la-ochsner-public-key-local.pem" -elif [ "$env" = "staging" ]; then - echo "Using staging public keys" - # flexion_key="/path/to/organization-trusted-intermediary-public-key-staging.pem" - # al_phl_key="/path/to/organization-al-phl-public-key-staging.pem" - # oracle_rln_key="/path/to/organization-oracle-rln-public-key-staging.pem" - # la_phl_key="/path/to/organization-la-phl-public-key-staging.pem" - # la_ochsner_key="/path/to/organization-la-ochsner-public-key-staging.pem" -elif [ "$env" = "prod" ]; then - echo "Using prod public keys" - # flexion_key="/path/to/organization-trusted-intermediary-public-key-prod.pem" - # al_phl_key="/path/to/organization-al-phl-public-key-prod.pem" - # oracle_rln_key="/path/to/organization-oracle-rln-public-key-prod.pem" - # la_phl_key="/path/to/organization-la-phl-public-key-prod.pem" - # la_ochsner_key="/path/to/organization-la-ochsner-public-key-prod.pem" -else - echo "Unknown environment: $env" - exit 1 -fi - -## Flexion -./prime multiple-settings set -s -e $env -i ./settings/STLTs/Flexion/flexion.yml -./prime organization addkey -e $env --public-key $flexion_key --scope "flexion.*.report" --orgName flexion --kid flexion.etor-service-sender --doit -./prime organization addkey -e $env --public-key $flexion_key --scope "flexion.*.report" --orgName flexion --kid flexion.simulated-hospital --doit -./prime organization addkey -e $env --public-key $flexion_key --scope "flexion.*.report" --orgName flexion --kid flexion.simulated-lab --doit -./prime organization addkey -e $env --public-key $flexion_key --scope "flexion.*.report" --orgName flexion --kid flexion.simulated-sender --doit - -## CA -./prime multiple-settings set -s -e $env -i ./settings/STLTs/CA/ucsd.yml - -## LA -./prime multiple-settings set -s -e $env -i ./settings/STLTs/LA/la-phl.yml -# ./prime organization addkey -e $env --public-key $la_phl_key --scope "la-phl.*.report" --orgName la-phl --kid la-phl.etor-nbs-results --doit -./prime multiple-settings set -s -e $env -i ./settings/STLTs/LA/la-ochsner.yml -# ./prime organization addkey -e $env --public-key $la_ochsner_key --scope "la-ochsner.*.report" --orgName la-ochsner --kid la-ochsner.etor-nbs-orders --doit diff --git a/scripts/rs/reset.sh b/scripts/rs/reset.sh deleted file mode 100755 index 558b7a799..000000000 --- a/scripts/rs/reset.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -# This script resets the database and loads the baseline settings. -# NOTE: Remember to run this script inside the prime-router directory of the prime-reportstream codebase - -# Reset database -../gradlew resetDB - -# Reload tables -./prime lookuptables loadall - -# Load baseline organization settings -./prime multiple-settings set -s -i ./settings/organizations.yml diff --git a/scripts/rs/setup-local-vault.sh b/scripts/rs/setup-local-vault.sh deleted file mode 100755 index 953f66a0a..000000000 --- a/scripts/rs/setup-local-vault.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -# This script loads the credentials into the local vault to set up the ETOR receivers. -# NOTE: Remember to run this script inside the prime-router directory of the prime-reportstream codebase -# Make sure to add a CDCTI_HOME environment variable pointing to the trusted-intermediary directory -# export CDCTI_HOME="/path/to/trusted-intermediary" - -private_key=$(cat $CDCTI_HOME/mock_credentials/organization-report-stream-private-key-local.pem) - -export $(xargs <.vault/env/.env.local) - -./prime create-credential --type UserPass --user foo --pass pass --persist DEFAULT-SFTP -./prime create-credential --type UserApiKey --apikey-user flexion --apikey "$private_key" --persist FLEXION--ETOR-SERVICE-RECEIVER-ORDERS -./prime create-credential --type UserApiKey --apikey-user flexion --apikey "$private_key" --persist FLEXION--ETOR-SERVICE-RECEIVER-RESULTS -./prime create-credential --type UserApiKey --apikey-user ucsd --apikey "$private_key" --persist UCSD--ETOR-NBS-RESULTS -./prime create-credential --type UserApiKey --apikey-user la-phl --apikey "$private_key" --persist LA-PHL--ETOR-NBS-ORDERS -./prime create-credential --type UserApiKey --apikey-user la-ochsner --apikey "$private_key" --persist LA-OCHSNER--ETOR-NBS-RESULTS diff --git a/scripts/rs/update_org_yaml.sh b/scripts/rs/update_org_yaml.sh deleted file mode 100755 index 5ccce812e..000000000 --- a/scripts/rs/update_org_yaml.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash - -source "$CDCTI_HOME/scripts/hurl/utils.sh" - -# This script updates the organization settings YAML files in RS to: -# - use local REST transport settings for Flexion's etor-service-receiver receivers -# - use local SFTP transport settings for Flexion's simulated-hospital and simulated-lab receivers -# - use local SFTP transport settings for partner organizations - -# Requirements: -# - yq (https://github.com/mikefarah/yq) -# - This script should run inside the prime-router directory of the prime-reportstream codebase - -ORG_SETTINGS_DIR="settings/STLTs" - -check_installed_commands yq - -echo "Updating transport in Flexion org settings file..." -yq eval '.[0].receivers[] |= ( - select(.name == "simulated-hospital" or .name == "simulated-lab").transport = { - "type": "SFTP", - "host": "sftp", - "port": 22, - "filePath": "./upload", - "credentialName": "DEFAULT-SFTP" - } | - select(.name == "etor-service-receiver-orders") |= ( - .transport.authTokenUrl = "http://host.docker.internal:8080/v1/auth/token" | - .transport.reportUrl = "http://host.docker.internal:8080/v1/etor/orders" - ) | - select(.name == "etor-service-receiver-results") |= ( - .transport.authTokenUrl = "http://host.docker.internal:8080/v1/auth/token" | - .transport.reportUrl = "http://host.docker.internal:8080/v1/etor/results" - ) -)' -i "$ORG_SETTINGS_DIR/Flexion/flexion.yml" - -echo "Updating transport in partner org settings files..." -for file in "$ORG_SETTINGS_DIR/CA/ucsd.yml" "$ORG_SETTINGS_DIR/LA/la-ochsner.yml" "$ORG_SETTINGS_DIR/LA/la-phl.yml"; do - yq eval '.[0].receivers[] |= select(.name == "etor-nbs-results" or .name == "etor-nbs-orders").transport = { - "type": "SFTP", - "host": "sftp", - "port": 22, - "filePath": "./upload", - "credentialName": "DEFAULT-SFTP" - }' -i "$file" -done - -echo "Updates completed." diff --git a/scripts/setup/setup-reportstream.sh b/scripts/setup/setup-reportstream.sh new file mode 100755 index 000000000..2fdc3710c --- /dev/null +++ b/scripts/setup/setup-reportstream.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash + +[ -z "${CDCTI_HOME}" ] && echo "Error: Environment variable CDCTI_HOME is not set. Please refer to /scripts/README.md for instructions" && exit 1 +source "$CDCTI_HOME/scripts/lib/common.sh" + +# Check requirements for this script +check_env_vars RS_HOME +check_installed_commands yq + +# Need to CD to the RS codebase local working copy to run the gradlew commands +CURRENT_DIR=$(pwd) +cd "$RS_HOME" || exit + +echo "Resetting the database and loading the baseline settings..." +./gradlew resetDB +./gradlew reloadTable +./gradlew reloadSettings + +# Need to CD to prime-router to run the prime CLI +cd "prime-router" || exit + +echo "Updating transport settings in Flexion org file..." +yq eval '.[0].receivers[] |= ( + select(.name == "etor-service-receiver-orders") |= ( + .transport.authTokenUrl = "__TI_API_URL__/v1/auth/token" | + .transport.reportUrl = "__TI_API_URL__/v1/etor/orders" | + .transport.authHeaders.Host = "__TI_API_HOST__" + ) | + select(.name == "etor-service-receiver-results") |= ( + .transport.authTokenUrl = "__TI_API_URL__/v1/auth/token" | + .transport.reportUrl = "__TI_API_URL__/v1/etor/results" | + .transport.authHeaders.Host = "__TI_API_HOST__" + ) | + select(.name == "simulated-hospital" or .name == "simulated-lab").transport = { + "type": "SFTP", + "host": "sftp", + "port": 22, + "filePath": "./upload", + "credentialName": "DEFAULT-SFTP" + } +)' -i "settings/STLTs/Flexion/flexion.yml" + +echo "Updating local URL and host in transport settings..." +sed -i '' "s|__TI_API_URL__|${TI_LCL_API_URL}|g" "settings/STLTs/Flexion/flexion.yml" +sed -i '' "s|__TI_API_HOST__|$(extract_host_from_url "${TI_LCL_API_URL}")|g" "settings/STLTs/Flexion/flexion.yml" + +echo "Updating transport settings in partner org files..." +for file in "settings/STLTs/CA/ucsd.yml" "settings/STLTs/LA/la-ochsner.yml" "settings/STLTs/LA/la-phl.yml"; do + yq eval '.[0].receivers[] |= select(.name == "etor-nbs-results" or .name == "etor-nbs-orders").transport = { + "type": "SFTP", + "host": "sftp", + "port": 22, + "filePath": "./upload", + "credentialName": "DEFAULT-SFTP" + }' -i "$file" +done + +echo "Setting up the organization settings..." +./prime multiple-settings set -s -i ./settings/STLTs/Flexion/flexion.yml +./prime multiple-settings set -s -i ./settings/STLTs/CA/ucsd.yml +./prime multiple-settings set -s -i ./settings/STLTs/LA/la-phl.yml +./prime multiple-settings set -s -i ./settings/STLTs/LA/la-ochsner.yml + +echo "Adding public keys for senders..." +./prime organization addkey --public-key "$TI_LOCAL_PUBLIC_KEY_PATH" --scope "flexion.*.report" --orgName flexion --kid flexion.etor-service-sender --doit +./prime organization addkey --public-key "$TI_LOCAL_PUBLIC_KEY_PATH" --scope "flexion.*.report" --orgName flexion --kid flexion.simulated-hospital --doit +./prime organization addkey --public-key "$TI_LOCAL_PUBLIC_KEY_PATH" --scope "flexion.*.report" --orgName flexion --kid flexion.simulated-lab --doit +./prime organization addkey --public-key "$TI_LOCAL_PUBLIC_KEY_PATH" --scope "flexion.*.report" --orgName flexion --kid flexion.simulated-sender --doit + +echo "Adding credentials for receivers..." +export $(xargs <"$RS_HOME/prime-router/.vault/env/.env.local") +rs_private_key=$(cat "$RS_LOCAL_PRIVATE_KEY_PATH") + +./prime create-credential --type UserPass --user foo --pass pass --persist DEFAULT-SFTP +./prime create-credential --type UserApiKey --apikey-user flexion --apikey "$rs_private_key" --persist FLEXION--ETOR-SERVICE-RECEIVER-ORDERS +./prime create-credential --type UserApiKey --apikey-user flexion --apikey "$(cat "$RS_LOCAL_PRIVATE_KEY_PATH")" --persist FLEXION--ETOR-SERVICE-RECEIVER-RESULTS +./prime create-credential --type UserApiKey --apikey-user ucsd --apikey "$rs_private_key" --persist UCSD--ETOR-NBS-RESULTS +./prime create-credential --type UserApiKey --apikey-user la-phl --apikey "$rs_private_key" --persist LA-PHL--ETOR-NBS-ORDERS +./prime create-credential --type UserApiKey --apikey-user la-ochsner --apikey "$rs_private_key" --persist LA-OCHSNER--ETOR-NBS-RESULTS + +cd "$CURRENT_DIR" || exit diff --git a/scripts/hurl/update_examples.sh b/scripts/setup/update-examples-snapshots.sh similarity index 53% rename from scripts/hurl/update_examples.sh rename to scripts/setup/update-examples-snapshots.sh index d140ebfab..959457294 100755 --- a/scripts/hurl/update_examples.sh +++ b/scripts/setup/update-examples-snapshots.sh @@ -1,6 +1,8 @@ #!/bin/bash -source ./utils.sh +[ -z "${CDCTI_HOME}" ] && echo "Error: Environment variable CDCTI_HOME is not set. Please refer to /scripts/README.md for instructions" && exit 1 +source "$CDCTI_HOME/scripts/lib/common.sh" +source "$CDCTI_HOME/scripts/lib/submission-utils.sh" env=local @@ -10,5 +12,5 @@ check_apis "$(get_api_url "$env" "rs")" "$(get_api_url "$env" "ti")" find "$CDCTI_HOME/examples" -type f -name "*$FILE_NAME_SUFFIX_STEP_0.hl7" | while read -r file; do echo "-----------------------------------------------------------------------------------------------------------" echo "Submitting message: $file" - submit_message "$env" "$file" "$RS_CLIENT_LOCAL_PRIVATE_KEY_PATH" "$TI_CLIENT_LOCAL_PRIVATE_KEY_PATH" + submit_message "$env" "$file" "$TI_LOCAL_PRIVATE_KEY_PATH" "$RS_LOCAL_PRIVATE_KEY_PATH" done diff --git a/scripts/start-here.sh b/scripts/start-here.sh deleted file mode 100755 index 3392408f8..000000000 --- a/scripts/start-here.sh +++ /dev/null @@ -1 +0,0 @@ -export CDCTI_HOME="/path/to/trusted-intermediary" diff --git a/scripts/hurl/submit_message.sh b/scripts/submit.sh similarity index 84% rename from scripts/hurl/submit_message.sh rename to scripts/submit.sh index 35c7ccfdb..1a93990b5 100755 --- a/scripts/hurl/submit_message.sh +++ b/scripts/submit.sh @@ -1,6 +1,8 @@ #!/bin/bash -source ./utils.sh +[ -z "${CDCTI_HOME}" ] && echo "Error: Environment variable CDCTI_HOME is not set. Please refer to /scripts/README.md for instructions" && exit 1 +source "$CDCTI_HOME/scripts/lib/common.sh" +source "$CDCTI_HOME/scripts/lib/submission-utils.sh" env="local" @@ -10,7 +12,7 @@ Usage: $(basename "$0") -f [-e ] Options: -f Message file path (Required) - -e Environment: local|staging|production (Default: $DEFAULT_ENV) + -e Environment: local|staging|production (Default: $env) -x Path to the client private key for authentication with RS API (Required for non-local environments) -z Path to the client private key for authentication with TI API (Optional for all environments) -h Display this help and exit @@ -46,7 +48,7 @@ parse_arguments() { setup_credentials() { # Handle RS client key if [ "$env" = "local" ] && [ -z "$rs_client_private_key" ]; then - rs_client_private_key="$RS_CLIENT_LOCAL_PRIVATE_KEY_PATH" + rs_client_private_key="$TI_LOCAL_PRIVATE_KEY_PATH" fi [ "$env" != "local" ] && [ -z "$rs_client_private_key" ] && fail "RS client private key (-x) is required for non-local environments" @@ -54,7 +56,7 @@ setup_credentials() { # Handle optional TI client key if [ "$env" = "local" ] && [ -z "$ti_client_private_key" ]; then - ti_client_private_key="$TI_CLIENT_LOCAL_PRIVATE_KEY_PATH" + ti_client_private_key="$RS_LOCAL_PRIVATE_KEY_PATH" fi # Only verify TI key if provided diff --git a/scripts/hurl/ti.sh b/scripts/ti.sh similarity index 83% rename from scripts/hurl/ti.sh rename to scripts/ti.sh index 9278dc147..6df6c342c 100755 --- a/scripts/hurl/ti.sh +++ b/scripts/ti.sh @@ -1,6 +1,7 @@ #!/bin/bash -source ./utils.sh +[ -z "${CDCTI_HOME}" ] && echo "Error: Environment variable CDCTI_HOME is not set. Please refer to /scripts/README.md for instructions" && exit 1 +source "$CDCTI_HOME/scripts/lib/common.sh" # default values env=local @@ -9,7 +10,7 @@ client=report-stream show_usage() { cat < [OPTIONS] +Usage: ./$(basename "$0") [OPTIONS] ENDPOINT_NAME: The name of the endpoint to call (required) @@ -23,9 +24,6 @@ Options: -i Submission ID for metadata API (Required for orders, results and metadata API) -v Verbose mode -h Display this help and exit - -Environment Variables: - CDCTI_HOME Base directory for CDC TI repository (Required) EOF } @@ -36,7 +34,7 @@ parse_arguments() { fi [ $# -eq 0 ] && fail "Missing required argument " - endpoint_name="ti/$1.hurl" + hurl_file_path="$CDCTI_HOME/scripts/hurl/ti/$1.hurl" shift # Remove endpoint name from args while getopts ':f:r:e:c:k:i:v' opt; do @@ -52,16 +50,16 @@ parse_arguments() { esac done - shift "$(($OPTIND - 1))" + shift "$((OPTIND - 1))" remaining_args="$*" } setup_credentials() { if [ -z "$private_key" ] && [ "$client" = "report-stream" ] && [ "$env" = "local" ]; then - if [ -f "$TI_CLIENT_LOCAL_PRIVATE_KEY_PATH" ]; then - private_key="$TI_CLIENT_LOCAL_PRIVATE_KEY_PATH" + if [ -f "$RS_LOCAL_PRIVATE_KEY_PATH" ]; then + private_key="$RS_LOCAL_PRIVATE_KEY_PATH" else - fail "Local environment client private key not found at: $TI_CLIENT_LOCAL_PRIVATE_KEY_PATH" + fail "Local environment client private key not found at: $RS_LOCAL_PRIVATE_KEY_PATH" fi fi @@ -85,11 +83,10 @@ run_hurl_command() { --variable "jwt=$jwt_token" \ ${submission_id:-} \ ${verbose:-} \ - "$endpoint_name" \ + "$hurl_file_path" \ ${remaining_args:+$remaining_args} } -check_env_vars CDCTI_HOME parse_arguments "$@" setup_credentials run_hurl_command