Skip to content

Commit

Permalink
Add the deploy_api and delete_proxygen_deployments scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
kris-szlapa committed Sep 9, 2024
1 parent 14c0817 commit e190234
Show file tree
Hide file tree
Showing 2 changed files with 262 additions and 0 deletions.
71 changes: 71 additions & 0 deletions .github/scripts/delete_proxygen_deployments.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/bin/env bash

# Generic script for removing proxygen deployed APIs where the pull request is closed

# Set the repo name to be the name of the repo this is running in
REPO_NAME=electronic-prescription-service-clinical-prescription-tracker

# Main function to delete relevant proxygen deployments
main() {
echo "Checking clinical tracker deployments"
PULL_REQUEST_PROXYGEN_REGEX=prescription-clinical-tracker-pr-
delete_apigee_deployments "internal-dev" "prescription-clinical-tracker-api" "ClinicalTrackerProxygenPrivateKey" "eps-clinical-tracker"
delete_apigee_deployments "internal-dev-sandbox" "prescription-clinical-tracker-api" "ClinicalTrackerProxygenPrivateKey" "eps-clinical-tracker"
}

# Function to delete Apigee deployments
delete_apigee_deployments() {
APIGEE_ENVIRONMENT=$1
APIGEE_API=$2
PROXYGEN_PRIVATE_KEY_NAME=$3
PROXYGEN_KID=$4
proxygen_private_key_arn=$(aws cloudformation list-exports --query "Exports[?Name=='account-resources:${PROXYGEN_PRIVATE_KEY_NAME}'].Value" --output text)

echo
echo "Checking Apigee deployments on ${APIGEE_ENVIRONMENT}"
echo

jq -n --arg apiName "${APIGEE_API}" \
--arg environment "${APIGEE_ENVIRONMENT}" \
--arg kid "${PROXYGEN_KID}" \
--arg proxygenSecretName "${proxygen_private_key_arn}" \
'{apiName: $apiName, environment: $environment, kid, $kid, proxygenSecretName: $proxygenSecretName}' > payload.json

aws lambda invoke --function-name "lambda-resources-ProxygenPTLInstanceGet" --cli-binary-format raw-in-base64-out --payload file://payload.json out.json > response.json

if eval "cat response.json | jq -e '.FunctionError' >/dev/null"; then
echo 'Error calling lambda'
cat out.json
exit 1
fi

jq -r '.[].name' "out.json" | while read -r i; do
echo "Checking if Apigee deployment $i has open pull request"
PULL_REQUEST=${i//${PULL_REQUEST_PROXYGEN_REGEX}/}
echo "Checking pull request ID ${PULL_REQUEST}"
URL="https://api.github.com/repos/NHSDigital/${REPO_NAME}/pulls/${PULL_REQUEST}"
RESPONSE=$(curl "${URL}" 2>/dev/null)
STATE=$(echo "${RESPONSE}" | jq -r .state)
if [ "$STATE" == "closed" ]; then
echo "** Going to delete Apigee deployment $i as state is ${STATE} **"
jq -n --arg apiName "${APIGEE_API}" \
--arg environment "${APIGEE_ENVIRONMENT}" \
--arg instance "${i}" \
--arg kid "${PROXYGEN_KID}" \
--arg proxygenSecretName "${proxygen_private_key_arn}" \
'{apiName: $apiName, environment: $environment, kid, $kid, proxygenSecretName: $proxygenSecretName, instance: $instance}' > payload.json

aws lambda invoke --function-name "lambda-resources-ProxygenPTLInstanceDelete" --cli-binary-format raw-in-base64-out --payload file://payload.json out.txt > response.json
if eval "cat response.json | jq -e '.FunctionError' >/dev/null"; then
echo 'Error calling lambda'
cat out.txt
exit 1
fi

else
echo "Not going to delete Apigee deployment $i as state is ${STATE}"
fi
done
}

main
191 changes: 191 additions & 0 deletions .github/scripts/deploy_api.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
#!/usr/bin/env bash
set -eu pipefail

echo "Specification path: ${SPEC_PATH}"
echo "Specification version: ${VERSION_NUMBER}"
echo "Stack name: ${STACK_NAME}"
echo "AWS environment: ${AWS_ENVIRONMENT}"
echo "Apigee environment: ${APIGEE_ENVIRONMENT}"
echo "Proxygen private key name: ${PROXYGEN_PRIVATE_KEY_NAME}"
echo "Proxygen KID: ${PROXYGEN_KID}"
echo "Dry run: ${DRY_RUN}"

client_private_key=$(cat ~/.proxygen/tmp/client_private_key)
client_cert=$(cat ~/.proxygen/tmp/client_cert)

if [ -z "${client_private_key}" ]; then
echo "client_private_key is unset or set to the empty string"
exit 1
fi
if [ -z "${client_cert}" ]; then
echo "client_cert is unset or set to the empty string"
exit 1
fi

put_secret_lambda=lambda-resources-ProxygenPTLMTLSSecretPut
instance_put_lambda=lambda-resources-ProxygenPTLInstancePut
spec_publish_lambda=lambda-resources-ProxygenPTLSpecPublish

if [[ "$APIGEE_ENVIRONMENT" =~ ^(int|sandbox|prod)$ ]]; then
put_secret_lambda=lambda-resources-ProxygenProdMTLSSecretPut
instance_put_lambda=lambda-resources-ProxygenProdInstancePut
spec_publish_lambda=lambda-resources-ProxygenProdSpecPublish
fi

is_pull_request=false
instance_suffix=""
if [[ ${STACK_NAME} == clinical-tracker-pr-* ]]; then
is_pull_request=true
# Extracting the PR ID from $STACK_NAME
pr_id=$(echo "${STACK_NAME}" | cut -d'-' -f3)
instance_suffix=-"pr-${pr_id}"
fi

# Determine the proxy instance based on the provided $STACK_NAME
instance="prescription-clinical-tracker${instance_suffix}"
apigee_api=prescription-clinical-tracker-api

echo "Is pull request: ${is_pull_request}"
echo "Proxy instance: ${instance}"
echo "Apigee api: ${apigee_api}"

echo

echo "Fixing the spec"
# Find and replace the title
title=$(jq -r '.info.title' "${SPEC_PATH}")
if [[ "${is_pull_request}" == "true" ]]; then
jq --arg title "[PR-${pr_id}] $title" '.info.title = $title' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}"
fi

