diff --git a/.secrets.baseline b/.secrets.baseline index 897697770..132069bbd 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -218,7 +218,7 @@ "filename": "operations/template/db.tf", "hashed_secret": "7cb6efb98ba5972a9b5090dc2e517fe14d12cb04", "is_verified": false, - "line_number": 20, + "line_number": 16, "is_secret": false } ], @@ -243,5 +243,5 @@ } ] }, - "generated_at": "2024-05-28T21:15:26Z" + "generated_at": "2024-11-21T18:04:15Z" } diff --git a/operations/template/db.tf b/operations/template/db.tf index d93844836..bf267fb35 100644 --- a/operations/template/db.tf +++ b/operations/template/db.tf @@ -1,7 +1,3 @@ -data "azuread_service_principal" "principal" { - object_id = data.azurerm_client_config.current.object_id -} - resource "azurerm_postgresql_flexible_server" "database" { name = "cdcti-${var.environment}-database" resource_group_name = data.azurerm_resource_group.group.name diff --git a/operations/template/main.tf b/operations/template/main.tf index bc083cff3..f6af3dd36 100644 --- a/operations/template/main.tf +++ b/operations/template/main.tf @@ -17,4 +17,5 @@ data "azurerm_resource_group" "group" { name = "csels-rsti-${var.environment}-moderate-rg" } +# See here for explanation: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/client_config.html data "azurerm_client_config" "current" {} diff --git a/scripts/.env.template b/scripts/.env.template index 11167ff81..4e274092e 100644 --- a/scripts/.env.template +++ b/scripts/.env.template @@ -11,7 +11,7 @@ TI_LCL_API_URL="http://host.docker.internal: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 +# Sender 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" diff --git a/scripts/README.md b/scripts/README.md index 2e8ae53b4..554dd3434 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -39,8 +39,8 @@ 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) + -x Path to the sender private key for authentication with RS API (Required for non-local environments) + -z Path to the sender private key for authentication with TI API (Optional for all environments) -h Display this help and exit ``` @@ -62,14 +62,14 @@ 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) + -e Environment: local|staging (Default: local) + -f Path to the message file to submit (Required for submission endpoints) + -r Root path to the message files (Default: /Users/bbogado/Code/Flexion/CDC-TI/trusted-intermediary/examples/) + -t Content type for the message file (Default: application/hl7-v2) + -k Path to the sender private key (Required for non-local environments) + -s Sender ID used for authentication (Default: flexion.simulated-sender) + -u URL root for the API endpoint (Default: auto-detected) + -i Submission ID (Required for query endpoints) -v Verbose mode -h Display this help and exit ``` @@ -91,7 +91,7 @@ Sending a result to local environment 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 +./rs.sh waters -f Test/Orders/003_AL_ORM_O01_NBS_Fully_Populated_0_initial_message.hl7 -e staging -k /path/to/sender/staging/private/key ``` Checking the history in local environment for a submission id @@ -103,7 +103,7 @@ Checking the history in local environment for a submission id Checking the history in staging for a submission id ``` -./rs.sh history -i 100 -e staging -k /path/to/client/staging/private/key +./rs.sh history -i 100 -e staging -k /path/to/sender/staging/private/key ``` ### ti.sh @@ -124,12 +124,14 @@ 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) + -f Path to the message file to submit (Required for submission endpoints) + -r Root path to the message files (Default: /Users/bbogado/Code/Flexion/CDC-TI/trusted-intermediary/examples/) + -t Content type for the message file (Default: application/fhir+ndjson) + -k Path to the sender private key (Required for non-local environments) + -s Sender ID used for authentication (Default: report-stream) + -u URL root for the API endpoint (Default: auto-detected) + -i Submission ID (Required for query endpoints) -v Verbose mode -h Display this help and exit ``` @@ -143,7 +145,7 @@ Submit an order to local environment: 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 +./ti.sh orders -f Test/Orders/003_AL_ORM_O01_NBS_Fully_Populated_0_initial_message.hl7 -e staging -k /path/to/sender/staging/private/key ``` @@ -172,9 +174,9 @@ Get Health info from local environment: ./ti.sh health ``` -### epic.sh +### ucsd.sh -Submit requests to Epic API endpoints +Submit requests to UCSD API endpoints #### Requirements @@ -182,12 +184,12 @@ Submit requests to Epic API endpoints #### Before running the script -- Add the `client` id to `epic.sh` +- Add the `sender` id to `ucsd.sh` - Update the `secret` variable path #### Usage -`./epic.sh results` +`./ucsd.sh results -k /path/to/ucsd-ucsd-private-key.pem -s sender_name` ### setup/update-examples-snapshots.sh diff --git a/scripts/epic.sh b/scripts/epic.sh deleted file mode 100755 index e1aabbb00..000000000 --- a/scripts/epic.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/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" - -client= -audience=https://epicproxy-np.et0502.epichosted.com/FhirProxy/oauth2/token -secret=/path/to/ucsd-epic-private-key.pem -root=$CDCTI_HOME/examples/CA/ -fpath="$1" -shift - -jwt_token=$(generate_jwt "$client" "$audience" "$secret") || fail "Failed to generate JWT token" - -hurl \ - --variable "fpath=$fpath" \ - --file-root "$root" \ - --variable "jwt=$jwt_token" \ - "$CDCTI_HOME"/scripts/epic/results.hurl \ - "$@" diff --git a/scripts/hurl/rs/delivery.hurl b/scripts/hurl/rs/delivery.hurl index ec86bc53a..b04dacc98 100644 --- a/scripts/hurl/rs/delivery.hurl +++ b/scripts/hurl/rs/delivery.hurl @@ -1,8 +1,8 @@ -# curl --header 'Content-Type: application/x-www-form-urlencoded' --data 'scope=flexion.*.report' --data 'client_assertion=$(jwt encode --exp=+5min --jti $(uuidgen) --alg RS256 -k $client -i $client -s $client -a $host --no-iat -S @/path/to/ucsd-epic-private-key.pem) --data 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' --data 'grant_type=client_credentials' 'http://localhost:7071/api/token' +# curl --header 'Content-Type: application/x-www-form-urlencoded' --data 'scope=flexion.*.report' --data 'client_assertion=$(jwt encode --exp=+5min --jti $(uuidgen) --alg RS256 -k $sender -i $sender -s $sender -a $host --no-iat -S @/path/to/ucsd-epic-private-key.pem) --data 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' --data 'grant_type=client_credentials' 'http://localhost:7071/api/token' POST {{url}}/api/token Content-Type: application/x-www-form-urlencoded [FormParams] -scope: {{client-id}}.*.report +scope: {{sender-org}}.*.report client_assertion: {{jwt}} client_assertion_type: urn:ietf:params:oauth:client-assertion-type:jwt-bearer grant_type: client_credentials diff --git a/scripts/hurl/rs/history.hurl b/scripts/hurl/rs/history.hurl index 5eec369cf..db98abd07 100644 --- a/scripts/hurl/rs/history.hurl +++ b/scripts/hurl/rs/history.hurl @@ -1,8 +1,8 @@ -# curl --header 'Content-Type: application/x-www-form-urlencoded' --data 'scope=flexion.*.report' --data 'client_assertion=$(jwt encode --exp=+5min --jti $(uuidgen) --alg RS256 -k $client -i $client -s $client -a $host --no-iat -S @/path/to/ucsd-epic-private-key.pem) --data 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' --data 'grant_type=client_credentials' 'http://localhost:7071/api/token' +# curl --header 'Content-Type: application/x-www-form-urlencoded' --data 'scope=flexion.*.report' --data 'client_assertion=$(jwt encode --exp=+5min --jti $(uuidgen) --alg RS256 -k $sender -i $sender -s $sender -a $host --no-iat -S @/path/to/ucsd-epic-private-key.pem) --data 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' --data 'grant_type=client_credentials' 'http://localhost:7071/api/token' POST {{url}}/api/token Content-Type: application/x-www-form-urlencoded [FormParams] -scope: {{client-id}}.*.report +scope: {{sender-org}}.*.report client_assertion: {{jwt}} client_assertion_type: urn:ietf:params:oauth:client-assertion-type:jwt-bearer grant_type: client_credentials diff --git a/scripts/hurl/rs/token.hurl b/scripts/hurl/rs/token.hurl index d4479d6a3..9217ccdae 100644 --- a/scripts/hurl/rs/token.hurl +++ b/scripts/hurl/rs/token.hurl @@ -1,8 +1,8 @@ -# curl --header 'Content-Type: application/x-www-form-urlencoded' --data 'scope=flexion.*.report' --data 'client_assertion=$(jwt encode --exp=+5min --jti $(uuidgen) --alg RS256 -k $client -i $client -s $client -a $host --no-iat -S @/path/to/ucsd-epic-private-key.pem) --data 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' --data 'grant_type=client_credentials' 'http://localhost:7071/api/token' +# curl --header 'Content-Type: application/x-www-form-urlencoded' --data 'scope=flexion.*.report' --data 'client_assertion=$(jwt encode --exp=+5min --jti $(uuidgen) --alg RS256 -k $sender -i $sender -s $sender -a $host --no-iat -S @/path/to/ucsd-epic-private-key.pem) --data 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' --data 'grant_type=client_credentials' 'http://localhost:7071/api/token' POST {{url}}/api/token Content-Type: application/x-www-form-urlencoded [FormParams] -scope: {{client-id}}.*.report +scope: {{sender-org}}.*.report client_assertion: {{jwt}} client_assertion_type: urn:ietf:params:oauth:client-assertion-type:jwt-bearer grant_type: client_credentials diff --git a/scripts/hurl/rs/waters.hurl b/scripts/hurl/rs/waters.hurl index e212141a1..c114b348f 100644 --- a/scripts/hurl/rs/waters.hurl +++ b/scripts/hurl/rs/waters.hurl @@ -1,8 +1,8 @@ -# curl --header 'Content-Type: application/x-www-form-urlencoded' --data 'scope=flexion.*.report' --data 'client_assertion=$(jwt encode --exp=+5min --jti $(uuidgen) --alg RS256 -k $client -i $client -s $client -a $host --no-iat -S @/path/to/ucsd-epic-private-key.pem) --data 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' --data 'grant_type=client_credentials' 'http://localhost:7071/api/token' +# curl --header 'Content-Type: application/x-www-form-urlencoded' --data 'scope=flexion.*.report' --data 'client_assertion=$(jwt encode --exp=+5min --jti $(uuidgen) --alg RS256 -k $sender -i $sender -s $sender -a $host --no-iat -S @/path/to/ucsd-epic-private-key.pem) --data 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' --data 'grant_type=client_credentials' 'http://localhost:7071/api/token' POST {{url}}/api/token Content-Type: application/x-www-form-urlencoded [FormParams] -scope: {{client-id}}.*.report +scope: {{sender-org}}.*.report client_assertion: {{jwt}} client_assertion_type: urn:ietf:params:oauth:client-assertion-type:jwt-bearer grant_type: client_credentials @@ -15,6 +15,6 @@ token: jsonpath "$['access_token']" # curl --header 'Content-Type: application/hl7-v2' --header 'Client: flexion.simulated-sender' --header 'Authorization: Bearer $token' --data-binary '@/path/to/message.hl7' 'http://localhost:7071/api/waters' POST {{url}}/api/waters Content-Type: {{content-type}} -Client: {{client-id}}.{{client-sender}} +Client: {{sender-org}}.{{sender-name}} Authorization: Bearer {{token}} file,{{fpath}}; diff --git a/scripts/hurl/ti/auth.hurl b/scripts/hurl/ti/auth.hurl index 427f914db..99d91aa1f 100644 --- a/scripts/hurl/ti/auth.hurl +++ b/scripts/hurl/ti/auth.hurl @@ -1,5 +1,5 @@ POST {{url}}/v1/auth/token Content-Type: application/x-www-form-urlencoded [FormParams] -scope: {{client}} +scope: {{sender}} client_assertion: {{jwt}} diff --git a/scripts/hurl/ti/metadata.hurl b/scripts/hurl/ti/metadata.hurl index d85272593..4b8c86985 100644 --- a/scripts/hurl/ti/metadata.hurl +++ b/scripts/hurl/ti/metadata.hurl @@ -1,7 +1,7 @@ POST {{url}}/v1/auth/token Content-Type: application/x-www-form-urlencoded [FormParams] -scope: {{client}} +scope: {{sender}} client_assertion: {{jwt}} HTTP 200 diff --git a/scripts/hurl/ti/orders.hurl b/scripts/hurl/ti/orders.hurl index 2e36856b1..2c94d5e85 100644 --- a/scripts/hurl/ti/orders.hurl +++ b/scripts/hurl/ti/orders.hurl @@ -1,7 +1,7 @@ POST {{url}}/v1/auth/token Content-Type: application/x-www-form-urlencoded [FormParams] -scope: {{client}} +scope: {{sender}} client_assertion: {{jwt}} HTTP 200 diff --git a/scripts/hurl/ti/results.hurl b/scripts/hurl/ti/results.hurl index efecc9eba..b5ed90fa3 100644 --- a/scripts/hurl/ti/results.hurl +++ b/scripts/hurl/ti/results.hurl @@ -1,7 +1,7 @@ POST {{url}}/v1/auth/token Content-Type: application/x-www-form-urlencoded [FormParams] -scope: {{client}} +scope: {{sender}} client_assertion: {{jwt}} HTTP 200 diff --git a/scripts/hurl/epic/results.hurl b/scripts/hurl/ucsd/results.hurl similarity index 77% rename from scripts/hurl/epic/results.hurl rename to scripts/hurl/ucsd/results.hurl index dbc9e1c3b..af6f7b08f 100644 --- a/scripts/hurl/epic/results.hurl +++ b/scripts/hurl/ucsd/results.hurl @@ -1,5 +1,5 @@ -# curl -H 'Content-Type: application/x-www-form-urlencoded' --data 'client_assertion=$(jwt encode --exp=+5min --jti $(uuidgen) --alg RS256 -k $client -i $client -s $client -a https://epicproxy-np.et0502.epichosted.com/FhirProxy/oauth2/token --no-iat -S @/path/to/ucsd-epic-private-key.pem)' --data 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' --data 'grant_type=client_credentials' 'https://epicproxy-np.et0502.epichosted.com/FhirProxy/oauth2/token' -POST https://epicproxy-np.et0502.epichosted.com/FhirProxy/oauth2/token +# curl -H 'Content-Type: application/x-www-form-urlencoded' --data 'client_assertion=$(jwt encode --exp=+5min --jti $(uuidgen) --alg RS256 -k $sender -i $sender -s $sender -a https://epicproxy-np.et0502.epichosted.com/FhirProxy/oauth2/token --no-iat -S @/path/to/ucsd-epic-private-key.pem)' --data 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' --data 'grant_type=client_credentials' 'https://epicproxy-np.et0502.epichosted.com/FhirProxy/oauth2/token' +POST {{url}}/FhirProxy/oauth2/token Content-Type: application/x-www-form-urlencoded [FormParams] client_assertion: {{jwt}} @@ -12,7 +12,7 @@ HTTP 200 token: jsonpath "$['access_token']" # curl -H 'Content-Type: application/hl7-v2' -H 'Authorization: Bearer $token' --data-binary '@/path/to/oru.hl7' 'https://epicproxy-np.et0502.epichosted.com/CDPH_NBGS_TST/api/epic/2015/EDI/HTTP/HL7v2/910377' -POST https://epicproxy-np.et0502.epichosted.com/CDPH_NBGS_TST/api/epic/2015/EDI/HTTP/HL7v2/910377 -Content-Type: application/hl7-v2 +POST {{url}}/CDPH_NBGS_TST/api/epic/2015/EDI/HTTP/HL7v2/910377 +Content-Type: {{content-type}} Authorization: Bearer {{token}} file,{{fpath}}; diff --git a/scripts/lib/api.sh b/scripts/lib/api.sh new file mode 100755 index 000000000..b673bf432 --- /dev/null +++ b/scripts/lib/api.sh @@ -0,0 +1,95 @@ +#!/bin/bash + +show_usage() { + local script_name=$1 + + cat < [OPTIONS] + +ENDPOINT_NAME: + The name of the endpoint to call (required) + +Options: + -e Environment: local|staging (Default: $ENVIRONMENT) + -f Path to the message file to submit (Required for submission endpoints) + -r Root path to the message files (Default: $ROOT_PATH) + -t Content type for the message file (Default: $CONTENT_TYPE) + -k Path to the sender private key (Required for non-local environments) + -s Sender ID used for authentication (Default: $SENDER) + -u URL root for the API endpoint (Default: auto-detected) + -i Submission ID (Required for query endpoints) + -v Verbose mode + -h Display this help and exit +EOF +} + +parse_args() { + local type=$1 + shift + + [ "$1" = "-h" ] || [ "$1" = "--help" ] && return 1 + [ $# -eq 0 ] && fail "Missing required argument " + + HURL_FILE_PATH="$CDCTI_HOME/scripts/hurl/$type/$1.hurl" + shift + + while getopts ':e:f:r:t:k:s:u:i:v' opt; do + case "$opt" in + e) ENVIRONMENT="$OPTARG" ;; + f) REL_PATH="$OPTARG" ;; + r) ROOT_PATH="$OPTARG" ;; + t) CONTENT_TYPE="$OPTARG" ;; + k) SENDER_PRIVATE_KEY="$OPTARG" ;; + s) SENDER="$OPTARG" ;; + u) URL="$OPTARG" ;; + i) SUBMISSION_ID="$OPTARG" ;; + v) VERBOSE="--verbose" ;; + ?) fail "Invalid option -$OPTARG" ;; + esac + done + + parse_sender_string "$SENDER" + + if [ -z "$SENDER_PRIVATE_KEY" ] && [ "$ENVIRONMENT" = "local" ] && [ -f "$DEFAULT_SENDER_PRIVATE_KEY_PATH" ] && [ "$SENDER_ORG" = "$DEFAULT_SENDER_PRIVATE_KEY_ORG" ]; then + SENDER_PRIVATE_KEY="$DEFAULT_SENDER_PRIVATE_KEY_PATH" + elif [ -z "$SENDER_PRIVATE_KEY" ] && [ "$ENVIRONMENT" != "local" ]; then + fail "Sender private key (-k) is required for non-local environments" + fi + + [ ! -f "$SENDER_PRIVATE_KEY" ] && fail "Sender private key file not found: $SENDER_PRIVATE_KEY" + + shift "$((OPTIND - 1))" + REMAINING_ARGS="$*" +} + +handle_api_request() { + local api_type=$1 + shift + + local host jwt_token + [ -z "$URL" ] && URL=$(get_api_url "$ENVIRONMENT" "$api_type") + host=$(extract_host_from_url "$URL") + jwt_token=$(generate_jwt "$SENDER" "$host" "$SENDER_PRIVATE_KEY") + + local vars=( + --variable fpath=$REL_PATH + --file-root $ROOT_PATH + --variable url=$URL + --variable jwt=$jwt_token + --variable content-type=$CONTENT_TYPE + ) + + if [ "$api_type" = "rs" ]; then + vars+=( + --variable sender-org=$SENDER_ORG + --variable sender-name=$SENDER_NAME + ) + else + vars+=(--variable sender=$SENDER) + fi + + if [ -n "$SUBMISSION_ID" ]; then vars+=(--variable submissionid="$SUBMISSION_ID"); fi + if [ -n "$VERBOSE" ]; then vars+=("$VERBOSE"); fi + + hurl "${vars[@]}" "$HURL_FILE_PATH" ${REMAINING_ARGS:+$REMAINING_ARGS} +} diff --git a/scripts/lib/common.sh b/scripts/lib/common.sh index a4702d178..347511c2f 100755 --- a/scripts/lib/common.sh +++ b/scripts/lib/common.sh @@ -79,9 +79,23 @@ extract_host_from_url() { echo "$url" | sed 's|^.*://\([^/:]*\)[:/].*|\1|' } +parse_sender_string() { + local sender_string=$1 + + if [[ "$sender_string" =~ ^([^.]+)\.([^.]+)$ ]]; then + SENDER_ORG="${BASH_REMATCH[1]}" + SENDER_NAME="${BASH_REMATCH[2]}" + return 0 + else + SENDER_ORG="$sender_string" + SENDER_NAME="" + return 1 + fi +} + generate_jwt() { # requires: jwt-cli - local client=$1 + local sender=$1 local audience=$2 local secret_path=$3 @@ -89,9 +103,9 @@ generate_jwt() { --exp='+5min' \ --jti "$(uuidgen)" \ --alg RS256 \ - -k "$client" \ - -i "$client" \ - -s "$client" \ + -k "$sender" \ + -i "$sender" \ + -s "$sender" \ -a "$audience" \ --no-iat \ -S "@$secret_path" diff --git a/scripts/lib/submission-utils.sh b/scripts/lib/submission-utils.sh index 21a72e2b7..5d7fd2427 100755 --- a/scripts/lib/submission-utils.sh +++ b/scripts/lib/submission-utils.sh @@ -82,8 +82,8 @@ submit_message() { # requires: hurl, jq, az local env=$1 local file=$2 - local rs_client_private_key=$3 - local ti_client_private_key=$4 + local rs_sender_private_key=$3 + local ti_sender_private_key=$4 local message_file_path message_file_name message_base_name message_file_path="$(dirname "${file}")" @@ -109,7 +109,7 @@ submit_message() { echo "Assuming receivers are '$first_leg_receiver' and '$second_leg_receiver' because of MSH-9 value '$msh9'" - waters_response=$("$CDCTI_HOME"/scripts/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_sender_private_key") || { exit_code=$? if [ $exit_code -ne 0 ]; then fail "Expected exit code 0 but got $exit_code for RS waters API call" @@ -118,7 +118,7 @@ submit_message() { submission_id=$(echo "$waters_response" | jq -r '.id') echo "[First leg] Checking submission status for ID: $submission_id" - if ! check_submission_status "$env" "$submission_id" "$rs_client_private_key"; then + if ! check_submission_status "$env" "$submission_id" "$rs_sender_private_key"; then echo "Failed to deliver the first leg of the message. Skipping the next steps." return fi @@ -134,9 +134,9 @@ submit_message() { fi echo "[Intermediary] Getting outbound submission ID" - if [ -n "$ti_client_private_key" ]; then + if [ -n "$ti_sender_private_key" ]; then echo " Attempting to get outbound submission ID from TI's metadata API..." - metadata_response=$("$CDCTI_HOME"/scripts/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_sender_private_key") || { echo "Failed to get metadata for inbound submission ID: $inbound_submission_id" outbound_submission_id="" } @@ -165,7 +165,7 @@ submit_message() { fi echo "[Second leg] Checking submission status for ID: $outbound_submission_id" - if ! check_submission_status "$env" "$outbound_submission_id" "$rs_client_private_key"; then + if ! check_submission_status "$env" "$outbound_submission_id" "$rs_sender_private_key"; then echo "Failed to deliver the second leg of the message. Skipping the next steps." return fi diff --git a/scripts/rs.sh b/scripts/rs.sh index 1a5da946a..05bd6e89f 100755 --- a/scripts/rs.sh +++ b/scripts/rs.sh @@ -2,99 +2,19 @@ [ -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/api.sh" # default values -env=local -root=$CDCTI_HOME/examples/ -content_type=application/hl7-v2 -client_id=flexion -client_sender=simulated-sender - -show_usage() { - cat < [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: $root) - -t Content type for the message (Default: $content_type) - -e Environment: local|staging|production (Default: $env) - -c Client ID (Default: $client_id) - -s Client sender (Default: $client_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 -EOF -} - -parse_arguments() { - if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then - show_usage - exit 0 - fi - - [ $# -eq 0 ] && fail "Missing required argument " - 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 - case "$opt" in - f) fpath="$OPTARG" ;; - r) root="$OPTARG" ;; - t) content_type="$OPTARG" ;; - e) env="$OPTARG" ;; - c) client_id="$OPTARG" ;; - s) client_sender="$OPTARG" ;; - k) private_key="$OPTARG" ;; - i) submission_id="--variable submissionid=$OPTARG" ;; - v) verbose="--verbose" ;; - ?) fail "Invalid option -$OPTARG" ;; - esac - done - - shift "$((OPTIND - 1))" - remaining_args="$*" -} - -setup_credentials() { - if [ -z "$private_key" ] && [ "$client_id" = "flexion" ] && [ "$env" = "local" ]; then - 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: $TI_LOCAL_PRIVATE_KEY_PATH" - fi - fi - - if [ "$env" != "local" ]; then - [ -z "$private_key" ] && fail "Client private key (-k) is required for non-local environments" - fi - - [ ! -f "$private_key" ] && fail "Client private key file not found: $private_key" -} - -run_hurl_command() { - url=$(get_api_url "$env" "rs") - host=$(extract_host_from_url "$url") - jwt_token=$(generate_jwt "$client_id.$client_sender" "$host" "$private_key") || fail "Failed to generate JWT token" - - hurl \ - --variable "fpath=$fpath" \ - --file-root "$root" \ - --variable "url=$url" \ - --variable "content-type=$content_type" \ - --variable "client-id=$client_id" \ - --variable "client-sender=$client_sender" \ - --variable "jwt=$jwt_token" \ - ${submission_id:-} \ - ${verbose:-} \ - "$hurl_file_path" \ - ${remaining_args:+$remaining_args} +ENVIRONMENT=local +ROOT_PATH=$CDCTI_HOME/examples/ +CONTENT_TYPE=application/hl7-v2 +SENDER=flexion.simulated-sender +DEFAULT_SENDER_PRIVATE_KEY_ORG=flexion +DEFAULT_SENDER_PRIVATE_KEY_PATH="$TI_LOCAL_PRIVATE_KEY_PATH" + +parse_args "rs" "$@" || { + show_usage "$(basename "$0")" + exit 0 } -parse_arguments "$@" -setup_credentials -run_hurl_command +handle_api_request "rs" "$@" diff --git a/scripts/submit.sh b/scripts/submit.sh index 1a93990b5..1ec1abca3 100755 --- a/scripts/submit.sh +++ b/scripts/submit.sh @@ -8,13 +8,13 @@ env="local" show_usage() { cat < [-e ] +Usage: ./$(basename "$0") -f [-e ] Options: -f Message file path (Required) -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) + -x Path to the sender private key for authentication with RS API (Required for non-local environments) + -z Path to the sender private key for authentication with TI API (Optional for all environments) -h Display this help and exit EOF exit 1 @@ -28,8 +28,8 @@ parse_arguments() { case $opt in e) env="$OPTARG" ;; f) file="$OPTARG" ;; - x) rs_client_private_key="$OPTARG" ;; - z) ti_client_private_key="$OPTARG" ;; + x) rs_sender_private_key="$OPTARG" ;; + z) ti_sender_private_key="$OPTARG" ;; h) show_usage ;; ?) fail "Invalid option: -$OPTARG" ;; esac @@ -46,25 +46,25 @@ parse_arguments() { } setup_credentials() { - # Handle RS client key - if [ "$env" = "local" ] && [ -z "$rs_client_private_key" ]; then - rs_client_private_key="$TI_LOCAL_PRIVATE_KEY_PATH" + # Handle RS sender key + if [ "$env" = "local" ] && [ -z "$rs_sender_private_key" ]; then + rs_sender_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" - [ ! -f "$rs_client_private_key" ] && fail "RS client private key file not found: $rs_client_private_key" + [ "$env" != "local" ] && [ -z "$rs_sender_private_key" ] && fail "RS sender private key (-x) is required for non-local environments" + [ ! -f "$rs_sender_private_key" ] && fail "RS sender private key file not found: $rs_sender_private_key" - # Handle optional TI client key - if [ "$env" = "local" ] && [ -z "$ti_client_private_key" ]; then - ti_client_private_key="$RS_LOCAL_PRIVATE_KEY_PATH" + # Handle optional TI sender key + if [ "$env" = "local" ] && [ -z "$ti_sender_private_key" ]; then + ti_sender_private_key="$RS_LOCAL_PRIVATE_KEY_PATH" fi # Only verify TI key if provided - [ -n "$ti_client_private_key" ] && [ ! -f "$ti_client_private_key" ] && fail "TI client private key file not found: $ti_client_private_key" + [ -n "$ti_sender_private_key" ] && [ ! -f "$ti_sender_private_key" ] && fail "TI sender private key file not found: $ti_sender_private_key" } check_installed_commands hurl jq az check_apis "$(get_api_url "$env" "rs")" "$(get_api_url "$env" "ti")" parse_arguments "$@" setup_credentials -submit_message "$env" "$file" "$rs_client_private_key" "$ti_client_private_key" +submit_message "$env" "$file" "$rs_sender_private_key" "$ti_sender_private_key" diff --git a/scripts/ti.sh b/scripts/ti.sh index 6df6c342c..abff75e2c 100755 --- a/scripts/ti.sh +++ b/scripts/ti.sh @@ -2,91 +2,19 @@ [ -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/api.sh" # default values -env=local -root=$CDCTI_HOME/examples/ -client=report-stream - -show_usage() { - cat < [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: $root) - -e Environment: local|staging (Default: $env) - -c Client ID to create JWT with (Default: $client) - -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 -EOF -} - -parse_arguments() { - if [ $# -eq 0 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then - show_usage - exit 0 - fi - - [ $# -eq 0 ] && fail "Missing required argument " - 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 - case "$opt" in - f) fpath="$OPTARG" ;; - r) root="$OPTARG" ;; - e) env="$OPTARG" ;; - c) client="$OPTARG" ;; - k) private_key="$OPTARG" ;; - i) submission_id="--variable submissionid=$OPTARG" ;; - v) verbose="--verbose" ;; - ?) fail "Invalid option -$OPTARG" ;; - esac - done - - shift "$((OPTIND - 1))" - remaining_args="$*" -} - -setup_credentials() { - if [ -z "$private_key" ] && [ "$client" = "report-stream" ] && [ "$env" = "local" ]; then - 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: $RS_LOCAL_PRIVATE_KEY_PATH" - fi - fi - - if [ "$env" != "local" ]; then - [ -z "$private_key" ] && fail "Client private key (-k) is required for non-local environments" - fi - - [ ! -f "$private_key" ] && fail "Client private key file not found: $private_key" -} - -run_hurl_command() { - url=$(get_api_url "$env" "ti") - host=$(extract_host_from_url "$url") - jwt_token=$(generate_jwt "$client" "$host" "$private_key") || fail "Failed to generate JWT token" - - hurl \ - --variable "fpath=$fpath" \ - --file-root "$root" \ - --variable "url=$url" \ - --variable "client=$client" \ - --variable "jwt=$jwt_token" \ - ${submission_id:-} \ - ${verbose:-} \ - "$hurl_file_path" \ - ${remaining_args:+$remaining_args} +ENVIRONMENT=local +ROOT_PATH=$CDCTI_HOME/examples/ +CONTENT_TYPE=application/fhir+ndjson +SENDER=report-stream +DEFAULT_SENDER_PRIVATE_KEY_ORG=report-stream +DEFAULT_SENDER_PRIVATE_KEY_PATH="$RS_LOCAL_PRIVATE_KEY_PATH" + +parse_args "ti" "$@" || { + show_usage "$(basename "$0")" + exit 0 } -parse_arguments "$@" -setup_credentials -run_hurl_command +handle_api_request "ti" "$@" diff --git a/scripts/ucsd.sh b/scripts/ucsd.sh new file mode 100755 index 000000000..bbc5c3feb --- /dev/null +++ b/scripts/ucsd.sh @@ -0,0 +1,18 @@ +#!/bin/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" +source "$CDCTI_HOME/scripts/lib/api.sh" + +# default values +ENVIRONMENT=staging +ROOT_PATH=$CDCTI_HOME/examples/CA/ +CONTENT_TYPE=application/hl7-v2 +URL=https://epicproxy-np.et0502.epichosted.com/FhirProxy/oauth2/token + +parse_args "ucsd" "$@" || { + show_usage "$(basename "$0")" + exit 0 +} + +handle_api_request "ucsd" "$@"