-
Notifications
You must be signed in to change notification settings - Fork 11
Draft: Remove Azure pipeline task. Support protected files and remove need for rg permissions for service principal #39
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
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,14 +24,19 @@ inputs: | |
default: "nginx.conf" | ||
transformed-nginx-config-directory-path: | ||
description: > | ||
'The transformed absolute path of the NGINX configuration directory in NGINXaaS for Azure deployment, example: "/etc/nginx/". | ||
If the "include" directive in the NGINX configuration files uses absolute paths, the path transformation | ||
can be used to overwrite the file paths when the action synchronizes the files to the NGINXaaS for Azure deployment.' | ||
'The absolute directory path in the NGINXaaS for Azure deployment where your configuration files will be placed. | ||
All files found in the nginx-config-directory-path will be copied to this location in the deployment. | ||
For example, use "/etc/nginx/" to match the standard NGINX directory structure on Azure. | ||
If your NGINX configuration files use absolute paths in "include" directives, this setting ensures those paths are correctly mapped in the deployment by prepending the specified directory.' | ||
required: false | ||
default: "" | ||
nginx-certificates: | ||
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 | ||
protected-files: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From an Actions perspective, this is a new feature in that it was not there earlier on and now we have added support for handling protected files via the action:
|
||
description: "Comma-separated list of file paths relative to nginx-config-directory-path that should be marked as protected. Example: 'ssl/private.key,conf.d/secrets.conf'" | ||
required: false | ||
default: "" | ||
debug: | ||
description: "Enable/Disable debug output." | ||
required: false | ||
|
@@ -40,10 +45,10 @@ runs: | |
using: "composite" | ||
steps: | ||
- name: "Synchronize NGINX certificate(s) from the Git repository to an NGINXaaS 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-certificates) }} --debug=${{ inputs.debug }} | ||
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-certificates) }} --debug=${{ inputs.debug }} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. https://github.com/kuthiala/nginx-for-azure-deploy-action/blob/f9dbec3c93f58bd3634762d4b2de1f2f0193a4d7/src/deploy-certificate.sh The input handling here needs to be fixed. I am okay if you want to preserve both but in that separate MR, I think you can safely consider refactoring configs and certs both as separate commits. Folks may have a preference in splitting that up further as the changeset will be a bit large but 👍 |
||
if: ${{ inputs.nginx-deployment-location != '' && inputs.nginx-certificates != '' }} | ||
shell: bash | ||
- name: "Synchronize NGINX configuration from the Git repository to an NGINXaaS for Azure deployment" | ||
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 }} --debug=${{ inputs.debug }} | ||
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 }} --nginx-config-directory-path=${{ inputs.nginx-config-directory-path }} --nginx-root-config-file=${{ inputs.nginx-root-config-file }} --transformed-nginx-config-directory-path=${{ inputs.transformed-nginx-config-directory-path }} --protected-files=${{ inputs.protected-files }} --debug=${{ inputs.debug }} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. here's a quick suggestion: I agree with what you are doing here but:
I'd recommend the following:
|
||
if: ${{ inputs.nginx-config-directory-path != '' }} | ||
shell: bash |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,69 +1,72 @@ | ||
#!/bin/bash | ||
set -euo pipefail | ||
set -eo pipefail | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. was there a reason to drop |
||
IFS=$'\n\t' | ||
|
||
transformed_config_dir_path='' | ||
for i in "$@" | ||
do | ||
case $i in | ||
--subscription_id=*) | ||
--subscription-id=*) | ||
subscription_id="${i#*=}" | ||
shift | ||
;; | ||
--resource_group_name=*) | ||
--resource-group-name=*) | ||
resource_group_name="${i#*=}" | ||
shift | ||
;; | ||
--nginx_deployment_name=*) | ||
--nginx-deployment-name=*) | ||
nginx_deployment_name="${i#*=}" | ||
shift | ||
;; | ||
--config_dir_path=*) | ||
--nginx-config-directory-path=*) | ||
config_dir_path="${i#*=}" | ||
shift | ||
;; | ||
--root_config_file=*) | ||
--nginx-root-config-file=*) | ||
root_config_file="${i#*=}" | ||
shift | ||
;; | ||
--transformed_config_dir_path=*) | ||
--transformed-nginx-config-directory-path=*) | ||
transformed_config_dir_path="${i#*=}" | ||
shift | ||
;; | ||
--debug=*) | ||
debug="${i#*=}" | ||
shift | ||
;; | ||
--protected-files=*) | ||
protected_files="${i#*=}" | ||
shift | ||
;; | ||
*) | ||
echo "Not matched option '${i#*=}' passed in." | ||
echo "Unknown option '${i}' passed in." | ||
exit 1 | ||
;; | ||
esac | ||
done | ||
|
||
if [[ ! -v subscription_id ]]; | ||
then | ||
echo "Please set 'subscription-id' ..." | ||
exit 1 | ||
# Validate Required Parameters | ||
missing_params=() | ||
if [ -z "$subscription_id" ]; then | ||
missing_params+=("subscription-id") | ||
fi | ||
if [[ ! -v resource_group_name ]]; | ||
then | ||
echo "Please set 'resource-group-name' ..." | ||
exit 1 | ||
if [ -z "$resource_group_name" ]; then | ||
missing_params+=("resource-group-name") | ||
fi | ||
if [[ ! -v nginx_deployment_name ]]; | ||
then | ||
echo "Please set 'nginx-deployment-name' ..." | ||
exit 1 | ||
if [ -z "$nginx_deployment_name" ]; then | ||
missing_params+=("nginx-deployment-name") | ||
fi | ||
if [[ ! -v config_dir_path ]]; | ||
then | ||
echo "Please set 'nginx-config-directory-path' ..." | ||
exit 1 | ||
if [ -z "$config_dir_path" ]; then | ||
missing_params+=("nginx-config-directory-path") | ||
fi | ||
if [[ ! -v root_config_file ]]; | ||
then | ||
echo "Please set 'nginx-root-config-file' ..." | ||
if [ -z "$root_config_file" ]; then | ||
missing_params+=("nginx-root-config-file") | ||
fi | ||
|
||
# Check and print if any required params are missing | ||
if [ ${#missing_params[@]} -gt 0 ]; then | ||
echo "Error: Missing required variables in the workflow:" | ||
echo "${missing_params[*]}" | ||
exit 1 | ||
fi | ||
|
||
|
@@ -121,60 +124,206 @@ fi | |
transformed_root_config_file_path="$transformed_config_dir_path$root_config_file" | ||
echo "The transformed root NGINX configuration file path is '$transformed_root_config_file_path'." | ||
|
||
# Create a NGINX configuration tarball. | ||
# Common utility functions | ||
|
||
# Function to trim whitespace from a string | ||
trim_whitespace() { | ||
local var="$1" | ||
# Trim leading whitespace from the file path (var) | ||
# ${var%%[![:space:]]*} starts at the file path's end | ||
# and finds the longest match of non-whitespace | ||
# characters leaving only leading whitespaces | ||
# ${var#"..." } removes the leading whitespace found | ||
var="${var#"${var%%[![:space:]]*}"}" | ||
# Remove trailing whitespace | ||
# See explanation above. The process is reversed here. | ||
var="${var%"${var##*[![:space:]]}"}" | ||
# Check if the file exists in the repository | ||
echo "$var" | ||
} | ||
|
||
# Function to encode file content to base64 | ||
encode_file_base64() { | ||
local file_path="$1" | ||
# Use base64 to encode the file content | ||
# -w 0 option is used to avoid line wrapping in the output | ||
base64 -w 0 "$file_path" | ||
} | ||
|
||
config_tarball="nginx-config.tar.gz" | ||
# Function to build virtual path from relative path | ||
build_virtual_path() { | ||
local relative_path="$1" | ||
echo "${transformed_config_dir_path}${relative_path}" | ||
} | ||
|
||
echo "Creating a tarball from the NGINX configuration directory." | ||
tar -cvzf "$config_tarball" -C "$config_dir_path" --xform s:'./':"$transformed_config_dir_path": . | ||
echo "Successfully created the tarball from the NGINX configuration directory." | ||
# Function to add a file entry to a JSON array | ||
# The add_file_to_json_array function uses indirect variable references | ||
# and global assignment to update JSON arrays and flags that track | ||
# which files have been processed. The variable names for the JSON array | ||
# and the "first file" flag are passed as arguments, allowing the | ||
# function to generically update different arrays | ||
# (for regular and protected files) without hardcoding their names. | ||
# The syntax ${!var} retrieves the value of the variable whose | ||
# name is stored in 'var', and declare -g ensures the updated | ||
# values are set globally, so changes persist outside the function. | ||
add_file_to_json_array() { | ||
local file_path="$1" | ||
local virtual_path="$2" | ||
local file_type="$3" # "regular" or "protected" | ||
local json_var_name="$4" # Variable name to modify | ||
local first_file_var_name="$5" # Variable name for first_file flag | ||
|
||
if [ -f "$file_path" ]; then | ||
echo "Processing $file_type file: $file_path -> $virtual_path" | ||
|
||
# Base64 encode the file content | ||
local file_content_b64 | ||
file_content_b64=$(encode_file_base64 "$file_path") | ||
|
||
# Get current values using indirect variable references | ||
local current_json="${!json_var_name}" | ||
local is_first_file="${!first_file_var_name}" | ||
|
||
# Add comma separator if not the first file | ||
if [ "$is_first_file" = false ]; then | ||
current_json+="," | ||
fi | ||
|
||
# Add the file entry to JSON array | ||
current_json+="{\"content\":\"$file_content_b64\",\"virtual-path\":\"$virtual_path\"}" | ||
|
||
# Update the variables using indirect assignment | ||
declare -g "$json_var_name=$current_json" | ||
declare -g "$first_file_var_name=false" | ||
|
||
if [[ "$debug" == true ]]; then | ||
echo "$file_type file virtual path: $virtual_path" | ||
echo "$file_type file content (base64): ${file_content_b64:0:50}..." | ||
fi | ||
else | ||
echo "Warning: $file_type file '$file_path' not found" | ||
fi | ||
} | ||
|
||
# Process protected files first to build exclusion list | ||
protected_files_list=() | ||
if [ -n "$protected_files" ]; then | ||
IFS=',' read -ra files <<< "$protected_files" | ||
|
||
for file in "${files[@]}"; do | ||
file=$(trim_whitespace "$file") | ||
if [ -n "$file" ]; then | ||
protected_files_list+=("$file") | ||
fi | ||
done | ||
fi | ||
|
||
# Function to check if a file is in the protected files list | ||
is_protected_file() { | ||
local relative_path="$1" | ||
for protected_file in "${protected_files_list[@]}"; do | ||
if [ "$relative_path" = "$protected_file" ]; then | ||
return 0 # File is protected | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Since you have the doc string on the function, I think it's okay to drop these inline comments. The logic makes it obvious 👍 |
||
fi | ||
done | ||
return 1 # File is not protected | ||
} | ||
|
||
echo "Listing the NGINX configuration file paths in the tarball." | ||
tar -tf "$config_tarball" | ||
# Process all configuration files individually (excluding protected files) | ||
|
||
echo "Processing NGINX configuration files individually." | ||
|
||
# Build the files JSON array | ||
files_json="[" | ||
files_first_file=true | ||
|
||
# Find all files in the config directory and process them (excluding protected files) | ||
while IFS= read -r -d '' file; do | ||
# Get relative path from config directory | ||
relative_path="${file#$config_dir_path}" | ||
|
||
# Skip if this file is in the protected files list | ||
if is_protected_file "$relative_path"; then | ||
echo "Skipping protected file from regular files: $relative_path" | ||
continue | ||
fi | ||
|
||
# Apply transformation to get virtual path | ||
virtual_path=$(build_virtual_path "$relative_path") | ||
|
||
add_file_to_json_array "$file" "$virtual_path" "regular" "files_json" "files_first_file" | ||
done < <(find "$config_dir_path" -type f -print0) | ||
|
||
encoded_config_tarball=$(base64 "$config_tarball") | ||
files_json+="]" | ||
|
||
if [[ "$debug" == true ]]; then | ||
echo "The base64 encoded NGINX configuration tarball" | ||
echo "$encoded_config_tarball" | ||
echo "Regular files JSON: $files_json" | ||
fi | ||
echo "" | ||
|
||
# Synchronize the NGINX configuration tarball to the NGINXaaS for Azure deployment. | ||
# Process protected files if specified | ||
protected_files_arg="" | ||
if [ -n "$protected_files" ]; then | ||
echo "Processing protected files: $protected_files" | ||
|
||
# Build the protected files JSON array | ||
protected_files_json="[" | ||
protected_first_file=true | ||
IFS=',' read -ra files <<< "$protected_files" | ||
|
||
for file in "${files[@]}"; do | ||
file=$(trim_whitespace "$file") | ||
if [ -n "$file" ]; then | ||
repo_file_path="${config_dir_path}${file}" | ||
virtual_path=$(build_virtual_path "$file") | ||
|
||
add_file_to_json_array "$repo_file_path" "$virtual_path" "protected" "protected_files_json" "protected_first_file" | ||
fi | ||
done | ||
|
||
protected_files_json+="]" | ||
|
||
if [ "$protected_first_file" = false ]; then | ||
protected_files_arg="--protected-files" | ||
if [[ "$debug" == true ]]; then | ||
echo "Protected files JSON: $protected_files_json" | ||
fi | ||
fi | ||
fi | ||
|
||
uuid="$(cat /proc/sys/kernel/random/uuid)" | ||
template_file="template-$uuid.json" | ||
template_deployment_name="${nginx_deployment_name:0:20}-$uuid" | ||
|
||
wget -O "$template_file" https://raw.githubusercontent.com/nginxinc/nginx-for-azure-deploy-action/487d1394d6115d4f42ece6200cbd20859595557d/src/nginx-for-azure-configuration-template.json | ||
echo "Downloaded the ARM template for synchronizing NGINX configuration." | ||
cat "$template_file" | ||
echo "" | ||
# Synchronize the NGINX configuration files to the NGINXaaS for Azure deployment. | ||
|
||
echo "Synchronizing NGINX configuration" | ||
echo "Subscription ID: $subscription_id" | ||
echo "Resource group name: $resource_group_name" | ||
echo "NGINXaaS for Azure deployment name: $nginx_deployment_name" | ||
echo "ARM template deployment name: $template_deployment_name" | ||
echo "" | ||
|
||
az account set -s "$subscription_id" --verbose | ||
|
||
echo "Installing the az nginx extension if not already installed." | ||
az extension add --name nginx --allow-preview true | ||
|
||
az_cmd=( | ||
"az" | ||
"nginx" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you need |
||
"deployment" | ||
"group" | ||
"create" | ||
"--name" "$template_deployment_name" | ||
"configuration" | ||
"update" | ||
"--name" "default" | ||
"--deployment-name" "$nginx_deployment_name" | ||
"--resource-group" "$resource_group_name" | ||
"--template-file" "$template_file" | ||
"--parameters" | ||
"nginxDeploymentName=$nginx_deployment_name" | ||
"rootFile=$transformed_root_config_file_path" | ||
"tarball=$encoded_config_tarball" | ||
"--root-file" "$transformed_root_config_file_path" | ||
"--files" "$files_json" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if a user has large number of static files to host static content via git, you will very likely hit the Azure API limit of 4M using this action. In those cases, a tarball is of huge help. You should consider the tradeoffs of dropping tarball support in favor using the config files directly. It's common for users to host static content on Github. Example: https://github.com/nginx/documentation/ |
||
"--verbose" | ||
) | ||
|
||
# Add protected files argument if present | ||
if [ -n "$protected_files_arg" ]; then | ||
az_cmd+=("$protected_files_arg") | ||
az_cmd+=("$protected_files_json") | ||
fi | ||
|
||
if [[ "$debug" == true ]]; then | ||
az_cmd+=("--debug") | ||
echo "${az_cmd[@]}" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example, use "/etc/nginx/" to match the standard NGINX directory structure on Azure.
->For example, use "/etc/nginx/" to match the standard NGINX directory structure on your deployment.
<< something along these lines.