Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: [AEA-4261] - use proxygen lambdas for proxygen work #559

Merged
merged 31 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
eb3b1a1
use proxygen lambda
anthony-nhs Jul 19, 2024
c2d2bda
pass the kid
anthony-nhs Jul 19, 2024
6fb77ab
Merge remote-tracking branch 'origin/main' into use_proxygen_lambda
anthony-nhs Jul 23, 2024
d88d518
pass secret name to lambda
anthony-nhs Jul 23, 2024
bb32607
correct lambda name
anthony-nhs Jul 23, 2024
c41441a
try using prod api
anthony-nhs Jul 23, 2024
e700104
check for errors
anthony-nhs Jul 23, 2024
0e6b93e
set secret using lambda
anthony-nhs Jul 24, 2024
c4de065
fix deploy
anthony-nhs Jul 24, 2024
20be823
use new lambda for secret
anthony-nhs Jul 24, 2024
2d59b03
correct input to lambda
anthony-nhs Jul 24, 2024
a0f19ee
correct putting secret
anthony-nhs Jul 24, 2024
eb7c646
Merge remote-tracking branch 'origin/main' into use_proxygen_lambda
anthony-nhs Jul 24, 2024
4b98f71
try publishing spec
anthony-nhs Jul 24, 2024
ea73146
publish spec for this pr
anthony-nhs Jul 24, 2024
c570252
use pr splunk
anthony-nhs Jul 25, 2024
1f7c18e
Merge branch 'main' into use_proxygen_lambda
anthony-nhs Jul 25, 2024
5154970
Merge remote-tracking branch 'origin/main' into use_proxygen_lambda
anthony-nhs Jul 25, 2024
671d4db
Merge remote-tracking branch 'origin/main' into use_proxygen_lambda
anthony-nhs Aug 6, 2024
7a239a4
Merge remote-tracking branch 'origin/main' into use_proxygen_lambda
anthony-nhs Aug 6, 2024
ca4fd57
use lambdas
anthony-nhs Aug 6, 2024
bd47c27
no need for poetry
anthony-nhs Aug 6, 2024
93da880
Merge remote-tracking branch 'origin/main' into use_proxygen_lambda
anthony-nhs Aug 6, 2024
4142f74
modify delete stacks
anthony-nhs Aug 6, 2024
34c914c
Merge branch 'main' into use_proxygen_lambda
anthony-nhs Aug 7, 2024
ac114c2
fix api name
anthony-nhs Aug 7, 2024
b8ef3c2
Merge branch 'use_proxygen_lambda' of github-work:NHSDigital/eps-pres…
anthony-nhs Aug 7, 2024
30d5a45
remove reference to proxygen cli
anthony-nhs Aug 7, 2024
89409fe
Merge remote-tracking branch 'origin/main' into use_proxygen_lambda
anthony-nhs Aug 7, 2024
0936690
use correct lambda-resources
anthony-nhs Aug 7, 2024
520bf35
Merge branch 'main' into use_proxygen_lambda
anthony-nhs Aug 7, 2024
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
76 changes: 76 additions & 0 deletions .github/scripts/delete_proxygen_deployments.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/usr/bin/env bash

# generic script for removing cloudformation stacks and 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=eps-prescription-status-update-api

# this should be customised to delete cloudformation stacks and proxygen deployments if they are used
main() {
echo "Checking prescripton status update deployments"
PULL_REQUEST_PROXYGEN_REGEX=prescription-status-update-pr-
delete_apigee_deployments "internal-dev" "prescription-status-update-api" "PSUProxygenPrivateKey" "eps-cli-key-1"
delete_apigee_deployments "internal-dev-sandbox" "prescription-status-update-api" "PSUProxygenPrivateKey" "eps-cli-key-1"

echo "Checking custom prescripton status update deployments"
PULL_REQUEST_PROXYGEN_REGEX=custom-prescription-status-update-pr-
delete_apigee_deployments "internal-dev" "custom-prescription-status-update-api" "CPSUProxygenPrivateKey" "eps-cli-key-cpsu-1"
delete_apigee_deployments "internal-dev-sandbox" "custom-prescription-status-update-api" "CPSUProxygenPrivateKey" "eps-cli-key-cpsu-1"
}

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
74 changes: 0 additions & 74 deletions .github/scripts/delete_stacks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,10 @@ CAPTURE_REGEX="^psu-pr-(\\d+)(-sandbox)?$"
# this is used in a replace command to replace the stack name so what is left is just the pull request id
PULL_REQUEST_STACK_REGEX=psu-pr-

# this should be a regex that is used to get the pull request id from the proxygen deployed API
# this is used in a replace command to replace the proxy name so what is left is just the pull request id
PULL_REQUEST_PROXYGEN_REGEX=prescription-status-update-pr-

# this should be customised to delete cloudformation stacks and proxygen deployments if they are used
main() {
delete_cloudformation_stacks
create_proxygen_credentials "PSUProxygenPrivateKey" "eps-cli-key-1" "prescription-status-update-api"
delete_apigee_deployments "internal-dev"
delete_apigee_deployments "internal-dev-sandbox"

PULL_REQUEST_PROXYGEN_REGEX=custom-prescription-status-update-pr-
create_proxygen_credentials "CPSUProxygenPrivateKey" "eps-cli-key-cpsu-1" "custom-prescription-status-update-api"
delete_apigee_deployments "internal-dev"
delete_apigee_deployments "internal-dev-sandbox"
}

delete_cloudformation_stacks() {
Expand Down Expand Up @@ -56,68 +45,5 @@ delete_cloudformation_stacks() {
done
}

create_proxygen_credentials() {
PROXYGEN_PRIVATE_KEY_NAME=$1
PROXYGEN_KID=$2
APIGEE_API=$3
echo
echo "getting proxygen key"
echo "PROXYGEN_PRIVATE_KEY_NAME: ${PROXYGEN_PRIVATE_KEY_NAME}"
echo "PROXYGEN_KID: ${PROXYGEN_KID}"
echo "APIGEE_API: ${APIGEE_API}"
echo
# Retrieve the proxygen private key
proxygen_private_key_arn=$(aws cloudformation list-exports --query "Exports[?Name=='account-resources:${PROXYGEN_PRIVATE_KEY_NAME}'].Value" --output text)
proxygen_private_key=$(aws secretsmanager get-secret-value --secret-id "${proxygen_private_key_arn}" --query SecretString --output text)

# Create the .proxygen/tmp directory if it doesn't exist
mkdir -p ~/.proxygen/tmp

# Save the proxygen private key, client private key, and client cert to temporary files
echo "$proxygen_private_key" > ~/.proxygen/tmp/proxygen_private_key.pem

# Create the .proxygen/tmp directory if it doesn't exist
mkdir -p ~/.proxygen/tmp
# Create credentials.yaml file
cat <<EOF > ~/.proxygen/credentials.yaml
client_id: ${APIGEE_API}-client
key_id: ${PROXYGEN_KID}
private_key_path: tmp/proxygen_private_key.pem
base_url: https://identity.prod.api.platform.nhs.uk/realms/api-producers
client_secret: https://nhsdigital.github.io/identity-service-jwks/jwks/paas/${APIGEE_API}.json
EOF

# Create settings.yaml file
cat <<EOF > ~/.proxygen/settings.yaml
api: ${APIGEE_API}
endpoint_url: https://proxygen.prod.api.platform.nhs.uk
spec_output_format: json
EOF
}

delete_apigee_deployments() {
APIGEE_ENVIRONMENT=$1
echo
echo "checking apigee deployments on ${APIGEE_ENVIRONMENT}"
echo
ACTIVE_APIGEE=$(poetry run proxygen instance list --env "${APIGEE_ENVIRONMENT}" | awk 'NR > 2 {print $3}')
mapfile -t ACTIVE_APIGEE_ARRAY <<< "$ACTIVE_APIGEE"

for i in "${ACTIVE_APIGEE_ARRAY[@]}"
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} **"
poetry run proxygen instance delete --no-confirm "${APIGEE_ENVIRONMENT}" "${i}"
else
echo "not going to delete apigee deployment $i as state is ${STATE}"
fi
done
}

main
126 changes: 82 additions & 44 deletions .github/scripts/deploy_api.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
set -eu pipefail

