Skip to content

Certificate deployment in github action #19

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

Merged
merged 1 commit into from
Aug 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Certificate update from github action
Add test files

Enhanced certificate script

Correct template to correctly name certificate; cleanup

Finalize the github action

Use named parameters

Implement new cert logic that skips KV step

Incorporate certificate changes in github action

use named arguments for deploy-config script

Validate JSON certificate details

Test my action; Cleanup

Correct per shell checks

Correct per shell checks

Manually run workflow

Remove validate bits

Run correct action

Run correct action

Run correct action

Correct typo

Trigger push

Trigger push

Update tag

Update tag

Use new tag

Make cert script executable

Make deploy-certificate.sh executable

Enclose JSON array argument in quotes

Remove buggy json check

Download ARM template from public storage

Echo json to view if valid

Echo json to view if valid

Echo json to view if valid

JSON array through action to test

View nginx-cert-details content

View nginx-cert-details content

revert script

Parse certificate arg directly

test toJSON

test toJSON

test toJSON

test toJSON

test toJSON in action

Push certs

A bug free run..

Remove jq parse bit

Restore prev workflow

Intro new entry script for smart deployment

Shell check fixes

Make deploy.sh executable

add path for external scripts

triggers for workflow

correct call

Add check confg and cert scripts since I can't run scripts inline

Rename file

Make scripts executable

Rename files as per ops

Correct conditions

Do checks on action

cleanup;pass correct arg

change arm template URI

correct URI

clean workflow

rename action name and other variables

Add new lines as flagged on github

Add new lines as flagged on github

remove .gitignore

Remove test workflow
  • Loading branch information
george-ngugi committed Aug 25, 2022
commit a69d33feaa1a8a012ec44c138ca78c6ec4db9f29
19 changes: 15 additions & 4 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: 'NGINX configuration sync'
description: 'The action synchronizes NGINX configuration from a Git repository to an NGINX for Azure deployment.'
name: 'NGINX For Azure Deployment Sync'
description: 'The action synchronizes NGINX configuration from a Git repository and/or certificates already on Azure keyvault to an NGINX for Azure deployment'
inputs:
subscription-id:
description: 'The Azure subscription ID of the NGINX for Azure deployment.'
Expand All @@ -10,9 +10,12 @@ inputs:
nginx-deployment-name:
description: 'The name of the NGINX for Azure deployment.'
required: true
nginx-deployment-location:
description: 'The location where the NGINX deployment is located. Example westcentralus'
required: false
nginx-config-directory-path:
description: 'The NGINX configuration directory path relative to the root of the Git repository, example: "config/".'
required: true
required: false
nginx-root-config-file:
description: >
'The root NGINX configuration file path relative to the NGINX configuration directory in the Git repository, example: "nginx.conf".'
Expand All @@ -25,9 +28,17 @@ inputs:
can be used to overwrite the file paths when the action synchronizes the files to the NGINX for Azure deployment.'
required: false
default: ''
nginx-certificate-details:
description: 'An array of JSON objects each with keys nginx_cert_name, keyvault_secret, certificate_virtual_path and key_virtual_path. Example: [{"certificateName": "server1", "keyvaultSecret": "https://...", "certificateVirtualPath": "/etc/ssl/certs/server1.crt", "keyVirtualPath": "/etc/ssl/certs/server1.key" }, {"name": "server2", "keyvaultSecret": "https://...", "certificateVirtualPath": "/etc/ssl/certs/server2.crt", "keyVirtualPath": "/etc/ssl/certs/server2.key" }] '
required: false
runs:
using: "composite"
steps:
- name: 'Synchronize NGINX configuration from the Git repository to an NGINX for Azure deployment'
run: ${{github.action_path}}/src/deploy-config.sh ${{ inputs.subscription-id }} ${{ inputs.resource-group-name }} ${{ inputs.nginx-deployment-name }} ${{ inputs.nginx-config-directory-path }} ${{ inputs.nginx-root-config-file }} ${{ inputs.transformed-nginx-config-directory-path }}
run: ${{github.action_path}}/src/deploy-config.sh --subscription_id=${{ inputs.subscription-id }} --resource_group_name=${{ inputs.resource-group-name }} --nginx_deployment_name=${{ inputs.nginx-deployment-name }} --config_dir_path=${{ inputs.nginx-config-directory-path }} --root_config_file=${{ inputs.nginx-root-config-file }} --transformed_config_dir_path=${{ inputs.transformed-nginx-config-directory-path }}
if: ${{ inputs.nginx-config-directory-path != '' }}
shell: bash
- name: 'Synchronize NGINX certificate(s) from the Git repository to an NGINX for Azure deployment'
run: ${{github.action_path}}/src/deploy-certificate.sh --subscription_id=${{ inputs.subscription-id }} --resource_group_name=${{ inputs.resource-group-name }} --nginx_deployment_name=${{ inputs.nginx-deployment-name }} --nginx_resource_location=${{ inputs.nginx-deployment-location }} --certificates=${{ toJSON(inputs.nginx-certificate-details) }}
if: ${{ inputs.nginx-deployment-location != '' && inputs.nginx-certificate-details != '' }}
shell: bash
130 changes: 130 additions & 0 deletions src/deploy-certificate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'

for i in "$@"
do
case $i in
--subscription_id=*)
subscription_id="${i#*=}"
shift
;;
--resource_group_name=*)
resource_group_name="${i#*=}"
shift
;;
--nginx_deployment_name=*)
nginx_deployment_name="${i#*=}"
shift
;;
--nginx_resource_location=*)
nginx_resource_location="${i#*=}"
shift
;;
--certificates=*)
certificates="${i#*=}"
shift
;;
*)
echo "Not matched option '${i#*=}' passed in."
exit 1
;;
esac
done

if [[ ! -v subscription_id ]];
then
echo "Please set 'subscription-id' ..."
exit 1
fi
if [[ ! -v resource_group_name ]];
then
echo "Please set 'resource-group-name' ..."
exit 1
fi
if [[ ! -v nginx_deployment_name ]];
then
echo "Please set 'nginx-deployment-name' ..."
exit 1
fi
if [[ ! -v nginx_resource_location ]];
then
echo "Please set 'nginx-resource-location' ..."
exit 1
fi
if [[ ! -v certificates ]];
then
echo "Please set 'nginx-certificate-details' ..."
exit 1
fi

arm_template_file="nginx-for-azure-certificate-template.json"

#get the ARM template file
wget -O "$arm_template_file" https://nginxgithubactions.blob.core.windows.net/armtemplates/nginx-for-azure-certificate-template.json
echo "Downloaded the ARM template for synchronizing NGINX certificate."

cat "$arm_template_file"
echo ""

az account set -s "$subscription_id" --verbose

count=$(echo $certificates | jq '. | length')
for (( i=0; i<count; i++ ));
do
nginx_cert_name=$(echo $certificates | jq -r '.['"$i"'].certificateName')
nginx_cert_file=$(echo $certificates | jq -r '.['"$i"'].certificateVirtualPath')
nginx_key_file=$(echo $certificates | jq -r '.['"$i"'].keyVirtualPath')
keyvault_secret=$(echo $certificates | jq -r '.['"$i"'].keyvaultSecret')

do_nginx_arm_deployment=1
err_msg=" "
if [ -z "$nginx_cert_name" ] || [ "$nginx_cert_name" = "null" ]
then
err_msg+="nginx_cert_name is empty;"
do_nginx_arm_deployment=0
fi
if [ -z "$nginx_cert_file" ] || [ "$nginx_cert_file" = "null" ]
then
err_msg+="nginx_cert_file is empty;"
do_nginx_arm_deployment=0
fi
if [ -z "$nginx_key_file" ] || [ "$nginx_key_file" = "null" ]
then
err_msg+="nginx_key_file is empty;"
do_nginx_arm_deployment=0
fi
if [ -z "$keyvault_secret" ] || [ "$keyvault_secret" = "null" ]
then
err_msg+="keyvault_secret is empty;"
do_nginx_arm_deployment=0
fi

uuid="$(cat /proc/sys/kernel/random/uuid)"
template_file="template-$uuid.json"
template_deployment_name="${nginx_deployment_name:0:20}-$uuid"

cp "$arm_template_file" "$template_file"

echo "Synchronizing NGINX certificate"
echo "Subscription ID: $subscription_id"
echo "Resource group name: $resource_group_name"
echo "NGINX for Azure deployment name: $nginx_deployment_name"
echo "NGINX for Azure Location: $nginx_resource_location"
echo "ARM template deployment name: $template_deployment_name"
echo ""
echo "NGINX for Azure cert name: $nginx_cert_name"
echo "NGINX for Azure cert file location: $nginx_cert_file"
echo "NGINX for Azure key file location: $nginx_key_file"
echo ""

if [ $do_nginx_arm_deployment -eq 1 ]
then
set +e
az deployment group create --name "$template_deployment_name" --resource-group "$resource_group_name" --template-file "$template_file" --parameters name="$nginx_cert_name" location="$nginx_resource_location" nginxDeploymentName="$nginx_deployment_name" certificateVirtualPath="$nginx_cert_file" keyVirtualPath="$nginx_key_file" keyVaultSecretID="$keyvault_secret" --verbose
set -e
else
echo "Skipping JSON object $i cert deployment with error:$err_msg"
echo ""
fi
done
66 changes: 60 additions & 6 deletions src/deploy-config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,66 @@
set -euo pipefail
IFS=$'\n\t'