# Find and replace the specification version number
jq --arg version "${VERSION_NUMBER}" '.info.version = $version' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}"

# Find and replace the x-nhsd-apim.target.url value
jq --arg stack_name "${STACK_NAME}" --arg aws_env "${AWS_ENVIRONMENT}" '.["x-nhsd-apim"].target.url = "https://\($stack_name).\($aws_env).eps.national.nhs.uk"' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}"

# Find and replace the servers object
if [[ "${APIGEE_ENVIRONMENT}" == "prod" ]]; then
jq --arg inst "${instance}" '.servers = [ { "url": "https://api.service.nhs.uk/\($inst)" } ]' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}"
else
jq --arg env "${APIGEE_ENVIRONMENT}" --arg inst "${instance}" '.servers = [ { "url": "https://\($env).api.service.nhs.uk/\($inst)" } ]' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}"
fi

# Find and replace securitySchemes
if [[ "${APIGEE_ENVIRONMENT}" == "prod" ]]; then
jq '.components.securitySchemes."app-level3" = {"$ref": "https://proxygen.prod.api.platform.nhs.uk/components/securitySchemes/app-level3"}' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}"
else
jq '.components.securitySchemes."app-level3" = {"$ref": "https://proxygen.ptl.api.platform.nhs.uk/components/securitySchemes/app-level3"}' "${SPEC_PATH}" > temp.json && mv temp.json "${SPEC_PATH}"
fi

# Remove target attributes if the environment is sandbox
if [[ "${APIGEE_ENVIRONMENT}" == *"sandbox"* ]]; then
echo "Removing target attributes for sandbox environment"
jq 'del(."x-nhsd-apim"."target-attributes")' "$SPEC_PATH" > temp.json && mv temp.json "${SPEC_PATH}"
fi

echo

echo "Retrieving proxygen credentials"

# Retrieve the proxygen private key and client private key and cert from AWS Secrets Manager
proxygen_private_key_arn=$(aws cloudformation list-exports --query "Exports[?Name=='account-resources:${PROXYGEN_PRIVATE_KEY_NAME}'].Value" --output text)

if [[ "${is_pull_request}" == "false" ]]; then
echo
echo "Store the secret used for mutual TLS to AWS using Proxygen proxy lambda"
if [[ "${DRY_RUN}" == "false" ]]; then
jq -n --arg apiName "${apigee_api}" \
--arg environment "${APIGEE_ENVIRONMENT}" \
--arg secretName "clinical-tracker-mtls-1" \
--arg secretKey "${client_private_key}" \
--arg secretCert "${client_cert}" \
--arg kid "${PROXYGEN_KID}" \
--arg proxygenSecretName "${proxygen_private_key_arn}" \
'{apiName: $apiName, environment: $environment, secretName: $secretName, secretKey: $secretKey, secretCert: $secretCert, kid, $kid, proxygenSecretName: $proxygenSecretName}' > payload.json

aws lambda invoke --function-name "${put_secret_lambda}" --cli-binary-format raw-in-base64-out --payload file://payload.json out.txt > response.json
if eval "cat response.json | jq -e '.FunctionError' >/dev/null"; then
echo 'Error calling lambda'
cat out.txt
exit 1
fi
echo "Secret stored successfully"
else
echo "Would call ${put_secret_lambda}"
fi
fi

echo
echo "Deploy the API instance using Proxygen proxy lambda"
if [[ "${DRY_RUN}" == "false" ]]; then

jq -n --argfile spec "${SPEC_PATH}" \
--arg apiName "${apigee_api}" \
--arg environment "${APIGEE_ENVIRONMENT}" \
--arg instance "${instance}" \
--arg kid "${PROXYGEN_KID}" \
--arg proxygenSecretName "${proxygen_private_key_arn}" \
'{apiName: $apiName, environment: $environment, specDefinition: $spec, instance: $instance, kid: $kid, proxygenSecretName: $proxygenSecretName}' > payload.json

aws lambda invoke --function-name "${instance_put_lambda}" --cli-binary-format raw-in-base64-out --payload file://payload.json out.txt > response.json

if eval "cat response.json | jq -e '.FunctionError' >/dev/null"; then
echo 'Error calling lambda'
cat out.txt
exit 1
fi
echo "Instance deployed"
else
echo "Would call ${instance_put_lambda}"
fi

if [[ "${APIGEE_ENVIRONMENT}" == "int" ]]; then
echo
echo "Deploy the API spec to prod catalogue as it is int environment"
if [[ "${DRY_RUN}" == "false" ]]; then
jq -n --argfile spec "${SPEC_PATH}" \
--arg apiName "${apigee_api}" \
--arg environment "prod" \
--arg instance "${instance}" \
--arg kid "${PROXYGEN_KID}" \
--arg proxygenSecretName "${proxygen_private_key_arn}" \
'{apiName: $apiName, environment: $environment, specDefinition: $spec, instance: $instance, kid: $kid, proxygenSecretName: $proxygenSecretName}' > payload.json

aws lambda invoke --function-name "${spec_publish_lambda}" --cli-binary-format raw-in-base64-out --payload file://payload.json out.txt > response.json

if eval "cat response.json | jq -e '.FunctionError' >/dev/null"; then
echo 'Error calling lambda'
cat out.txt
exit 1
fi
echo "Spec deployed"
else
echo "Would call ${spec_publish_lambda}"
fi
fi

if [[ "${APIGEE_ENVIRONMENT}" == "internal-dev" && "${is_pull_request}" == "false" ]]; then
echo
echo "Deploy the API spec to uat catalogue as it is internal-dev environment"
if [[ "${DRY_RUN}" == "false" ]]; then
jq -n --argfile spec "${SPEC_PATH}" \
--arg apiName "${apigee_api}" \
--arg environment "uat" \
--arg instance "${instance}" \
--arg kid "${PROXYGEN_KID}" \
--arg proxygenSecretName "${proxygen_private_key_arn}" \
'{apiName: $apiName, environment: $environment, specDefinition: $spec, instance: $instance, kid: $kid, proxygenSecretName: $proxygenSecretName}' > payload.json

aws lambda invoke --function-name "${spec_publish_lambda}" --cli-binary-format raw-in-base64-out --payload file://payload.json out.txt > response.json

if eval "cat response.json | jq -e '.FunctionError' >/dev/null"; then
echo 'Error calling lambda'
cat out.txt
exit 1
fi
echo "Spec deployed"
else
echo "Would call ${spec_publish_lambda}"
fi
fi

0 comments on commit e190234

Please sign in to comment.