echo "API type: ${API_TYPE}"
echo "Proxygen path: ${PROXYGEN_PATH}"
echo "Specification path: ${SPEC_PATH}"
echo "Specification version: ${VERSION_NUMBER}"
echo "Stack name: ${STACK_NAME}"
Expand All @@ -13,6 +12,30 @@ echo "Proxygen KID: ${PROXYGEN_KID}"
echo "Deploy Check Prescription Status Update: ${DEPLOY_CHECK_PRESCRIPTION_STATUS_UPDATE}"
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} == psu-pr-* ]]; then
Expand Down Expand Up @@ -94,74 +117,89 @@ 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)
client_private_key_arn=$(aws cloudformation list-exports --query "Exports[?Name=='account-resources:PsuClientKeySecret'].Value" --output text)
client_cert_arn=$(aws cloudformation list-exports --query "Exports[?Name=='account-resources:PsuClientCertSecret'].Value" --output text)

proxygen_private_key=$(aws secretsmanager get-secret-value --secret-id "${proxygen_private_key_arn}" --query SecretString --output text)
client_private_key=$(aws secretsmanager get-secret-value --secret-id "${client_private_key_arn}" --query SecretString --output text)
client_cert=$(aws secretsmanager get-secret-value --secret-id "${client_cert_arn}" --query SecretString --output text)

# Create the .proxygen/tmp directory if it doesn't exist
mkdir -p ~/.proxygen/tmp

# Save the proxygen private key, client private key, and client cert to temporary files
echo "${proxygen_private_key}" > ~/.proxygen/tmp/proxygen_private_key.pem
echo "${client_private_key}" > ~/.proxygen/tmp/client_private_key.pem
echo "${client_cert}" > ~/.proxygen/tmp/client_cert.pem

cat <<EOF > ~/.proxygen/credentials.yaml
client_id: ${apigee_api}-client
key_id: ${PROXYGEN_KID}
private_key_path: tmp/proxygen_private_key.pem
base_url: https://identity.prod.api.platform.nhs.uk/realms/api-producers
client_secret: https://nhsdigital.github.io/identity-service-jwks/jwks/paas/${apigee_api}.json
EOF

# Create settings.yaml file
cat <<EOF > ~/.proxygen/settings.yaml
api: ${apigee_api}
endpoint_url: https://proxygen.prod.api.platform.nhs.uk
spec_output_format: json
EOF

if [[ "${is_pull_request}" == "false" ]]; then
echo
echo "Store the secret used for mutual TLS to AWS using Proxygen CLI"
echo "Store the secret used for mutual TLS to AWS using Proxygen proxy lambda"
if [[ "${DRY_RUN}" == "false" ]]; then
"${PROXYGEN_PATH}" secret put --mtls-cert ~/.proxygen/tmp/client_cert.pem --mtls-key ~/.proxygen/tmp/client_private_key.pem "${APIGEE_ENVIRONMENT}" psu-mtls-1
jq -n --arg apiName "${apigee_api}" \
--arg environment "${APIGEE_ENVIRONMENT}" \
--arg secretName "psu-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 succesfully"

else
echo "Would run this command"
echo "${PROXYGEN_PATH} secret put --mtls-cert ~/.proxygen/tmp/client_cert.pem --mtls-key ~/.proxygen/tmp/client_private_key.pem ${APIGEE_ENVIRONMENT} psu-mtls-1"
echo "Would call ${put_secret_lambda}"
fi
fi

echo
echo "Deploy the API instance using Proxygen CLI"
echo "Deploy the API instance using Proxygen proxy lambda"
if [[ "${DRY_RUN}" == "false" ]]; then
"${PROXYGEN_PATH}" instance deploy --no-confirm "${APIGEE_ENVIRONMENT}" "${instance}" "${SPEC_PATH}"

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 run this command"
echo "${PROXYGEN_PATH} instance deploy --no-confirm ${APIGEE_ENVIRONMENT} ${instance} ${SPEC_PATH}"
echo "Would call ${instance_put_lambda}"
fi

if [[ "${APIGEE_ENVIRONMENT}" == "int" ]]; then
echo
echo "Deploy the API spec if in the int environment"
if [[ "${DRY_RUN}" == "false" ]]; then
"${PROXYGEN_PATH}" spec publish --no-confirm "${SPEC_PATH}"
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
else
echo "Would run this command"
echo "${PROXYGEN_PATH} spec publish --no-confirm ${SPEC_PATH}"
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 if in the internal-dev environment"
if [[ "${DRY_RUN}" == "false" ]]; then
"${PROXYGEN_PATH}" spec publish --uat --no-confirm "${SPEC_PATH}"
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
else
echo "Would run this command"
echo "${PROXYGEN_PATH} spec publish --uat --no-confirm ${SPEC_PATH}"
echo "Would call ${spec_publish_lambda}"
fi
fi
Loading