subscription_id=$1
resource_group_name=$2
nginx_deployment_name=$3
config_dir_path=$4
root_config_file=$5
transformed_config_dir_path=${6:-''}
transformed_config_dir_path=''
for i in "$@"
do
case $i in
--subscription_id=*)
subscription_id="${i#*=}"
shift
;;
--resource_group_name=*)
resource_group_name="${i#*=}"
shift
;;
--nginx_deployment_name=*)
nginx_deployment_name="${i#*=}"
shift
;;
--config_dir_path=*)
config_dir_path="${i#*=}"
shift
;;
--root_config_file=*)
root_config_file="${i#*=}"
shift
;;
--transformed_config_dir_path=*)
transformed_config_dir_path="${i#*=}"
shift
;;
*)
echo "Not matched option '${i#*=}' passed in."
exit 1
;;
esac
done

if [[ ! -v subscription_id ]];
then
echo "Please set 'subscription-id' ..."
exit 1
fi
if [[ ! -v resource_group_name ]];
then
echo "Please set 'resource-group-name' ..."
exit 1
fi
if [[ ! -v nginx_deployment_name ]];
then
echo "Please set 'nginx-deployment-name' ..."
exit 1
fi
if [[ ! -v config_dir_path ]];
then
echo "Please set 'nginx-config-directory-path' ..."
exit 1
fi
if [[ ! -v root_config_file ]];
then
echo "Please set 'nginx-root-config-file' ..."
exit 1
fi

# Validation and preprocessing

Expand Down
88 changes: 88 additions & 0 deletions src/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'

for i in "$@"
do
case $i in
--subscription_id=*)
subscription_id="${i#*=}"
shift
;;
--resource_group_name=*)
resource_group_name="${i#*=}"
shift
;;
--nginx_deployment_name=*)
nginx_deployment_name="${i#*=}"
shift
;;
--nginx_resource_location=*)
nginx_resource_location="${i#*=}"
shift
;;
--config_dir_path=*)
config_dir_path="${i#*=}"
shift
;;
--root_config_file=*)
root_config_file="${i#*=}"
shift
;;
--transformed_config_dir_path=*)
transformed_config_dir_path="${i#*=}"
shift
;;
--certificates=*)
certificates="${i#*=}"
shift
;;
*)
echo "Not matched option '${i#*=}' passed in."
exit 1
;;
esac
done

if [[ ! -v subscription_id ]];
then
echo "Please set 'subscription-id' ..."
exit 1
fi
if [[ ! -v resource_group_name ]];
then
echo "Please set 'resource-group-name' ..."
exit 1
fi
if [[ ! -v nginx_deployment_name ]];
then
echo "Please set 'nginx-deployment-name' ..."
exit 1
fi

if [[ -v nginx_resource_location ]] && [[ -v certificates ]];
then
./deploy-certificate.sh \
--subscription_id="$subscription_id" \
--resource_group_name="$resource_group_name" \
--nginx_deployment_name="$nginx_deployment_name" \
--nginx_resource_location="$nginx_resource_location" \
--certificates="$certificates"
fi

if [[ ! -v transformed_config_dir_path ]];
then
transformed_config_dir_path=''
fi

if [[ -v config_dir_path ]] && [[ -v root_config_file ]];
then
./deploy-config.sh \
--subscription_id="$subscription_id" \
--resource_group_name="$resource_group_name" \
--nginx_deployment_name="$nginx_deployment_name" \
--config_dir_path="$config_dir_path" \
--root_config_file="$root_config_file" \
--transformed_config_dir_path="$transformed_config_dir_path"
fi

55 changes: 55 additions & 0 deletions src/nginx-for-azure-certificate-template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"name": {
"type": "string",
"metadata": {
"description": "The name of the cert resource"
}
},
"location": {
"type": "string",
"metadata": {
"description": "The location for all resources"
}
},
"nginxDeploymentName": {
"type": "string",
"metadata": {
"description": "The name of your NGINX deployment resource"
}
},
"certificateVirtualPath": {
"type": "string",
"metadata": {
"description": "The file path of the certificate file"
}
},
"keyVirtualPath": {
"type": "string",
"metadata": {
"description": "The file path of the certificate key file"
}
},
"keyVaultSecretID": {
"type": "string",
"metadata": {
"description": "The secret ID of the key vault holding the certificate"
}
}
},
"resources": [
{
"type": "NGINX.NGINXPLUS/nginxDeployments/certificates",
"apiVersion": "2021-05-01-preview",
"name": "[concat(parameters('nginxDeploymentName'), concat('/', parameters('name')))]",
"location": "[parameters('location')]",
"properties": {
"certificateVirtualPath": "[parameters('certificateVirtualPath')]",
"keyVirtualPath": "[parameters('keyVirtualPath')]",
"keyVaultSecretId": "[parameters('keyVaultSecretID')]"
}
}
]
}