Skip to content

Instantly share code, notes, and snippets.

@Yvand
Last active August 16, 2021 06:57
Show Gist options
  • Save Yvand/674c334fade0cb89f58a7dca44329914 to your computer and use it in GitHub Desktop.
Save Yvand/674c334fade0cb89f58a7dca44329914 to your computer and use it in GitHub Desktop.
#!/bin/bash
set -euo pipefail
IFS=$'\n\t ' # Shell uses IFS to determine the field separators. Use the space ' ' to split param_rgNames to an array
# -e: immediately exit if any command has a non-zero exit status
# -u: immediately exit if using a variable not previously declared
# -o: prevents errors in a pipeline from being masked
usage() { echo "Usage: $0 -u <servicePrincipal-id> -s <servicePrincipal-secret> -t <tenant-id> -g '<rgName1 rgName2 rgName3>';" exit 1; }
: '
DESCRIPTION
This script checks the network security groups of the resource groups specified, and if needed, adds/updates a rule to allow remote access only from the internet IP of this machine.
CREATE THE SERVICE PRINCIPAL
az ad sp create-for-rbac --name CheckRemoteAccessRules --skip-assignment
az role assignment create --assignee APP_ID --role Contributor
Minimal permissions required by the sp (NOT tested):
Microsoft.Network/networkSecurityGroups/read
Microsoft.Network/networkSecurityGroups/write
'
nsgRuleName="allow-remoteaccess-singleip"
nsgRulePriority=100
msgRulePorts="3389 22"
param_servicePrincipalId=""
param_servicePrincipalSecret=""
param_tenantId=""
param_rgNames=()
GREEN='\033[0;32m'
NC='\033[0m' # No Color
# Initialize parameters specified from command line
while getopts ":u:s:t:g:" arg; do
case "${arg}" in
u)
param_servicePrincipalId=${OPTARG}
;;
s)
param_servicePrincipalSecret=${OPTARG}
;;
t)
param_tenantId=${OPTARG}
;;
g)
param_rgNames=${OPTARG}
;;
esac
done
shift $((OPTIND-1))
internetip=$(curl -s 'https://api.ipify.org')
if [ -z "$internetip" ]; then
echo "Could not get the internet IP address of the machine"
exit 1
fi
echo "Internet IP address of machine is '$internetip'. Sign-in as service principal ID '$param_servicePrincipalId' to check the resource groups $param_rgNames..."
az login --service-principal --username $param_servicePrincipalId --password $param_servicePrincipalSecret --tenant $param_tenantId 1> /dev/null
pids_rgs=()
read -r -a rgNames <<< "$param_rgNames"
for rgName in ${rgNames[@]}; do
(
echo "Checking resource group $rgName..."
nsgs=$(az network nsg list -g $rgName --query '[].['name']' -o tsv)
nsgs=($nsgs) # split to make it an actual array
pids_nsgs=()
for nsgName in "${nsgs[@]}"; do
(
echo "Checking resource in resource group '$rgName' / network security group '$nsgName'..."
# Check if the rule exists
if ! ipCurrentlySet=$(az network nsg rule show -g $rgName --nsg-name $nsgName --name $nsgRuleName --query 'sourceAddressPrefix' -o tsv 2> /dev/null); then
# Rule does not exist
# Check if a rule on priority $nsgRulePriority already exists, and if so delete it before creating the rule
existingRuleId=$(az network nsg rule list -g $rgName --nsg-name $nsgName --query "[?to_string(priority)=='$nsgRulePriority'].[id]" -o tsv)
if [ ! -z "$existingRuleId" ]; then
echo "Deleting rule with priority $nsgRulePriority in resource group '$rgName' / network security group '$nsgName' before adding new rule '$nsgRuleName'..."
az network nsg rule delete --ids $existingRuleId
fi
echo "Adding rule '$nsgRuleName' in resource group '$rgName' / network security group '$nsgName' to allow inbound ports '$msgRulePorts' only from IP '$internetip'..."
az network nsg rule create -g $rgName --nsg-name $nsgName -n $nsgRuleName --priority $nsgRulePriority \
--source-address-prefixes $internetip --source-port-ranges '*' \
--direction Inbound --destination-port-ranges $msgRulePorts --protocol Tcp --access Allow 1> /dev/null
echo -e "${GREEN}Rule '$nsgRuleName' added successfully in resource group '$rgName' / network security group '$nsgName'.${NC}"
else
if [ "$ipCurrentlySet" == "$internetip" ]; then
echo "Rule is already up to date in resource group '$rgName' / network security group '$nsgName'."
else
echo "Updating rule '$nsgRuleName' in resource group '$rgName' / network security group '$nsgName' to allow inbound ports '$msgRulePorts' only from IP '$internetip'..."
az network nsg rule update -g $rgName --nsg-name $nsgName -n $nsgRuleName --source-address-prefixes $internetip 1> /dev/null
echo -e "${GREEN}Rule updated successfully in resource group '$rgName' / network security group '$nsgName'.${NC}"
fi
fi
) &
pids_nsgs+=( $! )
done
for pid_nsg in "${pids_nsgs[@]}"; do
wait $pid_nsg
done
) &
pids_rgs+=( $! )
done
for pid_rg in "${pids_rgs[@]}"; do
wait $pid_rg
done
echo "Finished."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment